Added feature #16315: New extension manager part 1: splitting classes: em files
authorSteffen Kamper <info@sk-typo3.de>
Fri, 12 Nov 2010 23:52:00 +0000 (23:52 +0000)
committerSteffen Kamper <info@sk-typo3.de>
Fri, 12 Nov 2010 23:52:00 +0000 (23:52 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@9361 709f56b5-9817-0410-a4d7-c38de5d9e867

57 files changed:
typo3/sysext/em/classes/conf.php [new file with mode: 0644]
typo3/sysext/em/classes/connection/class.tx_em_connection_extdirectserver.php [new file with mode: 0644]
typo3/sysext/em/classes/connection/class.tx_em_connection_soap.php [new file with mode: 0644]
typo3/sysext/em/classes/connection/class.tx_em_connection_ter.php [new file with mode: 0644]
typo3/sysext/em/classes/database/class.tx_em_database.php [new file with mode: 0644]
typo3/sysext/em/classes/exception/class.em_connection_exception.php [deleted file]
typo3/sysext/em/classes/exception/class.tx_em_connection_exception.php [new file with mode: 0644]
typo3/sysext/em/classes/exception/class.tx_em_extensionimport_exception.php [new file with mode: 0644]
typo3/sysext/em/classes/exception/class.tx_em_extensionxml_exception.php [new file with mode: 0644]
typo3/sysext/em/classes/exception/class.tx_em_mirrorxml_exception.php [new file with mode: 0644]
typo3/sysext/em/classes/exception/class.tx_em_xml_exception.php [new file with mode: 0644]
typo3/sysext/em/classes/extensions/class.tx_em_extensions_details.php [new file with mode: 0644]
typo3/sysext/em/classes/extensions/class.tx_em_extensions_list.php [new file with mode: 0644]
typo3/sysext/em/classes/import/class.tx_em_import_extensionlistimporter.php [new file with mode: 0644]
typo3/sysext/em/classes/import/class.tx_em_import_mirrorlistimporter.php [new file with mode: 0644]
typo3/sysext/em/classes/index.php [new file with mode: 0644]
typo3/sysext/em/classes/install/class.tx_em_install.php [new file with mode: 0644]
typo3/sysext/em/classes/parser/class.tx_em_parser_extensionxmlabstractparser.php [new file with mode: 0644]
typo3/sysext/em/classes/parser/class.tx_em_parser_extensionxmlpullparser.php [new file with mode: 0644]
typo3/sysext/em/classes/parser/class.tx_em_parser_extensionxmlpushparser.php [new file with mode: 0644]
typo3/sysext/em/classes/parser/class.tx_em_parser_mirrorxmlabstractparser.php [new file with mode: 0644]
typo3/sysext/em/classes/parser/class.tx_em_parser_mirrorxmlpullparser.php [new file with mode: 0644]
typo3/sysext/em/classes/parser/class.tx_em_parser_xmlabstractparser.php [new file with mode: 0644]
typo3/sysext/em/classes/parser/class.tx_em_parser_xmlparserfactory.php [new file with mode: 0644]
typo3/sysext/em/classes/repository/class.tx_em_repository.php [new file with mode: 0644]
typo3/sysext/em/classes/repository/class.tx_em_repository_mirrors.php [new file with mode: 0644]
typo3/sysext/em/classes/repository/class.tx_em_repository_utility.php [new file with mode: 0644]
typo3/sysext/em/classes/settings/class.tx_em_settings.php [new file with mode: 0644]
typo3/sysext/em/classes/tasks/class.em_tasks_updateextensionlist.php [deleted file]
typo3/sysext/em/classes/tasks/class.tx_em_tasks_updateextensionlist.php [new file with mode: 0644]
typo3/sysext/em/classes/tools/class.tx_em_tools.php [new file with mode: 0644]
typo3/sysext/em/classes/tools/class.tx_em_tools_unzip.php [new file with mode: 0644]
typo3/sysext/em/classes/tools/class.tx_em_tools_xmlhandler.php [new file with mode: 0644]
typo3/sysext/em/classes/translations/class.tx_em_translations.php [new file with mode: 0644]
typo3/sysext/em/ext_autoload.php
typo3/sysext/em/ext_emconf.php
typo3/sysext/em/ext_localconf.php
typo3/sysext/em/ext_tables.php
typo3/sysext/em/ext_tables.sql [new file with mode: 0644]
typo3/sysext/em/ext_tables_static+adt.sql [new file with mode: 0644]
typo3/sysext/em/interfaces/interface.em_index_checkdatabaseupdateshook.php [deleted file]
typo3/sysext/em/interfaces/interface.tx_em_index_checkdatabaseupdateshook.php [new file with mode: 0644]
typo3/sysext/em/language/locallang.xml
typo3/sysext/em/mod1/class.em_index.php [deleted file]
typo3/sysext/em/mod1/class.em_soap.php [deleted file]
typo3/sysext/em/mod1/class.em_terconnection.php [deleted file]
typo3/sysext/em/mod1/class.em_unzip.php [deleted file]
typo3/sysext/em/mod1/class.em_xmlhandler.php [deleted file]
typo3/sysext/em/mod1/class.nusoap.php [deleted file]
typo3/sysext/em/mod1/clear.gif [deleted file]
typo3/sysext/em/mod1/conf.php [deleted file]
typo3/sysext/em/mod1/download.png [deleted file]
typo3/sysext/em/mod1/em.gif [deleted file]
typo3/sysext/em/mod1/index.php [deleted file]
typo3/sysext/em/mod1/install.gif [deleted file]
typo3/sysext/em/mod1/oodoc.gif [deleted file]
typo3/sysext/em/mod1/uninstall.gif [deleted file]

diff --git a/typo3/sysext/em/classes/conf.php b/typo3/sysext/em/classes/conf.php
new file mode 100644 (file)
index 0000000..b79be8e
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+define('TYPO3_MOD_PATH', 'typo3/sysext/em/');
+$BACK_PATH='';
+
+$MLANG['default']['tabs_images']['tab'] = 'em.gif';
+$MLANG['default']['ll_ref'] = 'LLL:EXT:em/language/locallang.xml';
+
+$MCONF['script']='_DISPATCH';
+$MCONF['access']='admin';
+$MCONF['name']='tools_em';
+$MCONF['workspaces']='online';
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/connection/class.tx_em_connection_extdirectserver.php b/typo3/sysext/em/classes/connection/class.tx_em_connection_extdirectserver.php
new file mode 100644 (file)
index 0000000..f3f37c2
--- /dev/null
@@ -0,0 +1,683 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2010 Steffen Kamper (info@sk-typo3.de)
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+/**
+ * Module: Extension manager, developer module
+ *
+ * This class handles all Ajax calls coming from ExtJS
+ *
+ * $Id: class.tx_em_Connection_ExtDirectServer.php 2083 2010-03-22 00:48:31Z steffenk $
+ *
+ * @author     Steffen Kamper <info@sk-typo3.de>
+ */
+
+
+class tx_em_Connection_ExtDirectServer {
+       /**
+        * @var tx_em_Tools_XmlHandler
+        */
+       var $xmlhandler;
+
+       /**
+        * Keeps instance of settings class.
+        *
+        * @var tx_em_Settings
+        */
+       static protected $objSettings;
+
+
+       /*********************************************************************/
+       /* General                                                           */
+       /*********************************************************************/
+
+       /**
+        * Constructor
+        *
+        * @return void
+        */
+       public function __construct() {
+               $GLOBALS['TBE_TEMPLATE'] = t3lib_div::makeInstance('template');
+       }
+
+
+       /**
+        * Method returns instance of settings class.
+        *
+        * @access  protected
+        * @return  em_settings  instance of settings class
+        */
+       protected function getSettingsObject() {
+               if (!is_object(self::$objSettings) && !(self::$objSettings instanceof tx_em_Settings)) {
+                       self::$objSettings = t3lib_div::makeInstance('tx_em_Settings');
+               }
+               return self::$objSettings;
+       }
+
+
+       /*********************************************************************/
+       /* Local Extension List                                              */
+       /*********************************************************************/
+
+
+       /**
+        * Render local extension list
+        *
+        * @return string $content
+        */
+       public function getExtensionList() {
+               $list = t3lib_div::makeInstance('tx_em_Extensions_List');
+               $extList = $list->getInstalledExtensions(TRUE);
+
+
+               return array(
+                       'length' => count($extList),
+                       'data' => $extList
+               );
+
+       }
+
+       /**
+        * Enter description here...
+        *
+        * @return unknown
+        */
+       public function getInstalledExtkeys() {
+               $list = t3lib_div::makeInstance('tx_em_Extensions_List');
+               $extList = $list->getInstalledExtensions(TRUE);
+
+
+               $temp = $this->getSettings();
+               $selectedLanguage = unserialize($temp['selectedLanguages']);
+
+
+               $keys = array();
+               $i = 0;
+               foreach ($extList as $ext) {
+                       if ($ext['installed']) {
+                               $keys[$i] = array(
+                                       'extkey' => $ext['extkey'],
+                                       'icon' => $ext['icon'],
+                                       'stype' => $ext['typeShort'],
+                               );
+                               foreach ($selectedLanguage as $language) {
+                                       $keys[$i]['lang'][] = $GLOBALS['LANG']->sL('LLL:EXT:setup/mod/locallang.xml:lang_' . $language);
+                               }
+                               $i++;
+                       }
+               }
+
+               return array(
+                       'length' => count($keys),
+                       'data' => $keys,
+               );
+       }
+
+       /**
+        * Render module content
+        *
+        * @return string $content
+        */
+       public function getExtensionDetails() {
+               $list = t3lib_div::makeInstance('tx_em_Extensions_List');
+               $extList = $list->getInstalledExtensions(TRUE);
+
+
+               return array(
+                       'length' => count($extList),
+                       'data' => $extList
+               );
+
+       }
+
+       /**
+        * Render extension update
+        *
+        * @var string $extKey
+        * @return string $content
+        */
+       public function getExtensionUpdate($extKey) {
+               if (isset($GLOBALS['TYPO3_LOADED_EXT'][$extKey])) {
+                       $path = t3lib_extMgm::extPath($extKey);
+                       $ext = array();
+
+                       $install = t3lib_div::makeInstance('tx_em_Install');
+                       $extension = t3lib_div::makeInstance('tx_em_Extensions_List');
+                       $extension->singleExtInfo($extKey, $path, $ext);
+                       $ext = $ext[0];
+                       $update = $install->checkDBupdates($extKey, $ext);
+                       return $update ? $update : 'Extension is up to date.';
+               } else {
+                       return 'Extension "' . htmlspecialchars($extKey) . '" is not installed.';
+               }
+       }
+
+
+       /**
+        * Render extension configuration
+        *
+        * @var string $extKey
+        * @return string $content
+        */
+       public function getExtensionConfiguration($extKey) {
+               $extensionList = t3lib_div::makeInstance('tx_em_Extensions_List', $this);
+               list($list,) = $extensionList->getInstalledExtensions();
+               $install = t3lib_div::makeInstance('tx_em_Install');
+               $form = $install->updatesForm($extKey, $list[$extKey], 1);
+               if (!$form) {
+                       return '<p>' . 'This extension has no configuration.' . '</p>';
+               } else {
+                       return $form;
+               }
+       }
+
+       /**
+        * Save extension configuration
+        *
+        * @formHandler
+        * @param array $parameter
+        * @return array
+        */
+       public function saveExtensionConfiguration($parameter) {
+               return array(
+                       'success' => true,
+                       'data' => $parameter
+               );
+       }
+
+       /**
+        * genereates a file tree
+        *
+        * @param object $parameter
+        * @return array
+        */
+       public function getExtFileTree($parameter) {
+               $ext = array();
+               $extKey = $parameter->extkey;
+               $type = $parameter->typeShort;
+               $node = strpos($parameter->node, '/') !== FALSE ? $parameter->node : $parameter->baseNode;
+
+               $path = PATH_site . $node;
+               $fileArray = array();
+
+               $dirs = t3lib_div::get_dirs($path);
+               $files = t3lib_div::getFilesInDir($path, '', FALSE, '', '');
+
+               $editTypes = explode(',', $GLOBALS['TYPO3_CONF_VARS']['SYS']['textfile_ext']);
+               $imageTypes = array('gif', 'jpg', 'png');
+
+               if (!is_array($files) || !count($files)) {
+                       return array();
+               }
+
+               foreach ($dirs as $dir) {
+                       if ($dir{0} !== '.') {
+                               $fileArray[] = array(
+                                       'id' => $node . '/' . $dir,
+                                       'text' => htmlspecialchars($dir),
+                                       'leaf' => false,
+                                       'qtip' => ''
+                               );
+                       }
+               }
+
+
+               foreach ($files as $key => $file) {
+                       $fileExt = strtolower(substr($file, strrpos($file, '.') + 1));
+                       if (in_array($fileExt, $imageTypes)) {
+                               $cls = 'tree-image';
+                       } elseif (in_array($fileExt, $editTypes)) {
+                               $cls = 'tree-edit';
+                       } else {
+                               $cls = 'tree-unknown';
+                       }
+                       $fileArray[] = array(
+                               'id' => $node . '/' . $file,
+                               'text' => htmlspecialchars($file),
+                               'leaf' => true,
+                               'qtip' => $fileExt . ' - file',
+                               'iconCls' => $cls
+                       );
+               }
+               return $fileArray;
+       }
+
+       /**
+        * Read extension file and send content
+        *
+        * @param string $path
+        * @return string file content
+        */
+       public function readExtFile($path) {
+               $path = PATH_site . $path;
+               if (@file_exists($path)) {
+                       //TODO: charset conversion
+                       return t3lib_div::getURL($path);
+               }
+               return '';
+       }
+
+       /**
+        * Save extension file
+        *
+        * @param string $file
+        * @param string $content
+        * @return boolean success
+        */
+       public function saveExtFile($file, $content) {
+               $path = PATH_site . $path;
+               if (@file_exists($path)) {
+                       //TODO: save only if saving was enabled
+                       return t3lib_div::writeFile($path, $content);
+               }
+               return FALSE;
+       }
+
+
+       /**
+        * Load upload form for extension upload to TER
+        *
+        * @formcHandler
+        * @return array
+        */
+       public function loadUploadExtToTer() {
+               $settings = $this->getSettings();
+               return array(
+                       'success' => TRUE,
+                       'data' => array(
+                               'fe_u' => $settings['fe_u'],
+                               'fe_p' => $settings['fe_p']
+                       )
+               );
+       }
+
+       /**
+        * Upload extension to TER
+        *
+        * @formHandler
+        *
+        * @param string $parameter
+        * @return array
+        */
+       public function uploadExtToTer($parameter) {
+               return array(
+                       'success' => TRUE,
+                       'fe_p' => $parameter['fe_p'],
+                       'fe_u' => $parameter['fe_u'],
+                       'newversion' => $parameter['newversion'],
+                       'uploadcomment' => $parameter['uploadcomment']
+               );
+       }
+
+       /**
+        * Prints developer information
+        *
+        * @param string $parameter
+        * @return array
+        */
+       public function getExtensionDevelopInfo($extKey) {
+               $extensionList = t3lib_div::makeInstance('tx_em_Extensions_List', $this);
+               list($list,) = $extensionList->getInstalledExtensions();
+               $extensionDetails = t3lib_div::makeInstance('tx_em_Extensions_Details', $this);
+               return $extensionDetails->extInformationarray($extKey, $list[$extKey]);
+       }
+
+       /*********************************************************************/
+       /* Remote Extension List                                             */
+       /*********************************************************************/
+
+
+       /**
+        * Render remote extension list
+        *
+        * @param object $parameters
+        * @return string $content
+        */
+       public function getRemoteExtensionList($parameters) {
+               /* @var $repoUtility em_repository_utility */
+               $repoUtility = t3lib_div::makeInstance('tx_em_Repository_Utility');
+               $repoUtility->setRepository($this->getSettingsObject()->getSelectedRepository());
+
+               $search = $parameters->query;
+               $limit = $parameters->start . ', ' . $parameters->limit;
+               $orderBy = $parameters->sort;
+               $orderDir = $parameters->dir;
+
+               if ($search == '*') {
+                       $where = '';
+               } else {
+                       $quotedSearch = $GLOBALS['TYPO3_DB']->escapeStrForLike(
+                               $GLOBALS['TYPO3_DB']->quoteStr($search, 'cache_extensions'),
+                               'cache_extensions'
+                       );
+                       $where = ' AND (extkey LIKE \'%' . $quotedSearch . '%\' OR title LIKE \'%' . $quotedSearch . '%\')';
+               }
+
+               $list = tx_em_Database::getExtensionListFromRepository(
+                       $repoUtility->getRepositoryUID(),
+                       $where,
+                       $orderBy,
+                       $orderDir,
+                       $limit
+               );
+
+
+               return array(
+                       'length' => $list['count'],
+                       'data' => $list['results']
+               );
+
+       }
+
+
+       /**
+        * Loads repositories
+        *
+        * @return array
+        */
+       public function repositoryUpdateLoad() {
+               $settings = $this->getSettings();
+               $repositories = tx_em_Database::getRepositories();
+               foreach ($repositories as $uid => $repository) {
+                       $data[] = array(
+                               'title' => $repository['title'],
+                               'value' => $repository['uid'],
+                               'description' => $repository['description'],
+                               'wsdl_url' => $repository['wsdl_url'],
+                               'mirror_url' => $repository['mirror_url'],
+                               'count' => $repository['extCount'],
+                               'updated' => $repository['lastUpdated'] ? date('d/m/Y H:i', $repository['lastUpdated']) : 'never',
+                               'selected' => $repository['uid'] === $settings['selectedRepository'],
+                       );
+               }
+
+               return array(
+                       'length' => count($data),
+                       'data' => $data,
+               );
+       }
+
+       /**
+        * Edit / Create repository
+        *
+        * @formHandler
+        * @param array $parameter
+        * @return array
+        */
+       public function repositoryEditFormSubmit($parameter) {
+               return array(
+                       'success' => TRUE,
+                       'data' => array(
+                               'params' => $parameter
+                       ),
+               );
+       }
+
+       /**
+        * Update repository
+        *
+        * @formHandler
+        *
+        * @param array $parameter
+        * @return array
+        */
+       public function repositoryUpdate($parameter) {
+               //debug($parameter);
+               if (!intval($parameter['rep'])) {
+                       return array(
+                               'success' => FALSE,
+                               'errors' => 'no repository choosen'
+                       );
+               }
+
+               $objRepository = t3lib_div::makeInstance('tx_em_Repository', intval($parameter['rep']));
+               $objRepositoryUtility = t3lib_div::makeInstance('tx_em_Repository_Utility', $objRepository);
+               $count = $objRepositoryUtility->updateExtList();
+
+
+               if ($count) {
+                       $objRepository->setExtensionCount($count);
+                       $objRepository->setLastUpdate(time());
+                       tx_em_Database::updateRepository($objRepository);
+                       return array(
+                               'success' => TRUE,
+                               'data' => array(
+                                       'count' => $count
+                               )
+                       );
+               } else {
+                       return array(
+                               'success' => FALSE,
+                               'errormsg' => 'Your repository is up to date.'
+                       );
+               }
+       }
+
+
+       /*********************************************************************/
+       /* Translation Handling                                              */
+       /*********************************************************************/
+
+
+       /**
+        * Enter description here...
+        *
+        * @return unknown
+        */
+       public function getLanguages() {
+
+               $temp = $this->getSettings();
+               $selected = unserialize($temp['selectedLanguages']);
+               $theLanguages = t3lib_div::trimExplode('|', TYPO3_languages);
+               //drop default
+               array_shift($theLanguages);
+               $lang = array();
+               foreach ($theLanguages as $language) {
+                       $label = htmlspecialchars($GLOBALS['LANG']->sL('LLL:EXT:setup/mod/locallang.xml:lang_' . $language));
+                       $flag = @is_file(PATH_typo3 . 'gfx/flags/' . $language . '.gif') ? 'gfx/flags/' . $language . '.gif' : 'gfx/flags/unknown.gif';
+                       $lang[] = array(
+                               'label' => $label,
+                               'lang' => $language,
+                               'flag' => $flag,
+                               'selected' => in_array($language, $selected) ? 1 : 0
+                       );
+               }
+               return array(
+                       'length' => count($lang),
+                       'data' => $lang,
+               );
+
+       }
+
+       /**
+        * Saves language selection
+        *
+        * @param array $parameter
+        * @return string
+        */
+       public function saveLanguageSelection($parameter) {
+               $this->saveSetting('selectedLanguages', serialize($parameter));
+                       //TODO: use language label
+               return 'Saved languages: ' . implode(', ', $parameter);
+       }
+
+
+       /**
+        * Fetches translation from server
+        *
+        * @param string $extkey
+        * @param string $type
+        * @param array $selection
+        * @return array
+        */
+       public function fetchTranslations($extkey, $type, $selection) {
+               $result = array();
+               if (is_array($selection) && count($selection)) {
+                       $terConnection = t3lib_div::makeInstance('tx_em_Connection_Ter', $this);
+                       $this->xmlhandler = t3lib_div::makeInstance('tx_em_Tools_XmlHandler');
+                       $this->xmlhandler->emObj = $this;
+                       $mirrorURL = $this->getSettingsObject()->getMirrorURL();
+
+                       foreach ($selection as $lang) {
+                               $fetch = $terConnection->fetchTranslationStatus($extkey, $mirrorURL);
+                               $localmd5 = '';
+                               if (!isset($fetch[$lang])) {
+                                       //no translation available
+                                       $result[0][$lang] = 'N/A';
+                               } else {
+                                       $localmd5 = '';
+                                       if (is_file(PATH_site . 'typo3temp/' . $extkey . '-l10n-' . $lang . '.zip')) {
+                                               $localmd5 = md5_file(PATH_site . 'typo3temp/' . $extkey . '-l10n-' . $lang . '.zip');
+                                       }
+                                       if ($localmd5 !== $fetch[$lang]['md5']) {
+                                               if ($type) {
+                                                       //fetch translation
+                                                       $ret = $terConnection->updateTranslation($extkey, $lang, $mirrorURL);
+                                                       $result[0][$lang] = $ret ? 'updated' : 'failed';
+                                               } else {
+                                                       //translation status
+                                                       $result[0][$lang] = $localmd5 !== '' ? 'update' : 'new';
+                                               }
+                                       } else {
+                                               //translation is up to date
+                                               $result[0][$lang] = 'ok';
+                                       }
+                               }
+
+
+                       }
+               }
+               return $result;
+       }
+
+
+       /*********************************************************************/
+       /* Settings                                                          */
+       /*********************************************************************/
+
+       /**
+        * Returns settings object.
+        *
+        * @access  public
+        * @return  tx_em_Settings  instance of settings object
+        */
+       public function getSettings() {
+               return $this->getSettingsObject()->getSettings();
+       }
+
+       /**
+        * Enter description here...
+        *
+        * @param string $name
+        * @param mixed $value
+        * @return boolean
+        */
+       public function saveSetting($name, $value) {
+               $this->getSettingsObject()->saveSetting($name, $value);
+               return TRUE;
+       }
+
+       /**
+        * Load form values for settings form
+        *
+        * @return array FormValues
+        */
+       public function settingsFormLoad() {
+               $settings = $this->getSettings();
+
+               return array(
+                       'success' => TRUE,
+                       'data' => array(
+                               'display_unchecked' => $settings['display_unchecked'],
+                               'fe_u' => $settings['fe_u'],
+                               'fe_p' => $settings['fe_p'],
+                               'selectedMirror' => $settings['selectedMirror'],
+                               'selectedRepository' => $settings['selectedRepository'],
+                       )
+               );
+       }
+
+       /**
+        * Save settings from form submit
+        *
+        * @formHandler
+        * @param array $parameter
+        * @return array
+        */
+       public function settingsFormSubmit($parameter) {
+               $settings = $this->getSettingsObject()->saveSettings(array(
+                       'display_unchecked' => isset($parameter['display_unchecked']),
+                       'fe_u' => $parameter['fe_u'],
+                       'fe_p' => $parameter['fe_p'],
+                       'selectedMirror' => $parameter['selectedMirror'],
+                       'selectedRepository' => $parameter['selectedRepository'],
+               ));
+               return array(
+                       'success' => TRUE,
+                       'data' => $parameter,
+                       'settings' => $settings
+               );
+       }
+
+
+       /*********************************************************************/
+       /* EM Tools                                                          */
+       /*********************************************************************/
+
+       /**
+        * Upload an extension
+        *
+        * @formHandler
+        *
+        * @access  public
+        * @param $parameter composed parameter from $POST and $_FILES
+        * @return  array status
+        */
+       public function uploadExtension($parameter) {
+               $uploadedTempFile = t3lib_div::upload_to_tempfile($parameter['extupload-path']['tmp_name']);
+               $location = ($parameter['loc'] === 'G' || $parameter['loc'] === 'S') ? $parameter['loc'] : 'L';
+               $uploadOverwrite = $parameter['uploadOverwrite'] ? TRUE : FALSE;
+
+               $install = t3lib_div::makeInstance('tx_em_Install', $this);
+               $upload = $install->uploadExtensionFile($uploadedTempFile, $location, $uploadOverwrite);
+
+               if ($upload[0] === FALSE) {
+                       return array(
+                               'success' => FALSE,
+                               'error' => $upload[1]
+                       );
+               }
+               $extKey = $upload[1][0]['extKey'];
+               $result = $install->installExtension($upload[1], $location);
+               return array(
+                       'success' => TRUE,
+                       'data' => $result,
+                       'extKey' => $extKey
+               );
+
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/connection/class.tx_em_connection_soap.php b/typo3/sysext/em/classes/connection/class.tx_em_connection_soap.php
new file mode 100644 (file)
index 0000000..d27a41a
--- /dev/null
@@ -0,0 +1,274 @@
+<?php
+/* **************************************************************
+*  Copyright notice
+*
+*  (c) webservices.nl
+*  (c) 2006-2010 Karsten Dambekalns <karsten@typo3.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/* $Id: class.tx_em_Connection_Soap.php 1978 2010-03-09 03:18:50Z mkrause $ */
+
+/**
+ * Enter description here...
+ *
+ */
+class tx_em_Connection_Soap {
+       /**
+        * valid options passed to the constructor :
+        * wsdl            : The WSDL location, can be a local file location or
+        *                                an URL.
+        * soapoptions  : Associative array of SOAP options to be passed to
+        *                                the SOAP implementation constructor, only used for
+        *                                the phpsoap implement.
+        * authentication : method of authentication :
+        *                                'headers'   soap headers are used
+        *                                'prefix'      function prefixes are used
+        * prefix                : optional prefix to be put in front of all methods.
+        * format                : Which type of return structure :
+        *                                'object'      PHP objects
+        *                                'array'        PHP arrays, default
+        */
+       var $options = array();
+
+       /**
+        * SOAP client, instance of PHP SOAP class
+        *
+        * @var SoapClient
+        */
+       var $client = false;
+
+       var $error = false;
+       var $username = false;
+       var $password = false;
+       var $reactid = false;
+
+       /**
+        * Init Soap
+        *
+        * @param       array           $options
+        * @param       string          $username
+        * @param       string          $password
+        * @return      [type]          ...
+        */
+       function init($options = false, $username = false, $password = false) {
+               if ($username !== false) {
+                       if ($password === false) {
+                               $this->reactid = $username;
+                       } else {
+                               $this->username = $username;
+                               $this->password = $password;
+                       }
+               }
+
+               $options['format'] = $options['format'] == 'object' ? 'object' : 'array';
+
+               if ($options !== false) {
+                       $this->options = (array) $options;
+               }
+
+               if (defined('SOAP_1_2')) {
+                       $this->client = new SoapClient($options['wsdl'], (array) $options['soapoptions']);
+               } else {
+                       $this->client = FALSE;
+                       throw new Exception('PHP soap extension not available');
+               }
+       }
+
+       /**
+        * Login
+        *
+        * @param       string          $username
+        * @param       string          $password
+        * @return      mixed           false on failure, $reactid on success
+        */
+       function login($username, $password) {
+               $reactid = $this->call('login', array('username' => $username, 'password' => $password));
+
+               if ($this->error) {
+                       return false;
+               }
+
+               $this->reactid = $reactid;
+               $this->username = $username;
+               $this->password = false;
+
+               return $reactid;
+       }
+
+       /**
+        * Logout
+        *
+        * @return      unknown
+        */
+       function logout() {
+               $this->call('logout');
+               $this->reactid = false;
+               if ($this->error) {
+                       return false;
+               }
+               return true;
+       }
+
+
+       /**
+        * Soapcall
+        *
+        * @param       unknown_type            $func
+        * @param       unknown_type            $param
+        * @param       unknown_type            $username
+        * @param       unknown_type            $password
+        * @return      unknown
+        */
+       function call($func, $param = array(), $username = false, $password = false) {
+               if (!$this->client) {
+                       $this->error = sprintf(
+                               'Error in %s: No soap client implementation found. ' .
+                                               'Make sure PHP soap extension is available!', __FILE__);
+                       return false;
+               }
+
+               if ($username !== false) {
+                       if ($password === false) {
+                               $this->reactid = $username;
+                       } else {
+                               $this->username = $username;
+                               $this->password = $password;
+                       }
+               }
+
+               if ($this->options['authentication'] == 'prefix') {
+                       $param = array_merge(array('reactid' => $this->reactid), $param);
+               }
+
+               if ($this->options['prefix']) {
+                       $func = $this->options['prefix'] . ucfirst($func);
+               }
+               $this->error = false;
+
+               return $this->callPhpSOAP($func, $param);
+       }
+
+       /**
+        * Call php soap
+        *
+        * @param       unknown_type            $func
+        * @param       unknown_type            $param
+        * @return      unknown
+        */
+       function callPhpSOAP($func, $param) {
+               $header = null;
+               if ($this->options['authentication'] == 'headers') {
+                       if ($this->reactid) {
+                               $header = new SoapHeader(
+                                       '', 'HeaderAuthenticate',
+                                       (object) array('reactid' => $this->reactid), 1
+                               );
+                       } elseif ($this->username && $this->password) {
+                               $header = new SoapHeader(
+                                       '', 'HeaderLogin',
+                                       (object) array(
+                                               'username' => $this->username,
+                                               'password' => $this->password
+                                       ), 1
+                               );
+                               $this->password = false;
+                       }
+               }
+
+               $result = $this->client->__soapCall($func, $param, NULL, $header);
+
+               if (is_soap_fault($result)) {
+                       $this->error = $result;
+                       return false;
+               }
+
+               if (is_a($this->client->headersIn['HeaderAuthenticate'], 'stdClass')) {
+                       $this->reactid = $this->client->headersIn['HeaderAuthenticate']->reactid;
+               }
+
+               return $this->options['format'] == 'object' ? $result : $this->object2array($result);
+       }
+
+       /**
+        * Convert object to array
+        *
+        * @param       object  $object
+        * @return      array
+        */
+       function object2array($object) {
+               if (!is_object($object) && !is_array($object)) {
+                       return $object;
+               }
+
+               $array = (array) $object;
+               foreach ($array as $key => $value) {
+                       $array[$key] = $this->object2array($value);
+               }
+               return $array;
+       }
+
+       /**
+        * Convert array to object
+        *
+        * @param       unknown_type            $array
+        * @return      unknown
+        */
+       function array2object($array) {
+               if (!is_array($array)) {
+                       return $array;
+               }
+
+               foreach ($array as $key => $value) {
+                       $array[$key] = $this->array2object($value);
+               }
+               return (object) $array;
+       }
+
+       /**
+        * Get last request.
+        *
+        * @return      unknown
+        */
+       function lastRequest() {
+               return $this->client->__getLastRequest();
+       }
+
+       /**
+        * Get last response
+        *
+        * @return      unknown
+        */
+       function lastResponse() {
+               $this->client->__getLastResponse();
+       }
+
+       /**
+        * Get available functions
+        *
+        * @return      unknown
+        */
+       function getFunctions() {
+               return $this->client->__getFunctions();
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/connection/class.tx_em_connection_ter.php b/typo3/sysext/em/classes/connection/class.tx_em_connection_ter.php
new file mode 100644 (file)
index 0000000..76935f9
--- /dev/null
@@ -0,0 +1,364 @@
+<?php
+/* **************************************************************
+*  Copyright notice
+*
+*  (c) 1999-2010 Kasper Skårhøj (kasperYYYY@typo3.com)
+*  (c) 2006-2010 Karsten Dambekalns <karsten@typo3.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+
+/**
+ * TER2 connection handling class for the TYPO3 Extension Manager.
+ *
+ * It contains methods for downloading and uploading extensions and related code
+ *
+ * @author Karsten Dambekalns <karsten@typo3.org>
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
+ * @package TYPO3
+ * @subpackage EM
+ */
+class tx_em_Connection_Ter {
+       var $wsdlURL;
+
+       /**
+        * Extension manager module
+        *
+        * @var SC_mod_tools_em_index
+        */
+       var $emObj;
+
+       public function __construct($emObj) {
+               $this->emObj = $emObj;
+       }
+
+       /**
+        * Fetches an extension from the given mirror
+        *
+        * @param       string          $extKey Extension Key
+        * @param       string          $version        Version to install
+        * @param       string          $expectedMD5    Expected MD5 hash of extension file
+        * @param       string          $mirrorURL      URL of mirror to use
+        * @return      mixed           T3X data (array) or error message (string)
+        */
+       function fetchExtension($extKey, $version, $expectedMD5, $mirrorURL) {
+               $extPath = t3lib_div::strtolower($extKey);
+               $mirrorURL .= $extPath{0} . '/' . $extPath{1} . '/' . $extPath . '_' . $version . '.t3x';
+               $t3x = t3lib_div::getURL($mirrorURL, 0, array(TYPO3_user_agent));
+               $MD5 = md5($t3x);
+
+               if ($t3x === FALSE) {
+                       return 'The T3X file could not be fetched. Possible reasons: network problems, allow_url_fopen is off, curl is not enabled in Install tool.';
+               }
+
+               if ($MD5 == $expectedMD5) {
+                       // Fetch and return:
+                       return $this->decodeExchangeData($t3x);
+               } else {
+                       return 'Error: MD5 hash of downloaded file not as expected:<br />' . $MD5 . ' != ' . $expectedMD5;
+               }
+       }
+
+       /**
+        * Fetches an extensions l10n file from the given mirror
+        *
+        * @param string $extKey        Extension Key
+        * @param string $lang  The language code of the translation to fetch
+        * @param string $mirrorURL     URL of mirror to use
+        * @return mixed        Array containing l10n data or error message (string)
+        */
+       function fetchTranslation($extKey, $lang, $mirrorURL) {
+               $extPath = t3lib_div::strtolower($extKey);
+               $mirrorURL .= $extPath{0} . '/' . $extPath{1} . '/' . $extPath . '-l10n/' . $extPath . '-l10n-' . $lang . '.zip';
+               $l10n = t3lib_div::getURL($mirrorURL, 0, array(TYPO3_user_agent));
+
+               if ($l10n !== false) {
+                       return array($l10n);
+               } else {
+                       return 'Error: Translation could not be fetched.';
+               }
+       }
+
+       /**
+        * Install translations for all selected languages for an extension
+        *
+        * @param string $extKey                The extension key to install the translations for
+        * @param string $lang          Language code of translation to fetch
+        * @param string $mirrorURL             Mirror URL to fetch data from
+        * @return mixed        true on success, error string on fauilure
+        */
+       function updateTranslation($extKey, $lang, $mirrorURL) {
+               $l10n = $this->fetchTranslation($extKey, $lang, $mirrorURL);
+               if (is_array($l10n)) {
+                       $file = PATH_site . 'typo3temp/' . $extKey . '-l10n-' . $lang . '.zip';
+                       $path = 'l10n/' . $lang . '/';
+                       if (!is_dir(PATH_typo3conf . $path)) {
+                               t3lib_div::mkdir_deep(PATH_typo3conf, $path);
+                       }
+                       t3lib_div::writeFile($file, $l10n[0]);
+                       if (tx_em_Tools::unzip($file, PATH_typo3conf . $path)) {
+                               return TRUE;
+                       }
+               }
+               return FALSE;
+       }
+
+       /**
+        * Fetches extension l10n status from the given mirror
+        *
+        * @param string         $extKey        Extension Key
+        * @param string         $mirrorURL     URL of mirror to use
+        * @return mixed        Array containing l10n status data or FALSE if no status could be fetched
+        */
+       function fetchTranslationStatus($extKey, $mirrorURL) {
+               $extPath = t3lib_div::strtolower($extKey);
+               $mirrorURL .= $extPath{0} . '/' . $extPath{1} . '/' . $extPath . '-l10n/' . $extPath . '-l10n.xml';
+               $remote = t3lib_div::getURL($mirrorURL, 0, array(TYPO3_user_agent));
+
+               if ($remote !== false) {
+                       $parsed = $this->emObj->xmlhandler->parseL10nXML($remote);
+                       return $parsed['languagePackIndex'];
+               }
+
+               return FALSE;
+       }
+
+       /**
+        * Decode server data
+        * This is information like the extension list, extension information etc., return data after uploads (new em_conf)
+        *
+        * @param       string          Data stream from remove server
+        * @return      mixed           On success, returns an array with data array and stats array as key 0 and 1. Otherwise returns error string
+        * @see fetchServerData(), processRepositoryReturnData()
+        */
+       function decodeServerData($externalData) {
+               $parts = explode(':', $externalData, 4);
+               $dat = base64_decode($parts[2]);
+               // compare hashes ignoring any leading whitespace. See bug #0000365.
+               if (ltrim($parts[0]) == md5($dat)) {
+                       if ($parts[1] == 'gzcompress') {
+                               if (function_exists('gzuncompress')) {
+                                       $dat = gzuncompress($dat);
+                               } else {
+                                       return 'Decoding Error: No decompressor available for compressed content. gzuncompress() function is not available!';
+                               }
+                       }
+                       $listArr = unserialize($dat);
+
+                       if (is_array($listArr)) {
+                               return $listArr;
+                       } else {
+                               return 'Error: Unserialized information was not an array - strange!';
+                       }
+               } else {
+                       return 'Error: MD5 hashes in T3X data did not match!';
+               }
+       }
+
+       /**
+        * Decodes extension upload array.
+        * This kind of data is when an extension is uploaded to TER
+        *
+        * @param       string          Data stream
+        * @return      mixed           Array with result on success, otherwise an error string.
+        */
+       function decodeExchangeData($str) {
+               $parts = explode(':', $str, 3);
+               if ($parts[1] == 'gzcompress') {
+                       if (function_exists('gzuncompress')) {
+                               $parts[2] = gzuncompress($parts[2]);
+                       } else {
+                               return 'Decoding Error: No decompressor available for compressed content. gzcompress()/gzuncompress() functions are not available!';
+                       }
+               }
+               if (md5($parts[2]) == $parts[0]) {
+                       $output = unserialize($parts[2]);
+                       if (is_array($output)) {
+                               return array($output, '');
+                       } else {
+                               return 'Error: Content could not be unserialized to an array. Strange (since MD5 hashes match!)';
+                       }
+               } else {
+                       return 'Error: MD5 mismatch. Maybe the extension file was downloaded and saved as a text file by the browser and thereby corrupted!? (Always select "All" filetype when saving extensions)';
+               }
+       }
+
+
+       /**
+        * Encodes extension upload array
+        *
+        * @param       array           Array containing extension
+        * @return      string          Content stream
+        */
+       function makeUploadDataFromarray($uploadArray) {
+               if (is_array($uploadArray)) {
+                       $serialized = serialize($uploadArray);
+                       $md5 = md5($serialized);
+
+                       $content = $md5 . ':';
+                       $content .= 'gzcompress:';
+                       $content .= gzcompress($serialized);
+               }
+               return $content;
+       }
+
+       /**
+        * Upload extension to ter
+        * @param  $em
+        * @return
+        */
+       function uploadToTER($em) {
+               $uArr = $this->emObj->makeUploadarray($em['extKey'], $em['extInfo']);
+               if (!is_array($uArr)) {
+                       return $uArr;
+               }
+
+               // Render new version number:
+               $newVersionBase = $em['extInfo']['EM_CONF']['version'];
+               switch ((string) $em['upload']['mode']) {
+                       case 'new_dev':
+                               $cmd = 'dev';
+                               break;
+                       case 'new_sub':
+                               $cmd = 'sub';
+                               break;
+                       case 'new_main':
+                               $cmd = 'main';
+                               break;
+                       case 'custom':
+                               $newVersionBase = $em['upload']['version'];
+                       case 'latest':
+                       default:
+                               $cmd = '';
+                               break;
+               }
+               $versionArr = tx_em_Tools::renderVersion($newVersionBase, $cmd);
+               $em['version'] = $versionArr['version'];
+
+               // Create dependency / conflict information:
+               $dependenciesArr = array();
+               $extKeysArr = $uArr['EM_CONF']['constraints']['depends'];
+
+               if (is_array($extKeysArr)) {
+                       foreach ($extKeysArr as $extKey => $version) {
+                               if (strlen($extKey)) {
+                                       $dependenciesArr[] = array(
+                                               'kind' => 'depends',
+                                               'extensionKey' => utf8_encode($extKey),
+                                               'versionRange' => utf8_encode($version),
+                                       );
+                               }
+                       }
+               }
+
+               $extKeysArr = $uArr['EM_CONF']['constraints']['conflicts'];
+               if (is_array($extKeysArr)) {
+                       foreach ($extKeysArr as $extKey => $version) {
+                               if (strlen($extKey)) {
+                                       $dependenciesArr[] = array(
+                                               'kind' => 'conflicts',
+                                               'extensionKey' => utf8_encode($extKey),
+                                               'versionRange' => utf8_encode($version),
+                                       );
+                               }
+                       }
+               }
+               // FIXME: This part must be removed, when the problem is solved on the TER-Server #5919
+               if (count($dependenciesArr) == 1) {
+                       $dependenciesArr[] = array(
+                               'kind' => 'depends',
+                               'extensionKey' => '',
+                               'versionRange' => '',
+                       );
+               }
+               // END for Bug #5919
+
+               // Compile data for SOAP call:
+               $accountData = array(
+                       'username' => $em['user']['fe_u'],
+                       'password' => $em['user']['fe_p']
+               );
+               $extensionData = array(
+                       'extensionKey' => utf8_encode($em['extKey']),
+                       'version' => utf8_encode($em['version']),
+                       'metaData' => array(
+                               'title' => utf8_encode($uArr['EM_CONF']['title']),
+                               'description' => utf8_encode($uArr['EM_CONF']['description']),
+                               'category' => utf8_encode($uArr['EM_CONF']['category']),
+                               'state' => utf8_encode($uArr['EM_CONF']['state']),
+                               'authorName' => utf8_encode($uArr['EM_CONF']['author']),
+                               'authorEmail' => utf8_encode($uArr['EM_CONF']['author_email']),
+                               'authorCompany' => utf8_encode($uArr['EM_CONF']['author_company']),
+                       ),
+                       'technicalData' => array(
+                               'dependencies' => $dependenciesArr,
+                               'loadOrder' => utf8_encode($uArr['EM_CONF']['loadOrder']),
+                               'uploadFolder' => (boolean) intval($uArr['EM_CONF']['uploadfolder']),
+                               'createDirs' => utf8_encode($uArr['EM_CONF']['createDirs']),
+                               'shy' => (boolean) intval($uArr['EM_CONF']['shy']),
+                               'modules' => utf8_encode($uArr['EM_CONF']['module']),
+                               'modifyTables' => utf8_encode($uArr['EM_CONF']['modify_tables']),
+                               'priority' => utf8_encode($uArr['EM_CONF']['priority']),
+                               'clearCacheOnLoad' => (boolean) intval($uArr['EM_CONF']['clearCacheOnLoad']),
+                               'lockType' => utf8_encode($uArr['EM_CONF']['lockType']),
+                       ),
+                       'infoData' => array(
+                               'codeLines' => intval($uArr['misc']['codelines']),
+                               'codeBytes' => intval($uArr['misc']['codebytes']),
+                               'codingGuidelinesCompliance' => utf8_encode($uArr['EM_CONF']['CGLcompliance']),
+                               'codingGuidelinesComplianceNotes' => utf8_encode($uArr['EM_CONF']['CGLcompliance_note']),
+                               'uploadComment' => utf8_encode($em['upload']['comment']),
+                               'techInfo' => $uArr['techInfo'],
+                       ),
+               );
+
+               $filesData = array();
+               foreach ($uArr['FILES'] as $filename => $infoArr) {
+                       $filesData[] = array(
+                               'name' => utf8_encode($infoArr['name']),
+                               'size' => intval($infoArr['size']),
+                               'modificationTime' => intval($infoArr['mtime']),
+                               'isExecutable' => intval($infoArr['is_executable']),
+                               'content' => $infoArr['content'],
+                               'contentMD5' => $infoArr['content_md5'],
+                       );
+               }
+
+               $soap = t3lib_div::makeInstance('tx_em_Connection_Soap');
+               $soap->init(array('wsdl' => $this->wsdlURL, 'soapoptions' => array('trace' => 1, 'exceptions' => 0)));
+               $response = $soap->call('uploadExtension', array('accountData' => $accountData, 'extensionData' => $extensionData, 'filesData' => $filesData));
+
+               if ($response===false) {
+                       switch (true) {
+                               case is_string($soap->error):
+                                       return $soap->error;
+                                       break;
+                               default:
+                                       return $soap->error->faultstring;
+                       }
+               }
+
+               return $response;
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/database/class.tx_em_database.php b/typo3/sysext/em/classes/database/class.tx_em_database.php
new file mode 100644 (file)
index 0000000..bb4ea6d
--- /dev/null
@@ -0,0 +1,407 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2010 Marcus Krause <marcus#exp2010@t3sec.info>
+ *  (c) 2010 Steffen Kamper <info@sk-typo3.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+/**
+ * class.tx_em_database.php
+ *
+ * Module: Extension manager - DB access
+ *
+ * $Id: class.tx_em_database.php 2082 2010-03-21 17:19:42Z steffenk $
+ *
+ * @author  Marcus Krause <marcus#exp2010@t3sec.info>
+ * @author  Steffen Kamper <info@sk-typo3.de>
+ */
+
+/**
+ * DB access class for extension manager.
+ *
+ * Contains static methods for DB operations.
+ *
+ * @author       Marcus Krause <marcus#exp2010@t3sec.info>
+ * @author       Steffen Kamper <info@sk-typo3.de>
+ *
+ * @since         2010-02-27
+ * @package     TYPO3
+ * @subpackage  EM
+ */
+final class tx_em_Database {
+
+       const MULTI_LINEBREAKS = "\n\n\n";
+
+       const TABLE_REPOSITORY = 'sys_ter';
+
+       const TABLE_EXTENSION = 'cache_extensions';
+
+
+       /**
+        * Get the count of extensions in cache_extensions from a repository.
+        *
+        * If $repository parameter is obmitted, sum of all extensions will be
+        * returned.
+        *
+        * @access  public
+        * @param   integer  $repository  (optional) repository uid of extensions to count
+        * @return  integer  sum of extensions in database
+        */
+       public function getExtensionCountFromRepository($repository = NULL) {
+               if (is_null($repository)) {
+                       return $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
+                               'DISTINCT(extkey)',
+                               self::TABLE_EXTENSION
+                       );
+               } else {
+                       return $GLOBALS['TYPO3_DB']->exec_SELECTcountRows(
+                               'DISTINCT(extkey)',
+                               self::TABLE_EXTENSION,
+                               'repository=' . intval($repository)
+                       );
+               }
+       }
+
+       /**
+        * Get extension list from cache_extensions
+        *
+        * @param int $repository
+        * @param string $andWhere
+        * @param string $orderBy
+        * @param string $orderDir
+        * @param string $limit
+        * @return array
+        */
+       public function getExtensionListFromRepository($repository, $andWhere = '', $orderBy = '', $orderDir = 'ASC', $limit = '') {
+               $order = $orderBy ? $orderBy . ' ' . $orderDir : '';
+               $ret = array();
+
+               $temp = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                       'count(*) count',
+                       'cache_extensions',
+                       'repository=' . intval($repository) . $andWhere,
+                       'extkey'
+               );
+               $ret['count'] = count($temp);
+               $ret['results'] = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                       '*, count(*) versions, max(intversion) maxintversion',
+                       'cache_extensions',
+                       'repository=' . intval($repository) . $andWhere,
+                       'extkey',
+                       $order,
+                       $limit
+               );
+               return $ret;
+       }
+
+       /**
+        * Get versions of extension
+        *
+        * @param int $repository
+        * @param string $extKey
+        * @return array $versions
+        */
+       public function getExtensionVersionsFromRepository($repository, $extKey) {
+               $versions = array();
+               //TODO: implement
+               return $versions;
+       }
+
+       /**
+        * Function inserts a repository object into database.
+        *
+        * @access  public
+        * @param   tx_em_Repository $repository  repository object
+        * @return  void
+        */
+       public function updateRepository(tx_em_Repository $repository) {
+               $GLOBALS['TYPO3_DB']->exec_UPDATEquery(self::TABLE_REPOSITORY, $repository->getId(),
+                       array(
+                               'title' => $repository->getTitle(),
+                               'description' => $repository->getDescription(),
+                               'wsdl_url' => $repository->getWsdlUrl(),
+                               'mirror_url' => $repository->getMirrorListUrl(),
+                               'lastUpdated' => $repository->getLastUpdate(),
+                               'extCount' => $repository->getExtensionCount(),
+                       ));
+
+       }
+
+
+       /**
+        * Function inserts a repository object into database.
+        *
+        * @access  public
+        * @param   tx_em_Repository $repository  repository object
+        * @return  integer  UID of the newly inserted repository object
+        */
+       public function insertRepository(tx_em_Repository $repository) {
+               $GLOBALS['TYPO3_DB']->exec_INSERTquery(self::TABLE_REPOSITORY,
+                       array(
+                               'title' => $repository->getId(),
+                               'description' => $repository->getDescription(),
+                               'wsdl_url' => $repository->getWsdlUrl(),
+                               'mirror_url' => $repository->getMirrorListUrl(),
+                               'lastUpdated' => $repository->getLastUpdate(),
+                               'extCount' => $repository->getExtensionCount(),
+                       ));
+               return $GLOBALS['TYPO3_DB']->sql_insert_id();
+       }
+
+       /**
+        * Insert version
+        *
+        * @param  $arrFields
+        * @return void
+        */
+       public function insertVersion(array $arrFields) {
+               $GLOBALS['TYPO3_DB']->exec_INSERTquery(self::TABLE_EXTENSION, $arrFields);
+       }
+
+       /**
+        * Method finds and returns repository fields identified by its UID.
+        *
+        * @access  public
+        * @param   int  $uid  repository UID
+        */
+       public function getRepositoryByUID($uid) {
+               $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', self::TABLE_REPOSITORY, 'uid=' . intval($uid));
+
+               return $row[0];
+       }
+
+       /**
+        * Method finds and returns repository identified by its title
+        *
+        * @param  $title
+        * @return
+        */
+       public function getRepositoryByTitle($title) {
+               return $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                       '*',
+                       self::TABLE_REPOSITORY,
+                       'title=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($title,
+                       self::TABLE_REPOSITORY)
+               );
+       }
+
+       /**
+        * Get available repositories
+        *
+        * @param string $where
+        * @return array
+        */
+       public function getRepositories($where = NULL) {
+               return $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
+                       '*',
+                       self::TABLE_REPOSITORY,
+                       $where ? $where : ''
+               );
+       }
+
+       /**
+        * Dump table content
+        * Is DBAL compliant, but the dump format is written as MySQL standard. If the INSERT statements should be imported in a DBMS using other quoting than MySQL they must first be translated. t3lib_sqlengine can parse these queries correctly and translate them somehow.
+        *
+        * @param       string          Table name
+        * @param       array           Field structure
+        * @return      string          SQL Content of dump (INSERT statements)
+        */
+       function dumpTableContent($table, $fieldStructure) {
+
+               // Substitution of certain characters (borrowed from phpMySQL):
+               $search = array('\\', '\'', "\x00", "\x0a", "\x0d", "\x1a");
+               $replace = array('\\\\', '\\\'', '\0', '\n', '\r', '\Z');
+
+               $lines = array();
+
+               // Select all rows from the table:
+               $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, '');
+
+               // Traverse the selected rows and dump each row as a line in the file:
+               while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
+                       $values = array();
+                       foreach ($fieldStructure as $field) {
+                               $values[] = isset($row[$field]) ? "'" . str_replace($search, $replace, $row[$field]) . "'" : 'NULL';
+                       }
+                       $lines[] = 'INSERT INTO ' . $table . ' VALUES (' . implode(', ', $values) . ');';
+               }
+
+               // Free DB result:
+               $GLOBALS['TYPO3_DB']->sql_free_result($result);
+
+               // Implode lines and return:
+               return implode(LF, $lines);
+       }
+
+       /**
+        * Gets the table and field structure from database.
+        * Which fields and which tables are determined from the ext_tables.sql file
+        *
+        * @param       string          Array with table.field values
+        * @return      array           Array of tables and fields splitted.
+        */
+       function getTableAndFieldStructure($parts) {
+               // Instance of install tool
+               $instObj = new t3lib_install();
+               $dbFields = $instObj->getFieldDefinitions_database(TYPO3_db);
+
+               $outTables = array();
+               foreach ($parts as $table) {
+                       $sub = explode('.', $table);
+                       if ($sub[0] && isset($dbFields[$sub[0]])) {
+                               if ($sub[1]) {
+                                       $key = explode('KEY:', $sub[1], 2);
+                                       if (count($key) == 2 && !$key[0]) { // key:
+                                               if (isset($dbFields[$sub[0]]['keys'][$key[1]])) {
+                                                       $outTables[$sub[0]]['keys'][$key[1]] = $dbFields[$sub[0]]['keys'][$key[1]];
+                                               }
+                                       } else {
+                                               if (isset($dbFields[$sub[0]]['fields'][$sub[1]])) {
+                                                       $outTables[$sub[0]]['fields'][$sub[1]] = $dbFields[$sub[0]]['fields'][$sub[1]];
+                                               }
+                                       }
+                               } else {
+                                       $outTables[$sub[0]] = $dbFields[$sub[0]];
+                               }
+                       }
+               }
+
+               return $outTables;
+       }
+
+
+       /**
+        * Makes a dump of the tables/fields definitions for an extension
+        *
+        * @param       array           Array with table => field/key definition arrays in
+        * @return      string          SQL for the table definitions
+        * @see dumpStaticTables()
+        */
+       function dumpTableAndFieldStructure($arr) {
+               $tables = array();
+
+               if (count($arr)) {
+
+                       // Get file header comment:
+                       $tables[] = self::dumpHeader();
+
+                       // Traverse tables, write each table/field definition:
+                       foreach ($arr as $table => $fieldKeyInfo) {
+                               $tables[] = self::dumpTableHeader($table, $fieldKeyInfo);
+                       }
+               }
+
+               // Return result:
+               return implode(LF . LF . LF, $tables);
+       }
+
+       /**
+        * Dump content for static tables
+        *
+        * @param       string          Comma list of tables from which to dump content
+        * @return      string          Returns the content
+        * @see dumpTableAndFieldStructure()
+        */
+       function dumpStaticTables($tableList) {
+               $instObj = t3lib_div::makeInstance('t3lib_install');
+               $dbFields = $instObj->getFieldDefinitions_database(TYPO3_db);
+
+               $out = '';
+               $parts = t3lib_div::trimExplode(',', $tableList, TRUE);
+
+               // Traverse the table list and dump each:
+               foreach ($parts as $table) {
+                       if (is_array($dbFields[$table]['fields'])) {
+                               $header = self::dumpHeader();
+                               $tableHeader = self::dumpTableHeader($table, $dbFields[$table], TRUE);
+                               $insertStatements = self::dumpTableContent($table, $dbFields[$table]['fields']);
+                               $out .= $header . self::MULTI_LINEBREAKS .
+                                               $tableHeader . self::MULTI_LINEBREAKS .
+                                               $insertStatements . self::MULTI_LINEBREAKS;
+                       } else {
+                               throw new RuntimeException(
+                                       'TYPO3 Fatal Error: ' . $GLOBALS['LANG']->getLL('dumpStaticTables_table_not_found'),
+                                       1270853983
+                               );
+                       }
+               }
+               unset($instObj);
+               return $out;
+       }
+
+       /**
+        * Header comments of the SQL dump file
+        *
+        * @return      string          Table header
+        */
+       function dumpHeader() {
+               return trim('
+# TYPO3 Extension Manager dump 1.1
+#
+# Host: ' . TYPO3_db_host . '    Database: ' . TYPO3_db . '
+#--------------------------------------------------------
+');
+       }
+
+       /**
+        * Dump CREATE TABLE definition
+        *
+        * @param       string          Table name
+        * @param       array           Field and key information (as provided from Install Tool class!)
+        * @param       boolean         If true, add "DROP TABLE IF EXISTS"
+        * @return      string          Table definition SQL
+        */
+       function dumpTableHeader($table, $fieldKeyInfo, $dropTableIfExists = 0) {
+               $lines = array();
+               $dump = '';
+
+               // Create field definitions
+               if (is_array($fieldKeyInfo['fields'])) {
+                       foreach ($fieldKeyInfo['fields'] as $fieldN => $data) {
+                               $lines[] = '  ' . $fieldN . ' ' . $data;
+                       }
+               }
+
+               // Create index key definitions
+               if (is_array($fieldKeyInfo['keys'])) {
+                       foreach ($fieldKeyInfo['keys'] as $fieldN => $data) {
+                               $lines[] = '  ' . $data;
+                       }
+               }
+
+               // Compile final output:
+               if (count($lines)) {
+                       $dump = trim('
+#
+# Table structure for table "' . $table . '"
+#
+' . ($dropTableIfExists ? 'DROP TABLE IF EXISTS ' . $table . ';
+' : '') . 'CREATE TABLE ' . $table . ' (
+' . implode(',' . LF, $lines) . '
+);');
+               }
+
+               return $dump;
+       }
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/exception/class.em_connection_exception.php b/typo3/sysext/em/classes/exception/class.em_connection_exception.php
deleted file mode 100644 (file)
index 7c2394a..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-/***************************************************************
-*  Copyright notice
-*
-*  (c) 2010 Marcus Krause <marcus#exp2010@t3sec.info>
-*           Steffen Kamper <info@sk-typo3.de>
-*  All rights reserved
-*
-*  This script is part of the TYPO3 project. The TYPO3 project is
-*  free software; you can redistribute it and/or modify
-*  it under the terms of the GNU General Public License as published by
-*  the Free Software Foundation; either version 2 of the License, or
-*  (at your option) any later version.
-*
-*  The GNU General Public License can be found at
-*  http://www.gnu.org/copyleft/gpl.html.
-*
-*  This script is distributed in the hope that it will be useful,
-*  but WITHOUT ANY WARRANTY; without even the implied warranty of
-*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*  GNU General Public License for more details.
-*
-*  This copyright notice MUST APPEAR in all copies of the script!
-***************************************************************/
-/**
- * Module: Extension manager - connection exception
- *
- * $Id: class.em_connection_exception.php 1876 2010-02-18 23:23:13Z mkrause $
- */
-
-/**
- * Exception for internet connection handling.
- *
- * This exception is supposed to be thrown when
- * there are problems with the internet connections
- * initialized by the web server.
- *
- * @author      Marcus Krause <marcus#exp2010@t3sec.info>
- * @author      Steffen Kamper <info@sk-typo3.de>
- *
- * @since       2010-02-18
- * @package     TYPO3
- * @subpackage  EM
- */
-class em_connection_Exception extends Exception {
-
-}
-?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/exception/class.tx_em_connection_exception.php b/typo3/sysext/em/classes/exception/class.tx_em_connection_exception.php
new file mode 100644 (file)
index 0000000..75e17db
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 Marcus Krause <marcus#exp2010@t3sec.info>
+*           Steffen Kamper <info@sk-typo3.de>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/**
+ * Module: Extension manager - connection exception
+ *
+ * $Id: class.tx_em_connection_exception.php 1876 2010-02-18 23:23:13Z mkrause $
+ */
+
+/**
+ * Exception for internet connection handling.
+ *
+ * This exception is supposed to be thrown when
+ * there are problems with the internet connections
+ * initialized by the web server.
+ *
+ * @author      Marcus Krause <marcus#exp2010@t3sec.info>
+ * @author      Steffen Kamper <info@sk-typo3.de>
+ *
+ * @since       2010-02-18
+ * @package     TYPO3
+ * @subpackage  EM
+ */
+class tx_em_ConnectionException extends Exception {
+
+}
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/exception/class.tx_em_extensionimport_exception.php b/typo3/sysext/em/classes/exception/class.tx_em_extensionimport_exception.php
new file mode 100644 (file)
index 0000000..2703110
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 Marcus Krause <marcus#exp2010@t3sec.info>
+*           Steffen Kamper <info@sk-typo3.de>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/**
+ * Module: Extension manager - Extension import exception
+ *
+ * $Id: class.tx_em_extensionimport_exception.php 1883 2010-02-19 13:45:32Z mkrause $
+ */
+
+/**
+ * Exception for extension import handling.
+ *
+ * TODO: this is currently unused
+ *
+ * @author      Marcus Krause <marcus#exp2010@t3sec.info>
+ * @author      Steffen Kamper <info@sk-typo3.de>
+ *
+ * @since       2010-02-18
+ * @package     TYPO3
+ * @subpackage  EM
+ */
+class tx_em_ExtensionImportException extends Exception {
+
+}
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/exception/class.tx_em_extensionxml_exception.php b/typo3/sysext/em/classes/exception/class.tx_em_extensionxml_exception.php
new file mode 100644 (file)
index 0000000..3b9094e
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 Marcus Krause <marcus#exp2010@t3sec.info>
+*           Steffen Kamper <info@sk-typo3.de>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/**
+ * Module: Extension manager - Extension.xml exception
+ *
+ * $Id: class.tx_em_extensionxml_exception.php 1870 2010-02-18 12:55:17Z mkrause $
+ */
+
+
+/**
+ * Exception for extension.xml handling.
+ *
+ * @author      Marcus Krause <marcus#exp2010@t3sec.info>
+ * @author      Steffen Kamper <info@sk-typo3.de>
+ *
+ * @since       2010-02-10
+ * @package     TYPO3
+ * @subpackage  EM
+ */
+class tx_em_ExtensionXmlException extends tx_em_XmlException {
+
+}
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/exception/class.tx_em_mirrorxml_exception.php b/typo3/sysext/em/classes/exception/class.tx_em_mirrorxml_exception.php
new file mode 100644 (file)
index 0000000..4ee1726
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 Marcus Krause <marcus#exp2010@t3sec.info>
+*           Steffen Kamper <info@sk-typo3.de>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/**
+ * Module: Extension manager - Extension.xml exception
+ *
+ * $Id: class.tx_em_mirrorxml_exception.php 1883 2010-02-19 13:45:32Z mkrause $
+ */
+
+
+/**
+ * Exception for extension.xml handling.
+ *
+ * @author      Marcus Krause <marcus#exp2010@t3sec.info>
+ * @author      Steffen Kamper <info@sk-typo3.de>
+ *
+ * @since       2010-02-18
+ * @package     TYPO3
+ * @subpackage  EM
+ */
+class tx_em_MirrorXmlException extends tx_em_XmlException {
+
+}
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/exception/class.tx_em_xml_exception.php b/typo3/sysext/em/classes/exception/class.tx_em_xml_exception.php
new file mode 100644 (file)
index 0000000..28475f0
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2010 Marcus Krause <marcus#exp2010@t3sec.info>
+*           Steffen Kamper <info@sk-typo3.de>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/**
+ * Module: Extension manager - XML exception
+ *
+ * $Id: class.tx_em_xml_exception.php 1870 2010-02-18 12:55:17Z mkrause $
+ */
+
+/**
+ * Exception for XML handling.
+ *
+ * @author      Marcus Krause <marcus#exp2010@t3sec.info>
+ * @author      Steffen Kamper <info@sk-typo3.de>
+ *
+ * @since       2010-02-18
+ * @package     TYPO3
+ * @subpackage  EM
+ */
+class tx_em_XmlException extends Exception {
+
+}
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/extensions/class.tx_em_extensions_details.php b/typo3/sysext/em/classes/extensions/class.tx_em_extensions_details.php
new file mode 100644 (file)
index 0000000..c5a7ec9
--- /dev/null
@@ -0,0 +1,787 @@
+<?php
+/* **************************************************************
+*  Copyright notice
+*
+*  (c) webservices.nl
+*  (c) 2006-2010 Karsten Dambekalns <karsten@typo3.org>
+*  (c) 2010 Steffen Kamper <steffen@typo3.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/* $Id: class.tx_em_extensions_details.php 2058 2010-03-17 09:39:15Z steffenk $ */
+
+/**
+ * This class handles extension details
+ *
+ */
+
+class tx_em_Extensions_Details {
+
+       protected $maxUploadSize = 31457280;
+       protected $descrTable = '_MOD_tools_em';
+       protected $parentObject;
+
+       /**
+        * Class for install extensions
+        *
+        * @var em_install
+        */
+       public $install;
+
+       /**
+        * Constructor
+        *
+        * @param object $parentObject
+        */
+       public function __construct($parentObject = NULL) {
+               $this->parentObject = $parentObject;
+               $this->install = t3lib_div::makeInstance('tx_em_Install', $this);
+               $GLOBALS['LANG']->includeLLFile(t3lib_extMgm::extPath('em') . 'language/locallang.xml');
+       }
+
+
+       /**
+        * Reads $confFilePath (a module $conf-file) and returns information on the existence of TYPO3_MOD_PATH definition and MCONF_name
+        *
+        * @param       string          Absolute path to a "conf.php" file of a module which we are analysing.
+        * @return      array           Information found.
+        * @see writeTYPO3_MOD_PATH()
+        */
+       function modConfFileAnalysis($confFilePath) {
+               $lines = explode(LF, t3lib_div::getUrl($confFilePath));
+               $confFileInfo = array();
+               $confFileInfo['lines'] = $lines;
+               $reg = array();
+
+               foreach ($lines as $k => $l) {
+                       $line = trim($l);
+
+                       unset($reg);
+                       if (preg_match('/^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;/', $line, $reg)) {
+                               $confFileInfo['TYPO3_MOD_PATH'] = array($k, $reg);
+                       }
+
+                       unset($reg);
+                       if (preg_match('/^\$MCONF\[["\']?name["\']?\][[:space:]]*=[[:space:]]*["\']([[:alnum:]_]+)["\'];/', $line, $reg)) {
+                               $confFileInfo['MCONF_name'] = array($k, $reg);
+                       }
+               }
+               return $confFileInfo;
+       }
+
+       /**
+        * Check if upload folder / "createDir" directories should be created.
+        *
+        * @param       string          Extension key
+        * @param       array           Extension information array
+        * @return      string          HTML content.
+        */
+       function checkUploadFolder($extKey, $extInfo) {
+
+               // Checking for upload folder:
+               $uploadFolder = PATH_site . tx_em_Tools::uploadFolder($extKey);
+               if ($extInfo['EM_CONF']['uploadfolder'] && !@is_dir($uploadFolder)) {
+                       if (t3lib_div::_POST('_uploadfolder')) { // CREATE dir:
+                               t3lib_div::mkdir($uploadFolder);
+                               $indexContent = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<HTML>
+<HEAD>
+       <TITLE></TITLE>
+<META http-equiv=Refresh Content="0; Url=../../">
+</HEAD>
+</HTML>';
+                               t3lib_div::writeFile($uploadFolder . 'index.html', $indexContent);
+                       } else { // Show checkbox / HTML for creation:
+                               $content .= '
+                                       <br /><h3>' . $GLOBALS['LANG']->getLL('checkUploadFolder_create_upload_folder') . '</h3>
+                                       <p>' . sprintf($GLOBALS['LANG']->getLL('checkUploadFolder_upload_folder_needed'),
+                                       tx_em_Tools::uploadFolder($extKey)
+                               ) . '<br />
+                                               <label for="check_uploadfolder">' . sprintf($GLOBALS['LANG']->getLL('checkUploadFolder_create_dir'),
+                                       tx_em_Tools::uploadFolder($extKey)
+                               ) . '</label>
+                                               <input type="checkbox" name="_uploadfolder" id="check_uploadfolder" checked="checked" value="1" /><br />
+                                       </p>
+                               ';
+                       }
+               }
+
+               // Additional directories that should be created:
+               if ($extInfo['EM_CONF']['createDirs']) {
+                       $createDirs = array_unique(t3lib_div::trimExplode(',', $extInfo['EM_CONF']['createDirs'], 1));
+
+                       foreach ($createDirs as $crDir) {
+                               if (!@is_dir(PATH_site . $crDir)) {
+                                       if (t3lib_div::_POST('_createDir_' . md5($crDir))) { // CREATE dir:
+
+                                               // Initialize:
+                                               $crDirStart = '';
+                                               $dirs_in_path = explode('/', preg_replace('/\/$/', '', $crDir));
+
+                                               // Traverse each part of the dir path and create it one-by-one:
+                                               foreach ($dirs_in_path as $dirP) {
+                                                       if (strcmp($dirP, '')) {
+                                                               $crDirStart .= $dirP . '/';
+                                                               if (!@is_dir(PATH_site . $crDirStart)) {
+                                                                       t3lib_div::mkdir(PATH_site . $crDirStart);
+                                                                       $finalDir = PATH_site . $crDirStart;
+                                                               }
+                                                       } else {
+                                                               throw new RuntimeException(
+                                                                       'TYPO3 Fatal Error: ' . sprintf($GLOBALS['LANG']->getLL('checkUploadFolder_error'), PATH_site . $crDir),
+                                                                       1270853982
+                                                               );
+                                                       }
+                                               }
+                                               if ($finalDir) {
+                                                       $indexContent = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<HTML>
+<HEAD>
+       <TITLE></TITLE>
+<META http-equiv=Refresh Content="0; Url=/">
+</HEAD>
+</HTML>';
+                                                       t3lib_div::writeFile($finalDir . 'index.html', $indexContent);
+                                               }
+                                       } else { // Show checkbox / HTML for creation:
+                                               $md5CrDir = md5($crDir);
+                                               $content .= '
+                                                       <br />
+                                                       <h3>' . $GLOBALS['LANG']->getLL('checkUploadFolder_create_folder') . '</h3>
+                                                       <p>' . sprintf($GLOBALS['LANG']->getLL('checkUploadFolder_folder_needed'),
+                                                       $crDir
+                                               ) . '<br />
+                                                               <label for="check_createDir_' . $md5CrDir . '">' . sprintf($GLOBALS['LANG']->getLL('checkUploadFolder_create_dir'),
+                                                       $crDir
+                                               ) . '</label>
+                                                               <input type="checkbox" name="_createDir_' . $md5CrDir . '" id="check_createDir_' . $md5CrDir . '" checked="checked" value="1" /><br />
+                                                       </p>
+                                               ';
+                                       }
+                               }
+                       }
+               }
+
+               return $content;
+       }
+
+
+       /**
+        * Processes return-data from online repository.
+        * Currently only the returned emconf array is written to extension.
+        *
+        * @param       array           Command array returned from TER
+        * @return      string          Message
+        */
+       function uploadExtensionToTER($em) {
+               $msg = '';
+               $response = $this->terConnection->uploadToTER($em);
+
+               if (!is_array($response)) {
+                       return $response;
+               }
+
+               if ($response['resultCode'] == TX_TER_RESULT_EXTENSIONSUCCESSFULLYUPLOADED) {
+                       $em['extInfo']['EM_CONF']['version'] = $response['version'];
+                       $response['resultMessages'][] = sprintf($GLOBALS['LANG']->getLL('terCommunication_ext_version'),
+                               $response['version']
+                       );
+                       $response['resultMessages'][] = $this->updateLocalEM_CONF($em['extKey'], $em['extInfo']);
+               }
+
+               $msg = '<ul><li>' . implode('</li><li>', $response['resultMessages']) . '</li></ul>';
+               return $msg;
+       }
+
+       /**
+        * Forces update of local EM_CONF. This will renew the information of changed files.
+        *
+        * @param       string          Extension key
+        * @param       array           Extension information array
+        * @return      string          Status message
+        */
+       function updateLocalEM_CONF($extKey, $extInfo) {
+               $extInfo['EM_CONF']['_md5_values_when_last_written'] = serialize($this->serverExtensionMD5array($extKey, $extInfo));
+               $emConfFileContent = $this->construct_ext_emconf_file($extKey, $extInfo['EM_CONF']);
+
+               $absPath = tx_em_Tools::getExtPath($extKey, $extInfo['type']);
+               $emConfFileName = $absPath . 'ext_emconf.php';
+               if ($emConfFileContent) {
+
+                       if (@is_file($emConfFileName)) {
+                               if (t3lib_div::writeFile($emConfFileName, $emConfFileContent) === true) {
+                                       return sprintf($GLOBALS['LANG']->getLL('updateLocalEM_CONF_ok'),
+                                               substr($emConfFileName, strlen($absPath)));
+                               } else {
+                                       return '<strong>' . sprintf($GLOBALS['LANG']->getLL('updateLocalEM_CONF_not_writable'),
+                                               $emConfFileName) . '</strong>';
+                               }
+                       } else {
+                               return ('<strong>' . sprintf($GLOBALS['LANG']->getLL('updateLocalEM_CONF_not_found'),
+                                       $emConfFileName) . '</strong>');
+                       }
+               } else {
+                       return sprintf($GLOBALS['LANG']->getLL('updateLocalEM_CONF_no_content'),
+                               substr($emConfFileName, strlen($absPath)));
+               }
+       }
+
+       /**
+        * Creates a MD5-hash array over the current files in the extension
+        *
+        * @param       string          Extension key
+        * @param       array           Extension information array
+        * @return      array           MD5-keys
+        */
+       function serverExtensionMD5array($extKey, $conf) {
+
+               // Creates upload-array - including filelist.
+               $mUA = $this->makeUploadarray($extKey, $conf);
+
+               $md5Array = array();
+               if (is_array($mUA['FILES'])) {
+
+                       // Traverse files.
+                       foreach ($mUA['FILES'] as $fN => $d) {
+                               if ($fN != 'ext_emconf.php') {
+                                       $md5Array[$fN] = substr($d['content_md5'], 0, 4);
+                               }
+                       }
+               } else {
+                       debug(array($mUA, $conf), 'serverExtensionMD5Array:' . $extKey);
+               }
+               return $md5Array;
+       }
+
+       /*******************************************
+        *
+        * Compiling upload information, emconf-file etc.
+        *
+        *******************************************/
+
+       /**
+        * Compiles the ext_emconf.php file
+        *
+        * @param       string          Extension key
+        * @param       array           EM_CONF array
+        * @return      string          PHP file content, ready to write to ext_emconf.php file
+        */
+       function construct_ext_emconf_file($extKey, $EM_CONF) {
+
+               // clean version number:
+               $vDat = tx_em_Tools::renderVersion($EM_CONF['version']);
+               $EM_CONF['version'] = $vDat['version'];
+
+               $code = '<?php
+
+########################################################################
+# Extension Manager/Repository config file for ext "' . $extKey . '".
+#
+# Auto generated ' . date('d-m-Y H:i') . '
+#
+# Manual updates:
+# Only the data in the array - everything else is removed by next
+# writing. "version" and "dependencies" must not be touched!
+########################################################################
+
+$EM_CONF[$_EXTKEY] = ' . tx_em_Tools::arrayToCode($EM_CONF, 0) . ';
+
+?>';
+               return str_replace(CR, '', $code);
+       }
+
+       /**
+        * Make upload array out of extension
+        *
+        * @param       string          Extension key
+        * @param       array           Extension information array
+        * @return      mixed           Returns array with extension upload array on success, otherwise an error string.
+        */
+       function makeUploadarray($extKey, $conf) {
+               $extPath = tx_em_Tools::getExtPath($extKey, $conf['type']);
+
+               if ($extPath) {
+
+                       // Get files for extension:
+                       $fileArr = array();
+                       $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr, $extPath, '', 0, 99, $GLOBALS['TYPO3_CONF_VARS']['EXT']['excludeForPackaging']);
+
+                       // Calculate the total size of those files:
+                       $totalSize = 0;
+                       foreach ($fileArr as $file) {
+                               $totalSize += filesize($file);
+                       }
+
+                       // If the total size is less than the upper limit, proceed:
+                       if ($totalSize < $this->maxUploadSize) {
+
+                               // Initialize output array:
+                               $uploadArray = array();
+                               $uploadArray['extKey'] = $extKey;
+                               $uploadArray['EM_CONF'] = $conf['EM_CONF'];
+                               $uploadArray['misc']['codelines'] = 0;
+                               $uploadArray['misc']['codebytes'] = 0;
+
+                               $uploadArray['techInfo'] = $this->install->makeDetailedExtensionAnalysis($extKey, $conf, 1);
+
+                               // Read all files:
+                               foreach ($fileArr as $file) {
+                                       $relFileName = substr($file, strlen($extPath));
+                                       $fI = pathinfo($relFileName);
+                                       if ($relFileName != 'ext_emconf.php') { // This file should be dynamically written...
+                                               $uploadArray['FILES'][$relFileName] = array(
+                                                       'name' => $relFileName,
+                                                       'size' => filesize($file),
+                                                       'mtime' => filemtime($file),
+                                                       'is_executable' => (TYPO3_OS == 'WIN' ? 0 : is_executable($file)),
+                                                       'content' => t3lib_div::getUrl($file)
+                                               );
+                                               if (t3lib_div::inList('php,inc', strtolower($fI['extension']))) {
+                                                       $uploadArray['FILES'][$relFileName]['codelines'] = count(explode(LF, $uploadArray['FILES'][$relFileName]['content']));
+                                                       $uploadArray['misc']['codelines'] += $uploadArray['FILES'][$relFileName]['codelines'];
+                                                       $uploadArray['misc']['codebytes'] += $uploadArray['FILES'][$relFileName]['size'];
+
+                                                       // locallang*.php files:
+                                                       if (substr($fI['basename'], 0, 9) == 'locallang' && strstr($uploadArray['FILES'][$relFileName]['content'], '$LOCAL_LANG')) {
+                                                               $uploadArray['FILES'][$relFileName]['LOCAL_LANG'] = tx_em_Tools::getSerializedLocalLang($file, $uploadArray['FILES'][$relFileName]['content']);
+                                                       }
+                                               }
+                                               $uploadArray['FILES'][$relFileName]['content_md5'] = md5($uploadArray['FILES'][$relFileName]['content']);
+                                       }
+                               }
+
+                               // Return upload-array:
+                               return $uploadArray;
+                       } else {
+                               return sprintf($GLOBALS['LANG']->getLL('makeUploadArray_error_size'),
+                                       $totalSize, t3lib_div::formatSize($this->maxUploadSize));
+                       }
+               } else {
+                       return sprintf($GLOBALS['LANG']->getLL('makeUploadArray_error_path'),
+                               $extKey);
+               }
+       }
+
+
+       /**
+        * Prints a table with extension information in it.
+        *
+        * @param       string          Extension key
+        * @param       array           Extension information array
+        * @param       boolean         If set, the information array shows information for a remote extension in TER, not a local one.
+        * @return      string          HTML content.
+        */
+       function extInformationarray($extKey, $extInfo, $remote = 0) {
+               $emConf = $extInfo['EM_CONF'];
+
+               $lines = array();
+               $lines[] = '
+                       <tr class="t3-row-header"><td colspan="2"><strong>' . $GLOBALS['LANG']->getLL('extInfoArray_general_info') . '</strong></td></tr>';
+
+               // row for the extension title
+               $key = 'title';
+               $dataCol = $emConf['_icon'] . $emConf[$key];
+               $lines[] = array(
+                       $this->headerCol($key),
+                       $dataCol
+               );
+
+               // row for the extension description
+               $key = 'description';
+               $dataCol = nl2br(htmlspecialchars($emConf[$key]));
+               $lines[] = array(
+                       $this->headerCol($key),
+                       $dataCol
+               );
+
+               // row for the extension author
+               $key = 'author';
+               $dataCol = tx_em_Tools::wrapEmail($emConf['author'] . ($emConf['author_email'] ? ' <' . $emConf['author_email'] . '>' : ''), $emConf['author_email']);
+               if ($emConf['author_company']) {
+                       $dataCol .= ', ' . $emConf['author_company'];
+               }
+               $lines[] = array(
+                       $this->headerCol($key),
+                       $dataCol
+               );
+
+               // row for the version
+               $key = 'version';
+               $dataCol = $emConf[$key];
+               $lines[] = array(
+                       $this->headerCol($key),
+                       $dataCol
+               );
+
+               // row for the category
+               $key = 'category';
+               $dataCol = $this->parentObject->categories[$emConf[$key]];
+               $lines[] = array(
+                       $this->headerCol($key),
+                       $dataCol
+               );
+
+               // row for the state
+               $key = 'state';
+               $dataCol = $this->parentObject->states[$emConf[$key]];
+               $lines[] = array(
+                       $this->headerCol($key),
+                       $dataCol
+               );
+
+               // row for the shy state
+               $key = 'shy';
+               if ($emConf[$key]) {
+                       $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes');
+               } else {
+                       $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:no');
+               }
+               $lines[] = array(
+                       $this->headerCol($key),
+                       $dataCol
+               );
+
+               // row for the internal state
+               $key = 'internal';
+               if ($emConf[$key]) {
+                       $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes');
+               } else {
+                       $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:no');
+               }
+               $lines[] = array(
+                       $this->headerCol($key),
+                       $dataCol
+               );
+
+               // row for the dependencies
+               $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_depends_on');
+               $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_dependencies', $headerCol);
+               $dataCol = tx_em_Tools::depToString($emConf['constraints']);
+               $lines[] = array(
+                       $headerCol,
+                       $dataCol
+               );
+
+               // row for the conflicts
+               $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_conflicts_with');
+               $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_conflicts', $headerCol);
+               $dataCol = tx_em_Tools::depToString($emConf['constraints'], 'conflicts');
+               $lines[] = array(
+                       $headerCol,
+                       $dataCol
+               );
+
+               // row for the suggestions
+               $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_suggests');
+               $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_conflicts', $headerCol);
+               $dataCol = tx_em_Tools::depToString($emConf['constraints'], 'suggests');
+               $lines[] = array(
+                       $this->headerCol('suggests'),
+                       $dataCol
+               );
+
+               if (!$remote) {
+
+                       $key = 'priority';
+                       $lines[] = array(
+                               $this->headerCol($key),
+                               $emConf[$key]
+                       );
+
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_clear_cache');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_clearCacheOnLoad', $headerCol);
+                       if ($emConf['clearCacheOnLoad']) {
+                               $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes');
+                       } else {
+                               $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:no');
+                       }
+                       $lines[] = array(
+                               $headerCol,
+                               $dataCol
+                       );
+
+                       $key = 'module';
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_incl_modules');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_module', $headerCol);
+                       $lines[] = array(
+                               $headerCol,
+                               $emConf[$key]
+                       );
+
+                       $key = 'lockType';
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_lock_type');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_lockType', $headerCol);
+                       $lines[] = array(
+                               $headerCol,
+                               ($emConf[$key] ? $emConf[$key] : '')
+                       );
+
+                       $key = 'doNotLoadInFE';
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_load_in_frontend');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_doNotLoadInFE', $headerCol);
+                       if (!$emConf['doNotLoadInFE']) {
+                               $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes');
+                       } else {
+                               $dataCol = $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:no');
+                       }
+                       $lines[] = array(
+                               $headerCol,
+                               $dataCol
+                       );
+
+                       $key = 'modify_tables';
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_modifies_tables');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_modify_tables', $headerCol);
+                       $lines[] = array(
+                               $headerCol,
+                               $emConf[$key]
+                       );
+
+
+                       // Installation status:
+                       $techInfo = $this->install->makeDetailedExtensionAnalysis($extKey, $extInfo, 1);
+                       $lines[] = array('<tr><td colspan="2">&nbsp;</td></tr>');
+                       $lines[] = array('<tr class="t3-row-header"><td colspan="2"><strong>' . $GLOBALS['LANG']->getLL('extInfoArray_inst_status') . '</strong></td></tr>');
+
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_inst_type');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_type', $headerCol);
+                       $dataCol = $this->parentObject->typeLabels[$extInfo['type']] . ' - <em>' . $this->parentObject->typeDescr[$extInfo['type']] . '</em>';
+                       $lines[] = array($headerCol, $dataCol);
+
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_inst_twice');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_doubleInstall', $headerCol);
+                       $dataCol = $this->extInformationArray_dbInst($extInfo['doubleInstall'], $extInfo['type']);
+                       $lines[] = array($headerCol, $dataCol);
+
+
+                       if (is_array($extInfo['files'])) {
+                               sort($extInfo['files']);
+                               $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_root_files');
+                               $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_rootfiles', $headerCol);
+                               $dataCol = implode('<br />', $extInfo['files']);
+                               $lines[] = array($headerCol, $dataCol);
+                       }
+
+                       if ($techInfo['tables'] || $techInfo['static'] || $techInfo['fields']) {
+                               if (!$remote && t3lib_extMgm::isLoaded($extKey)) {
+                                       $tableStatus = tx_em_Tools::rfw(($techInfo['tables_error'] ?
+                                                       '<strong>' . $GLOBALS['LANG']->getLL('extInfoArray_table_error') . '</strong><br />' .
+                                                                       $GLOBALS['LANG']->getLL('extInfoArray_missing_fields') : '') .
+                                                       ($techInfo['static_error'] ?
+                                                                       '<strong>' . $GLOBALS['LANG']->getLL('extInfoArray_static_table_error') . '</strong><br />' .
+                                                                                       $GLOBALS['LANG']->getLL('extInfoArray_static_tables_missing_empty') : ''));
+                               } else {
+                                       $tableStatus = $techInfo['tables_error'] || $techInfo['static_error'] ?
+                                                       $GLOBALS['LANG']->getLL('extInfoArray_db_update_needed') : $GLOBALS['LANG']->getLL('extInfoArray_tables_ok');
+                               }
+                       }
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_db_requirements');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_dbReq', $headerCol);
+                       $dataCol = $this->extInformationArray_dbReq($techInfo, 1);
+                       $lines[] = array($headerCol, $dataCol);
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_db_status');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_dbStatus', $headerCol);
+                       $lines[] = array($headerCol, $tableStatus);
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_flags');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_flags', $headerCol);
+                       $dataCol = (is_array($techInfo['flags']) ? implode('<br />', $techInfo['flags']) : '');
+                       $lines[] = array($headerCol, $dataCol);
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_config_template');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_conf', $headerCol);
+                       $dataCol = ($techInfo['conf'] ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes') : '');
+                       $lines[] = array($headerCol, $dataCol);
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_typoscript_files');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_TSfiles', $headerCol);
+                       $dataCol = (is_array($techInfo['TSfiles']) ? implode('<br />', $techInfo['TSfiles']) : '');
+                       $lines[] = array($headerCol, $dataCol);
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_language_files');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_locallang', $headerCol);
+                       $dataCol = (is_array($techInfo['locallang']) ? implode('<br />', $techInfo['locallang']) : '');
+                       $lines[] = array($headerCol, $dataCol);
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_upload_folder');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_uploadfolder', $headerCol);
+                       $dataCol = ($techInfo['uploadfolder'] ? $techInfo['uploadfolder'] : '');
+                       $lines[] = array($headerCol, $dataCol);
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_create_directories');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_createDirs', $headerCol);
+                       $dataCol = (is_array($techInfo['createDirs']) ? implode('<br />', $techInfo['createDirs']) : '');
+                       $lines[] = array($headerCol, $dataCol);
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_module_names');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_moduleNames', $headerCol);
+                       $dataCol = (is_array($techInfo['moduleNames']) ? implode('<br />', $techInfo['moduleNames']) : '');
+                       $lines[] = array($headerCol, $dataCol);
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_class_names');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_classNames', $headerCol);
+                       $dataCol = (is_array($techInfo['classes']) ? implode('<br />', $techInfo['classes']) : '');
+                       $lines[] = array($headerCol, $dataCol);
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_code_warnings') . '<br />' . $GLOBALS['LANG']->getLL('extInfoArray_dev_relevant');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_errors', $headerCol);
+                       $dataCol = (is_array($techInfo['errors']) ? tx_em_Tools::rfw(implode('<br />', $techInfo['errors'])) : '');
+                       $lines[] = array($headerCol, $dataCol);
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_annoyances') . '<br />' . $GLOBALS['LANG']->getLL('extInfoArray_dev_relevant');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_NSerrors', $headerCol);
+                       if (is_array($techInfo['NSerrors'])) {
+                               if (!t3lib_div::inList($this->parentObject->nameSpaceExceptions, $extKey)) {
+                                       $dataCol = t3lib_utility_Debug::viewarray($techInfo['NSerrors']);
+                               } else {
+                                       $dataCol = $GLOBALS['TBE_TEMPLATE']->dfw($GLOBALS['LANG']->getLL('extInfoArray_exception'));
+                               }
+
+                       }
+                       $lines[] = array($headerCol, $dataCol);
+
+                       $currentMd5Array = $this->serverExtensionMD5array($extKey, $extInfo);
+                       $affectedFiles = '';
+
+                       $msgLines = array();
+                       if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'], serialize($currentMd5Array))) {
+                               $msgLines[] = tx_em_Tools::rfw('<br /><strong>' . $GLOBALS['LANG']->getLL('extInfoArray_difference_detected') . '</strong>');
+                               $affectedFiles = tx_em_Tools::findMD5ArrayDiff($currentMd5Array, unserialize($extInfo['EM_CONF']['_md5_values_when_last_written']));
+                               if (count($affectedFiles)) {
+                                       $msgLines[] = '<br /><strong>' . $GLOBALS['LANG']->getLL('extInfoArray_modified_files') . '</strong><br />' .
+                                                       tx_em_Tools::rfw(implode('<br />', $affectedFiles));
+                               }
+                       }
+
+                       $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_files_changed');
+                       $headerCol = t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_filesChanged', $headerCol);
+                       $dataCol = implode('<br />', $msgLines);
+                       $lines[] = array($headerCol, $dataCol);
+               }
+
+               $output = '';
+               foreach ($lines as $cols) {
+                       // if it's just one line, we assume it's a headline,
+                       // thus no need to wrap it in HTML table tags
+                       if (count($cols) == 1) {
+                               $output .= $cols[0];
+                       } else {
+                               $output .= '
+                                       <tr class="bgColor4">
+                                               <td>' . $cols[0] . '</td>
+                                               <td>' . $cols[1] . '</td>
+                                       </tr>';
+                       }
+               }
+
+
+               return '<table border="0" cellpadding="1" cellspacing="2">
+                                       ' . $output . '
+                               </table>';
+       }
+
+       /**
+        * Returns HTML with information about database requirements
+        *
+        * @param       array           Technical information array
+        * @param       boolean         Table header displayed
+        * @return      string          HTML content.
+        */
+       function extInformationArray_dbReq($techInfo, $tableHeader = 0) {
+               return nl2br(trim((is_array($techInfo['tables']) ?
+                               ($tableHeader ?
+                                               "\n\n<strong>" . $GLOBALS['LANG']->getLL('extDumpTables_tables') . "</strong>\n" : '') .
+                                               implode(LF, $techInfo['tables']) : '') .
+                               (is_array($techInfo['static']) ?
+                                               "\n\n<strong>" . $GLOBALS['LANG']->getLL('extBackup_static_tables') . "</strong>\n" .
+                                                               implode(LF, $techInfo['static']) : '') .
+                               (is_array($techInfo['fields']) ?
+                                               "\n\n<strong>" . $GLOBALS['LANG']->getLL('extInfoArray_additional_fields') . "</strong>\n" .
+                                                               implode('<hr />', $techInfo['fields']) : '')));
+       }
+
+       /**
+        * Double install warning.
+        *
+        * @param       string          Double-install string, eg. "LG" etc.
+        * @param       string          Current scope, eg. "L" or "G" or "S"
+        * @return      string          Message
+        */
+       function extInformationArray_dbInst($dbInst, $current) {
+               if (strlen($dbInst) > 1) {
+                       $others = array();
+                       for ($a = 0; $a < strlen($dbInst); $a++) {
+                               if (substr($dbInst, $a, 1) != $current) {
+                                       $others[] = '"' . $this->parentObject->typeLabels[substr($dbInst, $a, 1)] . '"';
+                               }
+                       }
+                       return tx_em_Tools::rfw(
+                               sprintf($GLOBALS['LANG']->getLL('extInfoArray_double_installation_infotext'),
+                                       implode(' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:and') . ' ', $others),
+                                       $this->parentObject->typeLabels[$current]
+                               )
+                       );
+               } else {
+                       return '';
+               }
+       }
+
+
+       /**
+        * Returns help text if applicable.
+        *
+        * @param       string          Help text key
+        * @return      string          HTML table cell
+        * @deprecated since TYPO3 4.5, will be removed in TYPO3 4.7
+        */
+       function helpCol($key) {
+               global $BE_USER;
+               if ($BE_USER->uc['edit_showFieldHelp']) {
+                       if (empty($key)) {
+                               return '<td>&nbsp;</td>';
+                       }
+                       else {
+                               return t3lib_BEfunc::cshItem($this->parentObject->descrTable, 'emconf_' . $key, $GLOBALS['BACK_PATH'], '<td>|</td>');
+                       }
+               }
+               else {
+                       return '';
+               }
+       }
+
+       /**
+        * Returns the header column (for the extension details item), and applies help text if available
+        *
+        * @param       string  field key
+        * @return      string  HTML ready to go
+        */
+       function headerCol($key) {
+               $headerCol = $GLOBALS['LANG']->getLL('extInfoArray_' . $key);
+               return t3lib_BEfunc::wrapInHelp($this->parentObject->descrTable, 'emconf_' . $key, $headerCol);
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/extensions/class.tx_em_extensions_list.php b/typo3/sysext/em/classes/extensions/class.tx_em_extensions_list.php
new file mode 100644 (file)
index 0000000..a694d81
--- /dev/null
@@ -0,0 +1,845 @@
+<?php
+/* **************************************************************
+*  Copyright notice
+*
+*  (c) webservices.nl
+*  (c) 2006-2010 Karsten Dambekalns <karsten@typo3.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*  A copy is found in the textfile GPL.txt and important notices to the license
+*  from the author is found in LICENSE.txt distributed with these scripts.
+*
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+/* $Id: class.tx_em_extensions_list.php 2084 2010-03-22 01:46:37Z steffenk $ */
+
+/**
+ * This class handles extension listings
+ *
+ */
+class tx_em_Extensions_List {
+
+
+       protected $parentObject;
+
+       protected $categories;
+       protected $types;
+
+       /**
+        * Constructor
+        *
+        * @param object $parentObject
+        * @return void
+        */
+       public function __construct($parentObject = NULL) {
+               $this->parentObject = $parentObject;
+               $this->install = t3lib_div::makeInstance('tx_em_Install', $this);
+
+               $this->categories = array(
+                       'be' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:category_BE'),
+                       'module' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:category_BE_modules'),
+                       'fe' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:category_FE'),
+                       'plugin' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:category_FE_plugins'),
+                       'misc' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:category_miscellanous'),
+                       'services' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:category_services'),
+                       'templates' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:category_templates'),
+                       'example' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:category_examples'),
+                       'doc' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:category_documentation')
+               );
+               $this->types = array(
+                       'S' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:type_system'),
+                       'G' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:type_global'),
+                       'L' => $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:type_local'),
+               );
+       }
+
+
+       /**
+        * Returns the list of available (installed) extensions
+        *
+        * @return      array           Array with two arrays, list array (all extensions with info) and category index
+        * @see getInstExtList()
+        */
+       function getInstalledExtensions($new = FALSE) {
+               $list = array();
+
+               if (!$new) {
+                       $cat = $this->parentObject->defaultCategories;
+
+                       $path = PATH_typo3 . 'sysext/';
+                       $this->getInstExtList($path, $list, $cat, 'S');
+
+                       $path = PATH_typo3 . 'ext/';
+                       $this->getInstExtList($path, $list, $cat, 'G');
+
+                       $path = PATH_typo3conf . 'ext/';
+                       $this->getInstExtList($path, $list, $cat, 'L');
+
+                       return array($list, $cat);
+               } else {
+                       $path = PATH_typo3 . 'sysext/';
+                       $this->getFlatInstExtList($path, $list, 'S');
+
+                       $path = PATH_typo3 . 'ext/';
+                       $this->getFlatInstExtList($path, $list, 'G');
+
+                       $path = PATH_typo3conf . 'ext/';
+                       $this->getFlatInstExtList($path, $list, 'L');
+
+                       return $list;
+               }
+       }
+
+       /**
+        * Gathers all extensions in $path
+        *
+        * @param       string          Absolute path to local, global or system extensions
+        * @param       array           Array with information for each extension key found. Notice: passed by reference
+        * @param       array           Categories index: Contains extension titles grouped by various criteria.
+        * @param       string          Path-type: L, G or S
+        * @return      void            "Returns" content by reference
+        * @see getInstalledExtensions()
+        */
+       function getInstExtList($path, &$list, &$cat, $type) {
+
+               if (@is_dir($path)) {
+                       $extList = t3lib_div::get_dirs($path);
+                       if (is_array($extList)) {
+                               foreach ($extList as $extKey) {
+                                       if (@is_file($path . $extKey . '/ext_emconf.php')) {
+                                               $emConf = tx_em_Tools::includeEMCONF($path . $extKey . '/ext_emconf.php', $extKey);
+                                               if (is_array($emConf)) {
+                                                       if (is_array($list[$extKey])) {
+                                                               $list[$extKey] = array('doubleInstall' => $list[$extKey]['doubleInstall']);
+                                                       }
+                                                       $list[$extKey]['extkey'] = $extKey;
+                                                       $list[$extKey]['doubleInstall'] .= $type;
+                                                       $list[$extKey]['type'] = $type;
+                                                       $list[$extKey]['installed'] = t3lib_extMgm::isLoaded($extKey);
+                                                       $list[$extKey]['EM_CONF'] = $emConf;
+                                                       $list[$extKey]['files'] = t3lib_div::getFilesInDir($path . $extKey, '', 0, '', $this->excludeForPackaging);
+
+                                                       tx_em_Tools::setCat($cat, $list[$extKey], $extKey);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Gathers all extensions in $path
+        *
+        * @param       string          Absolute path to local, global or system extensions
+        * @param       array           Array with information for each extension key found. Notice: passed by reference
+        * @param       array           Categories index: Contains extension titles grouped by various criteria.
+        * @param       string          Path-type: L, G or S
+        * @return      void            "Returns" content by reference
+        * @access private
+        * @see getInstalledExtensions()
+        */
+       function getFlatInstExtList($path, &$list, $type) {
+
+
+               if (@is_dir($path)) {
+                       $extList = t3lib_div::get_dirs($path);
+                       if (is_array($extList)) {
+                               foreach ($extList as $extKey) {
+                                       $this->singleExtInfo($extKey, $path, $list, $type);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Gets a single extension info
+        *
+        * @param  $extKey
+        * @param  $path
+        * @param  $list
+        * @param string $type
+        * @return void
+        */
+       public function singleExtInfo($extKey, $path, &$list, $type = '') {
+               if (@is_file($path . $extKey . '/ext_emconf.php')) {
+                       $relPath = '../../../../' . substr($path, strlen(PATH_site));
+                       $emConf = tx_em_Tools::includeEMCONF($path . $extKey . '/ext_emconf.php', $extKey);
+                       $manual = $path . $extKey . '/doc/manual.sxw';
+                       if ($type === '') {
+                               $type = tx_em_Tools::getExtTypeFromPath($path);
+                       }
+                       if (is_array($emConf)) {
+                               $key = count($list);
+                               $loaded = t3lib_extMgm::isLoaded($extKey);
+                               if (is_array($list[$key])) {
+                                       $list[$key] = array('doubleInstall' => $list[$key]['doubleInstall']);
+                               }
+                               $list[$key]['extkey'] = $extKey;
+                               $list[$key]['path'] = $path . $extKey;
+                               $list[$key]['nodePath'] = substr($path . $extKey, strlen(PATH_site));
+                               $list[$key]['doubleInstall'] .= $this->types[$type];
+
+                               $list[$key]['type'] = $this->types[$type];
+                               $list[$key]['typeShort'] = $type;
+                               $list[$key]['installed'] = $loaded ? 1 : 0;
+                               // FIXME: raises PHP warning
+                               // "Core: Error handler (BE): PHP Warning: htmlspecialchars() expects parameter 1 to be string, array given in [...]/typo3/mod/tools/em/classes/class.tx_em_extensions_list.php line 185
+                               $list[$key] = t3lib_div::array_merge_recursive_overrule($list[$key], $emConf);
+                               $list[$key]['title'] = htmlspecialchars($list[$key]['title']);
+                               $list[$key]['description'] = htmlspecialchars($list[$key]['description']);
+                               $list[$key]['files'] = t3lib_div::getFilesInDir($path . $extKey, '', 0, '', $this->excludeForPackaging);
+                               $list[$key]['install'] = $loaded ? '<a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
+                                       'CMD[showExt]' => $extKey,
+                                       'CMD[remove]' => 1,
+                                       'CMD[clrCmd]' => 1,
+                                       'SET[singleDetails]' => 'info'
+                               ))) . '">' . tx_em_Tools::removeButton() . '</a>' :
+                                               '<a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
+                                                       'CMD[showExt]' => $extKey,
+                                                       'CMD[load]' => 1,
+                                                       'CMD[clrCmd]' => 1,
+                                                       'SET[singleDetails]' => 'info'
+                                               ))) . '">' . tx_em_Tools::installButton() . '</a>';
+
+                               $list[$key]['install'] = $loaded ? tx_em_Tools::removeButton() : tx_em_Tools::installButton();
+
+                               $list[$key]['download'] = '<a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
+                                       'CMD[doBackup]' => 1,
+                                       'SET[singleDetails]' => 'backup',
+                                       'CMD[showExt]' => $extKey
+                               ))) . '">' .
+                                               t3lib_iconWorks::getSpriteIcon('actions-system-extension-download') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:download') . '" alt=""></a>';
+
+                               $list[$key]['doc'] = '';
+                               if (@is_file($manual)) {
+                                       $list[$key]['doc'] = '<a href="' . htmlspecialchars($relPath . $extKey . '/doc/manual.sxw') . '" target="_blank">
+                                       <img src="res/icons/oodoc.gif" width="13" height="16" title="' . $GLOBALS['LANG']->getLL('listRow_local_manual') . '" alt="" /></a>';
+                               }
+                               $list[$key]['icon'] = @is_file($path . $extKey . '/ext_icon.gif') ? '<img src="' . $relPath . $extKey . '/ext_icon.gif" alt="" width="16" height="16" />' : '<img src="clear.gif" alt="" width="16" height="16" />';
+
+                               $list[$key]['categoryShort'] = $list[$key]['category'];
+                               $list[$key]['category'] = $this->categories[$list[$key]['category']];
+
+                               unset($list[$key]['_md5_values_when_last_written']);
+                       }
+               }
+       }
+
+
+       /**
+        * Listing of loaded (installed) extensions
+        *
+        * @return      void
+        */
+       function extensionList_loaded() {
+               global $TYPO3_LOADED_EXT;
+
+               list($list, $cat) = $this->getInstalledExtensions();
+
+               // Loaded extensions
+               $content = '';
+               $lines = array();
+
+               // Available extensions
+               if (is_array($cat[$this->parentObject->MOD_SETTINGS['listOrder']])) {
+                       $content = '';
+                       $lines = array();
+                       $lines[] = $this->extensionListRowHeader(' class="t3-row-header"', array('<td><img src="clear.gif" width="1" height="1" alt="" /></td>'));
+
+                       foreach ($cat[$this->parentObject->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) {
+
+                               natcasesort($extEkeys);
+                               $extensions = array();
+                               foreach ($extEkeys as $extKey => $data) {
+                                       if (array_key_exists($extKey, $TYPO3_LOADED_EXT) && ($this->parentObject->MOD_SETTINGS['display_shy'] || !$list[$extKey]['EM_CONF']['shy']) && $this->parentObject->searchExtension($extKey, $list[$extKey])) {
+                                               if (in_array($extKey, $this->parentObject->requiredExt)) {
+                                                       $loadUnloadLink = '<strong>' . $GLOBALS['TBE_TEMPLATE']->rfw($GLOBALS['LANG']->getLL('extension_required_short')) . '</strong>';
+                                               } else {
+                                                       $loadUnloadLink = '<a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
+                                                               'CMD[showExt]' => $extKey,
+                                                               'CMD[remove]' => 1
+                                                       ))) . '">' . tx_em_Tools::removeButton() . '</a>';
+                                               }
+
+                                               $extensions[] = $this->extensionListRow($extKey, $list[$extKey], array('<td class="bgColor">' . $loadUnloadLink . '</td>'));
+
+                                       }
+                               }
+                               if (count($extensions)) {
+                                       $lines[] = '<tr><td colspan="' . (3 + $this->parentObject->detailCols[$this->parentObject->MOD_SETTINGS['display_details']]) . '"><br /></td></tr>';
+                                       $lines[] = '<tr><td colspan="' . (3 + $this->parentObject->detailCols[$this->parentObject->MOD_SETTINGS['display_details']]) . '">' . t3lib_iconWorks::getSpriteIcon('apps-filetree-folder-default') . '<strong>' . htmlspecialchars($this->parentObject->listOrderTitle($this->parentObject->MOD_SETTINGS['listOrder'], $catName)) . '</strong></td></tr>';
+                                       $lines[] = implode(LF, $extensions);
+                               }
+                       }
+               }
+
+               $content .= '<form action="' . $this->parentObject->script . '" method="post" name="lookupform">';
+               $content .= '<label for="lookUp">' . $GLOBALS['LANG']->getLL('look_up') . '</label> <input type="text" id="lookUp" name="lookUp" value="' . htmlspecialchars($this->lookUpStr) . '" /><input type="submit" value="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:search') . '" /><br /><br />';
+
+               $content .= '</form>
+
+                       <!-- Loaded Extensions List -->
+                       <table border="0" cellpadding="2" cellspacing="1">' . implode('', $lines) . '</table>';
+
+               return $content;
+       }
+
+       /**
+        * Listing of available (installed) extensions
+        *
+        * @return      void
+        */
+       function extensionList_installed() {
+
+               list($list, $cat) = $this->getInstalledExtensions();
+
+               // Available extensions
+               if (is_array($cat[$this->parentObject->MOD_SETTINGS['listOrder']])) {
+                       $content = '';
+                       $lines = array();
+                       $lines[] = $this->extensionListRowHeader(' class="t3-row-header"', array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>'));
+
+                       $allKeys = array();
+                       foreach ($cat[$this->parentObject->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) {
+                               if (!$this->parentObject->MOD_SETTINGS['display_obsolete'] && $catName == 'obsolete') {
+                                       continue;
+                               }
+
+                               $allKeys[] = '';
+                               $allKeys[] = 'TYPE: ' . $catName;
+
+                               natcasesort($extEkeys);
+                               $extensions = array();
+                               foreach ($extEkeys as $extKey => $value) {
+                                       $allKeys[] = $extKey;
+                                       if ((!$list[$extKey]['EM_CONF']['shy'] || $this->parentObject->MOD_SETTINGS['display_shy']) &&
+                                                       ($list[$extKey]['EM_CONF']['state'] != 'obsolete' || $this->parentObject->MOD_SETTINGS['display_obsolete'])
+                                                       && $this->parentObject->searchExtension($extKey, $list[$extKey])) {
+                                               $loadUnloadLink = t3lib_extMgm::isLoaded($extKey) ?
+                                                               '<a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
+                                                                       'CMD[showExt]' => $extKey,
+                                                                       'CMD[remove]' => 1,
+                                                                       'CMD[clrCmd]' => 1,
+                                                                       'SET[singleDetails]' => 'info'
+                                                               ))) . '">' . tx_em_Tools::removeButton() . '</a>' :
+                                                               '<a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
+                                                                       'CMD[showExt]' => $extKey,
+                                                                       'CMD[load]' => 1,
+                                                                       'CMD[clrCmd]' => 1,
+                                                                       'SET[singleDetails]' => 'info'
+                                                               ))) . '">' . tx_em_Tools::installButton() . '</a>';
+                                               if (in_array($extKey, $this->parentObject->requiredExt)) {
+                                                       $loadUnloadLink = '<strong>' . $GLOBALS['TBE_TEMPLATE']->rfw($GLOBALS['LANG']->getLL('extension_required_short')) . '</strong>';
+                                               }
+                                               $theRowClass = t3lib_extMgm::isLoaded($extKey) ? 'em-listbg1' : 'em-listbg2';
+                                               $extensions[] = $this->extensionListRow($extKey, $list[$extKey], array('<td class="bgColor">' . $loadUnloadLink . '</td>'), $theRowClass);
+                                       }
+                               }
+                               if (count($extensions)) {
+                                       $lines[] = '<tr><td colspan="' . (3 + $this->parentObject->detailCols[$this->parentObject->MOD_SETTINGS['display_details']]) . '"><br /></td></tr>';
+                                       $lines[] = '<tr><td colspan="' . (3 + $this->parentObject->detailCols[$this->parentObject->MOD_SETTINGS['display_details']]) . '">' . t3lib_iconWorks::getSpriteIcon('apps-filetree-folder-default') . '<strong>' . htmlspecialchars($this->parentObject->listOrderTitle($this->parentObject->MOD_SETTINGS['listOrder'], $catName)) . '</strong></td></tr>';
+                                       $lines[] = implode(LF, $extensions);
+                               }
+                       }
+
+                       $content .= '
+
+
+<!--
+EXTENSION KEYS:
+
+' . trim(implode(LF, $allKeys)) . '
+
+-->
+
+';
+
+                       $content .= sprintf($GLOBALS['LANG']->getLL('how_to_install'), tx_em_Tools::installButton()) . ' <br />' .
+                                       sprintf($GLOBALS['LANG']->getLL('how_to_uninstall'), tx_em_Tools::removeButton()) . ' <br /><br />';
+                       $content .= '<form action="' . $this->parentObject->script . '" method="post" name="lookupform">';
+                       $content .= '<label for="lookUp">' . $GLOBALS['LANG']->getLL('look_up') . '</label> <input type="text" id="lookUp" name="lookUp" value="' . htmlspecialchars($this->parentObject->lookUpStr) . '" /><input type="submit" value="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:search') . '" /></form><br /><br />';
+                       $content .= $this->securityHint . '<br /><br />';
+
+                       $content .= '<table border="0" cellpadding="2" cellspacing="1">' . implode('', $lines) . '</table>';
+
+                       return $content;
+               }
+       }
+
+
+       /**
+        * Prints the header row for the various listings
+        *
+        * @param       string          Attributes for the <tr> tag
+        * @param       array           Preset cells in the beginning of the row. Typically a blank cell with a clear-gif
+        * @param       boolean         If set, the list is coming from remote server.
+        * @return      string          HTML <tr> table row
+        */
+       function extensionListRowHeader($trAttrib, $cells, $import = 0) {
+               $cells[] = '<td></td>';
+               $cells[] = '<td>' . $GLOBALS['LANG']->getLL('extInfoArray_title') . '</td>';
+
+               if (!$this->parentObject->MOD_SETTINGS['display_details']) {
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('extInfoArray_description') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('extInfoArray_author') . '</td>';
+               } elseif ($this->parentObject->MOD_SETTINGS['display_details'] == 2) {
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('extInfoArray_priority') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_modifies_tables_short') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_modules') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_clear_cache_short') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('extInfoArray_internal') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('extInfoArray_shy') . '</td>';
+               } elseif ($this->parentObject->MOD_SETTINGS['display_details'] == 3) {
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_tables_fields') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_ts_files') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_affects') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_modules') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_config') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('extInfoArray_code_warnings') . '</td>';
+               } elseif ($this->parentObject->MOD_SETTINGS['display_details'] == 4) {
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_locallang') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_classes') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('extInfoArray_code_warnings') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('extInfoArray_annoyances') . '</td>';
+               } elseif ($this->parentObject->MOD_SETTINGS['display_details'] == 5) {
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_changed_files') . '</td>';
+               } else {
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_ext_key') . '</td>';
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('extInfoArray_version') . '</td>';
+                       if (!$import) {
+                               $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_download_short') . '</td>';
+                               $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_documentation_short') . '</td>';
+                               $cells[] = '<td>' . $GLOBALS['LANG']->getLL('listRowHeader_type') . '</td>';
+                       } else {
+                               $cells[] = '<td' . tx_em_Tools::labelInfo($GLOBALS['LANG']->getLL('listRowHeader_title_upload_date')) . '>' .
+                                               $GLOBALS['LANG']->getLL('listRowHeader_upload_date') . '</td>';
+                               $cells[] = '<td>' . $GLOBALS['LANG']->getLL('extInfoArray_author') . '</td>';
+                               $cells[] = '<td' . tx_em_Tools::labelInfo($GLOBALS['LANG']->getLL('listRowHeader_title_current_version')) . '>' .
+                                               $GLOBALS['LANG']->getLL('listRowHeader_current_version') . '</td>';
+                               $cells[] = '<td' . tx_em_Tools::labelInfo($GLOBALS['LANG']->getLL('listRowHeader_title_current_type')) . '>' .
+                                               $GLOBALS['LANG']->getLL('listRowHeader_current_type') . '</td>';
+                               $cells[] = '<td' . tx_em_Tools::labelInfo($GLOBALS['LANG']->getLL('listRowHeader_title_number_of_downloads')) . '>' .
+                                               $GLOBALS['LANG']->getLL('listRowHeader_download_short') . '</td>';
+                       }
+                       $cells[] = '<td>' . $GLOBALS['LANG']->getLL('extInfoArray_state') . '</td>';
+               }
+               return '
+                       <tr' . $trAttrib . '>
+                               ' . implode('
+                               ', $cells) . '
+                       </tr>';
+       }
+
+
+       /**
+        * Prints a row with data for the various extension listings
+        *
+        * @param       string          Extension key
+        * @param       array           Extension information array
+        * @param       array           Preset table cells, eg. install/uninstall icons.
+        * @param       string          <tr> tag class
+        * @param       array           Array with installed extension keys (as keys)
+        * @param       boolean         If set, the list is coming from remote server.
+        * @param       string          Alternative link URL
+        * @return      string          HTML <tr> content
+        */
+       function extensionListRow($extKey, $extInfo, $cells, $bgColorClass = '', $inst_list = array(), $import = 0, $altLinkUrl = '') {
+               // Icon:
+               $imgInfo = @getImageSize(tx_em_Tools::getExtPath($extKey, $extInfo['type']) . '/ext_icon.gif');
+               if (is_array($imgInfo)) {
+                       $cells[] = '<td><img src="' . $GLOBALS['BACK_PATH'] . $this->parentObject->typeRelPaths[$extInfo['type']] . $extKey . '/ext_icon.gif' . '" ' . $imgInfo[3] . ' alt="" /></td>';
+               } elseif ($extInfo['_ICON']) {
+                       $cells[] = '<td>' . $extInfo['_ICON'] . '</td>';
+               } else {
+                       $cells[] = '<td><img src="clear.gif" width="1" height="1" alt="" /></td>';
+               }
+
+               // Extension title:
+               $cells[] = '<td nowrap="nowrap"><a href="' . htmlspecialchars($altLinkUrl ? $altLinkUrl : t3lib_div::linkThisScript(array(
+                       'CMD[showExt]' => $extKey,
+                       'SET[singleDetails]' => 'info'
+               ))) . '" title="' . htmlspecialchars($extInfo['EM_CONF']['description']) . '">'
+                               . t3lib_div::fixed_lgd_cs($extInfo['EM_CONF']['title'] ? htmlspecialchars($extInfo['EM_CONF']['title']) : '<em>' . $extKey . '</em>', 40) . '</a></td>';
+
+               // Based on the display mode you will see more or less details:
+               if (!$this->parentObject->MOD_SETTINGS['display_details']) {
+                       $cells[] = '<td>' . htmlspecialchars(t3lib_div::fixed_lgd_cs($extInfo['EM_CONF']['description'], 400)) . '<br /><img src="clear.gif" width="300" height="1" alt="" /></td>';
+                       $cells[] = '<td nowrap="nowrap">' . ($extInfo['EM_CONF']['author_email'] ? '<a href="mailto:' . htmlspecialchars($extInfo['EM_CONF']['author_email']) . '">' : '') . htmlspecialchars($extInfo['EM_CONF']['author']) . (htmlspecialchars($extInfo['EM_CONF']['author_email']) ? '</a>' : '') . ($extInfo['EM_CONF']['author_company'] ? '<br />' . htmlspecialchars($extInfo['EM_CONF']['author_company']) : '') . '</td>';
+               } elseif ($this->parentObject->MOD_SETTINGS['display_details'] == 2) {
+                       $cells[] = '<td nowrap="nowrap">' . $extInfo['EM_CONF']['priority'] . '</td>';
+                       $cells[] = '<td nowrap="nowrap">' . implode('<br />', t3lib_div::trimExplode(',', $extInfo['EM_CONF']['modify_tables'], 1)) . '</td>';
+                       $cells[] = '<td nowrap="nowrap">' . $extInfo['EM_CONF']['module'] . '</td>';
+                       $cells[] = '<td nowrap="nowrap">' . ($extInfo['EM_CONF']['clearCacheOnLoad'] ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes') : '') . '</td>';
+                       $cells[] = '<td nowrap="nowrap">' . ($extInfo['EM_CONF']['internal'] ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes') : '') . '</td>';
+                       $cells[] = '<td nowrap="nowrap">' . ($extInfo['EM_CONF']['shy'] ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes') : '') . '</td>';
+               } elseif ($this->parentObject->MOD_SETTINGS['display_details'] == 3) {
+                       $techInfo = $this->install->makeDetailedExtensionAnalysis($extKey, $extInfo);
+
+                       $cells[] = '<td>' . $this->parentObject->extensionDetails->extInformationArray_dbReq($techInfo) .
+                                       '</td>';
+                       $cells[] = '<td nowrap="nowrap">' . (is_array($techInfo['TSfiles']) ? implode('<br />', $techInfo['TSfiles']) : '') . '</td>';
+                       $cells[] = '<td nowrap="nowrap">' . (is_array($techInfo['flags']) ? implode('<br />', $techInfo['flags']) : '') . '</td>';
+                       $cells[] = '<td nowrap="nowrap">' . (is_array($techInfo['moduleNames']) ? implode('<br />', $techInfo['moduleNames']) : '') . '</td>';
+                       $cells[] = '<td nowrap="nowrap">' . ($techInfo['conf'] ? $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:yes') : '') . '</td>';
+                       $cells[] = '<td>' .
+                                       $GLOBALS['TBE_TEMPLATE']->rfw((t3lib_extMgm::isLoaded($extKey) && $techInfo['tables_error'] ?
+                                                       '<strong>' . $GLOBALS['LANG']->getLL('extInfoArray_table_error') . '</strong><br />' .
+                                                                       $GLOBALS['LANG']->getLL('extInfoArray_missing_fields') : '') .
+                                                       (t3lib_extMgm::isLoaded($extKey) && $techInfo['static_error'] ?
+                                                                       '<strong>' . $GLOBALS['LANG']->getLL('extInfoArray_static_table_error') . '</strong><br />' .
+                                                                                       $GLOBALS['LANG']->getLL('extInfoArray_static_tables_missing_empty') : '')) .
+                                       '</td>';
+               } elseif ($this->parentObject->MOD_SETTINGS['display_details'] == 4) {
+                       $techInfo = $this->install->makeDetailedExtensionAnalysis($extKey, $extInfo, 1);
+
+                       $cells[] = '<td>' . (is_array($techInfo['locallang']) ? implode('<br />', $techInfo['locallang']) : '') . '</td>';
+                       $cells[] = '<td>' . (is_array($techInfo['classes']) ? implode('<br />', $techInfo['classes']) : '') . '</td>';
+                       $cells[] = '<td>' . (is_array($techInfo['errors']) ? $GLOBALS['TBE_TEMPLATE']->rfw(implode('<hr />', $techInfo['errors'])) : '') . '</td>';
+                       $cells[] = '<td>' . (is_array($techInfo['NSerrors']) ?
+                                       (!t3lib_div::inList($this->parentObject->nameSpaceExceptions, $extKey) ?
+                                                       t3lib_utility_Debug::viewarray($techInfo['NSerrors']) :
+                                                       $GLOBALS['TBE_TEMPLATE']->dfw($GLOBALS['LANG']->getLL('extInfoArray_exception'))) : '') . '</td>';
+               } elseif ($this->parentObject->MOD_SETTINGS['display_details'] == 5) {
+                       $currentMd5Array = $this->parentObject->extensionDetails->serverExtensionMD5array($extKey, $extInfo);
+                       $affectedFiles = '';
+                       $msgLines = array();
+                       $msgLines[] = $GLOBALS['LANG']->getLL('listRow_files') . ' ' . count($currentMd5Array);
+                       if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'], serialize($currentMd5Array))) {
+                               $msgLines[] = $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>' . $GLOBALS['LANG']->getLL('extInfoArray_difference_detected') . '</strong>');
+                               $affectedFiles = tx_em_Tools::findMD5ArrayDiff($currentMd5Array, unserialize($extInfo['EM_CONF']['_md5_values_when_last_written']));
+                               if (count($affectedFiles)) {
+                                       $msgLines[] = '<br /><strong>' . $GLOBALS['LANG']->getLL('extInfoArray_modified_files') . '</strong><br />' .
+                                                       $GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />', $affectedFiles));
+                               }
+                       }
+                       $cells[] = '<td>' . implode('<br />', $msgLines) . '</td>';
+               } else {
+                       // Default view:
+                       $verDiff = $inst_list[$extKey] && tx_em_Tools::versionDifference($extInfo['EM_CONF']['version'], $inst_list[$extKey]['EM_CONF']['version'], $this->parentObject->versionDiffFactor);
+
+                       $cells[] = '<td nowrap="nowrap"><em>' . $extKey . '</em></td>';
+                       $cells[] = '<td nowrap="nowrap">' . ($verDiff ? '<strong>' . $GLOBALS['TBE_TEMPLATE']->rfw(htmlspecialchars($extInfo['EM_CONF']['version'])) . '</strong>' : $extInfo['EM_CONF']['version']) . '</td>';
+                       if (!$import) { // Listing extension on LOCAL server:
+                               // Extension Download:
+                               $cells[] = '<td nowrap="nowrap"><a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
+                                       'CMD[doBackup]' => 1,
+                                       'SET[singleDetails]' => 'backup',
+                                       'CMD[showExt]' => $extKey
+                               ))) . '" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:download') . '">' .
+                                               t3lib_iconWorks::getSpriteIcon('actions-system-extension-download') .
+                                               '</a></td>';
+
+                               // Manual download
+                               $fileP = PATH_site . $this->parentObject->typePaths[$extInfo['type']] . $extKey . '/doc/manual.sxw';
+                               $cells[] = '<td nowrap="nowrap">' .
+                                               ($this->parentObject->typePaths[$extInfo['type']] && @is_file($fileP) ?
+                                                               '<a href="' . htmlspecialchars(t3lib_div::resolveBackPath($this->parentObject->doc->backPath . '../' . $this->parentObject->typePaths[$extInfo['type']] . $extKey . '/doc/manual.sxw')) . '" target="_blank" title="' . $GLOBALS['LANG']->getLL('listRow_local_manual') . '">' .
+                                                                               t3lib_iconWorks::getSpriteIcon('actions-system-extension-documentation') . '</a>' : '') .
+                                               '</td>';
+
+                               // Double installation (inclusion of an extension in more than one of system, global or local scopes)
+                               $doubleInstall = '';
+                               if (strlen($extInfo['doubleInstall']) > 1) {
+                                       // Separate the "SL" et al. string into an array and replace L by Local, G by Global etc.
+                                       $doubleInstallations = str_replace(
+                                               array('S', 'G', 'L'),
+                                               array(
+                                                       $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:sysext'),
+                                                       $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:globalext'),
+                                                       $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:localext')
+                                               ),
+                                               str_split($extInfo['doubleInstall'])
+                                       );
+                                       // Last extension is the one actually used
+                                       $usedExtension = array_pop($doubleInstallations);
+                                       // Next extension is overridden
+                                       $overriddenExtensions = array_pop($doubleInstallations);
+                                       // If the array is not yet empty, the extension is actually installed 3 times (SGL)
+                                       if (count($doubleInstallations) > 0) {
+                                               $lastExtension = array_pop($doubleInstallations);
+                                               $overriddenExtensions .= ' ' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_common.xml:and') . ' ' . $lastExtension;
+                                       }
+                                       $doubleInstallTitle = sprintf(
+                                               $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:double_inclusion'),
+                                               $usedExtension,
+                                               $overriddenExtensions
+                                       );
+                                       $doubleInstall = ' <strong><abbr title="' . $doubleInstallTitle . '">' . $GLOBALS['TBE_TEMPLATE']->rfw($extInfo['doubleInstall']) . '</abbr></strong>';
+                               }
+                               $cells[] = '<td nowrap="nowrap">' . $this->parentObject->typeLabels[$extInfo['type']] . $doubleInstall . '</td>';
+                       } else { // Listing extensions from REMOTE repository:
+                               $inst_curVer = $inst_list[$extKey]['EM_CONF']['version'];
+                               if (isset($inst_list[$extKey])) {
+                                       if ($verDiff) {
+                                               $inst_curVer = '<strong>' . $GLOBALS['TBE_TEMPLATE']->rfw($inst_curVer) . '</strong>';
+                                       }
+                               }
+                               $cells[] = '<td nowrap="nowrap">' . t3lib_befunc::date($extInfo['EM_CONF']['lastuploaddate']) . '</td>';
+                               $cells[] = '<td nowrap="nowrap">' . htmlspecialchars(t3lib_div::fixed_lgd_cs($extInfo['EM_CONF']['author'], $GLOBALS['BE_USER']->uc[titleLen])) . '</td>';
+                               $cells[] = '<td nowrap="nowrap">' . $inst_curVer . '</td>';
+                               $cells[] = '<td nowrap="nowrap">' . $this->parentObject->typeLabels[$inst_list[$extKey]['type']] . (strlen($inst_list[$extKey]['doubleInstall']) > 1 ? '<strong> ' . $GLOBALS['TBE_TEMPLATE']->rfw($inst_list[$extKey]['doubleInstall']) . '</strong>' : '') . '</td>';
+                               $cells[] = '<td nowrap="nowrap">' . ($extInfo['downloadcounter_all'] ? $extInfo['downloadcounter_all'] : '&nbsp;&nbsp;') . '/' . ($extInfo['downloadcounter'] ? $extInfo['downloadcounter'] : '&nbsp;') . '</td>';
+                       }
+                       $cells[] = '<td nowrap="nowrap" class="extstate" style="background-color:' . $this->parentObject->stateColors[$extInfo['EM_CONF']['state']] . ';">' . $this->parentObject->states[$extInfo['EM_CONF']['state']] . '</td>';
+               }
+
+               // show a different background through a different class for insecure (-1) extensions,
+               // for unreviewed (0) and reviewed extensions (1), just use the regular class
+               if ($this->parentObject->xmlhandler->getReviewState($extKey, $extInfo['EM_CONF']['version']) < 0) {
+                       $bgclass = ' class="unsupported-ext"';
+               } else {
+                       $bgclass = ' class="' . ($bgColorClass ? $bgColorClass : 'em-listbg1') . '"';
+               }
+
+               return '
+                       <tr' . $bgclass . '>
+                               ' . implode('
+                               ', $cells) . '
+                       </tr>';
+       }
+
+
+       /**
+        *  Displays a list of extensions where a newer version is available
+        *  in the TER than the one that is installed right now
+        *  integrated from the extension "ter_update_check" for TYPO3 4.2 by Christian Welzel
+        *
+        * @return string
+        */
+       function showExtensionsToUpdate() {
+               global $LANG;
+               $extList = $this->getInstalledExtensions();
+
+               $content = '<table border="0" cellpadding="2" cellspacing="1">' .
+                               '<tr class="t3-row-header">' .
+                               '<td></td>' .
+                               '<td>' . $LANG->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:tab_mod_name') . '</td>' .
+                               '<td>' . $LANG->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:tab_mod_key') . '</td>' .
+                               '<td>' . $LANG->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:tab_mod_loc_ver') . '</td>' .
+                               '<td>' . $LANG->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:tab_mod_rem_ver') . '</td>' .
+                               '<td>' . $LANG->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:tab_mod_location') . '</td>' .
+                               '<td>' . $LANG->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:tab_mod_comment') . '</td>' .
+                               '</tr>';
+
+               foreach ($extList[0] as $name => $data) {
+                       $this->parentObject->xmlhandler->searchExtensionsXMLExact($name, '', '', TRUE, TRUE);
+                       if (!is_array($this->parentObject->xmlhandler->extensionsXML[$name])) {
+                               continue;
+                       }
+
+                       $v = $this->parentObject->xmlhandler->extensionsXML[$name]['versions'];
+                       $versions = array_keys($v);
+                       natsort($versions);
+                       $lastversion = end($versions);
+
+                       if ((t3lib_extMgm::isLoaded($name) || $this->parentObject->MOD_SETTINGS['display_installed']) &&
+                                       ($data['EM_CONF']['shy'] == 0 || $this->parentObject->MOD_SETTINGS['display_shy']) &&
+                                       tx_em_Tools::versionDifference($lastversion, $data['EM_CONF']['version'], 1)) {
+
+                               $imgInfo = @getImageSize(tx_em_Tools::getExtPath($name, $data['type']) . '/ext_icon.gif');
+                               if (is_array($imgInfo)) {
+                                       $icon = '<img src="' . $GLOBALS['BACK_PATH'] . $this->parentObject->typeRelPaths[$data['type']] . $name . '/ext_icon.gif' . '" ' . $imgInfo[3] . ' alt="" />';
+                               } elseif ($data['_ICON']) { //TODO: see if this can be removed, seems to be wrong in this context
+                                       $icon = $data['_ICON'];
+                               } else {
+                                       $icon = '<img src="clear.gif" width="1" height="1" alt="" />';
+                               }
+                               $comment = '<table cellpadding="0" cellspacing="0" width="100%">';
+                               foreach ($versions as $vk) {
+                                       $va = & $v[$vk];
+                                       if (t3lib_div::int_from_ver($vk) <= t3lib_div::int_from_ver($data['EM_CONF']['version'])) {
+                                               continue;
+                                       }
+                                       $comment .= '<tr><td valign="top" style="padding-right:2px;border-bottom:1px dotted gray">' . $vk . '</td>' . '<td valign="top" style="border-bottom:1px dotted gray">' . nl2br($va[uploadcomment]) . '</td></tr>';
+                               }
+                               $comment .= '</table>';
+
+                               $serverMD5Array = $this->parentObject->extensionDetails->serverExtensionMD5array($name, $data);
+                               if (is_array($serverMD5Array)) {
+                                       ksort($serverMD5Array);
+                               }
+                               $currentMD5Array = unserialize($data['EM_CONF']['_md5_values_when_last_written']);
+                               if (is_array($currentMD5Array)) {
+                                       @ksort($currentMD5Array);
+                               }
+                               $warn = '';
+                               if (strcmp(serialize($currentMD5Array), serialize($serverMD5Array))) {
+                                       $warn = '<tr class="bgColor4" style="color:red"><td colspan="7">' . $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>' . $name . ': ' . $LANG->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:msg_warn_diff') . '</strong>') . '</td></tr>' . LF;
+                                       if ($this->parentObject->MOD_SETTINGS['display_files'] == 1) {
+                                               $affectedFiles = tx_em_Tools::findMD5ArrayDiff($serverMD5Array, $currentMD5Array);
+                                               if (count($affectedFiles)) {
+                                                       $warn .= '<tr class="bgColor4"><td colspan="7"><strong>' . $LANG->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:msg_modified') . '</strong><br />' . $GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />', $affectedFiles)) . '</td></tr>' . LF;
+                                               }
+                                       }
+                               }
+                               //TODO: $extInfo is unknown in this context
+                               $content .= '<tr class="bgColor4"><td valign="top">' . $icon . '</td>' .
+                                               '<td valign="top">' . ($data['EM_CONF']['state'] == 'excludeFromUpdates' ? '<span style="color:#cf7307">' . $data['EM_CONF']['title'] . ' ' . $LANG->sL('LLL:EXT:lang/locallang_mod_tools_em.xml:write_protected') . '</span>' : '<a href="?CMD[importExtInfo]=' . $name . '">' . $data[EM_CONF][title] . '</a>') . '</td>' .
+                                               '<td valign="top">' . $name . '</td>' .
+                                               '<td valign="top" align="right">' . $data[EM_CONF][version] . '</td>' .
+                                               '<td valign="top" align="right">' . $lastversion . '</td>' .
+                                               '<td valign="top" nowrap="nowrap">' . $this->parentObject->typeLabels[$data['type']] . (strlen($data['doubleInstall']) > 1 ? '<strong> ' . $GLOBALS['TBE_TEMPLATE']->rfw($extInfo['doubleInstall']) . '</strong>' : '') . '</td>' .
+                                               '<td valign="top">' . $comment . '</td></tr>' . LF .
+                                               $warn .
+                                               '<tr class="bgColor4"><td colspan="7"><hr style="margin:0px" /></td></tr>' . LF;
+                       }
+               }
+
+               return $content . '</table><br />';
+       }
+
+       /**
+        * Maps remote extensions information into $cat/$list arrays for listing
+        *
+        * @param       boolean         If set the info in the internal extensionsXML array will be unset before returning the result.
+        * @return      array           List array and category index as key 0 / 1 in an array.
+        */
+       function prepareImportExtList($unsetProc = false) {
+               $list = array();
+               $cat = $this->parentObject->defaultCategories;
+               $filepath = $this->parentObject->getMirrorURL();
+
+               foreach ($this->parentObject->xmlhandler->extensionsXML as $extKey => $data) {
+                       $GLOBALS['LANG']->csConvObj->convarray($data, 'utf-8', $GLOBALS['LANG']->charSet); // is there a better place for conversion?
+                       $list[$extKey]['type'] = '_';
+                       $version = array_keys($data['versions']);
+                       $extPath = t3lib_div::strtolower($extKey);
+                       $list[$extKey]['_ICON'] = '<img alt="" src="' . $filepath . $extPath{0} . '/' . $extPath{1} . '/' . $extPath . '_' . end($version) . '.gif" />';
+                       $list[$extKey]['downloadcounter'] = $data['downloadcounter'];
+
+                       foreach (array_keys($data['versions']) as $version) {
+                               $list[$extKey]['versions'][$version]['downloadcounter'] = $data['versions'][$version]['downloadcounter'];
+
+                               $list[$extKey]['versions'][$version]['EM_CONF'] = array(
+                                       'version' => $version,
+                                       'title' => $data['versions'][$version]['title'],
+                                       'description' => $data['versions'][$version]['description'],
+                                       'category' => $data['versions'][$version]['category'],
+                                       'constraints' => $data['versions'][$version]['dependencies'],
+                                       'state' => $data['versions'][$version]['state'],
+                                       'reviewstate' => $data['versions'][$version]['reviewstate'],
+                                       'lastuploaddate' => $data['versions'][$version]['lastuploaddate'],
+                                       'author' => $data['versions'][$version]['authorname'],
+                                       'author_email' => $data['versions'][$version]['authoremail'],
+                                       'author_company' => $data['versions'][$version]['authorcompany'],
+                               );
+                       }
+                       tx_em_Tools::setCat($cat, $list[$extKey]['versions'][$version], $extKey);
+                       if ($unsetProc) {
+                               unset($this->parentObject->xmlhandler->extensionsXML[$extKey]);
+                       }
+               }
+
+               return array($list, $cat);
+       }
+
+
+       /**
+        * Adds extension to extension list and returns new list. If -1 is returned, an error happend.
+        * Checks dependencies etc.
+        *
+        * @param       string          Extension key
+        * @param       array           Extension information array - information about installed extensions
+        * @return      string          New list of installed extensions or -1 if error
+        * @see showExtDetails()
+        */
+       function addExtToList($extKey, $instExtInfo) {
+               global $TYPO3_LOADED_EXT;
+
+               // ext_emconf.php information:
+               $conf = $instExtInfo[$extKey]['EM_CONF'];
+
+               // Get list of installed extensions and add this one.
+               $listArr = array_keys($TYPO3_LOADED_EXT);
+               if ($conf['priority'] == 'top') {
+                       array_unshift($listArr, $extKey);
+               } else {
+                       $listArr[] = $extKey;
+               }
+
+               // Manage other circumstances:
+               $listArr = tx_em_Tools::managesPriorities($listArr, $instExtInfo);
+               $listArr = $this->removeRequiredExtFromListArr($listArr);
+
+               // Implode unique list of extensions to load and return:
+               $list = implode(',', array_unique($listArr));
+               return $list;
+       }
+
+       /**
+        * Remove extension key from the list of currently installed extensions and return list. If -1 is returned, an error happend.
+        * Checks dependencies etc.
+        *
+        * @param       string          Extension key
+        * @param       array           Extension information array - information about installed extensions
+        * @return      string          New list of installed extensions or -1 if error
+        * @see showExtDetails()
+        */
+       function removeExtFromList($extKey, $instExtInfo) {
+               global $TYPO3_LOADED_EXT;
+
+               // Initialize:
+               $depList = array();
+               $listArr = array_keys($TYPO3_LOADED_EXT);
+
+               // Traverse all installed extensions to check if any of them have this extension as dependency since if that is the case it will not work out!
+               foreach ($listArr as $k => $ext) {
+                       if ($instExtInfo[$ext]['EM_CONF']['dependencies']) {
+                               $dep = t3lib_div::trimExplode(',', $instExtInfo[$ext]['EM_CONF']['dependencies'], 1);
+                               if (in_array($extKey, $dep)) {
+                                       $depList[] = $ext;
+                               }
+                       }
+                       if (!strcmp($ext, $extKey)) {
+                               unset($listArr[$k]);
+                       }
+               }
+
+               // Returns either error or the new list
+               if (count($depList)) {
+                       $msg = sprintf($GLOBALS['LANG']->getLL('removeExtFromList_dependency'),
+                               implode(', ', $depList)
+                       );
+                       $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('removeExtFromList_dependency_error'), $msg, 0, 1, 2);
+                       return -1;
+               } else {
+                       $listArr = $this->removeRequiredExtFromListArr($listArr);
+                       $list = implode(',', array_unique($listArr));
+                       return $list;
+               }
+       }
+
+       /**
+        * This removes any required extensions from the $listArr - they should NOT be added to the common extension list, because they are found already in "requiredExt" list
+        *
+        * @param       array           Array of extension keys as values
+        * @return      array           Modified array
+        * @see removeExtFromList(), addExtToList()
+        */
+       function removeRequiredExtFromListArr($listArr) {
+               foreach ($listArr as $k => $ext) {
+                       if (in_array($ext, $this->parentObject->requiredExt) || !strcmp($ext, '_CACHEFILE')) {
+                               unset($listArr[$k]);
+                       }
+               }
+               return $listArr;
+       }
+
+
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/import/class.tx_em_import_extensionlistimporter.php b/typo3/sysext/em/classes/import/class.tx_em_import_extensionlistimporter.php
new file mode 100644 (file)
index 0000000..d5e292b
--- /dev/null
@@ -0,0 +1,208 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2010 Marcus Krause <marcus#exp2010@t3sec.info>
+ *                Steffen Kamper <info@sk-typo3.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+/**
+ * class.tx_em_import_extensionlistimporter.php
+ *
+ * Module: Extension manager - Extension list importer
+ *
+ * $Id: class.tx_em_import_extensionlistimporter.php 2016 2010-03-14 04:01:47Z mkrause $
+ *
+ * @author  Marcus Krause <marcus#exp2010@t3sec.info>
+ * @author  Steffen Kamper <info@sk-typo3.de>
+ */
+
+/**
+ * Importer object for extension list
+ *
+ * @author       Marcus Krause <marcus#exp2010@t3sec.info>
+ * @author       Steffen Kamper <info@sk-typo3.de>
+ *
+ * @since         2010-02-10
+ * @package     TYPO3
+ * @subpackage  EM
+ */
+class tx_em_Import_ExtensionListImporter implements SplObserver {
+
+       /**
+        * Keeps instance of a XML parser.
+        *
+        * @var em_xml_abstract_parser
+        */
+       protected $parser;
+
+       /**
+        * Keeps number of processed version records.
+        *
+        * @var integer
+        */
+       protected $sumRecords = 0;
+
+       /**
+        * Keeps record values to be inserted into database.
+        *
+        * @var  array
+        */
+       protected $arrRows = array();
+
+       /**
+        * Keeps fieldnames of cache_extension table.
+        *
+        * @var  array
+        */
+       static protected $fieldNames = array('extkey', 'version', 'intversion', 'alldownloadcounter', 'downloadcounter', 'title', 'ownerusername', 'authorname', 'authoremail', 'authorcompany', 'lastuploaddate', 't3xfilemd5', 'repository', 'state', 'reviewstate', 'category', 'description', 'dependencies', 'uploadcomment' /*, 'lastversion', 'lastreviewedversion'*/);
+
+       /**
+        * Keeps indexes of fields that should not be quoted.
+        *
+        * @var  array
+        */
+       static protected $fieldIndicesNoQuote = array(2, 3, 4, 10, 12, 13, 14, 15);
+
+
+       /**
+        * Keeps repository UID.
+        *
+        * The UID is necessary for inserting records.
+        *
+        * @var  integer
+        */
+       protected $repositoryUID = 1;
+
+
+       /**
+        * Class constructor.
+        *
+        * Method retrieves and initializes extension XML parser instance.
+        *
+        * @access  public
+        * @return  void
+        * @throws  tx_em_XmlException in case no valid parser instance is available
+        */
+       function __construct() {
+               // TODO catch parser exception
+               $this->parser = em_xml_parser_factory::getParserInstance('extension');
+               if (!is_object(tx_em_Parser_XmlParserFactory::getParserInstance('extension'))) {
+                       throw new tx_em_XmlException(get_class($this) . ': ' . 'No XML parser available.');
+               }
+       }
+
+       /**
+        * Gets parser object
+        *
+        * @return tx_em_XmlParserFactory
+        */
+       protected function getParser() {
+               $parser = tx_em_Parser_XmlParserFactory::getParserInstance('extension');
+               $parser->attach($this);
+               return $parser;
+       }
+
+       /**
+        * Method initializes parsing of extension.xml.gz file.
+        *
+        * @access  public
+        * @param   string   $localExtListFile  absolute path to (gzipped) local extension list xml file
+        * @param   integer  $repositoryUID      UID of repository to be used when inserting records into DB
+        * @return  integer  total number of imported extension versions
+        */
+       public function import($localExtListFile, $repositoryUID = NULL) {
+               if (!is_null($repositoryUID) && is_int($repositoryUID)) {
+                       $this->repositoryUID = $repositoryUID;
+               }
+               $zlibStream = 'compress.zlib://';
+               $this->sumRecords = 0;
+
+               $this->getParser()->parseXML($zlibStream . $localExtListFile);
+
+               // flush last rows to database if existing
+               if (count($this->arrRows)) {
+                       $GLOBALS['TYPO3_DB']->exec_INSERTmultipleRows(
+                               'cache_extensions',
+                               self::$fieldNames,
+                               $this->arrRows,
+                               self::$fieldIndicesNoQuote
+                       );
+               }
+               return $this->sumRecords;
+       }
+
+       /**
+        * Method collects and stores extension version details into the database.
+        *
+        * @access  protected
+        * @param   SplSubject  $subject  a subject notifying this observer
+        * @return  void
+        */
+       protected function loadIntoDB(SplSubject &$subject) {
+               // flush every 50 rows to database
+               if ($this->sumRecords !== 0 && $this->sumRecords % 50 === 0) {
+                       $GLOBALS['TYPO3_DB']->exec_INSERTmultipleRows(
+                               'cache_extensions',
+                               self::$fieldNames,
+                               $this->arrRows,
+                               self::$fieldIndicesNoQuote
+                       );
+                       $this->arrRows = array();
+               }
+               // order must match that of self::$fieldNamses!
+               $this->arrRows[] = array(
+                       $subject->getExtkey(),
+                       $subject->getVersion(),
+                       tx_em_Tools::makeVersion($subject->getVersion(), 'int'),
+                       intval($subject->getAlldownloadcounter()),
+                       intval($subject->getDownloadcounter()),
+                       !is_null($subject->getTitle()) ? $subject->getTitle() : '',
+                       $subject->getOwnerusername(),
+                       !is_null($subject->getAuthorname()) ? $subject->getAuthorname() : '',
+                       !is_null($subject->getAuthoremail()) ? $subject->getAuthoremail() : '',
+                       !is_null($subject->getAuthorcompany()) ? $subject->getAuthorcompany() : '',
+                       intval($subject->getLastuploaddate()),
+                       $subject->getT3xfilemd5(),
+                       $this->repositoryUID,
+                       tx_em_Tools::getDefaultState($subject->getState() ? $subject->getState() : ''),
+                       intval($subject->getReviewstate()),
+                       tx_em_Tools::getDefaultCategory($subject->getCategory() ? $subject->getCategory() : ''),
+                       $subject->getDescription() ? $subject->getDescription() : '',
+                       $subject->getDependencies() ? $subject->getDependencies() : '',
+                       $subject->getUploadcomment() ? $subject->getUploadcomment() : '',
+               );
+               ++$this->sumRecords;
+       }
+
+       /**
+        * Method receives an update from a subject.
+        *
+        * @access  public
+        * @param   SplSubject  $subject  a subject notifying this observer
+        * @return  void
+        */
+       public function update(SplSubject $subject) {
+               if (is_subclass_of($subject, 'tx_em_ExtensionXmlAbstractParser')) {
+                       $this->loadIntoDB($subject);
+               }
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/import/class.tx_em_import_mirrorlistimporter.php b/typo3/sysext/em/classes/import/class.tx_em_import_mirrorlistimporter.php
new file mode 100644 (file)
index 0000000..201ed21
--- /dev/null
@@ -0,0 +1,116 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2010 Marcus Krause <marcus#exp2010@t3sec.info>
+ *                Steffen Kamper <info@sk-typo3.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+/**
+ * class.tx_em_import_mirrorlistimporter.php
+ *
+ * Module: Extension manager - Mirror list importer
+ *
+ * $Id: class.tx_em_import_mirrorlistimporter.php 1982 2010-03-09 06:29:55Z mkrause $
+ *
+ * @author  Marcus Krause <marcus#exp2010@t3sec.info>
+ * @author  Steffen Kamper <info@sk-typo3.de>
+ */
+
+
+/**
+ * Importer object for mirror list.
+ *
+ * @author       Marcus Krause <marcus#exp2010@t3sec.info>
+ * @author       Steffen Kamper <info@sk-typo3.de>
+ *
+ * @since         2010-02-10
+ * @package     TYPO3
+ * @subpackage  EM
+ */
+class tx_em_Import_MirrorListImporter implements SplObserver {
+
+       /**
+        * Keeps instance of a XML parser.
+        *
+        * @var  tx_em_XmlAbstractParser
+        */
+       protected $parser;
+
+       /**
+        * Keeps mirrors' details.
+        *
+        * @var  array
+        */
+       protected $arrTmpMirrors = array();
+
+
+       /**
+        * Class constructor.
+        *
+        * Method retrieves and initializes extension XML parser instance.
+        *
+        * @access  public
+        * @return  void
+        * @throws  em_xml_Exception in case no valid parser instance is available
+        */
+       function __construct() {
+               // TODO catch parser exception
+               $this->parser = tx_em_Parser_XmlParserFactory::getParserInstance('mirror');
+               if (is_object($this->parser)) {
+                       $this->parser->attach($this);
+               } else {
+                       throw new tx_em_XmlException(get_class($this) . ': ' . 'No XML parser available.');
+               }
+       }
+
+       /**
+        * Method collects mirrors' details and returns instance of em_repository_mirrors
+        * with retrieved details.
+        *
+        * @access  public
+        * @param   string  $localMirrorListFile  bsolute path to (gzipped) local mirror list xml file
+        * @return  em_repository_mirrors
+        */
+       public function getMirrors($localMirrorListFile) {
+               $zlibStream = 'compress.zlib://';
+
+               $this->parser->parseXML($zlibStream . $localMirrorListFile);
+               $objRepositoryMirrors = t3lib_div::makeInstance('tx_em_Repository_Mirrors');
+               $objRepositoryMirrors->setMirrors($this->arrTmpMirrors);
+               $this->arrTmpMirrors = array();
+               return $objRepositoryMirrors;
+       }
+
+       /**
+        * Method receives an update from a subject.
+        *
+        * @access  public
+        * @param   SplSubject  $subject  a subject notifying this observer
+        * @return  void
+        */
+       public function update(SplSubject $subject) {
+               // TODO mirrorxml_abstract_parser
+               if (is_subclass_of($subject, 'tx_em_Parser_XmlAbstractParser')) {
+                       $this->arrTmpMirrors[] = $subject->getAll();
+               }
+       }
+}
+
+?>
\ No newline at end of file
diff --git a/typo3/sysext/em/classes/index.php b/typo3/sysext/em/classes/index.php
new file mode 100644 (file)
index 0000000..2da3ffd
--- /dev/null
@@ -0,0 +1,2691 @@
+<?php
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 1999-2010 Kasper Skårhøj (kasperYYYY@typo3.com)
+ *  (c) 2005-2010 Karsten Dambekalns <karsten@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+/**
+ * Module: Extension manager
+ *
+ * $Id: index.php 2083 2010-03-22 00:48:31Z steffenk $
+ *
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
+ * @author     Karsten Dambekalns <karsten@typo3.org>
+ * @author     Steffen Kamper <info@sk-typo3.de>
+ */
+
+$GLOBALS['LANG']->includeLLFile(t3lib_extMgm::extPath('em') . 'language/locallang.xml');
+
+// from tx_ter by Robert Lemke
+define('TX_TER_RESULT_EXTENSIONSUCCESSFULLYUPLOADED', '10504');
+
+define('EM_INSTALL_VERSION_MIN', 1);
+define('EM_INSTALL_VERSION_MAX', 2);
+define('EM_INSTALL_VERSION_STRICT', 3);
+
+unset($MCONF);
+require('conf.php');
+
+$BE_USER->modAccess($MCONF, 1);
+
+
+/**
+ * Module: Extension manager
+ *
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
+ * @author     Karsten Dambekalns <karsten@typo3.org>
+ * @package TYPO3
+ * @subpackage core
+ */
+class SC_mod_tools_em_index extends t3lib_SCbase {
+
+       // Internal, static:
+       var $versionDiffFactor = 1; // This means that version difference testing for import is detected for sub-versions only, not dev-versions. Default: 1000
+       var $systemInstall = 0; // If "1" then installs in the sysext directory is allowed. Default: 0
+       var $requiredExt = ''; // List of required extension (from TYPO3_CONF_VARS)
+       var $maxUploadSize = 31457280; // Max size in bytes of extension upload to repository
+       var $kbMax = 500; // Max size in kilobytes for files to be edited.
+       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
+       var $listingLimit = 500; // List that many extension maximally at one time (fixing memory problems)
+       var $listingLimitAuthor = 250; // List that many extension maximally at one time (fixing memory problems)
+       var $script = ''; //URL to this script
+
+
+       var $categories = array(); // Extension Categories (static var); see init()
+
+       var $states = array(); // Extension States; see init()
+
+       /**
+        * Internal variable loaded with extension categories (for display/listing). Should reflect $categories above
+        * Dynamic var.
+        */
+       var $defaultCategories = array(
+               'cat' => array(
+               'be' => array(),
+               'module' => array(),
+               'fe' => array(),
+               'plugin' => array(),
+               'misc' => array(),
+               'services' => array(),
+               'templates' => array(),
+               'example' => array(),
+               'doc' => array()
+               )
+       );
+
+       /**
+        * Colors for extension states
+        */
+       var $stateColors = array(
+               'alpha' => '#d12438',
+               'beta' => '#97b17e',
+               'stable' => '#3bb65c',
+               'experimental' => '#007eba',
+               'test' => '#979797',
+               'obsolete' => '#000000',
+               'excludeFromUpdates' => '#cf7307'
+       );
+
+       /**
+        * "TYPE" information; labels, paths, description etc. See init()
+        */
+       var $typeLabels = array();
+       var $typeDescr = array();
+       var $typeBackPaths = array(); // Also static, set in init()
+
+       var $typeRelPaths = array(
+               'S' => 'sysext/',
+               'G' => 'ext/',
+               'L' => '../typo3conf/ext/',
+       );
+
+       var $detailCols = array(
+               0 => 2,
+               1 => 5,
+               2 => 6,
+               3 => 6,
+               4 => 4,
+               5 => 1
+       );
+
+       var $fe_user = array(
+               'username' => '',
+               'password' => '',
+       );
+
+       var $privacyNotice; // Set in init()
+       var $securityHint; // Set in init()
+       var $editTextExtensions = 'html,htm,txt,css,tmpl,inc,php,sql,conf,cnf,pl,pm,sh,xml,ChangeLog';
+       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';
+
+
+       // Default variables for backend modules
+       var $MCONF = array(); // Module configuration
+       var $MOD_MENU = array(); // Module menu items
+       var $MOD_SETTINGS = array(); // Module session settings
+       /**
+        * Document Template Object
+        *
+        * @var noDoc
+        */
+       var $doc;
+       var $content; // Accumulated content
+
+       var $inst_keys = array(); // Storage of installed extensions
+       var $gzcompress = 0; // Is set true, if system support compression.
+
+       /**
+        * instance of TER connection handler
+        *
+        * @var tx_em_Connection_Ter
+        */
+       public $terConnection;
+
+       /**
+        * Develop Module
+        *
+        * @var tx_em_Develop
+        */
+       public $developModule;
+
+
+       /**
+        * XML handling class for the TYPO3 Extension Manager
+        *
+        * @var tx_em_Tools_XmlHandler
+        */
+       public $xmlhandler;
+
+
+       /**
+        * Class for printing extension lists
+        *
+        * @var tx_em_Extensions_List
+        */
+       public $extensionList;
+
+       /**
+        * Class for extension details
+        *
+        * @var tx_em_Extensions_Details
+        */
+       public $extensionDetails;
+
+       /**
+        * Class for new ExtJs Extension Manager
+        *
+        * @var tx_em_ExtensionManager
+        */
+       public $extensionmanager;
+
+       /**
+        * Class for translation handling
+        *
+        * @var tx_em_Translations
+        */
+       public $translations;
+
+       /**
+        * Class for install extensions
+        *
+        * @var tx_em_Install
+        */
+       public $install;
+
+
+       var $JScode; // JavaScript code to be forwared to $this->doc->JScode
+
+       // GPvars:
+       var $CMD = array(); // CMD array
+       var $listRemote; // If set, connects to remote repository
+       var $lookUpStr; // Search string when listing local extensions
+
+
+       /*********************************
+        *
+        * Standard module initialization
+        *
+        *********************************/
+
+       /**
+        * Standard init function of a module.
+        *
+        * @return      void
+        */
+       function init() {
+               global $BE_USER, $LANG, $BACK_PATH, $TYPO3_CONF_VARS;
+
+               /**
+                * Extension Categories (static var)
+                * Content must be redundant with the same internal variable as in class.tx_extrep.php!
+                */
+               $this->categories = array(
+                       'be' => $GLOBALS['LANG']->getLL('category_BE'),
+                       'module' => $GLOBALS['LANG']->getLL('category_BE_modules'),
+                       'fe' => $GLOBALS['LANG']->getLL('category_FE'),
+                       'plugin' => $GLOBALS['LANG']->getLL('category_FE_plugins'),
+                       'misc' => $GLOBALS['LANG']->getLL('category_miscellanous'),
+                       'services' => $GLOBALS['LANG']->getLL('category_services'),
+                       'templates' => $GLOBALS['LANG']->getLL('category_templates'),
+                       'example' => $GLOBALS['LANG']->getLL('category_examples'),
+                       'doc' => $GLOBALS['LANG']->getLL('category_documentation')
+               );
+
+               /**
+                * Extension States
+                * Content must be redundant with the same internal variable as in class.tx_extrep.php!
+                */
+               $this->states = array(
+                       'alpha' => $GLOBALS['LANG']->getLL('state_alpha'),
+                       'beta' => $GLOBALS['LANG']->getLL('state_beta'),
+                       'stable' => $GLOBALS['LANG']->getLL('state_stable'),
+                       'experimental' => $GLOBALS['LANG']->getLL('state_experimental'),
+                       'test' => $GLOBALS['LANG']->getLL('state_test'),
+                       'obsolete' => $GLOBALS['LANG']->getLL('state_obsolete'),
+                       'excludeFromUpdates' => $GLOBALS['LANG']->getLL('state_exclude_from_updates')
+               );
+
+               /**
+                * "TYPE" information; labels, paths, description etc.
+                */
+               $this->typeLabels = array(
+                       'S' => $GLOBALS['LANG']->getLL('type_system'),
+                       'G' => $GLOBALS['LANG']->getLL('type_global'),
+                       'L' => $GLOBALS['LANG']->getLL('type_local'),
+               );
+               $this->typeDescr = array(
+                       'S' => $GLOBALS['LANG']->getLL('descr_system'),
+                       'G' => $GLOBALS['LANG']->getLL('descr_global'),
+                       'L' => $GLOBALS['LANG']->getLL('descr_local'),
+               );
+
+
+               $this->typeBackPaths = array(
+                       'S' => '../../../',
+                       'G' => '../../../',
+                       'L' => '../../../../' . TYPO3_mainDir
+               );
+
+               $this->script = 'mod.php?M=tools_em';
+               $this->privacyNotice = $GLOBALS['LANG']->getLL('privacy_notice');
+               $securityMessage = $GLOBALS['LANG']->getLL('security_warning_extensions') .
+                               '<br /><br />' . sprintf($GLOBALS['LANG']->getLL('security_descr'),
+                       '<a href="http://typo3.org/teams/security/" target="_blank">', '</a>'
+               );
+               $flashMessage = t3lib_div::makeInstance(
+                       't3lib_FlashMessage',
+                       $securityMessage,
+                       $GLOBALS['LANG']->getLL('security_header'),
+                       t3lib_FlashMessage::INFO
+               );
+               $this->securityHint = $flashMessage->render();
+
+               $this->excludeForPackaging = $GLOBALS['TYPO3_CONF_VARS']['EXT']['excludeForPackaging'];
+
+               // Setting module configuration:
+               $this->MCONF = $GLOBALS['MCONF'];
+
+               // Setting GPvars:
+               $this->CMD = is_array(t3lib_div::_GP('CMD')) ? t3lib_div::_GP('CMD') : array();
+               $this->lookUpStr = trim(t3lib_div::_GP('lookUp'));
+               $this->listRemote = t3lib_div::_GP('ter_connect');
+               $this->listRemote_search = trim(t3lib_div::_GP('ter_search'));
+
+               $this->settings = t3lib_div::makeInstance('tx_em_Settings');
+               $this->install = t3lib_div::makeInstance('tx_em_Install', $this);
+
+               // Configure menu
+               $this->menuConfig();
+
+               // Setting internal static:
+
+               $this->requiredExt = t3lib_div::trimExplode(',', $TYPO3_CONF_VARS['EXT']['requiredExt'], 1);
+
+               // Initialize Document Template object:
+               $this->doc = t3lib_div::makeInstance('template');
+               $this->doc->backPath = $BACK_PATH;
+               $this->doc->setModuleTemplate('templates/em_index.html');
+
+               // Initialize helper objects
+               $this->terConnection = t3lib_div::makeInstance('tx_em_Connection_Ter', $this);
+               $this->terConnection->wsdlURL = $TYPO3_CONF_VARS['EXT']['em_wsdlURL'];
+
+
+               $this->xmlhandler = t3lib_div::makeInstance('tx_em_Tools_XmlHandler');
+               $this->xmlhandler->emObj = $this;
+               $this->xmlhandler->useObsolete = $this->MOD_SETTINGS['display_obsolete'];
+
+
+               // Initialize newListing
+               if (isset($this->MOD_MENU['function']['extensionmanager'])) {
+                       $this->extensionmanager = t3lib_div::makeInstance('tx_em_ExtensionManager', $this);
+               } else {
+                       $this->extensionmanager = &$this;
+               }
+
+               // Initialize develop module
+               if (isset($this->MOD_MENU['function']['develop'])) {
+                       $this->developModule = t3lib_div::makeInstance('tx_em_Develop', $this);
+               } else {
+                       $this->developModule = &$this;
+               }
+
+
+
+               // Output classes
+               $this->extensionList = t3lib_div::makeInstance('tx_em_Extensions_List', $this);
+               $this->extensionDetails = t3lib_div::makeInstance('tx_em_Extensions_Details', $this);
+               $this->translations = t3lib_div::makeInstance('tx_em_Translations', $this);
+
+
+               // the id is needed for getting same styles TODO: general table styles
+               $this->doc->bodyTagId = 'typo3-mod-tools-em-index-php';
+
+               // JavaScript
+               $this->doc->JScode = $this->doc->wrapScriptTags('
+                       script_ended = 0;
+                       function jumpToUrl(URL) {       //
+                               window.location.href = URL;
+                       }
+               ');
+
+               // Reload left frame menu
+               if ($this->CMD['refreshMenu']) {
+                       $this->doc->JScode .= $this->doc->wrapScriptTags('
+                               if(top.refreshMenu) {
+                                       top.refreshMenu();
+                               } else {
+                                       top.TYPO3ModuleMenu.refreshMenu();
+                               }
+                       ');
+               }
+
+
+               // Descriptions:
+               $this->descrTable = '_MOD_' . $this->MCONF['name'];
+               if ($BE_USER->uc['edit_showFieldHelp']) {
+                       $LANG->loadSingleTableDescription($this->descrTable);
+               }
+
+               // Setting username/password etc. for upload-user:
+               $this->fe_user['username'] = $this->MOD_SETTINGS['fe_u'];
+               $this->fe_user['password'] = $this->MOD_SETTINGS['fe_p'];
+               parent::init();
+               $this->handleExternalFunctionValue('singleDetails');
+       }
+
+       /**
+        * This function is a copy of the same function in t3lib_SCbase with one modification:
+        * In contrast to t3lib_SCbase::handleExternalFunctionValue() this function merges the $this->extClassConf array
+        * instead of overwriting it. That was necessary for including the Kickstarter as a submodule into the 'singleDetails'
+        * selectorbox as well as in the main 'function' selectorbox.
+        *
+        * @param       string          Mod-setting array key
+        * @param       string          Mod setting value, overriding the one in the key
+        * @return      void
+        * @see t3lib_SCbase::handleExternalFunctionValue()
+        */
+       function handleExternalFunctionValue($MM_key = 'function', $MS_value = NULL) {
+               $MS_value = is_null($MS_value) ? $this->MOD_SETTINGS[$MM_key] : $MS_value;
+               $externalItems = $this->getExternalItemConfig($this->MCONF['name'], $MM_key, $MS_value);
+               if (is_array($externalItems)) {
+                       $this->extClassConf = array_merge($externalItems, is_array($this->extClassConf) ? $this->extClassConf : array());
+               }
+               if (is_array($this->extClassConf) && $this->extClassConf['path']) {
+                       $this->include_once[] = $this->extClassConf['path'];
+               }
+       }
+
+       /**
+        * Configuration of which mod-menu items can be used
+        *
+        * @return      void
+        */
+       function menuConfig() {
+                       // MENU-ITEMS:
+               $this->MOD_MENU = $this->settings->MOD_MENU;
+
+               // temporary unset new modules
+               unset ($this->MOD_MENU['function']['extensionmanager'], $this->MOD_MENU['function']['develop']);
+
+
+               $this->MOD_MENU['singleDetails'] = $this->mergeExternalItems($this->MCONF['name'], 'singleDetails', $this->MOD_MENU['singleDetails']);
+
+                       // temporary set main repository
+               //$changed = array_merge((array) t3lib_div::_GP('SET'), array('selectedRepository' => '1'));
+
+
+                       // page/be_user TSconfig settings and blinding of menu-items
+               if (!$GLOBALS['BE_USER']->getTSConfigVal('mod.' . $this->MCONF['name'] . '.allowTVlisting')) {
+                       unset($this->MOD_MENU['display_details'][3]);
+                       unset($this->MOD_MENU['display_details'][4]);
+                       unset($this->MOD_MENU['display_details'][5]);
+               }
+
+                       // CLEANSE SETTINGS
+               $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']);
+
+
+               if ($this->MOD_SETTINGS['function'] == 2) {
+                       // If listing from online repository, certain items are removed though:
+                       unset($this->MOD_MENU['listOrder']['type']);
+                       unset($this->MOD_MENU['display_details'][2]);
+                       unset($this->MOD_MENU['display_details'][3]);
+                       unset($this->MOD_MENU['display_details'][4]);
+                       unset($this->MOD_MENU['display_details'][5]);
+                       $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']);
+               }
+
+               $this->settings->saveSettings($this->MOD_SETTINGS);
+               parent::menuConfig();
+
+               $this->settings->saveSettings($this->MOD_SETTINGS);
+       }
+
+       /**
+        * Main function for Extension Manager module.
+        *
+        * @return      void
+        */
+       function main() {
+               global $BE_USER, $LANG, $TYPO3_CONF_VARS;
+
+               if (empty($this->MOD_SETTINGS['mirrorListURL'])) {
+                       $this->MOD_SETTINGS['mirrorListURL'] = $TYPO3_CONF_VARS['EXT']['em_mirrorListURL'];
+               }
+
+               // Starting page:
+               $this->content .= $this->doc->header($GLOBALS['LANG']->getLL('header'));
+
+               // Command given which is executed regardless of main menu setting:
+               if ($this->CMD['showExt']) { // Show details for a single extension
+                       $this->showExtDetails($this->CMD['showExt']);
+               } elseif ($this->CMD['requestInstallExtensions']) { // Show details for a single extension
+                       $this->requestInstallExtensions($this->CMD['requestInstallExtensions']);
+               } elseif ($this->CMD['importExt'] || $this->CMD['uploadExt']) { // Imports an extension from online rep.
+                       $err = $this->importExtFromRep($this->CMD['importExt'], $this->CMD['extVersion'], $this->CMD['loc'], $this->CMD['uploadExt']);
+                       if ($err) {
+                               $this->content .= $this->doc->section('', $GLOBALS['TBE_TEMPLATE']->rfw($err));
+                       }
+                       if (!$err && $this->CMD['importExt']) {
+                               $this->translations->installTranslationsForExtension($this->CMD['importExt'], $this->getMirrorURL());
+                       }
+               } elseif ($this->CMD['importExtInfo']) { // Gets detailed information of an extension from online rep.
+                       $this->importExtInfo($this->CMD['importExtInfo'], $this->CMD['extVersion']);
+               } else { // No command - we show what the menu setting tells us:
+                       if (t3lib_div::inList('loaded_list,installed_list,import', $this->MOD_SETTINGS['function'])) {
+                               $menu .= '&nbsp;' . $GLOBALS['LANG']->getLL('group_by') . '&nbsp;' . t3lib_BEfunc::getFuncMenu(0, 'SET[listOrder]', $this->MOD_SETTINGS['listOrder'], $this->MOD_MENU['listOrder']) .
+                                       '&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 />';
+                       }
+                       if (t3lib_div::inList('loaded_list,installed_list,updates', $this->MOD_SETTINGS['function'])) {
+                               $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"');
+                       }
+                       if (t3lib_div::inList('import', $this->MOD_SETTINGS['function']) && strlen($this->fe_user['username'])) {
+                               $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"');
+                       }
+                       if (t3lib_div::inList('loaded_list,installed_list,import', $this->MOD_SETTINGS['function'])) {
+                               $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"');
+                       }
+
+                       $this->content .= $menu ? $this->doc->section('', '<form action="' . $this->script . '" method="post" name="pageform"><span class="nobr">' . $menu . '</span></form>') : '';
+
+                       switch ($this->MOD_SETTINGS['function']) {
+                               case 'loaded_list':
+                                       // Lists loaded (installed) extensions
+                                       $headline = $GLOBALS['LANG']->getLL('loaded_exts');
+                                       $headline = t3lib_BEfunc::wrapInHelp('_MOD_tools_em', 'loaded', $headline);
+                                       $content = $this->extensionList->extensionList_loaded();
+
+                                       $this->content .= $this->doc->section($headline, $content, FALSE, TRUE, FALSE, TRUE);
+                                       break;
+                               case 'installed_list':
+                                       // Lists the installed (available) extensions
+                                       $headline = sprintf($GLOBALS['LANG']->getLL('available_extensions'), $this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']]);
+                                       $headline = t3lib_BEfunc::wrapInHelp('_MOD_tools_em', 'avail', $headline);
+                                       $content = $this->extensionList->extensionList_installed();
+
+                                       $this->content .= $this->doc->section($headline, $content, FALSE, TRUE, FALSE, TRUE);
+                                       break;
+                               case 'import':
+                                       // Lists the extensions available from online rep.
+                                       $this->extensionList_import();
+                                       break;
+                               case 'settings':
+                                       // Shows the settings screen
+                                       $headline = $GLOBALS['LANG']->getLL('repository_settings');
+                                       $headline = t3lib_BEfunc::wrapInHelp('_MOD_tools_em', 'settings', $headline);
+                                       $content = $this->alterSettings();
+
+                                       $this->content .= $this->doc->section($headline, $content, FALSE, TRUE, FALSE, TRUE);
+                                       break;
+                               case 'translations':
+                                       // Allows to set the translation preferences and check the status
+                                       $this->translations->translationHandling();
+                                       break;
+                               case 'updates':
+                                       // Shows a list of extensions with updates in TER
+                                       $this->checkForUpdates();
+                                       break;
+                               case 'develop':
+                                       $this->content .= $this->developModule->renderModule();
+                                       break;
+                               default:
+                               case 'extensionmanager':
+                                       $this->content .= $this->extensionmanager->render();
+                                       break;
+                               default:
+                                       $this->extObjContent();
+                                       break;
+                       }
+               }
+
+                       // closing any form?
+               $formTags = substr_count($this->content, '<form') + substr_count($this->content, '</form');
+               if ($formTags % 2 > 0) {
+                       $this->content .= '</form>';
+               }
+
+               // Setting up the buttons and markers for docheader
+               $docHeaderButtons = $this->getButtons();
+               $markers = array(
+                       'CSH' => $docHeaderButtons['csh'],
+                       'FUNC_MENU' => $this->getFuncMenu(),
+                       'CONTENT' => $this->content
+               );
+
+               // Build the <body> for the module
+               $this->content = $this->doc->startPage('Extension Manager');
+               $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
+               $this->content .= $this->doc->endPage();
+               $this->content = $this->doc->insertStylesAndJS($this->content);
+       }
+
+       /**
+        * Print module content. Called as last thing in the global scope.
+        *
+        * @return      void
+        */
+       function printContent() {
+               if ($this->doPrintContent) {
+                       echo $this->content;
+               }
+       }
+
+       /**
+        * Create the function menu
+        *
+        * @return      string  HTML of the function menu
+        */
+       public function getFuncMenu() {
+               $funcMenu = '';
+               if (!$this->CMD['showExt'] && !$this->CMD['requestInstallExtensions'] && !$this->CMD['importExt'] && !$this->CMD['uploadExt'] && !$this->CMD['importExtInfo']) {
+                       $funcMenu = t3lib_BEfunc::getFuncMenu(0, 'SET[function]', $this->MOD_SETTINGS['function'], $this->MOD_MENU['function']);
+               } elseif ($this->CMD['showExt'] && (!$this->CMD['standAlone'] && !t3lib_div::_GP('standAlone'))) {
+                       $funcMenu = t3lib_BEfunc::getFuncMenu(0, 'SET[singleDetails]', $this->MOD_SETTINGS['singleDetails'], $this->MOD_MENU['singleDetails'], '', '&CMD[showExt]=' . $this->CMD['showExt']);
+               }
+               return $funcMenu;
+       }
+
+       /**
+        * Create the panel of buttons for submitting the form or otherwise perform operations.
+        *
+        * @return      array   all available buttons as an assoc. array
+        */
+       public function getButtons() {
+
+               $buttons = array(
+                       'csh' => '',
+                       'back' => '',
+                       'shortcut' => ''
+               );
+
+               // Shortcut
+               if ($GLOBALS['BE_USER']->mayMakeShortcut()) {
+                       $buttons['shortcut'] = $this->doc->makeShortcutIcon('CMD', 'function', $this->MCONF['name']);
+               }
+               // Back
+               if (($this->CMD['showExt'] && (!$this->CMD['standAlone'] && !t3lib_div::_GP('standAlone'))) || ($this->CMD['importExt'] || $this->CMD['uploadExt'] && (!$this->CMD['standAlone'])) || $this->CMD['importExtInfo']) {
+                       $buttons['back'] = '<a href="' . t3lib_div::linkThisScript(array(
+                               'CMD' => ''
+                       )) . '" class="typo3-goBack" title="' . $GLOBALS['LANG']->getLL('go_back') . '">' .
+                                       t3lib_iconWorks::getSpriteIcon('actions-view-go-back') .
+                                       '</a>';
+               }
+
+               return $buttons;
+       }
+
+
+       /*********************************
+        *
+        * Function Menu Applications
+        *
+        *********************************/
+
+
+       /**
+        * Listing remote extensions from online repository
+        *
+        * @return      void
+        */
+       function extensionList_import() {
+               global $TYPO3_LOADED_EXT;
+               $content = '';
+
+               // Listing from online repository:
+               if ($this->listRemote) {
+                       list($inst_list,) = $this->extensionList->getInstalledExtensions();
+                       $this->inst_keys = array_flip(array_keys($inst_list));
+
+                       $this->detailCols[1] += 6;
+
+                       // see if we have an extensionlist at all
+                       $this->extensionCount = $this->xmlhandler->countExtensions();
+                       if (!$this->extensionCount) {
+                               $content .= $this->fetchMetaData('extensions');
+                       }
+
+                       if ($this->MOD_SETTINGS['listOrder'] == 'author_company') {
+                               $this->listingLimit = $this->listingLimitAuthor;
+                       }
+
+                       $this->pointer = intval(t3lib_div::_GP('pointer'));
+                       $offset = $this->listingLimit * $this->pointer;
+
+                       if ($this->MOD_SETTINGS['display_own'] && strlen($this->fe_user['username'])) {
+                               $this->xmlhandler->searchExtensionsXML($this->listRemote_search, $this->fe_user['username'], $this->MOD_SETTINGS['listOrder'], TRUE);
+                       } else {
+                               $this->xmlhandler->searchExtensionsXML($this->listRemote_search, '', $this->MOD_SETTINGS['listOrder'], TRUE, FALSE, $offset, $this->listingLimit);
+                       }
+                       if (count($this->xmlhandler->extensionsXML)) {
+                               list($list, $cat) = $this->extensionList->prepareImportExtList(true);
+
+                               // Available extensions
+                               if (is_array($cat[$this->MOD_SETTINGS['listOrder']])) {
+                                       $lines = array();
+                                       $lines[] = $this->extensionList->extensionListRowHeader(' class="t3-row-header"', array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>'), 1);
+
+                                       foreach ($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys) {
+                                               if (count($extEkeys)) {
+                                                       $lines[] = '<tr><td colspan="' . (3 + $this->detailCols[$this->MOD_SETTINGS['display_details']]) . '"><br /></td></tr>';
+                                                       $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>';
+                                                       natcasesort($extEkeys);
+                                                       foreach ($extEkeys as $extKey => $value) {
+                                                               $version = array_keys($list[$extKey]['versions']);
+                                                               $version = end($version);
+                                                               $ext = $list[$extKey]['versions'][$version];
+                                                               $ext['downloadcounter_all'] = $list[$extKey]['downloadcounter'];
+                                                               $ext['_ICON'] = $list[$extKey]['_ICON'];
+                                                               $loadUnloadLink = '';
+                                                               if ($inst_list[$extKey]['type'] != 'S' && (!isset($inst_list[$extKey]) || tx_em_Tools::versionDifference($version, $inst_list[$extKey]['EM_CONF']['version'], $this->versionDiffFactor))) {
+                                                                       if (isset($inst_list[$extKey])) {
+                                                                               // update
+                                                                               if ($inst_list[$extKey]['EM_CONF']['state'] != 'excludeFromUpdates') {
+                                                                                       $loc = ($inst_list[$extKey]['type'] == 'G' ? 'G' : 'L');
+                                                                                       $aUrl = t3lib_div::linkThisScript(array(
+                                                                                               'CMD[importExt]' => $extKey,
+                                                                                               'CMD[extVersion]' => $version,
+                                                                                               'CMD[loc]' => $loc
+                                                                                       ));
+                                                                                       $loadUnloadLink .= '<a href="' . htmlspecialchars($aUrl) . '" title="' . sprintf($GLOBALS['LANG']->getLL('do_update'), ($loc == 'G' ? $GLOBALS['LANG']->getLL('global') : $GLOBALS['LANG']->getLL('local'))) . '">' .
+                                                                                                       t3lib_iconWorks::getSpriteIcon('actions-system-extension-update') .
+                                                                                                       '</a>';
+                                                                               } else {
+                                                                                       // extension is marked as "excludeFromUpdates"
+                                                                                       $loadUnloadLink .= t3lib_iconWorks::getSpriteIcon('status-dialog-warning', $GLOBALS['LANG']->getLL('excluded_from_updates'));
+                                                                               }
+                                                                       } else {
+                                                                               // import
+                                                                               $aUrl = t3lib_div::linkThisScript(array(
+                                                                                       'CMD[importExt]' => $extKey,
+                                                                                       'CMD[extVersion]' => $version,
+                                                                                       'CMD[loc]' => 'L'
+                                                                               ));
+                                                                               $loadUnloadLink .= '<a href="' . htmlspecialchars($aUrl) . '" title="' . $GLOBALS['LANG']->getLL('import_to_local_dir') . '">' . t3lib_iconWorks::getSpriteIcon('actions-system-extension-import') . '</a>';
+                                                                       }
+                                                               } else {
+                                                                       $loadUnloadLink = '&nbsp;';
+                                                               }
+
+                                                               if (isset($inst_list[$extKey])) {
+                                                                       $theRowClass = t3lib_extMgm::isLoaded($extKey) ? 'em-listbg1' : 'em-listbg2';
+                                                               } else {
+                                                                       $theRowClass = 'em-listbg3';
+                                                               }
+
+                                                               $lines[] = $this->extensionList->extensionListRow(
+                                                                       $extKey, $ext, array(
+                                                                       '<td class="bgColor">' . $loadUnloadLink . '</td>'
+                                                               ), $theRowClass, $inst_list, 1, t3lib_div::linkThisScript(array(
+                                                                       'CMD[importExtInfo]' => rawurlencode($extKey)
+                                                               )));
+                                                               unset($list[$extKey]);
+                                                       }
+                                               }
+                                       }
+                                       unset($list);
+
+                                       // headline and CSH
+                                       $headline = $GLOBALS['LANG']->getLL('extensions_repository_group_by') . ' ' .
+                                                       $this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']];
+                                       $headline = t3lib_BEfunc::wrapInHelp('_MOD_tools_em', 'import_ter', $headline);
+
+                                       $onsubmit = "window.location.href='" . $this->script . "&ter_connect=1&ter_search='+escape(this.elements['lookUp'].value);return false;";
+                                       $content .= '<form action="' . $this->script . '" method="post" onsubmit="' . htmlspecialchars($onsubmit) .
+                                                       '"><label for="lookUp">' . $GLOBALS['LANG']->getLL('list_or_look_up_extensions') . '</label><br />
+                                                       <input type="text" id="lookUp" name="lookUp" value="' . htmlspecialchars($this->listRemote_search) .
+                                                       '" /> <input type="submit" value="' . $GLOBALS['LANG']->getLL('look_up_button') . '" /></form><br /><br />';
+
+                                       $content .= $this->browseLinks();
+
+                                       $content .= '
+
+                                       <!-- TER Extensions list -->
+                                       <table border="0" cellpadding="2" cellspacing="1">' . implode(LF, $lines) . '</table>';
+                                       $content .= '<br />' . $this->browseLinks();
+                                       $content .= '<br /><br />' . $this->securityHint;
+                                       $content .= '<br /><br /><strong>' . $GLOBALS['LANG']->getLL('privacy_notice_header') .
+                                                       '</strong><br /> ' . $this->privacyNotice;
+
+                                       $this->content .= $this->doc->section($headline, $content, FALSE, TRUE, FALSE, TRUE);
+
+                                       // Plugins which are NOT uploaded to repository but present on this server.
+                                       $content = '';
+                                       $lines = array();
+                                       if (count($this->inst_keys)) {
+                                               foreach ($this->inst_keys as $extKey => $value) {
+                                                       $this->xmlhandler->searchExtensionsXMLExact($extKey, '', '', TRUE, TRUE);
+                                                       if ((strlen($this->listRemote_search) && !stristr($extKey, $this->listRemote_search)) || isset($this->xmlhandler->extensionsXML[$extKey])) {
+                                                               continue;
+                                                       }
+
+                                                       $loadUnloadLink = t3lib_extMgm::isLoaded($extKey) ?
+                                                                       '<a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
+                                                                               'CMD[showExt]' => $extKey,
+                                                                               'CMD[remove]' => 1,
+                                                                               'CMD[clrCmd]' => 1,
+                                                                               'SET[singleDetails]' => 'info'
+                                                                       ))) . '">' . tx_em_Tools::removeButton() . '</a>' :
+                                                                       '<a href="' . htmlspecialchars(t3lib_div::linkThisScript(array(
+                                                                               'CMD[showExt]' => $extKey,
+                                                                               'CMD[load]' => 1,
+                                                                               'CMD[clrCmd]' => 1,
+                                                                               'SET[singleDetails]' => 'info'
+                                                                       ))) . '">' . tx_em_Tools::installButton() . '</a>';
+                                                       if (in_array($extKey, $this->requiredExt)) {
+                                                               $loadUnloadLink = '<strong>' . $GLOBALS['TBE_TEMPLATE']->rfw($GLOBALS['LANG']->getLL('extension_required_short')) . '</strong>';
+                                                       }
+                                                       $lines[] = $this->extensionList->extensionListRow($extKey, $inst_list[$extKey], array('<td class="bgColor">' . $loadUnloadLink . '</td>'), t3lib_extMgm::isLoaded($extKey) ? 'em-listbg1' : 'em-listbg2');
+                                               }
+                                       }
+                                       if (count($lines)) {
+                                               $content .= $GLOBALS['LANG']->getLL('list_of_local_extensions') .
+                                                               '<br />' . $GLOBALS['LANG']->getLL('might_be_user_defined') . '<br /><br />';
+                                               $content .= '<table border="0" cellpadding="2" cellspacing="1">' .
+                                                               $this->extensionList->extensionListRowHeader(' class="t3-row-header"', array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>')) .
+                                                               implode('', $lines) . '</table>';
+                                               $this->content .= $this->doc->spacer(20);
+                                               $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('only_on_this_server'), $content, 0, 1);
+                                       }
+                               }
+                       } else {
+                               // headline and CSH
+                               $headline = $GLOBALS['LANG']->getLL('extensions_repository_group_by') . ' ' .
+                                               $this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']];
+                               $headline = t3lib_BEfunc::wrapInHelp('_MOD_tools_em', 'import_ter', $headline);
+
+                               $onsubmit = "window.location.href='" . $this->script . "&ter_connect=1&ter_search='+escape(this.elements['lookUp'].value);return false;";
+                               $content .= '<form action="' . $this->script . '" method="post" onsubmit="' . htmlspecialchars($onsubmit) .
+                                               '"><label for="lookUp">' .
+                                               $GLOBALS['LANG']->getLL('list_or_look_up_extensions') . '</label><br />
+                                       <input type="text" id="lookUp" name="lookUp" value="' . htmlspecialchars($this->listRemote_search) .
+                                               '" /> <input type="submit" value="' . $GLOBALS['LANG']->getLL('look_up_button') . '" /></form><br /><br />';
+
+                               $content .= '<p><strong>' . $GLOBALS['LANG']->getLL('no_matching_extensions') . '</strong></p>';
+
+                               $content .= '<br /><br /><strong>' . $GLOBALS['LANG']->getLL('privacy_notice_header') .
+                                               '</strong><br /> ' . $this->privacyNotice;
+                               $this->content .= $this->doc->section($headline, $content, FALSE, TRUE);
+                       }
+               } else {
+                       // section headline and CSH
+                       $headline = $GLOBALS['LANG']->getLL('in_repository');
+                       $headline = t3lib_BEfunc::wrapInHelp('_MOD_tools_em', 'import', $headline);
+
+                       $onsubmit = "window.location.href='" . $this->script . "&ter_connect=1&ter_search='+escape(this.elements['lookUp'].value);return false;";
+                       $content .= '<form action="' . $this->script . '" method="post" onsubmit="' . htmlspecialchars($onsubmit) .
+                                       '"><label for="lookUp">' .
+                                       $GLOBALS['LANG']->getLL('list_or_look_up_extensions') . '</label><br />
+                               <input type="text" id="lookUp" name="lookUp" value="" /> <input type="submit" value="' .
+                                       $GLOBALS['LANG']->getLL('look_up_button') . '" /><br /><br />';
+
+                       if ($this->CMD['fetchMetaData']) { // fetches mirror/extension data from online rep.
+                               $content .= $this->fetchMetaData($this->CMD['fetchMetaData']);
+                       } else {
+                               $onCLick = 'window.location.href="' . t3lib_div::linkThisScript(array(
+                                       'CMD[fetchMetaData]' => 'extensions'
+                               )) . '";return false;';
+                               $content .= $GLOBALS['LANG']->getLL('connect_to_ter') . '<br />
+                                       <input type="submit" value="' . $GLOBALS['LANG']->getLL('retrieve_update') .
+                                               '" onclick="' . htmlspecialchars($onCLick) . '" />';
+                               if (is_file(PATH_site . 'typo3temp/extensions.xml.gz')) {
+                                       $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'];
+                                       $timeFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
+                                       $content .= ' ' . sprintf($GLOBALS['LANG']->getLL('ext_list_last_updated') . ' ',
+                                               date(
+                                                       $dateFormat . ', ' . $timeFormat,
+                                                       filemtime(PATH_site . 'typo3temp/extensions.xml.gz')
+                                               ),
+                                               tx_em_Database::getExtensionCountFromRepository()
+                                       );
+                               }
+                       }
+                       $content .= '</form><br /><br />' . $this->securityHint;
+                       $content .= '<br /><br /><strong>' . $GLOBALS['LANG']->getLL('privacy_notice_header') .
+                                       '</strong><br />' . $this->privacyNotice;
+
+                       $this->content .= $this->doc->section($headline, $content, FALSE, TRUE, FALSE, TRUE);
+               }
+
+               // Upload:
+               if ($this->importAtAll()) {
+                       $content = '<form action="' . $this->script . '" enctype="' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'] . '" method="post">
+                       <label for="upload_ext_file">' . $GLOBALS['LANG']->getLL('upload_t3x') . '</label><br />
+                               <input type="file" size="60" id="upload_ext_file" name="upload_ext_file" /><br />' .
+                                       $GLOBALS['LANG']->getLL('upload_to_location') . '<br />
+                               <select name="CMD[loc]">';
+                       if (tx_em_Tools::importAsType('L')) {
+                               $content .= '<option value="L">' . $GLOBALS['LANG']->getLL('local_folder') . '</option>';
+                       }
+                       if (tx_em_Tools::importAsType('G')) {
+                               $content .= '<option value="G">' . $GLOBALS['LANG']->getLL('global_folder') . '</option>';
+                       }
+                       if (tx_em_Tools::importAsType('S')) {
+                               $content .= '<option value="S">' . $GLOBALS['LANG']->getLL('system_folder') . '</option>';
+                       }
+                       $content .= '</select><br />
+       <input type="checkbox" value="1" name="CMD[uploadOverwrite]" id="checkUploadOverwrite" /> <label for="checkUploadOverwrite">' .
+                                       $GLOBALS['LANG']->getLL('overwrite_ext') . '</label><br />
+       <input type="submit" name="CMD[uploadExt]" value="' . $GLOBALS['LANG']->getLL('upload_ext_file') . '" /></form><br />
+                       ';
+               } else {
+                       $content = tx_em_Tools::noImportMsg();
+               }
+
+               $this->content .= $this->doc->spacer(20);
+               $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('upload_ext_directly'), $content, 0, 1);
+       }
+
+       /**
+        * Generates a link to the next page of extensions
+        *
+        * @return      void
+        */
+       function browseLinks() {
+               $content = '';
+               if ($this->pointer) {
+                       $content .= '<a href="' . t3lib_div::linkThisScript(array('pointer' => $this->pointer - 1)) .
+                                       '" class="typo3-prevPage"><img' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],
+                               'gfx/pilleft_n.gif', 'width="14" height="14"') .
+                                       ' alt="' . $GLOBALS['LANG']->getLL('previous_page') . '" /> ' .
+                                       $GLOBALS['LANG']->getLL('previous_page') . '</a>';
+               }
+               if ($content) {
+                       $content .= '&nbsp;&nbsp;&nbsp;';
+               }
+               if (intval($this->xmlhandler->matchingCount / $this->listingLimit) > $this->pointer) {
+                       $content .= '<a href="' . t3lib_div::linkThisScript(array('pointer' => $this->pointer + 1)) .
+                                       '" class="typo3-nextPage"><img' . t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],
+                               'gfx/pilright_n.gif', 'width="14" height="14"') .
+                                       ' alt="' . $GLOBALS['LANG']->getLL('next_page') . '" /> ' .
+                                       $GLOBALS['LANG']->getLL('next_page') . '</a>';
+               }
+               $upper = (($this->pointer + 1) * $this->listingLimit);
+               if ($upper > $this->xmlhandler->matchingCount) {
+                       $upper = $this->xmlhandler->matchingCount;
+               }
+               if ($content) {
+                       $content .= '<br /><br />' .
+                                       sprintf($GLOBALS['LANG']->getLL('showing_extensions_from_to'),
+                                                       '<strong>' . ($this->pointer * $this->listingLimit + 1) . '</strong>',
+                                                       '<strong>' . $upper . '</strong>'
+                                       );
+               }
+               if ($content) {
+                       $content .= '<br /><br />';
+               }
+               return $content;
+       }
+
+       /**
+        * Allows changing of settings
+        *
+        * @return      void
+        */
+       function alterSettings() {
+
+               // Prepare the HTML output:
+               $content .= '
+                       <form action="' . $this->script . '" method="post" name="altersettings">
+                       <fieldset><legend>' . $GLOBALS['LANG']->getLL('user_settings') . '</legend>
+                       <table border="0" cellpadding="2" cellspacing="2">
+                               <tr class="bgColor4">
+                                       <td><label for="set_fe_u">' . $GLOBALS['LANG']->getLL('enter_repository_username') . '</label></td>
+                                       <td><input type="text" id="set_fe_u" name="SET[fe_u]" value="' . htmlspecialchars($this->MOD_SETTINGS['fe_u']) . '" /></td>
+                               </tr>
+                               <tr class="bgColor4">
+                                       <td><label for="set_fe_p">' . $GLOBALS['LANG']->getLL('enter_repository_password') . '</label></td>
+                                       <td><input type="password" id="set_fe_p" name="SET[fe_p]" value="' . htmlspecialchars($this->MOD_SETTINGS['fe_p']) . '" /></td>
+                               </tr>
+                       </table>
+                       <strong>' . $GLOBALS['LANG']->getLL('notice') . '</strong> ' .
+                               $GLOBALS['LANG']->getLL('repository_password_info') . '
+                       </fieldset>
+                       <br />
+                       <br />
+                       <fieldset><legend>' . $GLOBALS['LANG']->getLL('mirror_selection') . '</legend>
+                       <table border="0" cellpadding="2" cellspacing="2">
+                               <tr class="bgColor4">
+                                       <td><label for="set_mirror_list_url">' . $GLOBALS['LANG']->getLL('mirror_list_url') . '</label></td>
+                                       <td><input type="text" size="50" id="set_mirror_list_url" name="SET[mirrorListURL]" value="' . htmlspecialchars($this->MOD_SETTINGS['mirrorListURL']) . '" /></td>
+                               </tr>
+                       </table>
+                       </fieldset>
+                       <br />
+                       <p>' . $GLOBALS['LANG']->getLL('mirror_select') . '<br /><br /></p>
+                       <fieldset><legend>' . $GLOBALS['LANG']->getLL('mirror_list') . '</legend>';
+               if (!empty($this->MOD_SETTINGS['mirrorListURL'])) {
+                       if ($this->CMD['fetchMetaData']) { // fetches mirror/extension data from online rep.
+                               $content .= $this->fetchMetaData($this->CMD['fetchMetaData']);
+                       } else {
+                               $content .= '<a href="' . t3lib_div::linkThisScript(array(
+                                       'CMD[fetchMetaData]' => 'mirrors'
+                               )) . '">' . $GLOBALS['LANG']->getLL('mirror_list_reload') . '</a>';
+                       }
+               }
+               $content .= '<br />
+                       <table cellspacing="4" style="text-align:left; vertical-alignment:top;">
+                       <tr>
+                               <td>' . $GLOBALS['LANG']->getLL('mirror_use') . '</td>
+                               <td>' . $GLOBALS['LANG']->getLL('mirror_name') . '</td>
+                               <td>' . $GLOBALS['LANG']->getLL('mirror_url') . '</td>
+                               <td>' . $GLOBALS['LANG']->getLL('mirror_country') . '</td>
+                               <td>' . $GLOBALS['LANG']->getLL('mirror_sponsored_by') . '</td>
+                       </tr>
+               ';
+
+               if (!strlen($this->MOD_SETTINGS['extMirrors'])) {
+                       $this->fetchMetaData('mirrors');
+               }
+               $extMirrors = unserialize($this->MOD_SETTINGS['extMirrors']);
+               $extMirrors[''] = array('title' => $GLOBALS['LANG']->getLL('mirror_use_random'));
+               ksort($extMirrors);
+               if (is_array($extMirrors)) {
+                       foreach ($extMirrors as $k => $v) {
+                               if (isset($v['sponsor'])) {
+                                       $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>';
+                               }
+                               $selected = ($this->MOD_SETTINGS['selectedMirror'] == $k) ? 'checked="checked"' : '';
+                               $content .= '<tr class="bgColor4">
+                       <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>';
+                       }
+               }
+               $content .= '
+                       </table>
+                       </fieldset>
+                       <fieldset>
+                       <br />
+                       <table border="0" cellpadding="2" cellspacing="2">
+                               <tr class="bgColor4">
+                                       <td><label for="set_rep_url">' . $GLOBALS['LANG']->getLL('enter_repository_url') . '</label></td>
+                                       <td><input type="text" size="50" id="set_rep_url" name="SET[rep_url]" value="' . htmlspecialchars($this->MOD_SETTINGS['rep_url']) . '" /></td>
+                               </tr>
+                       </table>
+
+                       ' . $GLOBALS['LANG']->getLL('repository_url_hint') . '<br />
+                       </fieldset>
+                       <br />
+                       <input type="submit" value="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_tsfe.xml:update') . '" />
+                       </form>
+               ';
+
+               return $content;
+       }
+
+       /**
+        * Allows to set the translation preferences and check the status
+        *
+        * @return      void
+        */
+
+
+       /*********************************
+        *
+        * Command Applications (triggered by GET var)
+        *
+        *********************************/
+
+       /**
+        * Returns detailed info about an extension in the online repository
+        *
+        * @param       string          Extension repository uid + optional "private key": [uid]-[key].
+        * @param       [type]          $version: ...
+        * @return      void
+        */
+       function importExtInfo($extKey, $version = '') {
+
+               $content = '<form action="' . $this->script . '" method="post" name="pageform">';
+
+               // Fetch remote data:
+               $this->xmlhandler->searchExtensionsXMLExact($extKey, '', '', true, true);
+               list($fetchData,) = $this->extensionList->prepareImportExtList(true);
+
+               $versions = array_keys($fetchData[$extKey]['versions']);
+               natsort($versions);
+               $version = ($version == '') ? end($versions) : $version;
+
+               $opt = array();
+               foreach ($versions as $ver) {
+                       $opt[] = '<option value="' . $ver . '"' . (($version == $ver) ? ' selected="selected"' : '') . '>' . $ver . '</option>';
+               }
+
+               // "Select version" box:
+               $onClick = 'window.location.href="' . $this->script . '&CMD[importExtInfo]=' . $extKey . '&CMD[extVersion]="+document.pageform.extVersion.options[document.pageform.extVersion.selectedIndex].value; return false;';
+               $select = '<select name="extVersion">' . implode('', $opt) .
+                               '</select> <input type="submit" value="' . $GLOBALS['LANG']->getLL('ext_load_details_button') .
+                               '" onclick="' . htmlspecialchars($onClick) . '" />';
+
+               if ($this->importAtAll()) {
+                       // Check for write-protected extension
+                       list($inst_list,) = $this->extensionList->getInstalledExtensions();
+                       if ($inst_list[$extKey]['EM_CONF']['state'] != 'excludeFromUpdates') {
+                               $onClick = '
+                                               window.location.href="' . $this->script . '&CMD[importExt]=' . $extKey . '"
+                                                       +"&CMD[extVersion]="+document.pageform.extVersion.options[document.pageform.extVersion.selectedIndex].value
+                                                       +"&CMD[loc]="+document.pageform.loc.options[document.pageform.loc.selectedIndex].value;
+                                                       return false;';
+                               $select .= ' ' . $GLOBALS['LANG']->getLL('ext_or') . '<br /><br />
+                                       <input type="submit" value="' . $GLOBALS['LANG']->getLL('ext_import_update_button') .
+                                               '" onclick="' . htmlspecialchars($onClick) . '" /> ' . $GLOBALS['LANG']->getLL('ext_import_update_to') . '
+                                       <select name="loc">' .
+                                               (tx_em_Tools::importAsType('G', $fetchData['emconf_lockType']) ?
+                                                               '<option value="G">' . $GLOBALS['LANG']->getLL('ext_import_global') . ' ' . tx_em_Tools::typePath('G') . $extKey . '/' .
+                                                                               (@is_dir(tx_em_Tools::typePath('G') . $extKey) ?
+                                                                                               ' ' . $GLOBALS['LANG']->getLL('ext_import_overwrite') :
+                                                                                               ' ' . $GLOBALS['LANG']->getLL('ext_import_folder_empty')
+                                                                               ) . '</option>' : ''
+                                               ) .
+                                               (tx_em_Tools::importAsType('L', $fetchData['emconf_lockType']) ?
+                                                               '<option value="L">' . $GLOBALS['LANG']->getLL('ext_import_local') . ' ' . tx_em_Tools::typePath('L') . $extKey . '/' .
+                                                                               (@is_dir(tx_em_Tools::typePath('L') . $extKey) ?
+                                                                                               ' ' . $GLOBALS['LANG']->getLL('ext_import_overwrite') :
+                                                                                               ' ' . $GLOBALS['LANG']->getLL('ext_import_folder_empty')
+                                                                               ) . '</option>' : ''
+                                               ) .
+                                               (tx_em_Tools::importAsType('S', $fetchData['emconf_lockType']) ?
+                                                               '<option value="S">' . $GLOBALS['LANG']->getLL('ext_import_system') . ' ' . tx_em_Tools::typePath('S') . $extKey . '/' .
+                                                                               (@is_dir(tx_em_Tools::typePath('S') . $extKey) ?
+                                                                                               ' ' . $GLOBALS['LANG']->getLL('ext_import_overwrite') :
+                                                                                               ' ' . $GLOBALS['LANG']->getLL('ext_import_folder_empty')
+                                                                               ) . '</option>' : ''
+                                               ) .
+                                               '</select>
+                                       </form>';
+                       } else {
+                               $select .= '<br /><br />' . $GLOBALS['LANG']->getLL('ext_import_excluded_from_updates');
+                       }
+               } else {
+                       $select .= '<br /><br />' . tx_em_Tools::noImportMsg();
+               }
+               $content .= $select;
+               $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('ext_import_select_command'), $content, 0, 1);
+
+               // Details:
+               $eInfo = $fetchData[$extKey]['versions'][$version];
+               $content = '<strong>' . $fetchData[$extKey]['_ICON'] . ' &nbsp;' . $eInfo['EM_CONF']['title'] . ' (' . $extKey . ', ' . $version . ')</strong><br /><br />';
+               $content .= $this->extensionDetails->extInformationarray($extKey, $eInfo, 1);
+               $this->content .= $this->doc->spacer(10);
+               $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('ext_import_remote_ext_details'), $content, 0, 1);
+       }
+
+       /**
+        * Fetches metadata and stores it to the corresponding place. This includes the mirror list,
+        * extension XML files.
+        *
+        * @param       string          Type of data to fetch: (mirrors)
+        * @param       boolean         If true the method doesn't produce any output
+        * @return      void
+        */
+       function fetchMetaData($metaType) {
+               global $TYPO3_CONF_VARS;
+
+               switch ($metaType) {
+                       case 'mirrors':
+                               $mfile = t3lib_div::tempnam('mirrors');
+                               $mirrorsFile = t3lib_div::getURL($this->MOD_SETTINGS['mirrorListURL'], 0, array(TYPO3_user_agent));
+                               if ($mirrorsFile===false) {
+                                       t3lib_div::unlink_tempfile($mfile);
+                                       $content = '<p>' .
+                                                       sprintf($GLOBALS['LANG']->getLL('ext_import_list_not_updated'),
+                                                               $this->MOD_SETTINGS['mirrorListURL']
+                                                       ) . ' ' .
+                                                       $GLOBALS['LANG']->getLL('translation_problems') . '</p>';
+                               } else {
+                                       t3lib_div::writeFile($mfile, $mirrorsFile);
+                                       $mirrors = implode('', gzfile($mfile));
+                                       t3lib_div::unlink_tempfile($mfile);
+
+                                       $mirrors = $this->xmlhandler->parseMirrorsXML($mirrors);
+                                       if (is_array($mirrors) && count($mirrors)) {
+                                               t3lib_BEfunc::getModuleData($this->MOD_MENU, array('extMirrors' => serialize($mirrors)), $this->MCONF['name'], '', 'extMirrors');
+                                               $this->MOD_SETTINGS['extMirrors'] = serialize($mirrors);
+                                               $content = '<p>' .
+                                                               sprintf($GLOBALS['LANG']->getLL('ext_import_list_updated'),
+                                                                       count($mirrors)
+                                                               ) . '</p>';
+                                       }
+                                       else {
+                                               $content = '<p>' . $mirrors . '<br />' . $GLOBALS['LANG']->getLL('ext_import_list_empty') . '</p>';
+                                       }
+                               }
+                               break;
+                       case 'extensions':
+                               $this->fetchMetaData('mirrors'); // if we fetch the extensions anyway, we can as well keep this up-to-date
+
+                               $mirror = $this->getMirrorURL();
+                               $extfile = $mirror . 'extensions.xml.gz';
+                               $extmd5 = t3lib_div::getURL($mirror . 'extensions.md5', 0, array(TYPO3_user_agent));
+                               if (is_file(PATH_site . 'typo3temp/extensions.xml.gz')) {
+                                       $localmd5 = md5_file(PATH_site . 'typo3temp/extensions.xml.gz');
+                               }
+
+                               // count cached extensions. If cache is empty re-fill it
+                               $cacheCount = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('extkey', 'cache_extensions');
+
+                               if ($extmd5 === false) {
+                                       $content .= '<p>' .
+                                                       sprintf($GLOBALS['LANG']->getLL('ext_import_md5_not_updated'),
+                                                                       $mirror . 'extensions.md5'
+                                                       ) .
+                                                       $GLOBALS['LANG']->getLL('translation_problems') . '</p>';
+                               } elseif ($extmd5 == $localmd5 && $cacheCount) {
+                                       $flashMessage = t3lib_div::makeInstance(
+                                               't3lib_FlashMessage',
+                                               $GLOBALS['LANG']->getLL('ext_import_list_unchanged'),
+                                               $GLOBALS['LANG']->getLL('ext_import_list_unchanged_header'),
+                                               t3lib_FlashMessage::INFO
+                                       );
+                                       $content .= $flashMessage->render();
+                               } else {
+                                       $extXML = t3lib_div::getURL($extfile, 0, array(TYPO3_user_agent));
+                                       if ($extXML === false) {
+                                               $content .= '<p>' .
+                                                               sprintf($GLOBALS['LANG']->getLL('ext_import_list_unchanged'),
+                                                                       $extfile
+                                                               ) . ' ' .
+                                                               $GLOBALS['LANG']->getLL('translation_problems') . '</p>';
+                                       } else {
+                                               t3lib_div::writeFile(PATH_site . 'typo3temp/extensions.xml.gz', $extXML);
+                                               $content .= $this->xmlhandler->parseExtensionsXML(PATH_site . 'typo3temp/extensions.xml.gz');
+                                       }
+                               }
+                               break;
+               }
+
+               return $content;
+       }
+
+       /**
+        * Returns the base URL for the slected or a random mirror.
+        *
+        * @return      string          The URL for the selected or a random mirror
+        */
+       function getMirrorURL() {
+               if (strlen($this->MOD_SETTINGS['rep_url'])) {
+                       return $this->MOD_SETTINGS['rep_url'];
+               }
+
+               $mirrors = unserialize($this->MOD_SETTINGS['extMirrors']);
+               if (!is_array($mirrors)) {
+                       $this->fetchMetaData('mirrors');
+                       $mirrors = unserialize($this->MOD_SETTINGS['extMirrors']);
+                       if (!is_array($mirrors)) {
+                               return false;
+                       }
+               }
+               if ($this->MOD_SETTINGS['selectedMirror'] == '') {
+                       $rand = array_rand($mirrors);
+                       $url = 'http://' . $mirrors[$rand]['host'] . $mirrors[$rand]['path'];
+               }
+               else {
+                       $url = 'http://' . $mirrors[$this->MOD_SETTINGS['selectedMirror']]['host'] . $mirrors[$this->MOD_SETTINGS['selectedMirror']]['path'];
+               }
+
+               return $url;
+       }
+
+
+       /**
+        * Installs (activates) an extension
+        *
+        * For $mode use the three constants EM_INSTALL_VERSION_MIN, EM_INSTALL_VERSION_MAX, EM_INSTALL_VERSION_STRICT
+        *
+        * If an extension is loaded or imported already and the version requirement is matched, it will not be
+        * fetched from the repository. This means, if you use EM_INSTALL_VERSION_MIN, you will not always get the latest
+        * version of an extension!
+        *
+        * @param       string          $extKey The extension key to install
+        * @param       string          $version        A version number that should be installed
+        * @param       int             $mode   If a version is requested, this determines if it is the min, max or strict version requested
+        * @return      [type]          ...
+        * @todo Make the method able to handle needed interaction somehow (unmatched dependencies)
+        */
+       function installExtension($extKey, $version = null, $mode = EM_INSTALL_VERSION_MIN) {
+               list($inst_list,) = $this->extensionList->getInstalledExtensions();
+
+               // check if it is already installed and loaded with sufficient version
+               if (isset($inst_list[$extKey])) {
+                       $currentVersion = $inst_list[$extKey]['EM_CONF']['version'];
+
+                       if (t3lib_extMgm::isLoaded($extKey)) {
+                               if ($version===null) {
+                                       return array(true, $GLOBALS['LANG']->getLL('ext_import_ext_already_installed_loaded'));
+                               } else {
+                                       switch ($mode) {
+                                               case EM_INSTALL_VERSION_STRICT:
+                                                       if ($currentVersion == $version) {
+                                                               return array(true, $GLOBALS['LANG']->getLL('ext_import_ext_already_installed_loaded'));
+                                                       }
+                                                       break;
+                                               case EM_INSTALL_VERSION_MIN:
+                                                       if (version_compare($currentVersion, $version, '>=')) {
+                                                               return array(true, $GLOBALS['LANG']->getLL('ext_import_ext_already_installed_loaded'));
+                                                       }
+                                                       break;
+                                               case EM_INSTALL_VERSION_MAX:
+                                                       if (version_compare($currentVersion, $version, '<=')) {
+                                                               return array(true, $GLOBALS['LANG']->getLL('ext_import_ext_already_installed_loaded'));
+                                                       }
+                                                       break;
+                                       }
+                               }
+                       } else {
+                               if (!t3lib_extMgm::isLocalconfWritable()) {
+                                       return array(false, $GLOBALS['LANG']->getLL('ext_import_p_localconf'));
+                               }
+                               $newExtList = -1;
+                               switch ($mode) {
+                                       case EM_INSTALL_VERSION_STRICT:
+                                               if ($currentVersion == $version) {
+                                                       $newExtList = $this->extensionList->addExtToList($extKey, $inst_list);
+                                               }
+                                               break;
+                                       case EM_INSTALL_VERSION_MIN:
+                                               if (version_compare($currentVersion, $version, '>=')) {
+                                                       $newExtList = $this->extensionList->addExtToList($extKey, $inst_list);
+                                               }
+                                               break;
+                                       case EM_INSTALL_VERSION_MAX:
+                                               if (version_compare($currentVersion, $version, '<=')) {
+                                                       $newExtList = $this->extensionList->addExtToList($extKey, $inst_list);
+                                               }
+                                               break;
+                               }
+                               if ($newExtList != -1) {
+                                       $this->writeNewExtensionList($newExtList);
+                                       $this->refreshGlobalExtList();
+                                       $this->forceDBupdates($extKey, $inst_list[$extKey]);
+                                       return array(true, $GLOBALS['LANG']->getLL('ext_import_ext_loaded'));
+                               }
+                       }
+               }
+
+               // at this point we know we need to import (a matching version of) the extension from TER2
+
+               // see if we have an extension list at all
+               if (!$this->xmlhandler->countExtensions()) {
+                       $this->fetchMetaData('extensions');
+               }
+               $this->xmlhandler->searchExtensionsXMLExact($extKey, '', '', true);
+
+               // check if extension can be fetched
+               if (isset($this->xmlhandler->extensionsXML[$extKey])) {
+                       $versions = array_keys($this->xmlhandler->extensionsXML[$extKey]['versions']);
+                       $latestVersion = end($versions);
+                       switch ($mode) {
+                               case EM_INSTALL_VERSION_STRICT:
+                                       if (!isset($this->xmlhandler->extensionsXML[$extKey]['versions'][$version])) {
+                                               return array(false, $GLOBALS['LANG']->getLL('ext_import_ext_n_a'));
+                                       }
+                                       break;
+                               case EM_INSTALL_VERSION_MIN:
+                                       if (version_compare($latestVersion, $version, '>=')) {
+                                               $version = $latestVersion;
+                                       } else {
+                                               return array(false, $GLOBALS['LANG']->getLL('ext_import_ext_n_a'));
+                                       }
+                                       break;
+                               case EM_INSTALL_VERSION_MAX:
+                                       while (($v = array_pop($versions)) && version_compare($v, $version, '>=')) {
+                                               // Loop until a version is found
+                                       }
+
+                                       if ($v !== null && version_compare($v, $version, '<=')) {
+                                               $version = $v;
+                                       } else {
+                                               return array(false, $GLOBALS['LANG']->getLL('ext_import_ext_n_a'));
+                                       }
+                                       break;
+                       }
+                       $this->importExtFromRep($extKey, $version, 'L');
+                       $newExtList = $this->extensionList->addExtToList($extKey, $inst_list);
+                       if ($newExtList != -1) {
+                               $this->writeNewExtensionList($newExtList);
+                               $this->refreshGlobalExtList();
+                               $this->forceDBupdates($extKey, $inst_list[$extKey]);
+                               $this->translations->installTranslationsForExtension($extKey, $this->getMirrorURL());
+                               return array(true, $GLOBALS['LANG']->getLL('ext_import_ext_imported'));
+                       } else {
+                               return array(false, $GLOBALS['LANG']->getLL('ext_import_ext_not_loaded'));
+                       }
+               } else {
+                       return array(false, $GLOBALS['LANG']->getLL('ext_import_ext_n_a_rep'));
+               }
+       }
+
+       function refreshGlobalExtList() {
+               global $TYPO3_LOADED_EXT;
+
+               $TYPO3_LOADED_EXT = t3lib_extMgm::typo3_loadExtensions();
+               if ($TYPO3_LOADED_EXT['_CACHEFILE']) {
+                       require(PATH_typo3conf . $TYPO3_LOADED_EXT['_CACHEFILE'] . '_ext_localconf.php');
+               }
+               return;
+
+               $GLOBALS['TYPO3_LOADED_EXT'] = t3lib_extMgm::typo3_loadExtensions();
+               if ($TYPO3_LOADED_EXT['_CACHEFILE']) {
+                       require(PATH_typo3conf . $TYPO3_LOADED_EXT['_CACHEFILE'] . '_ext_localconf.php');
+               } else {
+                       $temp_TYPO3_LOADED_EXT = $TYPO3_LOADED_EXT;
+                       foreach ($temp_TYPO3_LOADED_EXT as $_EXTKEY => $temp_lEDat) {
+                               if (is_array($temp_lEDat) && $temp_lEDat['ext_localconf.php']) {
+                                       $_EXTCONF = $GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf'][$_EXTKEY];
+                                       require($temp_lEDat['ext_localconf.php']);
+                               }
+                       }
+               }
+       }
+
+
+       /**
+        * Imports an extensions from the online repository
+        * NOTICE: in version 4.0 this changed from "importExtFromRep_old($extRepUid,$loc,$uploadFlag=0,$directInput='',$recentTranslations=0,$incManual=0,$dontDelete=0)"
+        *
+        * @param       string          Extension key
+        * @param       string          Version
+        * @param       string          Install scope: "L" or "G" or "S"
+        * @param       boolean         If true, extension is uploaded as file
+        * @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.
+        * @param       array           Direct input array (like from kickstarter)
+        * @return      string          Return false on success, returns error message if error.
+        */
+       function importExtFromRep($extKey, $version, $loc, $uploadFlag = 0, $dontDelete = 0, $directInput = '') {
+
+               $uploadSucceed = false;
+               $uploadedTempFile = '';
+               if (is_array($directInput)) {
+                       $fetchData = array($directInput, '');
+                       $loc = ($loc==='G' || $loc==='S') ? $loc : 'L';
+               } elseif ($uploadFlag) {
+                       if (($uploadedTempFile = $this->CMD['alreadyUploaded']) || $_FILES['upload_ext_file']['tmp_name']) {
+
+                               // Read uploaded file:
+                               if (!$uploadedTempFile) {
+                                       if (!is_uploaded_file($_FILES['upload_ext_file']['tmp_name'])) {
+                                               t3lib_div::sysLog('Possible file upload attack: ' . $_FILES['upload_ext_file']['tmp_name'], 'Extension Manager', 3);
+
+                                               return $GLOBALS['LANG']->getLL('ext_import_file_not_uploaded');
+                                       }
+
+                                       $uploadedTempFile = t3lib_div::upload_to_tempfile($_FILES['upload_ext_file']['tmp_name']);
+                               }
+                               $fileContent = t3lib_div::getUrl($uploadedTempFile);
+
+                               if (!$fileContent) {
+                           &nbs