[ Index ]
 

Code source de Typo3 4.1.3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/typo3/mod/tools/em/ -> class.em_index.php (source)

   1  <?php
   2  /***************************************************************
   3  *  Copyright notice
   4  *
   5  *  (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
   6  *  (c) 2005-2006 Karsten Dambekalns <karsten@typo3.org>
   7  *  All rights reserved
   8  *
   9  *  This script is part of the TYPO3 project. The TYPO3 project is
  10  *  free software; you can redistribute it and/or modify
  11  *  it under the terms of the GNU General Public License as published by
  12  *  the Free Software Foundation; either version 2 of the License, or
  13  *  (at your option) any later version.
  14  *
  15  *  The GNU General Public License can be found at
  16  *  http://www.gnu.org/copyleft/gpl.html.
  17  *  A copy is found in the textfile GPL.txt and important notices to the license
  18  *  from the author is found in LICENSE.txt distributed with these scripts.
  19  *
  20  *
  21  *  This script is distributed in the hope that it will be useful,
  22  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  23  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24  *  GNU General Public License for more details.
  25  *
  26  *  This copyright notice MUST APPEAR in all copies of the script!
  27  ***************************************************************/
  28  /**
  29   * Module: Extension manager
  30   *
  31   * $Id: class.em_index.php 2464 2007-08-29 10:59:27Z mundaun $
  32   *
  33   * @author    Kasper Skaarhoj <kasperYYYY@typo3.com>
  34   * @author    Karsten Dambekalns <karsten@typo3.org>
  35   */
  36  /**
  37   * [CLASS/FUNCTION INDEX of SCRIPT]
  38   *
  39   *
  40   *
  41   *  194: class SC_mod_tools_em_index extends t3lib_SCbase
  42   *
  43   *              SECTION: Standard module initialization
  44   *  337:     function init()
  45   *  417:     function handleExternalFunctionValue($MM_key='function', $MS_value=NULL)
  46   *  431:     function menuConfig()
  47   *  508:     function main()
  48   *  584:     function printContent()
  49   *
  50   *              SECTION: Function Menu Applications
  51   *  609:     function extensionList_loaded()
  52   *  664:     function extensionList_installed()
  53   *  736:     function extensionList_import()
  54   *  903:     function alterSettings()
  55   *
  56   *              SECTION: Command Applications (triggered by GET var)
  57   * 1005:     function importExtInfo($extKey, $version='')
  58   * 1062:     function fetchMetaData($metaType)
  59   * 1125:     function getMirrorURL()
  60   * 1158:     function installExtension($extKey, $version=null, $mode=EM_INSTALL_VERSION_MIN)
  61   * 1279:     function importExtFromRep($extKey,$version,$loc,$uploadFlag=0,$dontDelete=0,$directInput='')
  62   * 1425:     function showExtDetails($extKey)
  63   *
  64   *              SECTION: Application Sub-functions (HTML parts)
  65   * 1737:     function updatesForm($extKey,$extInfo,$notSilent=0,$script='',$addFields='')
  66   * 1768:     function extDumpTables($extKey,$extInfo)
  67   * 1835:     function getFileListOfExtension($extKey,$conf)
  68   * 1889:     function extDelete($extKey,$extInfo)
  69   * 1920:     function extUpdateEMCONF($extKey,$extInfo)
  70   * 1940:     function extBackup($extKey,$extInfo)
  71   * 1987:     function extBackup_dumpDataTablesLine($tablesArray,$extKey)
  72   * 2015:     function extInformationArray($extKey,$extInfo,$remote=0)
  73   * 2097:     function extInformationArray_dbReq($techInfo,$tableHeader=0)
  74   * 2110:     function extInformationArray_dbInst($dbInst,$current)
  75   * 2129:     function getRepositoryUploadForm($extKey,$extInfo)
  76   *
  77   *              SECTION: Extension list rendering
  78   * 2190:     function extensionListRowHeader($trAttrib,$cells,$import=0)
  79   * 2251:     function extensionListRow($extKey,$extInfo,$cells,$bgColorClass='',$inst_list=array(),$import=0,$altLinkUrl='')
  80   *
  81   *              SECTION: Output helper functions
  82   * 2367:     function wrapEmail($str,$email)
  83   * 2380:     function helpCol($key)
  84   * 2396:     function labelInfo($str)
  85   * 2408:     function extensionTitleIconHeader($extKey,$extInfo,$align='top')
  86   * 2423:     function removeButton()
  87   * 2432:     function installButton()
  88   * 2441:     function noImportMsg()
  89   * 2454:     function depToString($dep,$type='depends')
  90   * 2473:     function stringToDep($dep)
  91   *
  92   *              SECTION: Read information about all available extensions
  93   * 2503:     function getInstalledExtensions()
  94   * 2530:     function getInstExtList($path,&$list,&$cat,$type)
  95   * 2561:     function fixEMCONF($emConf)
  96   * 2600:     function splitVersionRange($ver)
  97   * 2616:     function prepareImportExtList()
  98   * 2660:     function setCat(&$cat,$listArrayPart,$extKey)
  99   *
 100   *              SECTION: Extension analyzing (detailed information)
 101   * 2710:     function makeDetailedExtensionAnalysis($extKey,$extInfo,$validity=0)
 102   * 2892:     function getClassIndexLocallangFiles($absPath,$table_class_prefix,$extKey)
 103   * 2962:     function modConfFileAnalysis($confFilePath)
 104   * 2990:     function serverExtensionMD5Array($extKey,$conf)
 105   * 3015:     function findMD5ArrayDiff($current,$past)
 106   *
 107   *              SECTION: File system operations
 108   * 3047:     function createDirsInPath($dirs,$extDirPath)
 109   * 3065:     function removeExtDirectory($removePath,$removeContentOnly=0)
 110   * 3128:     function clearAndMakeExtensionDir($importedData,$type,$dontDelete=0)
 111   * 3182:     function removeCacheFiles()
 112   * 3192:     function extractDirsFromFileList($files)
 113   * 3218:     function getExtPath($extKey,$type)
 114   *
 115   *              SECTION: Writing to "conf.php" and "localconf.php" files
 116   * 3252:     function writeTYPO3_MOD_PATH($confFilePath,$type,$mP)
 117   * 3289:     function writeNewExtensionList($newExtList)
 118   * 3312:     function writeTsStyleConfig($extKey,$arr)
 119   * 3334:     function updateLocalEM_CONF($extKey,$extInfo)
 120   *
 121   *              SECTION: Compiling upload information, emconf-file etc.
 122   * 3376:     function construct_ext_emconf_file($extKey,$EM_CONF)
 123   * 3407:     function arrayToCode($array, $level=0)
 124   * 3433:     function makeUploadArray($extKey,$conf)
 125   * 3502:     function getSerializedLocalLang($file,$content)
 126   *
 127   *              SECTION: Managing dependencies, conflicts, priorities, load order of extension keys
 128   * 3538:     function addExtToList($extKey,$instExtInfo)
 129   * 3569:     function checkDependencies($extKey, $conf, $instExtInfo)
 130   * 3709:     function removeExtFromList($extKey,$instExtInfo)
 131   * 3746:     function removeRequiredExtFromListArr($listArr)
 132   * 3761:     function managesPriorities($listArr,$instExtInfo)
 133   *
 134   *              SECTION: System Update functions (based on extension requirements)
 135   * 3813:     function checkClearCache($extInfo)
 136   * 3840:     function checkUploadFolder($extKey,$extInfo)
 137   * 3925:     function checkDBupdates($extKey,$extInfo,$infoOnly=0)
 138   * 4022:     function forceDBupdates($extKey, $extInfo)
 139   * 4080:     function tsStyleConfigForm($extKey,$extInfo,$output=0,$script='',$addFields='')
 140   *
 141   *              SECTION: Dumping database (MySQL compliant)
 142   * 4175:     function dumpTableAndFieldStructure($arr)
 143   * 4200:     function dumpStaticTables($tableList)
 144   * 4229:     function dumpHeader()
 145   * 4246:     function dumpTableHeader($table,$fieldKeyInfo,$dropTableIfExists=0)
 146   * 4288:     function dumpTableContent($table,$fieldStructure)
 147   * 4323:     function getTableAndFieldStructure($parts)
 148   *
 149   *              SECTION: TER Communication functions
 150   * 4373:     function uploadExtensionToTER($em)
 151   *
 152   *              SECTION: Various helper functions
 153   * 4411:     function listOrderTitle($listOrder,$key)
 154   * 4436:     function makeVersion($v,$mode)
 155   * 4448:     function renderVersion($v,$raise='')
 156   * 4485:     function ulFolder($extKey)
 157   * 4494:     function importAtAll()
 158   * 4505:     function importAsType($type,$lockType='')
 159   * 4527:     function deleteAsType($type)
 160   * 4548:     function versionDifference($v1,$v2,$div=1)
 161   * 4560:     function first_in_array($str,$array,$caseInsensitive=FALSE)
 162   * 4578:     function includeEMCONF($path,$_EXTKEY)
 163   * 4593:     function searchExtension($extKey,$row)
 164   *
 165   * TOTAL FUNCTIONS: 90
 166   * (This index is automatically created/updated by the extension "extdeveval")
 167   *
 168   */
 169  
 170      // Include classes needed:
 171  require_once(PATH_t3lib.'class.t3lib_tcemain.php');
 172  require_once(PATH_t3lib.'class.t3lib_install.php');
 173  require_once(PATH_t3lib.'class.t3lib_tsstyleconfig.php');
 174  require_once(PATH_t3lib.'class.t3lib_scbase.php');
 175  
 176  require_once ('class.em_xmlhandler.php');
 177  require_once ('class.em_terconnection.php');
 178  require_once ('class.em_unzip.php');
 179  
 180      // from tx_ter by Robert Lemke
 181  define('TX_TER_RESULT_EXTENSIONSUCCESSFULLYUPLOADED', '10504');
 182  
 183  define('EM_INSTALL_VERSION_MIN', 1);
 184  define('EM_INSTALL_VERSION_MAX', 2);
 185  define('EM_INSTALL_VERSION_STRICT', 3);
 186  
 187  /**
 188   * Module: Extension manager
 189   *
 190   * @author    Kasper Skaarhoj <kasperYYYY@typo3.com>
 191   * @author    Karsten Dambekalns <karsten@typo3.org>
 192   * @package TYPO3
 193   * @subpackage core
 194   */
 195  class SC_mod_tools_em_index extends t3lib_SCbase {
 196  
 197          // Internal, static:
 198      var $versionDiffFactor = 1;        // This means that version difference testing for import is detected for sub-versions only, not dev-versions. Default: 1000
 199      var $systemInstall = 0;                // If "1" then installs in the sysext directory is allowed. Default: 0
 200      var $requiredExt = '';                // List of required extension (from TYPO3_CONF_VARS)
 201      var $maxUploadSize = 31457280;        // Max size in bytes of extension upload to repository
 202      var $kbMax = 500;                    // Max size in kilobytes for files to be edited.
 203      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
 204      var $listingLimit = 500;        // List that many extension maximally at one time (fixing memory problems)
 205      var $listingLimitAuthor = 250;        // List that many extension maximally at one time (fixing memory problems)
 206  
 207      /**
 208       * Internal variable loaded with extension categories (for display/listing). Should reflect $categories above
 209       * Dynamic var.
 210       */
 211      var $defaultCategories = Array(
 212          'cat' => Array (
 213              'be' => array(),
 214              'module' => array(),
 215              'fe' => array(),
 216              'plugin' => array(),
 217              'misc' => array(),
 218              'services' => array(),
 219              'templates' => array(),
 220              'example' => array(),
 221              'doc' => array()
 222          )
 223      );
 224  
 225      /**
 226       * Extension Categories (static var)
 227       * Content must be redundant with the same internal variable as in class.tx_extrep.php!
 228       */
 229      var $categories = Array(
 230          'be' => 'Backend',
 231          'module' => 'Backend Modules',
 232          'fe' => 'Frontend',
 233          'plugin' => 'Frontend Plugins',
 234          'misc' => 'Miscellaneous',
 235          'services' => 'Services',
 236          'templates' => 'Templates',
 237          'example' => 'Examples',
 238          'doc' => 'Documentation'
 239      );
 240  
 241      /**
 242       * Extension States
 243       * Content must be redundant with the same internal variable as in class.tx_extrep.php!
 244       */
 245      var $states = Array (
 246          'alpha' => 'Alpha',
 247          'beta' => 'Beta',
 248          'stable' => 'Stable',
 249          'experimental' => 'Experimental',
 250          'test' => 'Test',
 251          'obsolete' => 'Obsolete',
 252      );
 253  
 254      /**
 255       * Colors for extension states
 256       */
 257      var $stateColors = Array (
 258          'alpha' => '#d12438',
 259          'beta' => '#97b17e',
 260          'stable' => '#3bb65c',
 261          'experimental' => '#007eba',
 262          'test' => '#979797',
 263          'obsolete' => '#000000',
 264      );
 265  
 266      /**
 267       * "TYPE" information; labels, paths, description etc.
 268       */
 269      var $typeLabels = Array (
 270          'S' => 'System',
 271          'G' => 'Global',
 272          'L' => 'Local',
 273      );
 274      var $typeDescr = Array (
 275          'S' => 'System extension (typo3/sysext/) - Always distributed with source code (Static).',
 276          'G' => 'Global extensions (typo3/ext/) - Available for shared source on server (Dynamic).',
 277          'L' => 'Local extensions (typo3conf/ext/) - Local for this TYPO3 installation only (Dynamic).',
 278      );
 279      var $typePaths = Array();            // Also static, set in init()
 280      var $typeBackPaths = Array();        // Also static, set in init()
 281  
 282      var $typeRelPaths = Array (
 283          'S' => 'sysext/',
 284          'G' => 'ext/',
 285          'L' => '../typo3conf/ext/',
 286      );
 287  
 288      var $detailCols = Array (
 289          0 => 2,
 290          1 => 5,
 291          2 => 6,
 292          3 => 6,
 293          4 => 4,
 294          5 => 1
 295      );
 296  
 297      var $fe_user = array(
 298          'username' => '',
 299          'password' => '',
 300      );
 301  
 302      var $privacyNotice = 'When you interact with the online repository, server information may be sent and stored in the repository for statistics.';
 303      var $securityHint = '<strong>Found a security problem? Please get in touch with us!</strong><br />If you think you have found a security issue in TYPO3 or an extension, please contact the <a href="http://typo3.org/teams/security/" target="_blank">TYPO3 security team</a>! Thank you!';
 304      var $editTextExtensions = 'html,htm,txt,css,tmpl,inc,php,sql,conf,cnf,pl,pm,sh,xml,ChangeLog';
 305      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';
 306  
 307  
 308  
 309  
 310  
 311          // Default variables for backend modules
 312      var $MCONF = array();                // Module configuration
 313      var $MOD_MENU = array();            // Module menu items
 314      var $MOD_SETTINGS = array();        // Module session settings
 315      var $doc;                            // Document Template Object
 316      var $content;                        // Accumulated content
 317  
 318      var $inst_keys = array();            // Storage of installed extensions
 319      var $gzcompress = 0;                // Is set true, if system support compression.
 320  
 321      var $terConnection;            // instance of TER connection handler
 322  
 323          // GPvars:
 324      var $CMD = array();                    // CMD array
 325      var $listRemote;                    // If set, connects to remote repository
 326      var $lookUpStr;                        // Search string when listing local extensions
 327  
 328  
 329  
 330  
 331      /*********************************
 332      *
 333      * Standard module initialization
 334      *
 335      *********************************/
 336  
 337      /**
 338       * Standard init function of a module.
 339       *
 340       * @return    void
 341       */
 342  	function init()    {
 343          global $BE_USER,$LANG,$BACK_PATH,$TYPO3_CONF_VARS;
 344  
 345              // Setting paths of install scopes:
 346          $this->typePaths = Array (
 347              'S' => TYPO3_mainDir.'sysext/',
 348              'G' => TYPO3_mainDir.'ext/',
 349              'L' => 'typo3conf/ext/'
 350          );
 351          $this->typeBackPaths = Array (
 352              'S' => '../../../',
 353              'G' => '../../../',
 354              'L' => '../../../../'.TYPO3_mainDir
 355          );
 356  
 357          $this->excludeForPackaging = $GLOBALS['TYPO3_CONF_VARS']['EXT']['excludeForPackaging'];
 358  
 359              // Setting module configuration:
 360          $this->MCONF = $GLOBALS['MCONF'];
 361  
 362              // Setting GPvars:
 363          $this->CMD = t3lib_div::_GP('CMD');
 364          $this->lookUpStr = trim(t3lib_div::_GP('_lookUp'));
 365          $this->listRemote = t3lib_div::_GP('ter_connect');
 366          $this->listRemote_search = trim(t3lib_div::_GP('ter_search'));
 367  
 368  
 369              // Configure menu
 370          $this->menuConfig();
 371  
 372              // Setting internal static:
 373          if ($TYPO3_CONF_VARS['EXT']['allowSystemInstall'])    $this->systemInstall = 1;
 374          $this->requiredExt = t3lib_div::trimExplode(',',$TYPO3_CONF_VARS['EXT']['requiredExt'],1);
 375  
 376  
 377              // Initialize helper object
 378          $this->terConnection = t3lib_div::makeInstance('SC_mod_tools_em_terconnection');
 379          $this->terConnection->emObj =& $this;
 380          $this->terConnection->wsdlURL = $TYPO3_CONF_VARS['EXT']['em_wsdlURL'];
 381          $this->xmlhandler = t3lib_div::makeInstance('SC_mod_tools_em_xmlhandler');
 382          $this->xmlhandler->emObj =& $this;
 383          $this->xmlhandler->useUnchecked = $this->MOD_SETTINGS['display_unchecked'];
 384          $this->xmlhandler->useObsolete = $this->MOD_SETTINGS['display_obsolete'];
 385  
 386              // Initialize Document Template object:
 387          $this->doc = t3lib_div::makeInstance('noDoc');
 388          $this->doc->backPath = $BACK_PATH;
 389          $this->doc->docType = 'xhtml_trans';
 390  
 391              // JavaScript
 392          $this->doc->JScode = $this->doc->wrapScriptTags('
 393              script_ended = 0;
 394  			function jumpToUrl(URL)    {    //
 395                  window.location.href = URL;
 396              }
 397          ');
 398          $this->doc->form = '<form action="index.php" method="post" name="pageform">';
 399  
 400          // Descriptions:
 401          $this->descrTable = '_MOD_'.$this->MCONF['name'];
 402          if ($BE_USER->uc['edit_showFieldHelp'])    {
 403              $LANG->loadSingleTableDescription($this->descrTable);
 404          }
 405  
 406          // Setting username/password etc. for upload-user:
 407          $this->fe_user['username'] = $this->MOD_SETTINGS['fe_u'];
 408          $this->fe_user['password'] = $this->MOD_SETTINGS['fe_p'];
 409          parent::init();
 410          $this->handleExternalFunctionValue('singleDetails');
 411      }
 412  
 413      /**
 414       * This function is a copy of the same function in t3lib_SCbase with one modification:
 415       * In contrast to t3lib_SCbase::handleExternalFunctionValue() this function merges the $this->extClassConf array
 416       * instead of overwriting it. That was necessary for including the Kickstarter as a submodule into the 'singleDetails'
 417       * selectorbox as well as in the main 'function' selectorbox.
 418       *
 419       * @param    string        Mod-setting array key
 420       * @param    string        Mod setting value, overriding the one in the key
 421       * @return    void
 422       * @see t3lib_SCbase::handleExternalFunctionValue()
 423       */
 424  	function handleExternalFunctionValue($MM_key='function', $MS_value=NULL)    {
 425          $MS_value = is_null($MS_value) ? $this->MOD_SETTINGS[$MM_key] : $MS_value;
 426          $externalItems = $this->getExternalItemConfig($this->MCONF['name'],$MM_key,$MS_value);
 427          if (is_array($externalItems))    $this->extClassConf = array_merge($externalItems,is_array($this->extClassConf)?$this->extClassConf:array());
 428          if (is_array($this->extClassConf) && $this->extClassConf['path'])    {
 429              $this->include_once[]=$this->extClassConf['path'];
 430          }
 431      }
 432  
 433      /**
 434       * Configuration of which mod-menu items can be used
 435       *
 436       * @return    void
 437       */
 438  	function menuConfig()    {
 439          global $BE_USER, $TYPO3_CONF_VARS;
 440  
 441          // MENU-ITEMS:
 442          $this->MOD_MENU = array(
 443              'function' => array(
 444                  0 => 'Loaded extensions',
 445                  1 => 'Install extensions',
 446                  2 => 'Import extensions',
 447                  4 => 'Translation handling',
 448                  3 => 'Settings',
 449              ),
 450              'listOrder' => array(
 451                  'cat' => 'Category',
 452                  'author_company' => 'Author',
 453                  'state' => 'State',
 454                  'type' => 'Type'
 455              ),
 456              'display_details' => array(
 457                  1 => 'Details',
 458                  0 => 'Description',
 459                  2 => 'More details',
 460  
 461                  3 => 'Technical (takes time!)',
 462                  4 => 'Validating (takes time!)',
 463                  5 => 'Changed? (takes time!)',
 464              ),
 465              'display_shy' => '',
 466              'display_own' => '',
 467              'display_unchecked' => '',
 468              'display_obsolete' => '',
 469  
 470              'singleDetails' => array(
 471                  'info' => 'Information',
 472                  'edit' => 'Edit files',
 473                  'backup' => 'Backup/Delete',
 474                  'dump' => 'Dump DB',
 475                  'upload' => 'Upload to TER',
 476                  'updateModule' => 'UPDATE!',
 477              ),
 478              'fe_u' => '',
 479              'fe_p' => '',
 480  
 481              'mirrorListURL' => '',
 482              'rep_url' => '',
 483              'extMirrors' => '',
 484              'selectedMirror' => '',
 485  
 486              'selectedLanguages' => ''
 487          );
 488  
 489          $this->MOD_MENU['singleDetails'] = $this->mergeExternalItems($this->MCONF['name'],'singleDetails',$this->MOD_MENU['singleDetails']);
 490  
 491          // page/be_user TSconfig settings and blinding of menu-items
 492          if (!$BE_USER->getTSConfigVal('mod.'.$this->MCONF['name'].'.allowTVlisting'))    {
 493              unset($this->MOD_MENU['display_details'][3]);
 494              unset($this->MOD_MENU['display_details'][4]);
 495              unset($this->MOD_MENU['display_details'][5]);
 496          }
 497  
 498          // CLEANSE SETTINGS
 499          $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']);
 500  
 501          if ($this->MOD_SETTINGS['function']==2)    {
 502              // If listing from online repository, certain items are removed though:
 503              unset($this->MOD_MENU['listOrder']['type']);
 504              unset($this->MOD_MENU['display_details'][2]);
 505              unset($this->MOD_MENU['display_details'][3]);
 506              unset($this->MOD_MENU['display_details'][4]);
 507              unset($this->MOD_MENU['display_details'][5]);
 508              $this->MOD_SETTINGS = t3lib_BEfunc::getModuleData($this->MOD_MENU, t3lib_div::_GP('SET'), $this->MCONF['name']);
 509          }
 510          parent::menuConfig();
 511      }
 512  
 513      /**
 514       * Main function for Extension Manager module.
 515       *
 516       * @return    void
 517       */
 518  	function main()    {
 519          global $BE_USER,$LANG,$TYPO3_CONF_VARS;
 520  
 521          if (empty($this->MOD_SETTINGS['mirrorListURL'])) $this->MOD_SETTINGS['mirrorListURL'] = $TYPO3_CONF_VARS['EXT']['em_mirrorListURL'];
 522  
 523          // Starting page:
 524          $this->content.=$this->doc->startPage('Extension Manager');
 525          $this->content.=$this->doc->header('Extension Manager');
 526          $this->content.=$this->doc->spacer(5);
 527  
 528          // Commands given which is executed regardless of main menu setting:
 529          if ($this->CMD['showExt'])    {    // Show details for a single extension
 530              $this->showExtDetails($this->CMD['showExt']);
 531          } elseif ($this->CMD['requestInstallExtensions'])    {    // Show details for a single extension
 532                  $this->requestInstallExtensions($this->CMD['requestInstallExtensions']);
 533          } elseif ($this->CMD['importExt'] || $this->CMD['uploadExt'])    {    // Imports an extension from online rep.
 534              $err = $this->importExtFromRep($this->CMD['importExt'],$this->CMD['extVersion'],$this->CMD['loc'],$this->CMD['uploadExt']);
 535              if ($err)    {
 536                  $this->content.=$this->doc->section('',$GLOBALS['TBE_TEMPLATE']->rfw($err));
 537              }
 538              if(!$err && $this->CMD['importExt']) {
 539                  $this->installTranslationsForExtension($this->CMD['importExt'], $this->getMirrorURL());
 540              }
 541          } elseif ($this->CMD['importExtInfo'])    {    // Gets detailed information of an extension from online rep.
 542              $this->importExtInfo($this->CMD['importExtInfo'],$this->CMD['extVersion']);
 543          } else {    // No command - we show what the menu setting tells us:
 544  
 545              $menu = $LANG->sL('LLL:EXT:lang/locallang_core.php:labels.menu').' '.
 546              t3lib_BEfunc::getFuncMenu(0,'SET[function]',$this->MOD_SETTINGS['function'],$this->MOD_MENU['function']);
 547  
 548              if (t3lib_div::inList('0,1,2',$this->MOD_SETTINGS['function']))    {
 549                  $menu.='&nbsp;Group by:&nbsp;'.t3lib_BEfunc::getFuncMenu(0,'SET[listOrder]',$this->MOD_SETTINGS['listOrder'],$this->MOD_MENU['listOrder']).
 550                  '&nbsp;&nbsp;Show:&nbsp;'.t3lib_BEfunc::getFuncMenu(0,'SET[display_details]',$this->MOD_SETTINGS['display_details'],$this->MOD_MENU['display_details']).'<br />';
 551              }
 552              if (t3lib_div::inList('0,1',$this->MOD_SETTINGS['function']))    {
 553                  $menu.='<label for="checkDisplayShy">Display shy extensions:</label>&nbsp;&nbsp;'.t3lib_BEfunc::getFuncCheck(0,'SET[display_shy]',$this->MOD_SETTINGS['display_shy'],'','','id="checkDisplayShy"');
 554              }
 555              if (t3lib_div::inList('2',$this->MOD_SETTINGS['function']) && strlen($this->fe_user['username']))    {
 556                  $menu.='<label for="checkDisplayOwn">Only my extensions:</label>&nbsp;&nbsp;'.t3lib_BEfunc::getFuncCheck(0,'SET[display_own]',$this->MOD_SETTINGS['display_own'],'','','id="checkDisplayOwn"');
 557              }
 558              if (t3lib_div::inList('0,1,2',$this->MOD_SETTINGS['function']))    {
 559                  $menu.='&nbsp;&nbsp;<label for="checkDisplayObsolete">Show obsolete:</label>&nbsp;&nbsp;'.t3lib_BEfunc::getFuncCheck(0,'SET[display_obsolete]',$this->MOD_SETTINGS['display_obsolete'],'','','id="checkDisplayObsolete"');
 560              }
 561  
 562              $this->content.=$this->doc->section('','<span class="nobr">'.$menu.'</span>');
 563              $this->content.=$this->doc->spacer(10);
 564  
 565              switch((string)$this->MOD_SETTINGS['function'])    {
 566                  case '0':
 567                      // Lists loaded (installed) extensions
 568                      $this->extensionList_loaded();
 569                      break;
 570                  case '1':
 571                      // Lists the installed (available) extensions
 572                      $this->extensionList_installed();
 573                      break;
 574                  case '2':
 575                      // Lists the extensions available from online rep.
 576                      $this->extensionList_import();
 577                      break;
 578                  case '3':
 579                      // Shows the settings screen
 580                      $this->alterSettings();
 581                      break;
 582                  case '4':
 583                      // Allows to set the translation preferences and check the status
 584                      $this->translationHandling();
 585                      break;
 586                  default:
 587                      $this->extObjContent();
 588                      break;
 589              }
 590          }
 591  
 592          // Shortcuts:
 593          if ($BE_USER->mayMakeShortcut())    {
 594              $this->content.=$this->doc->spacer(20).$this->doc->section('',$this->doc->makeShortcutIcon('CMD','function',$this->MCONF['name']));
 595          }
 596      }
 597  
 598      /**
 599       * Print module content. Called as last thing in the global scope.
 600       *
 601       * @return    void
 602       */
 603  	function printContent()    {
 604          if ($this->doPrintContent) {
 605              $this->content.= $this->doc->endPage();
 606              echo $this->content;
 607          }
 608      }
 609  
 610  
 611  
 612  
 613  
 614  
 615  
 616  
 617  
 618  
 619      /*********************************
 620      *
 621      * Function Menu Applications
 622      *
 623      *********************************/
 624  
 625      /**
 626       * Listing of loaded (installed) extensions
 627       *
 628       * @return    void
 629       */
 630  	function extensionList_loaded()    {
 631          global $TYPO3_LOADED_EXT;
 632  
 633          list($list,$cat) = $this->getInstalledExtensions();
 634  
 635          // Loaded extensions
 636          $content = '';
 637          $lines = array();
 638  
 639          // Available extensions
 640          if (is_array($cat[$this->MOD_SETTINGS['listOrder']]))    {
 641              $content='';
 642              $lines=array();
 643              $lines[] = $this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="1" height="1" alt="" /></td>'));
 644  
 645              foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys)    {
 646                  natcasesort($extEkeys);
 647                  reset($extEkeys);
 648                  $extensions = array();
 649                  while(list($extKey)=each($extEkeys))    {
 650                      if (array_key_exists($extKey,$TYPO3_LOADED_EXT) && ($this->MOD_SETTINGS['display_shy'] || !$list[$extKey]['EM_CONF']['shy']) && $this->searchExtension($extKey,$list[$extKey]))    {
 651                          if (in_array($extKey, $this->requiredExt))    {
 652                              $loadUnloadLink = '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>';
 653                          } else {
 654                              $loadUnloadLink = '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1').'">'.$this->removeButton().'</a>';
 655                          }
 656  
 657                          $extensions[] = $this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'));
 658                      }
 659                  }
 660                  if(count($extensions)) {
 661                      $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>';
 662                      $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><img src="'.$GLOBALS['BACK_PATH'].'gfx/i/sysf.gif" width="18" height="16" align="top" alt="" /><strong>'.$this->listOrderTitle($this->MOD_SETTINGS['listOrder'],$catName).'</strong></td></tr>';
 663                      $lines[] = implode(chr(10),$extensions);
 664                  }
 665              }
 666          }
 667  
 668          $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'loaded', $GLOBALS['BACK_PATH'],'');
 669  
 670          $content.= '<label for="_lookUp">Look up:</label> <input type="text" id="_lookUp" name="_lookUp" value="'.htmlspecialchars($this->lookUpStr).'" /><input type="submit" value="Search"/><br/><br/>';
 671  
 672          $content.= '
 673  
 674              <!-- Loaded Extensions List -->
 675              <table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>';
 676  
 677          $this->content.=$this->doc->section('Loaded Extensions',$content,0,1);
 678      }
 679  
 680      /**
 681       * Listing of available (installed) extensions
 682       *
 683       * @return    void
 684       */
 685  	function extensionList_installed()    {
 686          global $TYPO3_LOADED_EXT;
 687  
 688          list($list,$cat)=$this->getInstalledExtensions();
 689  
 690          // Available extensions
 691          if (is_array($cat[$this->MOD_SETTINGS['listOrder']]))    {
 692              $content='';
 693              $lines=array();
 694              $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>'));
 695  
 696              $allKeys=array();
 697              foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys)    {
 698                  if(!$this->MOD_SETTINGS['display_obsolete'] && $catName=='obsolete') continue;
 699  
 700                  $allKeys[]='';
 701                  $allKeys[]='TYPE: '.$catName;
 702  
 703                  natcasesort($extEkeys);
 704                  reset($extEkeys);
 705                  $extensions = array();
 706                  while(list($extKey)=each($extEkeys))    {
 707                      $allKeys[]=$extKey;
 708                      if ((!$list[$extKey]['EM_CONF']['shy'] || $this->MOD_SETTINGS['display_shy']) &&
 709                              ($list[$extKey]['EM_CONF']['state']!='obsolete' || $this->MOD_SETTINGS['display_obsolete'])
 710                       && $this->searchExtension($extKey,$list[$extKey]))    {
 711                          $loadUnloadLink = t3lib_extMgm::isLoaded($extKey)?
 712                          '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().'</a>':
 713                          '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().'</a>';
 714                          if (in_array($extKey,$this->requiredExt))    {
 715                              $loadUnloadLink='<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>';
 716                          }
 717                          $theRowClass = t3lib_extMgm::isLoaded($extKey)? 'em-listbg1' : 'em-listbg2';
 718                          $extensions[]=$this->extensionListRow($extKey,$list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),$theRowClass);
 719                      }
 720                  }
 721                  if(count($extensions)) {
 722                      $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>';
 723                      $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><img src="'.$GLOBALS['BACK_PATH'].'gfx/i/sysf.gif" width="18" height="16" align="top" alt="" /><strong>'.$this->listOrderTitle($this->MOD_SETTINGS['listOrder'],$catName).'</strong></td></tr>';
 724                      $lines[] = implode(chr(10),$extensions);
 725                  }
 726              }
 727  
 728              $content.='
 729  
 730  
 731  <!--
 732  EXTENSION KEYS:
 733  
 734  '.trim(implode(chr(10),$allKeys)).'
 735  
 736  -->
 737  
 738  ';
 739  
 740              $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'avail', $GLOBALS['BACK_PATH'],'|<br/>');
 741              $content.= 'If you want to use an extension in TYPO3, you should simply click the "plus" button '.$this->installButton().' . <br />
 742                          Installed extensions can also be removed again - just click the remove button '.$this->removeButton().' .<br /><br />';
 743  
 744              $content.= '<label for="_lookUp">Look up:</label> <input type="text" id="_lookUp" name="_lookUp" value="'.htmlspecialchars($this->lookUpStr).'" /><input type="submit" value="Search"/><br/><br/>';
 745              $content.= $this->securityHint.'<br /><br />';
 746  
 747              $content.= '<table border="0" cellpadding="2" cellspacing="1">'.implode('',$lines).'</table>';
 748  
 749              $this->content.=$this->doc->section('Available Extensions - Grouped by: '.$this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']],$content,0,1);
 750          }
 751      }
 752  
 753      /**
 754       * Listing remote extensions from online repository
 755       *
 756       * @return    void
 757       */
 758  	function extensionList_import()    {
 759          global $TYPO3_LOADED_EXT;
 760          $content='';
 761  
 762              // Listing from online repository:
 763          if ($this->listRemote)    {
 764              list($inst_list,) = $this->getInstalledExtensions();
 765              $this->inst_keys = array_flip(array_keys($inst_list));
 766  
 767              $this->detailCols[1]+=6;
 768  
 769                  // see if we have an extensionlist at all
 770              $this->extensionCount = $this->xmlhandler->countExtensions();
 771              if (!$this->extensionCount)    {
 772                  $content .= $this->fetchMetaData('extensions');
 773              }
 774  
 775              if($this->MOD_SETTINGS['listOrder']=='author_company') {
 776                  $this->listingLimit = $this->listingLimitAuthor;
 777              }
 778  
 779              $this->pointer = intval(t3lib_div::_GP('pointer'));
 780              $offset = $this->listingLimit*$this->pointer;
 781  
 782              if($this->MOD_SETTINGS['display_own'] && strlen($this->fe_user['username'])) {
 783                  $this->xmlhandler->searchExtensionsXML($this->listRemote_search, $this->fe_user['username'], $this->MOD_SETTINGS['listOrder']);
 784              } else {
 785                  $this->xmlhandler->searchExtensionsXML($this->listRemote_search, '', $this->MOD_SETTINGS['listOrder'], false, false, $offset, $this->listingLimit);
 786              }
 787              if (count($this->xmlhandler->extensionsXML))    {
 788                  list($list,$cat) = $this->prepareImportExtList(true);
 789  
 790                      // Available extensions
 791                  if (is_array($cat[$this->MOD_SETTINGS['listOrder']]))    {
 792                      $lines=array();
 793                      $lines[]=$this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>'),1);
 794  
 795                      foreach($cat[$this->MOD_SETTINGS['listOrder']] as $catName => $extEkeys)    {
 796                          if (count($extEkeys))    {
 797                              $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><br /></td></tr>';
 798                              $lines[]='<tr><td colspan="'.(3+$this->detailCols[$this->MOD_SETTINGS['display_details']]).'"><img src="'.$GLOBALS['BACK_PATH'].'gfx/i/sysf.gif" width="18" height="16" align="top" alt="" /><strong>'.$this->listOrderTitle($this->MOD_SETTINGS['listOrder'],$catName).'</strong></td></tr>';
 799  
 800                              natcasesort($extEkeys);
 801                              reset($extEkeys);
 802                              while(list($extKey)=each($extEkeys))    {
 803                                  $version = array_keys($list[$extKey]['versions']);
 804                                  $version = end($version);
 805                                  $ext = $list[$extKey]['versions'][$version];
 806                                  $ext['downloadcounter_all'] = $list[$extKey]['downloadcounter'];
 807                                  $ext['_ICON'] = $list[$extKey]['_ICON'];
 808                                  $loadUnloadLink='';
 809                                  if ($inst_list[$extKey]['type']!='S' && (!isset($inst_list[$extKey]) || $this->versionDifference($version,$inst_list[$extKey]['EM_CONF']['version'],$this->versionDiffFactor)))    {
 810                                      if (isset($inst_list[$extKey]))    {
 811                                              // update
 812                                          $loc= ($inst_list[$extKey]['type']=='G'?'G':'L');
 813                                          $aUrl = 'index.php?CMD[importExt]='.$extKey.'&CMD[extVersion]='.$version.'&CMD[loc]='.$loc;
 814                                          $loadUnloadLink.= '<a href="'.htmlspecialchars($aUrl).'"><img src="'.$GLOBALS['BACK_PATH'].'gfx/import_update.gif" width="12" height="12" title="Update the extension in \''.($loc=='G'?'global':'local').'\' from online repository to server" alt="" /></a>';
 815                                      } else {
 816                                              // import
 817                                          $aUrl = 'index.php?CMD[importExt]='.$extKey.'&CMD[extVersion]='.$version.'&CMD[loc]=L';
 818                                          $loadUnloadLink.= '<a href="'.htmlspecialchars($aUrl).'"><img src="'.$GLOBALS['BACK_PATH'].'gfx/import.gif" width="12" height="12" title="Import this extension to \'local\' dir typo3conf/ext/ from online repository." alt="" /></a>';
 819                                      }
 820                                  } else {
 821                                      $loadUnloadLink = '&nbsp;';
 822                                  }
 823  
 824                                  if (isset($inst_list[$extKey]))    {
 825                                      $theRowClass = t3lib_extMgm::isLoaded($extKey) ? 'em-listbg1' : 'em-listbg2';
 826                                  } else {
 827                                      $theRowClass = 'em-listbg3';
 828                                  }
 829  
 830                                  $lines[]=$this->extensionListRow($extKey,$ext,array('<td class="bgColor">'.$loadUnloadLink.'</td>'),$theRowClass,$inst_list,1,'index.php?CMD[importExtInfo]='.rawurlencode($extKey));
 831                                  unset($list[$extKey]);
 832                              }
 833                          }
 834                      }
 835                      unset($list);
 836  
 837                          // CSH:
 838                      $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import_ter', $GLOBALS['BACK_PATH'],'|<br/>');
 839                      $onsubmit = "window.location.href='index.php?ter_connect=1&ter_search='+escape(this.elements['_lookUp'].value);return false;";
 840                      $content.= '</form><form action="index.php" method="post" onsubmit="'.htmlspecialchars($onsubmit).'"><label for="_lookUp">List or look up <strong'.($this->MOD_SETTINGS['display_unchecked']?' style="color:#900;">all':' style="color:#090;">reviewed').'</strong> extensions</label><br />
 841                              <input type="text" id="_lookUp" name="_lookUp" value="'.htmlspecialchars($this->listRemote_search).'" /> <input type="submit" value="Look up" /><br /><br />';
 842  
 843                       $content .= $this->browseLinks();
 844  
 845                      $content.= '
 846  
 847                      <!-- TER Extensions list -->
 848                      <table border="0" cellpadding="2" cellspacing="1">'.implode(chr(10),$lines).'</table>';
 849                       $content .= '<br />'.$this->browseLinks();
 850                      $content.= '<br /><br />'.$this->securityHint;
 851                      $content.= '<br /><br /><strong>PRIVACY NOTICE:</strong><br /> '.$this->privacyNotice;
 852  
 853                      $this->content.=$this->doc->section('Extensions in TYPO3 Extension Repository (online) - Grouped by: '.$this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']],$content,0,1);
 854  
 855                          // Plugins which are NOT uploaded to repository but present on this server.
 856                      $content='';
 857                      $lines=array();
 858                      if (count($this->inst_keys))    {
 859                          reset($this->inst_keys);
 860                          while(list($extKey)=each($this->inst_keys))    {
 861                               $this->xmlhandler->searchExtensionsXML($extKey, '', '', true);
 862                              if((strlen($this->listRemote_search) && !stristr($extKey,$this->listRemote_search)) || isset($this->xmlhandler->extensionsXML[$extKey])) continue;
 863  
 864                              $loadUnloadLink = t3lib_extMgm::isLoaded($extKey)?
 865                              '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().'</a>':
 866                              '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().'</a>';
 867                              if (in_array($extKey,$this->requiredExt))    $loadUnloadLink='<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('Rq').'</strong>';
 868                              $lines[]=$this->extensionListRow($extKey,$inst_list[$extKey],array('<td class="bgColor">'.$loadUnloadLink.'</td>'),t3lib_extMgm::isLoaded($extKey)?'em-listbg1':'em-listbg2');
 869                          }
 870                      }
 871                      if(count($lines)) {
 872                          $content.= 'This is the list of extensions which are available locally, but not in the repository.<br />They might be user-defined and should be prepended user_ then.<br /><br />';
 873                          $content.= '<table border="0" cellpadding="2" cellspacing="1">'.
 874                              $this->extensionListRowHeader(' class="bgColor5"',array('<td><img src="clear.gif" width="18" height="1" alt="" /></td>')).
 875                              implode('',$lines).'</table>';
 876                          $this->content.=$this->doc->spacer(20);
 877                          $this->content.=$this->doc->section('Extensions found only on this server',$content,0,1);
 878                      }
 879                  }
 880              } else {
 881                  $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import_ter', $GLOBALS['BACK_PATH'],'|<br/>');
 882                  $onsubmit = "window.location.href='index.php?ter_connect=1&ter_search='+escape(this.elements['_lookUp'].value);return false;";
 883                  $content.= '</form><form action="index.php" method="post" onsubmit="'.htmlspecialchars($onsubmit).'"><label for="_lookUp">List or look up <strong'.($this->MOD_SETTINGS['display_unchecked']?' style="color:#900;">all':' style="color:#090;">reviewed').'</strong> extensions</label><br />
 884                      <input type="text" id="_lookUp" name="_lookUp" value="'.htmlspecialchars($this->listRemote_search).'" /> <input type="submit" value="Look up" /><br /><br />';
 885  
 886                  $content.= '<p><strong>No matching extensions found.</strong></p>';
 887  
 888                  $content.= '<br /><br /><strong>PRIVACY NOTICE:</strong><br /> '.$this->privacyNotice;
 889                  $this->content.=$this->doc->section('Extensions in TYPO3 Extension Repository (online) - Grouped by: '.$this->MOD_MENU['listOrder'][$this->MOD_SETTINGS['listOrder']],$content,0,1);
 890              }
 891          } else {
 892                  // CSH
 893              $content.= t3lib_BEfunc::cshItem('_MOD_tools_em', 'import', $GLOBALS['BACK_PATH'],'|<br/>');
 894  
 895              $onsubmit = "window.location.href='index.php?ter_connect=1&ter_search='+escape(this.elements['_lookUp'].value);return false;";
 896              $content.= '</form><form action="index.php" method="post" onsubmit="'.htmlspecialchars($onsubmit).'"><label for="_lookUp">List or look up <strong'.($this->MOD_SETTINGS['display_unchecked']?' style="color:#900;">all':' style="color:#090;">reviewed').'</strong> extensions</label><br />
 897              <input type="text" id="_lookUp" name="_lookUp" value="" /> <input type="submit" value="Look up" /><br /><br />';
 898  
 899              if ($this->CMD['fetchMetaData'])    {    // fetches mirror/extension data from online rep.
 900                  $content .= $this->fetchMetaData($this->CMD['fetchMetaData']);
 901              } else {
 902                  $onCLick = "window.location.href='index.php?CMD[fetchMetaData]=extensions';return false;";
 903                  $content.= 'Connect to the current mirror and retrieve the current list of available plugins from the TYPO3 Extension Repository.<br />
 904                  <input type="submit" value="Retrieve/Update" onclick="'.htmlspecialchars($onCLick).'" />';
 905                  if (is_file(PATH_site.'typo3temp/extensions.xml.gz'))    {
 906                      $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'];
 907                      $timeFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'];
 908                      $content.= ' (last update: '.date($dateFormat.' '.$timeFormat,filemtime(PATH_site.'typo3temp/extensions.xml.gz')).')';
 909                  }
 910              }
 911              $content.= '<br /><br />'.$this->securityHint;
 912              $content.= '<br /><br /><strong>PRIVACY NOTICE:</strong><br />'.$this->privacyNotice;
 913  
 914              $this->content.=$this->doc->section('Extensions in TYPO3 Extension Repository',$content,0,1);
 915          }
 916  
 917              // Upload:
 918          if ($this->importAtAll())    {
 919              $content= '</form><form action="index.php" enctype="'.$GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'].'" method="post">
 920              <label for="upload_ext_file">Upload extension file (.t3x):</label><br />
 921                  <input type="file" size="60" id="upload_ext_file" name="upload_ext_file" /><br />
 922                  ... to location:<br />
 923                  <select name="CMD[loc]">';
 924              if ($this->importAsType('L'))    $content.='<option value="L">Local (../typo3conf/ext/)</option>';
 925              if ($this->importAsType('G'))    $content.='<option value="G">Global (typo3/ext/)</option>';
 926              if ($this->importAsType('S'))    $content.='<option value="S">System (typo3/sysext/)</option>';
 927              $content.='</select><br />
 928      <input type="checkbox" value="1" name="CMD[uploadOverwrite]" id="checkUploadOverwrite" /> <label for="checkUploadOverwrite">Overwrite any existing extension!</label><br />
 929      <input type="submit" name="CMD[uploadExt]" value="Upload extension file" /><br />
 930              ';
 931          } else $content=$this->noImportMsg();
 932  
 933          $this->content.=$this->doc->spacer(20);
 934          $this->content.=$this->doc->section('Upload extension file directly (.t3x):',$content,0,1);
 935      }
 936  
 937      /**
 938       * Generates a link to the next page of extensions
 939       *
 940       * @return    void
 941       */
 942  	function browseLinks()    {
 943          $content = '';
 944          if ($this->pointer)    {
 945              $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="Prev page" /> Prev page</a>';
 946          }
 947          if ($content) $content .= '&nbsp;&nbsp;&nbsp;';
 948          if (intval($this->xmlhandler->matchingCount/$this->listingLimit)>$this->pointer)    {
 949              $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="Next page" /> Next page</a>';
 950          }
 951          $upper = (($this->pointer+1)*$this->listingLimit);
 952          if ($upper>$this->xmlhandler->matchingCount)    {
 953              $upper = $this->xmlhandler->matchingCount;
 954          }
 955          if ($content) $content .= '<br /><br />Showing extensions <strong>'.($this->pointer*$this->listingLimit+1).'</strong> to <strong>'.$upper.'</strong>';
 956          if ($content) $content .= '<br /><br />';
 957          return $content;
 958      }
 959  
 960      /**
 961       * Allows changing of settings
 962       *
 963       * @return    void
 964       */
 965  	function alterSettings()    {
 966  
 967              // Prepare the HTML output:
 968          $content.= '
 969              '.t3lib_BEfunc::cshItem('_MOD_tools_em', 'settings', $GLOBALS['BACK_PATH'],'|<br/>').'
 970              <fieldset><legend>Security Settings</legend>
 971              <table border="0" cellpadding="2" cellspacing="2">
 972                  <tr class="bgColor4">
 973                      <td><label for="display_unchecked">Enable extensions without review (basic security check):</label></td>
 974                      <td>'.t3lib_BEfunc::getFuncCheck(0,'SET[display_unchecked]',$this->MOD_SETTINGS['display_unchecked'],'','','id="display_unchecked"').'</td>
 975                  </tr>
 976              </table>
 977              <strong>Notice:</strong> Make sure you know what consequences enabling this checkbox might have. Check the <a href="http://typo3.org/extensions/what-are-reviews/" target="_blank">information on typo3.org about security reviewing</a>!
 978              </fieldset>
 979              <br />
 980              <br />
 981              <fieldset><legend>User Settings</legend>
 982              <table border="0" cellpadding="2" cellspacing="2">
 983                  <tr class="bgColor4">
 984                      <td><label for="set_fe_u">Enter repository username:</label></td>
 985                      <td><input type="text" id="set_fe_u" name="SET[fe_u]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_u']).'" /></td>
 986                  </tr>
 987                  <tr class="bgColor4">
 988                      <td><label for="set_fe_p">Enter repository password:</label></td>
 989                      <td><input type="password" id="set_fe_p" name="SET[fe_p]" value="'.htmlspecialchars($this->MOD_SETTINGS['fe_p']).'" /></td>
 990                  </tr>
 991              </table>
 992              <strong>Notice:</strong> This is <em>not</em> your password to the TYPO3 backend! This user information is what is needed to log in at typo3.org with your account there!
 993              </fieldset>
 994              <br />
 995              <br />
 996              <fieldset><legend>Mirror selection</legend>
 997              <table border="0" cellpadding="2" cellspacing="2">
 998                  <tr class="bgColor4">
 999                      <td><label for="set_mirror_list_url">Enter mirror list URL:</label></a></td>
1000                      <td><input type="text" size="50" id="set_mirror_list_url" name="SET[mirrorListURL]" value="'.htmlspecialchars($this->MOD_SETTINGS['mirrorListURL']).'" /></td>
1001                  </tr>
1002              </table>
1003              <br />
1004              <p>Select a mirror from below. This list is built from the online mirror list retrieved from the URL above.<br /><br /></p>
1005              <fieldset><legend>Mirror list</legend>';
1006          if(!empty($this->MOD_SETTINGS['mirrorListURL'])) {
1007              if ($this->CMD['fetchMetaData'])    {    // fetches mirror/extension data from online rep.
1008                  $content .= $this->fetchMetaData($this->CMD['fetchMetaData']);
1009              } else {
1010                  $content.= '<a href="index.php?CMD[fetchMetaData]=mirrors">Click here to reload the list.</a>';
1011              }
1012          }
1013          $content .= '<br />
1014              <table cellspacing="4" style="text-align:left; vertical-alignment:top;">
1015              <tr><td>Use</td><td>Name</td><td>URL</td><td>Country</td><td>Sponsored by</td></tr>
1016          ';
1017  
1018          if (!strlen($this->MOD_SETTINGS['extMirrors'])) $this->fetchMetaData('mirrors');
1019          $extMirrors = unserialize($this->MOD_SETTINGS['extMirrors']);
1020          $extMirrors[''] = array('title'=>'Random (recommended!)');
1021          ksort($extMirrors);
1022          if(is_array($extMirrors)) {
1023              foreach($extMirrors as $k => $v) {
1024                  if(isset($v['sponsor'])) {
1025                      $sponsor = '<a href="'.htmlspecialchars($v['sponsor']['link']).'" target="_new"><img src="'.$v['sponsor']['logo'].'" title="'.htmlspecialchars($v['sponsor']['name']).'" alt="'.htmlspecialchars($v['sponsor']['name']).'" /></a>';
1026                  }
1027                  $selected = ($this->MOD_SETTINGS['selectedMirror']==$k) ? 'checked="checked"' : '';
1028                  $content.='<tr class="bgColor4">
1029              <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>';
1030              }
1031          }
1032          $content.= '
1033              </table>
1034              </fieldset>
1035              <br />
1036              <table border="0" cellpadding="2" cellspacing="2">
1037                  <tr class="bgColor4">
1038                      <td><label for="set_rep_url">Enter repository URL:</label></td>
1039                      <td><input type="text" size="50" id="set_rep_url" name="SET[rep_url]" value="'.htmlspecialchars($this->MOD_SETTINGS['rep_url']).'" /></td>
1040                  </tr>
1041              </table>
1042  
1043              If you set a repository URL, this overrides the use of a mirror. Use this to select a specific (private) repository.<br />
1044              </fieldset>
1045              <br />
1046              <input type="submit" value="Update" />
1047          ';
1048  
1049          $this->content.=$this->doc->section('Repository settings',$content,0,1);
1050      }
1051  
1052      /**
1053       * Allows to set the translation preferences and check the status
1054       *
1055       * @return    void
1056       */
1057  	function translationHandling()    {
1058          global $LANG, $TYPO3_LOADED_EXT;
1059          $LANG->includeLLFile('EXT:setup/mod/locallang.xml');
1060  
1061          $incoming = t3lib_div::_POST('SET');
1062          if(isset($incoming['selectedLanguages']) && is_array($incoming['selectedLanguages'])) {
1063              t3lib_BEfunc::getModuleData($this->MOD_MENU, array('selectedLanguages' => serialize($incoming['selectedLanguages'])), $this->MCONF['name'], '', 'selectedLanguages');
1064              $this->MOD_SETTINGS['selectedLanguages'] = serialize($incoming['selectedLanguages']);
1065          }
1066  
1067          $selectedLanguages = unserialize($this->MOD_SETTINGS['selectedLanguages']);
1068          if(count($selectedLanguages)==1 && empty($selectedLanguages[0])) $selectedLanguages = array();
1069          $theLanguages = t3lib_div::trimExplode('|',TYPO3_languages);
1070          foreach($theLanguages as $val)  {
1071              if ($val!='default')    {
1072                  $localLabel = '  -  ['.htmlspecialchars($GLOBALS['LOCAL_LANG']['default']['lang_'.$val]).']';
1073                  $selected = (is_array($selectedLanguages) && in_array($val, $selectedLanguages)) ? ' selected="selected"' : '';
1074                  $opt[$GLOBALS['LOCAL_LANG']['default']['lang_'.$val].'--'.$val]='
1075               <option value="'.$val.'"'.$selected.'>'.$LANG->getLL('lang_'.$val,1).$localLabel.'</option>';
1076              }
1077          }
1078          ksort($opt);
1079  
1080              // Prepare the HTML output:
1081          $content.= '
1082              '.t3lib_BEfunc::cshItem('_MOD_tools_em', 'translation', $GLOBALS['BACK_PATH'],'|<br/>').'
1083              <fieldset><legend>Translation Settings</legend>
1084              <table border="0" cellpadding="2" cellspacing="2">
1085                  <tr class="bgColor4">
1086                      <td>Languages to fetch:</td>
1087                      <td>
1088                        <select name="SET[selectedLanguages][]" multiple="multiple" size="10">
1089                        <option></option>'.
1090              implode('',$opt).'
1091              </select>
1092            </td>
1093                  </tr>
1094              </table>
1095              <br />
1096              <p>For the selected languages the EM tries to download and install translation files if available, whenever an extension is installed. (This replaces the <code>csh_*</code> extensions that were used to install core translations before TYPO3 version 4!)<br />
1097              <br />To request an update/install for already loaded extensions, see below.</p>
1098              </fieldset>
1099              <br />
1100              <input type="submit" value="Save selection" />
1101              <br />
1102              </fieldset>';
1103  
1104          $this->content.=$this->doc->section('Translation settings',$content,0,1);
1105  
1106          if(count($selectedLanguages)>0) {
1107              $mirrorURL = $this->getMirrorURL();
1108              $content = '<input type="button" value="Check status against repository" onclick="document.location.href=\''.t3lib_div::linkThisScript(array('l10n'=>'check')).'\'" />&nbsp;<input type="button" value="Update from repository" onclick="document.location.href=\''.t3lib_div::linkThisScript(array('l10n'=>'update')).'\'" />';
1109  
1110              if(t3lib_div::_GET('l10n') == 'check') {
1111                  $loadedExtensions = array_keys($TYPO3_LOADED_EXT);
1112                  $loadedExtensions = array_diff($loadedExtensions,array('_CACHEFILE'));
1113  
1114                      // Override content output - we now do that ourself:
1115                  echo ($this->content . $this->doc->section('Translation status',$content,0,1));
1116                  $this->doPrintContent = FALSE;
1117                  flush();
1118  
1119                  echo '
1120                  <br />
1121                  <br />
1122                  <p id="progress-message">
1123                      Checking translation status, please wait ...
1124                  </p>
1125                  <br />
1126                  <div style="width:100%; height:20px; border: 1px solid black;">
1127                      <div id="progress-bar" style="float: left; width: 0%; height: 20px; background-color:green;">&nbsp;</div>
1128                      <div id="transparent-bar" style="float: left; width: 100%; height: 20px; background-color:'.$this->doc->bgColor2.';">&nbsp;</div>
1129                  </div>
1130                  <br />
1131                  <br /><p>This table shows the status of the loaded extension\'s translations.</p><br />
1132                  <table border="0" cellpadding="2" cellspacing="2">
1133                      <tr class="bgColor2"><td>Extension key</td>
1134                  ';
1135  
1136                  foreach($selectedLanguages as $lang) {
1137                      echo ('<td>'.$LANG->getLL('lang_'.$lang,1).'</td>');
1138                  }
1139                  echo ('</tr>');
1140  
1141                  $counter = 1;
1142                  foreach($loadedExtensions as $extKey) {
1143  
1144                      $percentDone = intval (($counter / count($loadedExtensions)) * 100);
1145                      echo ('
1146                      <script>
1147                          document.getElementById("progress-bar").style.width = "'.$percentDone.'%";
1148                          document.getElementById("transparent-bar").style.width = "'.(100-$percentDone).'%";
1149                          document.getElementById("progress-message").firstChild.data="Checking translation status for extension \"'.$extKey.'\" ...";
1150                      </script>
1151                      ');
1152  
1153                      flush();
1154                      $translationStatusArr = $this->terConnection->fetchTranslationStatus($extKey,$mirrorURL);
1155  
1156                      echo ('<tr class="bgColor4"><td>'.$extKey.'</td>');
1157                      foreach($selectedLanguages as $lang) {
1158                          // remote unknown -> keine l10n
1159                          if(!isset($translationStatusArr[$lang])) {
1160                              echo ('<td title="No translation available">N/A</td>');
1161                              continue;
1162                          }
1163                              // determine local md5 from zip
1164                          if(is_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip')) {
1165                              $localmd5 = md5_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip');
1166                          } else {
1167                              echo ('<td title="Not installed / Unknown" style="background-color:#ff0">???</td>');
1168                              continue;
1169                          }
1170                              // local!=remote -> needs update
1171                          if($localmd5 != $translationStatusArr[$lang]['md5']) {
1172                              echo ('<td title="Needs update" style="background-color:#ff0">UPD</td>');
1173                              continue;
1174                          }
1175                          echo ('<td title="Is up to date" style="background-color:#69a550">OK</td>');
1176                      }
1177                      echo ('</tr>');
1178  
1179                      $counter ++;
1180                  }
1181                  echo '</table>
1182                      <script>
1183                          document.getElementById("progress-message").firstChild.data="Check done.";
1184                      </script>
1185                  ';
1186                  echo $this->doc->endPage();
1187                  return '';
1188  
1189              } elseif(t3lib_div::_GET('l10n') == 'update') {
1190                  $loadedExtensions = array_keys($TYPO3_LOADED_EXT);
1191                  $loadedExtensions = array_diff($loadedExtensions,array('_CACHEFILE'));
1192  
1193                      // Override content output - we now do that ourself:
1194                  echo ($this->content . $this->doc->section('Translation status',$content,0,1));
1195                  $this->doPrintContent = FALSE;
1196                  flush();
1197  
1198                  echo ('
1199                  <br />
1200                  <br />
1201                  <p id="progress-message">
1202                      Updating translations, please wait ...
1203                  </p>
1204                  <br />
1205                  <div style="width:100%; height:20px; border: 1px solid black;">
1206                      <div id="progress-bar" style="float: left; width: 0%; height: 20px; background-color:green;">&nbsp;</div>
1207                      <div id="transparent-bar" style="float: left; width: 100%; height: 20px; background-color:'.$this->doc->bgColor2.';">&nbsp;</div>
1208                  </div>
1209                  <br />
1210                  <br /><p>This table shows the update results of the loaded extension\'s translations.<br />
1211                  <em>If you want to force a full check/update, delete the l10n zip-files from the typo3temp folder.</em></p><br />
1212                  <table border="0" cellpadding="2" cellspacing="2">
1213                      <tr class="bgColor2"><td>Extension key</td>
1214                  ');
1215  
1216                  foreach($selectedLanguages as $lang) {
1217                      echo '<td>'.$LANG->getLL('lang_'.$lang,1).'</td>';
1218                  }
1219                  echo '</tr>';
1220  
1221                  $counter = 1;
1222                  foreach($loadedExtensions as $extKey) {
1223                      $percentDone = intval (($counter / count($loadedExtensions)) * 100);
1224                      echo ('
1225                      <script>
1226                          document.getElementById("progress-bar").style.width = "'.$percentDone.'%";
1227                          document.getElementById("transparent-bar").style.width = "'.(100-$percentDone).'%";
1228                          document.getElementById("progress-message").firstChild.data="Updating translation for extension \"'.$extKey.'\" ...";
1229                      </script>
1230                      ');
1231  
1232                      flush();
1233                      $translationStatusArr = $this->terConnection->fetchTranslationStatus($extKey,$mirrorURL);
1234  
1235                      echo ('<tr class="bgColor4"><td>'.$extKey.'</td>');
1236                      if(is_array($translationStatusArr)) {
1237                          foreach($selectedLanguages as $lang) {
1238                                  // remote unknown -> no l10n available
1239                              if(!isset($translationStatusArr[$lang])) {
1240                                  echo ('<td title="No translation available">N/A</td>');
1241                                  continue;
1242                              }
1243                                  // determine local md5 from zip
1244                              if(is_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip')) {
1245                                  $localmd5 = md5_file(PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip');
1246                              } else {
1247                                  $localmd5 = 'zzz';
1248                              }
1249                                  // local!=remote or not installed -> needs update
1250                              if($localmd5 != $translationStatusArr[$lang]['md5']) {
1251                                  $ret = $this->updateTranslation($extKey, $lang, $mirrorURL);
1252                                  if($ret === true) {
1253                                      echo ('<td title="Has been updated" style="background-color:#69a550">UPD</td>');
1254                                  } else {
1255                                      echo ('<td title="'.htmlspecialchars($ret).'" style="background-color:#cb3352">ERR</td>');
1256                                  }
1257                                  continue;
1258                              }
1259                              echo ('<td title="Is up to date" style="background-color:#69a550">OK</td>');
1260                          }
1261                      } else {
1262                          echo ('<td colspan="'.count($selectedLanguages).'" title="Possible reasons: network problems, allow_url_fopen off, curl not enabled in Install tool.">Could not fetch translation status</td>');
1263                      }
1264                      echo ('</tr>');
1265                      $counter++;
1266                  }
1267                  echo '</table>
1268                      <script>
1269                          document.getElementById("progress-message").firstChild.data="Update done.";
1270                      </script>
1271                  ';
1272                  echo $this->doc->endPage();
1273                  return '';
1274              }
1275  
1276              $this->content.=$this->doc->section('Translation status',$content,0,1);
1277          }
1278      }
1279  
1280      /**
1281       * Install translations for all selected languages for an extension
1282       *
1283       * @param string $extKey        The extension key to install the translations for
1284       * @param string $lang        Language code of translation to fetch
1285       * @param string $mirrorURL        Mirror URL to fetch data from
1286       * @return mixed    true on success, error string on fauilure
1287       */
1288  	function updateTranslation($extKey, $lang, $mirrorURL) {
1289          $l10n = $this->terConnection->fetchTranslation($extKey, $lang, $mirrorURL);
1290          if(is_array($l10n)) {
1291              $file = PATH_site.'typo3temp/'.$extKey.'-l10n-'.$lang.'.zip';
1292              $path = 'l10n/'.$lang.'/';
1293              if(!is_dir(PATH_typo3conf.$path)) t3lib_div::mkdir_deep(PATH_typo3conf,$path);
1294              t3lib_div::writeFile($file, $l10n[0]);
1295              if($this->unzip($file, PATH_typo3conf.$path)) {
1296                  return true;
1297              } else {
1298                  return 'Unpacking the language pack failed!';
1299              }
1300          } else {
1301              return $l10n;
1302          }
1303      }
1304  
1305      /**
1306       * Install translations for all selected languages for an extension
1307       *
1308       * @param string $extKey        The extension key to install the translations for
1309       * @param string $mirrorURL        Mirror URL to fetch data from
1310       * @return mixed    true on success, error string on fauilure
1311       */
1312  	function installTranslationsForExtension($extKey, $mirrorURL) {
1313          $selectedLanguages = unserialize($this->MOD_SETTINGS['selectedLanguages']);
1314          if(!is_array($selectedLanguages)) $selectedLanguages = array();
1315          foreach($selectedLanguages as $lang) {
1316              $l10n = $this->terConnection->fetchTranslation($extKey, $lang, $mirrorURL);
1317              if(is_array($l10n)) {
1318                  $file = PATH_typo3conf.'l10n/'.$extKey.'-l10n-'.$lang.'.zip';
1319                  $path = 'l10n/'.$lang.'/'.$extKey;
1320                  t3lib_div::writeFile($file, $l10n[0]);
1321                  if(!is_dir(PATH_typo3conf.$path)) t3lib_div::mkdir_deep(PATH_typo3conf,$path);
1322                  if($this->unzip($file, PATH_typo3conf.$path)) {
1323                      return true;
1324                  } else {
1325                      return 'Unpacking the language pack failed!';
1326                  }
1327              } else {
1328                  return $l10n;
1329              }
1330          }
1331      }
1332  
1333      /**
1334       * Unzips a zip file in the given path.
1335       *
1336       * Uses unzip binary if available, otherwise a pure PHP unzip is used.
1337       *
1338       * @param string $file        Full path to zip file
1339       * @param string $path        Path to change to before extracting
1340       * @return boolean    True on success, false in failure
1341       */
1342  	function unzip($file, $path) {
1343          if(strlen($GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path'])) {
1344              chdir($path);
1345              $cmd = $GLOBALS['TYPO3_CONF_VARS']['BE']['unzip_path'].' -o '.escapeshellarg($file);
1346              exec($cmd, $list, $ret);
1347              return ($ret === 0);
1348          } else {
1349                  // we use a pure PHP unzip
1350              $unzip = new em_unzip($file);
1351              $ret = $unzip->extract(array('add_path'=>$path));
1352              return (is_array($ret));
1353          }
1354      }
1355  
1356  
1357  
1358      /*********************************
1359      *
1360      * Command Applications (triggered by GET var)
1361      *
1362      *********************************/
1363  
1364      /**
1365       * Returns detailed info about an extension in the online repository
1366       *
1367       * @param    string        Extension repository uid + optional "private key": [uid]-[key].
1368       * @param    [type]        $version: ...
1369       * @return    void
1370       */
1371  	function importExtInfo($extKey, $version='')    {
1372  
1373              // "Go back" link
1374          $content = '<a href="index.php" class="typo3-goBack"><img'.t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],'gfx/goback.gif','width="14" height="14"').' alt="" /> Go back</a>';
1375          $this->content.= $this->doc->section('',$content);
1376          $content = '';
1377  
1378              // Fetch remote data:
1379          $this->xmlhandler->searchExtensionsXML($extKey, '', '', true, true);
1380          list($fetchData,) = $this->prepareImportExtList(true);
1381  
1382          $versions = array_keys($fetchData[$extKey]['versions']);
1383          $version = ($version == '') ? end($versions) : $version;
1384  
1385          $opt = array();
1386          foreach(array_keys($fetchData[$extKey]['versions']) as $ver)    {
1387              $opt[]='<option value="'.$ver.'"'.(($version == $ver) ? ' selected="selected"' : '').'>'.$ver.'</option>';
1388          }
1389  
1390              // "Select version" box:
1391          $onClick = 'window.location.href=\'index.php?CMD[importExtInfo]='.$extKey.'&CMD[extVersion]=\'+document.pageform.extVersion.options[document.pageform.extVersion.selectedIndex].value; return false;';
1392          $select='<select name="extVersion">'.implode('',$opt).'</select> <input type="submit" value="Load details" onclick="'.htmlspecialchars($onClick).'" /> or<br /><br />';
1393  
1394          if ($this->importAtAll())    {
1395              $onClick = '
1396                      window.location.href=\'index.php?CMD[importExt]='.$extKey.'\'
1397                          +\'&CMD[extVersion]=\'+document.pageform.extVersion.options[document.pageform.extVersion.selectedIndex].value
1398                          +\'&CMD[loc]=\'+document.pageform.loc.options[document.pageform.loc.selectedIndex].value;
1399                          return false;';
1400              $select.='
1401                  <input type="submit" value="Import/Update" onclick="'.htmlspecialchars($onClick).'"> to:
1402                  <select name="loc">'.
1403                  ($this->importAsType('G',$fetchData['emconf_lockType'])?'<option value="G">Global: '.$this->typePaths['G'].$extKey.'/'.(@is_dir(PATH_site.$this->typePaths['G'].$extKey)?' (OVERWRITE)':' (empty)').'</option>':'').
1404                  ($this->importAsType('L',$fetchData['emconf_lockType'])?'<option value="L">Local: '.$this->typePaths['L'].$extKey.'/'.(@is_dir(PATH_site.$this->typePaths['L'].$extKey)?' (OVERWRITE)':' (empty)').'</option>':'').
1405                  ($this->importAsType('S',$fetchData['emconf_lockType'])?'<option value="S">System: '.$this->typePaths['S'].$extKey.'/'.(@is_dir(PATH_site.$this->typePaths['S'].$extKey)?' (OVERWRITE)':' (empty)').'</option>':'').
1406                  '</select>';
1407          } else $select.= $this->noImportMsg();
1408          $content.= $select;
1409          $this->content.= $this->doc->section('Select command',$content,0,1);
1410  
1411              // Details:
1412          $eInfo = $fetchData[$extKey]['versions'][$version];
1413          $content='<strong>'.$fetchData[$extKey]['_ICON'].' &nbsp;'.$eInfo['EM_CONF']['title'].' ('.$extKey.', '.$version.')</strong><br /><br />';
1414          $content.=$this->extInformationArray($extKey,$eInfo,1);
1415          $this->content.=$this->doc->spacer(10);
1416          $this->content.=$this->doc->section('Remote Extension Details',$content,0,1);
1417      }
1418  
1419      /**
1420       * Fetches metadata and stores it to the corresponding place. This includes the mirror list,
1421       * extension XML files.
1422       *
1423       * @param    string        Type of data to fetch: (mirrors)
1424       * @param    boolean        If true the method doesn't produce any output
1425       * @return    void
1426       */
1427  	function fetchMetaData($metaType)    {
1428          global $TYPO3_CONF_VARS;
1429  
1430          switch($metaType) {
1431              case 'mirrors':
1432                  $mfile = t3lib_div::tempnam('mirrors');
1433                  $mirrorsFile = t3lib_div::getURL($this->MOD_SETTINGS['mirrorListURL']);
1434                  if($mirrorsFile===false) {
1435                      t3lib_div::unlink_tempfile($mfile);
1436                      $content = '<p>The mirror list was not updated, it could not be fetched from '.$this->MOD_SETTINGS['mirrorListURL'].'. Possible reasons: network problems, allow_url_fopen is off, curl is not enabled in Install tool.</p>';
1437                  } else {
1438                      t3lib_div::writeFile($mfile, $mirrorsFile);
1439                      $mirrors = implode('',gzfile($mfile));
1440                      t3lib_div::unlink_tempfile($mfile);
1441  
1442                      $mirrors = $this->xmlhandler->parseMirrorsXML($mirrors);
1443                      if(is_array($mirrors) && count($mirrors)) {
1444                          t3lib_BEfunc::getModuleData($this->MOD_MENU, array('extMirrors' => serialize($mirrors)), $this->MCONF['name'], '', 'extMirrors');
1445                          $this->MOD_SETTINGS['extMirrors'] = serialize($mirrors);
1446                          $content = '<p>The mirror list has been updated and now contains '.count($mirrors).' entries.</p>';
1447                      }
1448                      else {
1449                          $content = '<p>'.$mirrors.'<br />The mirror list was not updated as it contained no entries.</p>';
1450                      }
1451                  }
1452                  break;
1453              case 'extensions':
1454                  $this->fetchMetaData('mirrors'); // if we fetch the extensions anyway, we can as well keep this up-to-date
1455  
1456                  $mirror = $this->getMirrorURL();
1457                  $extfile = $mirror.'extensions.xml.gz';
1458                  $extmd5 = t3lib_div::getURL($mirror.'extensions.md5');
1459                  if(is_file(PATH_site.'typo3temp/extensions.xml.gz')) $localmd5 = md5_file(PATH_site.'typo3temp/extensions.xml.gz');
1460  
1461                  if($extmd5 === false) {
1462                      $content .= '<p>Error: The extension MD5 sum could not be fetched from '.$mirror.'extensions.md5. Possible reasons: network problems, allow_url_fopen is off, curl is not enabled in Install tool.</p>';
1463                  } elseif($extmd5 == $localmd5) {
1464                      $content .= '<p>The extension list has not changed remotely, it has thus not been fetched.</p>';
1465                  } else {
1466                      $extXML = t3lib_div::getURL($extfile);
1467                      if($extXML === false) {
1468                          $content .= '<p>Error: The extension list could not be fetched from '.$extfile.'. Possible reasons: network problems, allow_url_fopen is off, curl is not enabled in Install tool.</p>';
1469                      } else {
1470                          t3lib_div::writeFile(PATH_site.'typo3temp/extensions.xml.gz', $extXML);
1471                          $content .= $this->xmlhandler->parseExtensionsXML(PATH_site.'typo3temp/extensions.xml.gz');
1472                      }
1473                  }
1474                  break;
1475          }
1476  
1477          return $content;
1478      }
1479  
1480      /**
1481       * Returns the base URL for the slected or a random mirror.
1482       *
1483       * @return    string        The URL for the selected or a random mirror
1484       */
1485  	function getMirrorURL() {
1486          if(strlen($this->MOD_SETTINGS['rep_url'])) return $this->MOD_SETTINGS['rep_url'];
1487  
1488          $mirrors = unserialize($this->MOD_SETTINGS['extMirrors']);
1489          if(!is_array($mirrors)) {
1490              $this->fetchMetaData('mirrors');
1491              $mirrors = unserialize($this->MOD_SETTINGS['extMirrors']);
1492              if(!is_array($mirrors)) return false;
1493          }
1494          if($this->MOD_SETTINGS['selectedMirror']=='') {
1495              srand((float) microtime() * 10000000); // not needed after PHP 4.2.0...
1496              $rand = array_rand($mirrors);
1497              $url = 'http://'.$mirrors[$rand]['host'].$mirrors[$rand]['path'];
1498          }
1499          else {
1500              $url = 'http://'.$mirrors[$this->MOD_SETTINGS['selectedMirror']]['host'].$mirrors[$this->MOD_SETTINGS['selectedMirror']]['path'];
1501          }
1502  
1503          return $url;
1504      }
1505  
1506  
1507  
1508      /**
1509       * Installs (activates) an extension
1510       *
1511       * For $mode use the three constants EM_INSTALL_VERSION_MIN, EM_INSTALL_VERSION_MAX, EM_INSTALL_VERSION_STRICT
1512       *
1513       * If an extension is loaded or imported already and the version requirement is matched, it will not be
1514       * fetched from the repository. This means, if you use EM_INSTALL_VERSION_MIN, you will not always get the latest
1515       * version of an extension!
1516       *
1517       * @param    string        $extKey    The extension key to install
1518       * @param    string        $version    A version number that should be installed
1519       * @param    int        $mode    If a version is requested, this determines if it is the min, max or strict version requested
1520       * @return    [type]        ...
1521       * @todo Make the method able to handle needed interaction somehow (unmatched dependencies)
1522       */
1523  	function installExtension($extKey, $version=null, $mode=EM_INSTALL_VERSION_MIN) {
1524          list($inst_list,) = $this->getInstalledExtensions();
1525  
1526              // check if it is already installed and loaded with sufficient version
1527          if(isset($inst_list[$extKey])) {
1528              $currentVersion = $inst_list[$extKey]['EM_CONF']['version'];
1529  
1530              if(t3lib_extMgm::isLoaded($extKey)) {
1531                  if($version===null) {
1532                      return array(true, 'Extension already installed and loaded.');
1533                  } else {
1534                      switch($mode) {
1535                          case EM_INSTALL_VERSION_STRICT:
1536                              if ($currentVersion == $version)    {
1537                                  return array(true, 'Extension already installed and loaded.');
1538                              }
1539                              break;
1540                          case EM_INSTALL_VERSION_MIN:
1541                              if (version_compare($currentVersion, $version, '>='))    {
1542                                  return array(true, 'Extension already installed and loaded.');
1543                              }
1544                              break;
1545                          case EM_INSTALL_VERSION_MAX:
1546                              if (version_compare($currentVersion, $version, '<='))    {
1547                                  return array(true, 'Extension already installed and loaded.');
1548                              }
1549                              break;
1550                      }
1551                  }
1552              } else {
1553                  if (!t3lib_extMgm::isLocalconfWritable())    {
1554                      return array(false, 'localconf.php is not writable!');
1555                  }
1556                  $newExtList = -1;
1557                  switch($mode) {
1558                      case EM_INSTALL_VERSION_STRICT:
1559                          if ($currentVersion == $version)    {
1560                              $newExtList = $this->addExtToList($extKey, $inst_list);
1561                          }
1562                          break;
1563                      case EM_INSTALL_VERSION_MIN:
1564                          if (version_compare($currentVersion, $version, '>='))    {
1565                              $newExtList = $this->addExtToList($extKey, $inst_list);
1566                          }
1567                          break;
1568                      case EM_INSTALL_VERSION_MAX:
1569                          if (version_compare($currentVersion, $version, '<='))    {
1570                              $newExtList = $this->addExtToList($extKey, $inst_list);
1571                          }
1572                          break;
1573                  }
1574                  if ($newExtList!=-1)    {
1575                      $this->writeNewExtensionList($newExtList);
1576                      $this->refreshGlobalExtList();
1577                      $this->forceDBupdates($extKey, $inst_list[$extKey]);
1578                      return array(true, 'Extension was already installed, it has been loaded.');
1579                  }
1580              }
1581          }
1582  
1583              // at this point we know we need to import (a matching version of) the extension from TER2
1584  
1585              // see if we have an extensionlist at all
1586          if (!$this->xmlhandler->countExtensions())    {
1587              $this->fetchMetaData('extensions');
1588          }
1589          $this->xmlhandler->searchExtensionsXML($extKey, '', '', true);
1590  
1591              // check if extension can be fetched
1592          if(isset($this->xmlhandler->extensionsXML[$extKey])) {
1593              $versions = array_keys($this->xmlhandler->extensionsXML[$extKey]['versions']);
1594              $latestVersion = end($versions);
1595              switch($mode) {
1596                  case EM_INSTALL_VERSION_STRICT:
1597                      if(!isset($this->xmlhandler->extensionsXML[$extKey]['versions'][$version])) {
1598                          return array(false, 'Extension not available in matching version');
1599                      }
1600                      break;
1601                  case EM_INSTALL_VERSION_MIN:
1602                      if (version_compare($latestVersion, $version, '>='))    {
1603                          $version = $latestVersion;
1604                      } else {
1605                          return array(false, 'Extension not available in matching version');
1606                      }
1607                      break;
1608                  case EM_INSTALL_VERSION_MAX:
1609                      while (($v = array_pop($versions)) && version_compare($v, $version, '>='))    {
1610                          // Loop until a version is found
1611                      }
1612  
1613                      if ($v !== null && version_compare($v, $version, '<='))    {
1614                          $version = $v;
1615                      } else {
1616                          return array(false, 'Extension not available in matching version');
1617                      }
1618                      break;
1619              }
1620              $this->importExtFromRep($extKey, $version, 'L');
1621              $newExtList = $this->addExtToList($extKey, $inst_list);
1622              if ($newExtList!=-1)    {
1623                  $this->writeNewExtensionList($newExtList);
1624                  $this->refreshGlobalExtList();
1625                  $this->forceDBupdates($extKey, $inst_list[$extKey]);
1626                  $this->installTranslationsForExtension($extKey, $this->getMirrorURL());
1627                  return array(true, 'Extension has been imported from repository and loaded.');
1628              } else {
1629                  return array(false, 'Extension is in repository, but could not be loaded.');
1630              }
1631          } else {
1632              return array(false, 'Extension not available in repository');
1633          }
1634      }
1635  
1636  	function refreshGlobalExtList() {
1637          global $TYPO3_LOADED_EXT;
1638  
1639          $TYPO3_LOADED_EXT = t3lib_extMgm::typo3_loadExtensions();
1640          if ($TYPO3_LOADED_EXT['_CACHEFILE'])    {
1641              require(PATH_typo3conf.$TYPO3_LOADED_EXT['_CACHEFILE'].'_ext_localconf.php');
1642          }
1643          return;
1644  
1645          $GLOBALS['TYPO3_LOADED_EXT'] = t3lib_extMgm::typo3_loadExtensions();
1646          if ($TYPO3_LOADED_EXT['_CACHEFILE'])    {
1647              require(PATH_typo3conf.$TYPO3_LOADED_EXT['_CACHEFILE'].'_ext_localconf.php');
1648          } else {
1649              $temp_TYPO3_LOADED_EXT = $TYPO3_LOADED_EXT;
1650              reset($temp_TYPO3_LOADED_EXT);
1651              while(list($_EXTKEY,$temp_lEDat)=each($temp_TYPO3_LOADED_EXT))  {
1652                  if (is_array($temp_lEDat) && $temp_lEDat['ext_localconf.php'])  {
1653                      $_EXTCONF = $TYPO3_CONF_VARS['EXT']['extConf'][$_EXTKEY];
1654                      require($temp_lEDat['ext_localconf.php']);
1655                  }
1656              }
1657          }
1658      }
1659  
1660  
1661      /**
1662       * Imports an extensions from the online repository
1663       * NOTICE: in version 4.0 this changed from "importExtFromRep_old($extRepUid,$loc,$uploadFlag=0,$directInput='',$recentTranslations=0,$incManual=0,$dontDelete=0)"
1664       *
1665       * @param    string        Extension key
1666       * @param    string        Version
1667       * @param    string        Install scope: "L" or "G" or "S"
1668       * @param    boolean        If true, extension is uploaded as file
1669       * @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.
1670       * @param    array        Direct input array (like from kickstarter)
1671       * @return    string        Return false on success, returns error message if error.
1672       */
1673  	function importExtFromRep($extKey,$version,$loc,$uploadFlag=0,$dontDelete=0,$directInput='')    {
1674  
1675          $uploadSucceed = false;
1676          $uploadedTempFile = '';
1677          if (is_array($directInput))    {
1678              $fetchData = array($directInput,'');
1679              $loc = ($loc==='G'||$loc==='S') ? $loc : 'L';
1680          } elseif ($uploadFlag)    {
1681              if (($uploadedTempFile = $this->CMD['alreadyUploaded']) || $_FILES['upload_ext_file']['tmp_name'])    {
1682  
1683                      // Read uploaded file:
1684                  if (!$uploadedTempFile)    {
1685                      if (!is_uploaded_file($_FILES['upload_ext_file']['tmp_name'])) {
1686                           t3lib_div::sysLog('Possible file upload attack: '.$_FILES['upload_ext_file']['tmp_name'], 'Extension Manager', 3);
1687  
1688                          return 'File was not uploaded?!?';
1689                      }
1690  
1691                      $uploadedTempFile = t3lib_div::upload_to_tempfile($_FILES['upload_ext_file']['tmp_name']);
1692                  }
1693                  $fileContent = t3lib_div::getUrl($uploadedTempFile);
1694  
1695                  if (!$fileContent)    return 'File is empty!';
1696  
1697                      // Decode file data:
1698                  $fetchData = $this->terConnection->decodeExchangeData($fileContent);
1699  
1700                  if (is_array($fetchData))    {
1701                      $extKey = $fetchData[0]['extKey'];
1702                      if ($extKey)    {
1703                          if (!$this->CMD['uploadOverwrite'])    {
1704                              $loc = ($loc==='G'||$loc==='S') ? $loc : 'L';
1705                              $comingExtPath = PATH_site.$this->typePaths[$loc].$extKey.'/';
1706                              if (@is_dir($comingExtPath))    {
1707                                  return 'Extension was already present in "'.$comingExtPath.'" - and the overwrite flag was not set! So nothing done...';
1708                              }    // ... else go on, install...
1709                          }    // ... else go on, install...
1710                      } else return 'No extension key in file. Strange...';
1711                  } else return 'Wrong file format. No data recognized, '.$fetchData;
1712              } else return 'No file uploaded! Probably the file was too large for PHPs internal limit for uploadable files.';
1713          } else {
1714              $this->xmlhandler->searchExtensionsXML($extKey, '', '', true, true);
1715  
1716                  // Fetch extension from TER:
1717              if(!strlen($version)) {
1718                  $versions = array_keys($this->xmlhandler->extensionsXML[$extKey]['versions']);
1719                  $version = end($versions);
1720              }
1721              $fetchData = $this->terConnection->fetchExtension($extKey, $version, $this->xmlhandler->extensionsXML[$extKey]['versions'][$version]['t3xfilemd5'], $this->getMirrorURL());
1722          }
1723  
1724          // At this point the extension data should be present; so we want to write it to disc:
1725          if ($this->importAsType($loc))    {
1726              if (is_array($fetchData))    {    // There was some data successfully transferred
1727                  if ($fetchData[0]['extKey'] && is_array($fetchData[0]['FILES']))    {
1728                      $extKey = $fetchData[0]['extKey'];
1729                      if(!isset($fetchData[0]['EM_CONF']['constraints'])) $fetchData[0]['EM_CONF']['constraints'] = $this->xmlhandler->extensionsXML[$extKey]['versions'][$version]['dependencies'];
1730                      $EM_CONF = $this->fixEMCONF($fetchData[0]['EM_CONF']);
1731                      if (!$EM_CONF['lockType'] || !strcmp($EM_CONF['lockType'],$loc))    {
1732                              // check dependencies, act accordingly if ext is loaded
1733                          list($instExtInfo,)=$this->getInstalledExtensions();
1734                          $depStatus = $this->checkDependencies($extKey, $EM_CONF, $instExtInfo);
1735                          if(t3lib_extMgm::isLoaded($extKey) && !$depStatus['returnCode']) {
1736                              $this->content .= $depStatus['html'];
1737                              if ($uploadedTempFile)    {
1738                                  $this->content .= '<input type="hidden" name="CMD[alreadyUploaded]" value="'.$uploadedTempFile.'" />';
1739                              }
1740                          } else {
1741                              $res = $this->clearAndMakeExtensionDir($fetchData[0],$loc,$dontDelete);
1742                              if (is_array($res))    {
1743                                  $extDirPath = trim($res[0]);
1744                                  if ($extDirPath && @is_dir($extDirPath) && substr($extDirPath,-1)=='/')    {
1745  
1746                                      $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF);
1747                                      $dirs = $this->extractDirsFromFileList(array_keys($fetchData[0]['FILES']));
1748  
1749                                      $res = $this->createDirsInPath($dirs,$extDirPath);
1750                                      if (!$res)    {
1751                                          $writeFiles = $fetchData[0]['FILES'];
1752                                          $writeFiles['ext_emconf.php']['content'] = $emConfFile;
1753                                          $writeFiles['ext_emconf.php']['content_md5'] = md5($emConfFile);
1754  
1755                                              // Write files:
1756                                          foreach($writeFiles as $theFile => $fileData)    {
1757                                              t3lib_div::writeFile($extDirPath.$theFile,$fileData['content']);
1758                                              if (!@is_file($extDirPath.$theFile))    {
1759                                                  $content.='Error: File "'.$extDirPath.$theFile.'" could not be created!!!<br />';
1760                                              } elseif (md5(t3lib_div::getUrl($extDirPath.$theFile)) != $fileData['content_md5']) {
1761                                                  $content.='Error: File "'.$extDirPath.$theFile.'" MD5 was different from the original files MD5 - so the file is corrupted!<br />';
1762                                              }
1763                                          }
1764  
1765                                              // No content, no errors. Create success output here:
1766                                          if (!$content)    {
1767                                              $content='SUCCESS: '.$extDirPath.'<br />';
1768  
1769                                              $uploadSucceed = true;
1770  
1771                                                  // Fix TYPO3_MOD_PATH for backend modules in extension:
1772                                              $modules = t3lib_div::trimExplode(',',$EM_CONF['module'],1);
1773                                              if (count($modules))    {
1774                                                  foreach($modules as $mD)    {
1775                                                      $confFileName = $extDirPath.$mD.'/conf.php';
1776                                                      if (@is_file($confFileName))    {
1777                                                          $content.= $this->writeTYPO3_MOD_PATH($confFileName,$loc,$extKey.'/'.$mD.'/').'<br />';
1778                                                      } else $content.='Error: Couldn\'t find "'.$confFileName.'"<br />';
1779                                                  }
1780                                              }
1781                                                  // NOTICE: I used two hours trying to find out why a script, ext_emconf.php, written twice and in between included by PHP did not update correct the second time. Probably something with PHP-A cache and mtime-stamps.
1782                                                  // But this order of the code works.... (using the empty Array with type, EMCONF and files hereunder).
1783  
1784                                                  // Writing to ext_emconf.php:
1785                                              $sEMD5A = $this->serverExtensionMD5Array($extKey,array('type' => $loc, 'EM_CONF' => array(), 'files' => array()));
1786                                              $EM_CONF['_md5_values_when_last_written'] = serialize($sEMD5A);
1787                                              $emConfFile = $this->construct_ext_emconf_file($extKey,$EM_CONF);
1788                                              t3lib_div::writeFile($extDirPath.'ext_emconf.php',$emConfFile);
1789  
1790                                              $content.='ext_emconf.php: '.$extDirPath.'ext_emconf.php<br />';
1791                                              $content.='Type: '.$loc.'<br />';
1792  
1793                                                  // Remove cache files:
1794                                              if (t3lib_extMgm::isLoaded($extKey))    {
1795                                                  if ($this->removeCacheFiles())    {
1796                                                      $content.='Cache-files are removed and will be re-written upon next hit<br />';
1797                                                  }
1798  
1799                                                  list($new_list)=$this->getInstalledExtensions();
1800                                                  $content.=$this->updatesForm($extKey,$new_list[$extKey],1,'index.php?CMD[showExt]='.$extKey.'&SET[singleDetails]=info');
1801                                              }
1802  
1803                                                  // Install / Uninstall:
1804                                              if(!$this->CMD['standAlone']) {
1805                                                  $content = '<a href="index.php" class="typo3-goBack"><img'.t3lib_iconWorks::skinImg($GLOBALS['BACK_PATH'],'gfx/goback.gif','width="14" height="14"').' alt="" /> Go back</a><br />'.$content;
1806                                                  $content.='<h3>Install / Uninstall Extension:</h3>';
1807                                                  $content.= $new_list[$extKey] ?
1808                                                      '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->removeButton().' Uninstall extension</a>' :
1809                                                      '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1&CMD[clrCmd]=1&SET[singleDetails]=info').'">'.$this->installButton().' Install extension</a>';
1810                                              } else {
1811                                                  $content = 'Extension has been imported.<br /><br /><a href="javascript:opener.top.content.document.forms[0].submit();window.close();">Close window and recheck dependencies</a>';
1812                                              }
1813  
1814                                          }
1815                                      } else $content = $res;
1816                                  } else $content = 'Error: The extension path "'.$extDirPath.'" was different than expected...';
1817                              } else $content = $res;
1818                          }
1819                      } else $content = 'Error: The extension can only be installed in the path '.$this->typePaths[$EM_CONF['lockType']].' (lockType='.$EM_CONF['lockType'].')';
1820                  } else $content = 'Error: No extension key!!! Why? - nobody knows... (Or no files in the file-array...)';
1821              }  else $content = 'Error: The datatransfer did not succeed. '.$fetchData;
1822          }  else $content = 'Error: Installation is not allowed in this path ('.$this->typePaths[$loc].')';
1823  
1824          $this->content.=$this->doc->section('Extension import results',$content,0,1);
1825  
1826          if ($uploadSucceed && $uploadedTempFile)    {
1827              t3lib_div::unlink_tempfile($uploadedTempFile);
1828          }
1829  
1830          return false;
1831      }
1832  
1833      /**
1834       * Display extensions details.
1835       *
1836       * @param    string        Extension key
1837       * @return    void        Writes content to $this->content
1838       */
1839  	function showExtDetails($extKey)    {
1840          global $TYPO3_LOADED_EXT;
1841  
1842          list($list,)=$this->getInstalledExtensions();
1843          $absPath = $this->getExtPath($extKey,$list[$extKey]['type']);
1844  
1845          // Check updateModule:
1846          if (@is_file($absPath.'class.ext_update.php'))    {
1847              require_once($absPath.'class.ext_update.php');
1848              $updateObj = new ext_update;
1849              if (!$updateObj->access())    {
1850                  unset($this->MOD_MENU['singleDetails']['updateModule']);
1851              }
1852          } else {
1853              unset($this->MOD_MENU['singleDetails']['updateModule']);
1854          }
1855  
1856          if($this->CMD['doDelete']) {
1857              $this->MOD_MENU['singleDetails'] = array();
1858          }
1859  
1860              // Function menu here:
1861          if(!$this->CMD['standAlone'] && !t3lib_div::_GP('standAlone')) {
1862              $content = '
1863                  <table border="0" cellpadding="0" cellspacing="0" width="100%">
1864                      <tr>
1865                          <td nowrap="nowrap">Extension:&nbsp;<strong>'.$this->extensionTitleIconHeader($extKey,$list[$extKey]).'</strong> ('.$extKey.')</td>
1866                          <td align="right" nowrap="nowrap">'.
1867              t3lib_BEfunc::getFuncMenu(0,'SET[singleDetails]',$this->MOD_SETTINGS['singleDetails'],$this->MOD_MENU['singleDetails'],'','&CMD[showExt]='.$extKey).' &nbsp; &nbsp; '.
1868              '<a href="index.php" class="typo3-goBack"><img'.t3lib_iconWorks::skinImg($this->doc->backPath,'gfx/goback.gif','width="14" height="14"').' class="absmiddle" alt="" /> Go back</a></td>
1869                      </tr>
1870                  </table>';
1871              $this->content.=$this->doc->section('',$content);
1872          }
1873  
1874              // Show extension details:
1875          if ($list[$extKey])    {
1876  
1877                  // Checking if a command for install/uninstall is executed:
1878              if (($this->CMD['remove'] || $this->CMD['load']) && !in_array($extKey,$this->requiredExt))    {
1879  
1880                      // Install / Uninstall extension here:
1881                  if (t3lib_extMgm::isLocalconfWritable())    {
1882                          // Check dependencies:
1883                      $depStatus = $this->checkDependencies($extKey, $list[$extKey]['EM_CONF'], $list);
1884                      if(!$this->CMD['remove'] && !$depStatus['returnCode']) {
1885                          $this->content .= $depStatus['html'];
1886                          $newExtList = -1;
1887                      } elseif ($this->CMD['remove'])    {
1888                          $newExtList = $this->removeExtFromList($extKey,$list);
1889                      } else {
1890                          $newExtList = $this->addExtToList($extKey,$list);
1891                      }
1892  
1893                      // Success-installation:
1894                      if ($newExtList!=-1)    {
1895                          $updates = '';
1896                          if ($this->CMD['load'])    {
1897                              if($_SERVER['REQUEST_METHOD'] == 'POST') {
1898                                  $script = t3lib_div::linkThisScript(array('CMD[showExt]' => $extKey, 'CMD[load]' => 1, 'CMD[clrCmd]' => $this->CMD['clrCmd'], 'SET[singleDetails]' => 'info'));
1899                              } else {
1900                                  $script = '';
1901                              }
1902                              $updates = $this->updatesForm($extKey,$list[$extKey],1,$script,'<input type="hidden" name="_do_install" value="1" /><input type="hidden" name="_clrCmd" value="'.$this->CMD['clrCmd'].'" />');
1903                              if ($updates)    {
1904                                  $updates = 'Before the extension can be installed the database needs to be updated with new tables or fields. Please select which operations to perform:'.$updates;
1905                                  if($this->CMD['standAlone']) $updates .= '<input type="hidden" name="standAlone" value="1" />';
1906                                  $depsolver = t3lib_div::_POST('depsolver');
1907                                  if(is_array($depsolver['ignore'])) {
1908                                      foreach($depsolver['ignore'] as $depK => $depV)    {
1909                                          $updates .= '<input type="hidden" name="depsolver[ignore]['.$depK.']" value="1" />';
1910                                      }
1911                                  }
1912  
1913                                  $this->content.=$this->doc->section('Installing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Database needs to be updated'),$updates,1,1,1,1);
1914                              }
1915                          } elseif ($this->CMD['remove']) {
1916                              $updates.= $this->checkClearCache($list[$extKey]);
1917                              if ($updates)    {
1918                                  $updates = '
1919                                  </form><form action="'.t3lib_div::linkThisScript().'" method="post">'.$updates.'
1920                                  <br /><input type="submit" name="write" value="Remove extension" />
1921                                  <input type="hidden" name="_do_install" value="1" />
1922                                  <input type="hidden" name="_clrCmd" value="'.$this->CMD['clrCmd'].'" />
1923                                  <input type="hidden" name="standAlone" value="'.$this->CMD['standAlone'].'" />
1924                                  ';
1925                                  $this->content.=$this->doc->section('Removing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Database needs to be updated'),$updates,1,1,1,1);
1926                              }
1927                          }
1928                          if (!$updates || t3lib_div::_GP('_do_install')) {
1929                              $this->writeNewExtensionList($newExtList);
1930                              $GLOBALS['BE_USER']->writelog(5,1,0,0,'Extension list has been changed, extension %s has been %s',array($extKey,($this->CMD['load']?'installed':'removed')));
1931                              if ($this->CMD['clrCmd'] || t3lib_div::_GP('_clrCmd'))    {
1932                                  $vA = array('CMD'=>'');
1933                              } else {
1934                                  $vA = array('CMD'=>Array('showExt'=>$extKey));
1935                              }
1936                              if($this->CMD['standAlone'] || t3lib_div::_GP('standAlone')) {
1937                                  $this->content .= 'Extension has been '.($this->CMD['load'] ? 'installed' : 'removed').'.<br /><br /><a href="javascript:opener.top.content.document.forms[0].submit();window.close();">Close window and recheck dependencies</a>';
1938                              } else {
1939                                  header('Location: '.t3lib_div::linkThisScript($vA));
1940                              }
1941                          }
1942                      }
1943                  } else {
1944                      $this->content.=$this->doc->section('Installing '.$this->extensionTitleIconHeader($extKey,$list[$extKey]).strtoupper(': Write access error'),'typo3conf/localconf.php seems not to be writable, so the extension cannot be installed automatically!',1,1,2,1);
1945                  }
1946  
1947              } elseif ($this->CMD['downloadFile'] && !in_array($extKey,$this->requiredExt))    {
1948  
1949                  // Link for downloading extension has been clicked - deliver content stream:
1950                  $dlFile = $this->CMD['downloadFile'];
1951                  if (t3lib_div::isFirstPartOfStr($dlFile,PATH_site) && t3lib_div::isFirstPartOfStr($dlFile,$absPath) && @is_file($dlFile))    {
1952                      $mimeType = 'application/octet-stream';
1953                      Header('Content-Type: '.$mimeType);
1954                      Header('Content-Disposition: attachment; filename='.basename($dlFile));
1955                      echo t3lib_div::getUrl($dlFile);
1956                      exit;
1957                  } else die('Error while trying to download extension file...');
1958  
1959              } elseif ($this->CMD['editFile'] && !in_array($extKey,$this->requiredExt))    {
1960  
1961                  // Editing extension file:
1962                  $editFile = $this->CMD['editFile'];
1963                  if (t3lib_div::isFirstPartOfStr($editFile,PATH_site) && t3lib_div::isFirstPartOfStr($editFile,$absPath))    {    // Paranoia...
1964  
1965                      $fI = t3lib_div::split_fileref($editFile);
1966                      if (@is_file($editFile) && t3lib_div::inList($this->editTextExtensions,($fI['fileext']?$fI['fileext']:$fI['filebody'])))    {
1967                          if (filesize($editFile)<($this->kbMax*1024))    {
1968                              $outCode = '';
1969                              $info = '';
1970                              $submittedContent = t3lib_div::_POST('edit');
1971                              $saveFlag = 0;
1972  
1973                              if(isset($submittedContent['file']) && !$GLOBALS['TYPO3_CONF_VARS']['EXT']['noEdit'])    {        // Check referer here?
1974                                  $oldFileContent = t3lib_div::getUrl($editFile);
1975                                  if($oldFileContent != $submittedContent['file']) {
1976                                      $oldMD5 = md5(str_replace(chr(13),'',$oldFileContent));
1977                                      $info.= 'MD5: <b>'.$oldMD5.'</b> (Previous File)<br />';
1978                                      t3lib_div::writeFile($editFile,$submittedContent['file']);
1979                                      $saveFlag = 1;
1980                                  } else {
1981                                      $info .= 'No changes to the file detected!<br />';
1982                                  }
1983                              }
1984  
1985                              $fileContent = t3lib_div::getUrl($editFile);
1986  
1987                              $outCode.= 'File: <b>'.substr($editFile,strlen($absPath)).'</b> ('.t3lib_div::formatSize(filesize($editFile)).')<br />';
1988                              $fileMD5 = md5(str_replace(chr(13),'',$fileContent));
1989                              $info.= 'MD5: <b>'.$fileMD5.'</b> (Current File)<br />';
1990                              if($saveFlag)    {
1991                                  $saveMD5 = md5(str_replace(chr(13),'',$submittedContent['file']));
1992                                  $info.= 'MD5: <b>'.$saveMD5.'</b> (Submitted)<br />';
1993                                  if($fileMD5!=$saveMD5) $info .= $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>Saving failed, the content was not correctly written to disk. Changes have been lost!</strong>').'<br />';
1994                                  else $info.= $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>File saved.</strong>').'<br />';
1995                              }
1996  
1997                              $outCode.= '<textarea name="edit[file]" rows="35" wrap="off"'.$this->doc->formWidthText(48,'width:98%;height:70%','off').' class="fixed-font enable-tab">'.t3lib_div::formatForTextarea($fileContent).'</textarea>';
1998                              $outCode.= '<input type="hidden" name="edit[filename]" value="'.$editFile.'" />';
1999                              $outCode.= '<input type="hidden" name="CMD[editFile]" value="'.htmlspecialchars($editFile).'" />';
2000                              $outCode.= '<input type="hidden" name="CMD[showExt]" value="'.$extKey.'" />';
2001                              $outCode.= $info;
2002  
2003                              if (!$GLOBALS['TYPO3_CONF_VARS']['EXT']['noEdit'])    {
2004                                  $outCode.='<br /><input type="submit" name="save_file" value="Save file" />';
2005                              } else $outCode.=$GLOBALS['TBE_TEMPLATE']->rfw('<br />[SAVING IS DISABLED - can be enabled by the $TYPO3_CONF_VARS[\'EXT\'][\'noEdit\']-flag] ');
2006  
2007                              $onClick = 'window.location.href=\'index.php?CMD[showExt]='.$extKey.'\';return false;';
2008                              $outCode.='<input type="submit" name="cancel" value="Cancel" onclick="'.htmlspecialchars($onClick).'" />';
2009  
2010                              $theOutput.=$this->doc->spacer(15);
2011                              $theOutput.=$this->doc->section('Edit file:','',0,1);
2012                              $theOutput.=$this->doc->sectionEnd().$outCode;
2013                              $this->content.=$theOutput;
2014                          } else {
2015                              $theOutput.=$this->doc->spacer(15);
2016                              $theOutput.=$this->doc->section('Filesize exceeded '.$this->kbMax.' Kbytes','Files larger than '.$this->kbMax.' KBytes are not allowed to be edited.');
2017                          }
2018                      }
2019                  } else die('Fatal Edit error: File "'.$editFile.'" was not inside the correct path of the TYPO3 Extension!');
2020              } else {
2021  
2022                  // MAIN:
2023                  switch((string)$this->MOD_SETTINGS['singleDetails'])    {
2024                      case 'info':
2025                          // Loaded / Not loaded:
2026                          if (!in_array($extKey,$this->requiredExt))    {
2027                              if ($TYPO3_LOADED_EXT[$extKey])    {
2028                                  $content = '<strong>The extension is installed (loaded and running)!</strong><br />'.
2029                                  '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[remove]=1').'">Click here to remove the extension: '.$this->removeButton().'</a>';
2030                              } else {
2031                                  $content = 'The extension is <strong>not</strong> installed yet.<br />'.
2032                                  '<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[load]=1').'">Click here to install the extension: '.$this->installButton().'</a>';
2033                              }
2034                          } else {
2035                              $content = 'This extension is entered in the TYPO3_CONF_VARS[SYS][requiredExt] list and is therefore always loaded.';
2036                          }
2037                          $this->content.=$this->doc->spacer(10);
2038                          $this->content.=$this->doc->section('Active status:',$content,0,1);
2039  
2040                          if (t3lib_extMgm::isLoaded($extKey))    {
2041                              $updates=$this->updatesForm($extKey,$list[$extKey]);
2042                              if ($updates)    {
2043                                  $this->content.=$this->doc->spacer(10);
2044                                  $this->content.=$this->doc->section('Update needed:',$updates.'<br /><br />Notice: "Static data" may not <em>need</em> to be updated. You will only have to import static data each time you upgrade the extension.',0,1);
2045                              }
2046                          }
2047  
2048                          // Config:
2049                          if (@is_file($absPath.'ext_conf_template.txt'))    {
2050                              $this->content.=$this->doc->spacer(10);
2051                              $this->content.=$this->doc->section('Configuration:','(<em>Notice: You may need to clear the cache after configuration of the extension. This is required if the extension adds TypoScript depending on these settings.</em>)<br /><br />',0,1);
2052                              $this->tsStyleConfigForm($extKey,$list[$extKey]);
2053                          }
2054  
2055                          // Show details:
2056                          $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'info', $GLOBALS['BACK_PATH'],'|<br/>');
2057                          $content.= $this->extInformationArray($extKey,$list[$extKey]);
2058  
2059                          $this->content.=$this->doc->spacer(10);
2060                          $this->content.=$this->doc->section('Details:',$content,0,1);
2061                          break;
2062                      case 'upload':
2063                          $em = t3lib_div::_POST('em');
2064                          if($em['action'] == 'doUpload') {
2065                              $em['extKey'] = $extKey;
2066                              $em['extInfo'] = $list[$extKey];
2067                              $content = $this->uploadExtensionToTER($em);
2068                              $content .= $this->doc->spacer(10);
2069                                  // Must reload this, because EM_CONF information has been updated!
2070                              list($list,)=$this->getInstalledExtensions();
2071                          } else {
2072                                  // CSH:
2073                              $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'upload', $GLOBALS['BACK_PATH'],'|<br/>');
2074  
2075                                  // Upload:
2076                              if (substr($extKey,0,5)!='user_')    {
2077                                  $content.= $this->getRepositoryUploadForm($extKey,$list[$extKey]);
2078                                  $eC=0;
2079                              } else {
2080                                  $content.='The extensions has an extension key prefixed "user_" which indicates that it is a user-defined extension with no official unique identification. Therefore it cannot be uploaded.';
2081                                  $eC=2;
2082                              }
2083                              if (!$this->fe_user['username'])    {
2084                                  $content.= '<br /><br /><img src="'.$GLOBALS['BACK_PATH'].'gfx/icon_note.gif" width="18" height="16" align="top" alt="" />You have not configured a default username/password yet. <a href="index.php?SET[function]=3">Go to "Settings"</a> if you want to do that.<br />';
2085                              }
2086                          }
2087                          $this->content.=$this->doc->section('Upload extension to repository',$content,0,1,$eC);
2088                          break;
2089                      case 'backup':
2090                          if($this->CMD['doDelete']) {
2091                              $content = $this->extDelete($extKey,$list[$extKey]);
2092                              $this->content.=$this->doc->section('Delete',$content,0,1);
2093                          } else {
2094                              $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'backup_delete', $GLOBALS['BACK_PATH'],'|<br/>');
2095                              $content.= $this->extBackup($extKey,$list[$extKey]);
2096                              $this->content.=$this->doc->section('Backup',$content,0,1);
2097  
2098                              $content = $this->extDelete($extKey,$list[$extKey]);
2099                              $this->content.=$this->doc->section('Delete',$content,0,1);
2100  
2101                              $content = $this->extUpdateEMCONF($extKey,$list[$extKey]);
2102                              $this->content.=$this->doc->section('Update EM_CONF',$content,0,1);
2103                          }
2104                          break;
2105                      case 'dump':
2106                          $this->extDumpTables($extKey,$list[$extKey]);
2107                          break;
2108                      case 'edit':
2109                          $content = t3lib_BEfunc::cshItem('_MOD_tools_em', 'editfiles', $GLOBALS['BACK_PATH'],'|<br/>');
2110                          $content.= $this->getFileListOfExtension($extKey,$list[$extKey]);
2111  
2112                          $this->content.=$this->doc->section('Extension files',$content,0,1);
2113                          break;
2114                      case 'updateModule':
2115                          $this->content.=$this->doc->section('Update:',is_object($updateObj) ? $updateObj->main() : 'No update object',0,1);
2116                          break;
2117                      default:
2118                          $this->extObjContent();
2119                          break;
2120                  }
2121              }
2122          }
2123      }
2124  
2125      /**
2126       * Outputs a screen from where you can install multiple extensions in one go
2127       * This can be called from external modules with "...index.php?CMD[requestInstallExtensions]=
2128       *
2129       * @param    string        Comma list of extension keys to install. Renders a screen with checkboxes for all extensions not already imported or installed
2130       * @return    void
2131       */
2132  	function requestInstallExtensions($extList)    {
2133  
2134              // Return URL:
2135          $returnUrl = t3lib_div::_GP('returnUrl');
2136          $installOrImportExtension = t3lib_div::_POST('installOrImportExtension');
2137  
2138              // Extension List:
2139          $extArray = explode(',',$extList);
2140          $outputRow = array();
2141          $outputRow[] = '
2142              <tr class="bgColor5 tableheader">
2143                  <td>Install/Import:</td>
2144                  <td>Extension Key:</td>
2145              </tr>
2146          ';
2147  
2148          foreach($extArray as $extKey)    {
2149  
2150                  // Check for the request:
2151              if ($installOrImportExtension[$extKey])    {
2152                  $this->installExtension($extKey);
2153              }
2154  
2155                  // Display:
2156              if (!t3lib_extMgm::isLoaded($extKey))    {
2157                  $outputRow[] = '
2158                  <tr class="bgColor4">
2159                      <td><input type="checkbox" name="'.htmlspecialchars('installOrImportExtension['.$extKey.']').'" value="1" checked="checked" id="check_'.$extKey.'" /></td>
2160                      <td><label for="check_'.$extKey.'">'.htmlspecialchars($extKey).'</label></td>
2161                  </tr>
2162                  ';
2163              }
2164          }
2165  
2166          if (count($outputRow)>1 || !$returnUrl)    {
2167              $content = '
2168              </form>    <!-- ending page form ... -->
2169              <form action="'.htmlspecialchars(t3lib_div::getIndpEnv('REQUEST_URI')).'" method="post">
2170                  <table border="0" cellpadding="1" cellspacing="1">'.implode('',$outputRow).'</table>
2171              <input type="submit" name="_" value="Import and Install selected" />
2172              </form>
2173              <form>    <!-- continuing page form... -->';
2174  
2175              if ($returnUrl)    {
2176                  $content.= '
2177                  <br/>
2178                  <br/>
2179                  <a href="'.htmlspecialchars($returnUrl).'">Return</a>
2180                  ';
2181              }
2182  
2183              $this->content.= $this->doc->section('Import/Install Extensions:',$content,0,1);
2184          } else {
2185              header('Location: '.t3lib_div::locationHeaderUrl($returnUrl));
2186          }
2187      }
2188  
2189  
2190  
2191  
2192  
2193  
2194  
2195  
2196      /***********************************
2197      *
2198      * Application Sub-functions (HTML parts)
2199      *
2200      **********************************/
2201  
2202      /**
2203       * Creates a form for an extension which contains all options for configuration, updates of database, clearing of cache etc.
2204       * This form is shown when
2205       *
2206       * @param    string        Extension key
2207       * @param    array        Extension information array
2208       * @param    boolean        If set, the form will ONLY show if fields/tables should be updated (suppressing forms like general configuration and cache clearing).
2209       * @param    string        Alternative action=""-script
2210       * @param    string        HTML: Additional form fields
2211       * @return    string        HTML
2212       */
2213  	function updatesForm($extKey,$extInfo,$notSilent=0,$script='',$addFields='')    {
2214          $script = $script ? $script : t3lib_div::linkThisScript();
2215          $updates.= $this->checkDBupdates($extKey,$extInfo);
2216          $uCache = $this->checkClearCache($extInfo);
2217          if ($notSilent)    $updates.= $uCache;
2218          $updates.= $this->checkUploadFolder($extKey,$extInfo);
2219  
2220          $absPath = $this->getExtPath($extKey,$extInfo['type']);
2221          if ($notSilent && @is_file($absPath.'ext_conf_template.txt'))    {
2222              $cForm = $this->tsStyleConfigForm($extKey,$extInfo,1,$script,$updates.$addFields.'<br />');
2223          }
2224  
2225          if ($updates || $cForm)    {
2226              if ($cForm)    {
2227                  $updates = '</form>'.$cForm.'<form>';
2228              } else {
2229                  $updates = '</form><form action="'.htmlspecialchars($script).'" method="post">'.$updates.$addFields.'
2230                      <br /><input type="submit" name="write" value="Make updates" />
2231                  ';
2232              }
2233          }
2234          return $updates;
2235      }
2236  
2237      /**
2238       * Creates view for dumping static tables and table/fields structures...
2239       *
2240       * @param    string        Extension key
2241       * @param    array        Extension information array
2242       * @return    void
2243       */
2244  	function extDumpTables($extKey,$extInfo)    {
2245  
2246          // Get dbInfo which holds the structure known from the tables.sql file
2247          $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo);
2248          $absPath = $this->getExtPath($extKey,$extInfo['type']);
2249  
2250          // Static tables:
2251          if (is_array($techInfo['static']))    {
2252              if ($this->CMD['writeSTATICdump'])    {    // Writing static dump:
2253                  $writeFile = $absPath.'ext_tables_static+adt.sql';
2254                  if (@is_file($writeFile))    {
2255                      $dump_static = $this->dumpStaticTables(implode(',',$techInfo['static']));
2256                      t3lib_div::writeFile($writeFile,$dump_static);
2257                      $this->content.=$this->doc->section('Table and field structure required',t3lib_div::formatSize(strlen($dump_static)).'bytes written to '.substr($writeFile,strlen(PATH_site)),0,1);
2258                  }
2259              } else {    // Showing info about what tables to dump - and giving the link to execute it.
2260                  $msg = 'Dumping table content for static tables:<br />';
2261                  $msg.= '<br />'.implode('<br />',$techInfo['static']).'<br />';
2262  
2263                  // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content.
2264                  $this->content.=$this->doc->section('Static tables',$msg.'<hr /><strong><a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[writeSTATICdump]=1').'">Write current static table contents to ext_tables_static+adt.sql now!</a></strong>',0,1);
2265                  $this->content.=$this->doc->spacer(20);
2266              }
2267          }
2268  
2269          // Table and field definitions:
2270          if (is_array($techInfo['dump_tf']))    {
2271              $dump_tf_array = $this->getTableAndFieldStructure($techInfo['dump_tf']);
2272              $dump_tf = $this->dumpTableAndFieldStructure($dump_tf_array);
2273              if ($this->CMD['writeTFdump'])    {
2274                  $writeFile = $absPath.'ext_tables.sql';
2275                  if (@is_file($writeFile))    {
2276                      t3lib_div::writeFile($writeFile,$dump_tf);
2277                      $this->content.=$this->doc->section('Table and field structure required',t3lib_div::formatSize(strlen($dump_tf)).'bytes written to '.substr($writeFile,strlen(PATH_site)),0,1);
2278                  }
2279              } else {
2280                  $msg = 'Dumping current database structure for:<br />';
2281                  if (is_array($techInfo['tables']))    {
2282                      $msg.= '<br /><strong>Tables:</strong><br />'.implode('<br />',$techInfo['tables']).'<br />';
2283                  }
2284                  if (is_array($techInfo['fields']))    {
2285                      $msg.= '<br /><strong>Solo-fields:</strong><br />'.implode('<br />',$techInfo['fields']).'<br />';
2286                  }
2287  
2288                  // ... then feed that to this function which will make new CREATE statements of the same fields but based on the current database content.
2289                  $this->content.=$this->doc->section('Table and field structure required',$msg.'<hr /><strong><a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[writeTFdump]=1').'">Write this dump to ext_tables.sql now!</a></strong><hr />
2290                  <pre>'.htmlspecialchars($dump_tf).'</pre>',0,1);
2291  
2292  
2293                  $details = '                            This dump is based on two factors:<br />
2294                  <ul>
2295                  <li>1) All tablenames in ext_tables.sql which are <em>not</em> found in the "modify_tables" list in ext_emconf.php are dumped with the current database structure.</li>
2296                  <li>2) For any tablenames which <em>are</em> listed in "modify_tables" all fields and keys found for the table in ext_tables.sql will be re-dumped with the fresh equalents from the database.</li>
2297                  </ul>
2298                  Bottomline is: Whole tables are dumped from database with no regard to which fields and keys are defined in ext_tables.sql. But for tables which are only modified, any NEW fields added to the database must in some form or the other exist in the ext_tables.sql file as well.<br />';
2299                  $this->content.=$this->doc->section('',$details);
2300              }
2301          }
2302      }
2303  
2304      /**
2305       * Returns file-listing of an extension
2306       *
2307       * @param    string        Extension key
2308       * @param    array        Extension information array
2309       * @return    string        HTML table.
2310       */
2311  	function getFileListOfExtension($extKey,$conf)    {
2312          $content = '';
2313          $extPath = $this->getExtPath($extKey,$conf['type']);
2314  
2315          if ($extPath)    {
2316              // Read files:
2317              $fileArr = array();
2318              $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr,$extPath,'',0,99,$this->excludeForPackaging);
2319  
2320              // Start table:
2321              $lines = array();
2322              $totalSize = 0;
2323  
2324              // Header:
2325              $lines[] = '
2326                  <tr class="bgColor5">
2327                      <td>File:</td>
2328                      <td>Size:</td>
2329                      <td>Edit:</td>
2330                  </tr>';
2331  
2332              foreach($fileArr as $file)    {
2333                  $fI = t3lib_div::split_fileref($file);
2334                  $lines[] = '
2335                  <tr class="bgColor4">
2336                      <td><a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[downloadFile]='.rawurlencode($file)).'" title="Download...">'.substr($file,strlen($extPath)).'</a></td>
2337                      <td>'.t3lib_div::formatSize(filesize($file)).'</td>
2338                      <td>'.(!in_array($extKey,$this->requiredExt)&&t3lib_div::inList($this->editTextExtensions,($fI['fileext']?$fI['fileext']:$fI['filebody']))?'<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$extKey.'&CMD[editFile]='.rawurlencode($file)).'">Edit file</a>':'').'</td>
2339                  </tr>';
2340                  $totalSize+=filesize($file);
2341              }
2342  
2343              $lines[] = '
2344                  <tr class="bgColor6">
2345                      <td><strong>Total:</strong></td>
2346                      <td><strong>'.t3lib_div::formatSize($totalSize).'</strong></td>
2347                      <td>&nbsp;</td>
2348                  </tr>';
2349  
2350              $content = '
2351              Path: '.$extPath.'<br /><br />
2352              <table border="0" cellpadding="1" cellspacing="2">'.implode('',$lines).'</table>';
2353          }
2354  
2355          return $content;
2356      }
2357  
2358      /**
2359       * Delete extension from the file system
2360       *
2361       * @param    string        Extension key
2362       * @param    array        Extension info array
2363       * @return    string        Returns message string about the status of the operation
2364       */
2365  	function extDelete($extKey,$extInfo)    {
2366          $absPath = $this->getExtPath($extKey,$extInfo['type']);
2367          if (t3lib_extMgm::isLoaded($extKey))    {
2368              return 'This extension is currently installed (loaded and active) and so cannot be deleted!';
2369          } elseif (!$this->deleteAsType($extInfo['type'])) {
2370              return 'You cannot delete (and install/update) extensions in the '.$this->typeLabels[$extInfo['type']].' scope.';
2371          } elseif (t3lib_div::inList('G,L',$extInfo['type'])) {
2372              if ($this->CMD['doDelete'] && !strcmp($absPath,$this->CMD['absPath'])) {
2373                  $res = $this->removeExtDirectory($absPath);
2374                  if ($res) {
2375                      return 'ERROR: Could not remove extension directory "'.$absPath.'". Had the following errors:<br /><br />'.
2376                      nl2br($res);
2377                  } else {
2378                      return 'Removed extension in path "'.$absPath.'"!';
2379                  }
2380              } else {
2381                  $onClick = "if (confirm('Are you sure you want to delete this extension from the server?')) {window.location.href='index.php?CMD[showExt]=".$extKey.'&CMD[doDelete]=1&CMD[absPath]='.rawurlencode($absPath)."';}";
2382                  $content.= '<a href="#" onclick="'.htmlspecialchars($onClick).' return false;"><strong>DELETE EXTENSION FROM SERVER</strong> (in the "'.$this->typeLabels[$extInfo['type']].'" location "'.substr($absPath,strlen(PATH_site)).'")!</a>';
2383                  $content.= '<br /><br />(Maybe you should make a backup first, see above.)';
2384                  return $content;
2385              }
2386          } else return 'Extension is not a global or local extension and cannot be removed.';
2387      }
2388  
2389      /**
2390       * Update extension EM_CONF...
2391       *
2392       * @param    string        Extension key
2393       * @param    array        Extension information array
2394       * @return    string        HTML content.
2395       */
2396  	function extUpdateEMCONF($extKey,$extInfo)    {
2397          $absPath = $this->getExtPath($extKey,$extInfo['type']);
2398          if ($this->CMD['doUpdateEMCONF']) {
2399              return $this->updateLocalEM_CONF($extKey,$extInfo);
2400          } else {
2401              $onClick = "if (confirm('Are you sure you want to update EM_CONF?')) {window.location.href='index.php?CMD[showExt]=".$extKey."&CMD[doUpdateEMCONF]=1';}";
2402              $content.= '<a href="#" onclick="'.htmlspecialchars($onClick).' return false;"><strong>Update extension EM_CONF file</strong> (in the "'.$this->typeLabels[$extInfo['type']].'" location "'.substr($absPath,strlen(PATH_site)).'")!</a>';
2403              $content.= '<br /><br />If files are changed, added or removed to an extension this is normally detected and displayed so you know that this extension has been locally altered and may need to be uploaded or at least not overridden.<br />
2404                          Updating this file will first of all reset this registration.';
2405              return $content;
2406          }
2407      }
2408  
2409      /**
2410       * Download extension as file / make backup
2411       *
2412       * @param    string        Extension key
2413       * @param    array        Extension information array
2414       * @return    string        HTML content
2415       */
2416  	function extBackup($extKey,$extInfo)    {
2417          $uArr = $this->makeUploadArray($extKey,$extInfo);
2418          if (is_array($uArr))    {
2419              $backUpData = $this->terConnection->makeUploadDataFromArray($uArr);
2420              $filename = 'T3X_'.$extKey.'-'.str_replace('.','_',$extInfo['EM_CONF']['version']).'-z-'.date('YmdHi').'.t3x';
2421              if (intval($this->CMD['doBackup'])==1)    {
2422                  header('Content-Type: application/octet-stream');
2423                  header('Content-Disposition: attachment; filename='.$filename);
2424                  echo $backUpData;
2425                  exit;
2426              } elseif ($this->CMD['dumpTables'])    {
2427                  $filename='T3X_'.$extKey;
2428                  $cTables = count(explode(',',$this->CMD['dumpTables']));
2429                  if ($cTables>1)    {
2430                      $filename.='-'.$cTables.'tables';
2431                  } else {
2432                      $filename.='-'.$this->CMD['dumpTables'];
2433                  }
2434                  $filename.='+adt.sql';
2435  
2436                  header('Content-Type: application/octet-stream');
2437                  header('Content-Disposition: attachment; filename='.$filename);
2438                  echo $this->dumpStaticTables($this->CMD['dumpTables']);
2439                  exit;
2440              } else {
2441                  $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo);
2442                  $lines=array();
2443                  $lines[]='<tr class="bgColor5"><td colspan="2"><strong>Make selection:</strong></td></tr>';
2444                  $lines[]='<tr class="bgColor4"><td><strong>Extension files:</strong></td><td>'.
2445                  '<a href="'.htmlspecialchars('index.php?CMD[doBackup]=1&CMD[showExt]='.$extKey).'">Download extension "'.$extKey.'" as a file</a><br />('.$filename.', '.t3lib_div::formatSize(strlen($backUpData)).', MD5: '.md5($backUpData).')<br /></td></tr>';
2446  
2447                  if (is_array($techInfo['tables']))    {    $lines[]='<tr class="bgColor4"><td><strong>Data tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo['tables'],$extKey).'</td></tr>';    }
2448                  if (is_array($techInfo['static']))    {    $lines[]='<tr class="bgColor4"><td><strong>Static tables:</strong></td><td>'.$this->extBackup_dumpDataTablesLine($techInfo['static'],$extKey).'</td></tr>';    }
2449  
2450                  $content = '<table border="0" cellpadding="2" cellspacing="2">'.implode('',$lines).'</table>';
2451                  return $content;
2452              }
2453          } else die('Error...');
2454      }
2455  
2456      /**
2457       * Link to dump of database tables
2458       *
2459       * @param    string        Extension key
2460       * @param    array        Extension information array
2461       * @return    string        HTML
2462       */
2463  	function extBackup_dumpDataTablesLine($tablesArray,$extKey)    {
2464          $tables = array();
2465          $tablesNA = array();
2466  
2467          foreach($tablesArray as $tN)    {
2468              $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*)', $tN, '');
2469              if (!$GLOBALS['TYPO3_DB']->sql_error())    {
2470                  $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
2471                  $tables[$tN]='<tr><td>&nbsp;</td><td><a href="'.htmlspecialchars('index.php?CMD[dumpTables]='.rawurlencode($tN).'&CMD[showExt]='.$extKey).'" title="Dump table \''.$tN.'\'">'.$tN.'</a></td><td>&nbsp;&nbsp;&nbsp;</td><td>'.$row[0].' records</td></tr>';
2472              } else {
2473                  $tablesNA[$tN]='<tr><td>&nbsp;</td><td>'.$tN.'</td><td>&nbsp;</td><td>Did not exist.</td></tr>';
2474              }
2475          }
2476          $label = '<table border="0" cellpadding="0" cellspacing="0">'.implode('',array_merge($tables,$tablesNA)).'</table>';// Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
2477          if (count($tables))    {
2478              $label = '<a href="'.htmlspecialchars('index.php?CMD[dumpTables]='.rawurlencode(implode(',',array_keys($tables))).'&CMD[showExt]='.$extKey).'" title="Dump all existing tables.">Download all data from:</a><br /><br />'.$label;
2479          } else $label = 'Nothing to dump...<br /><br />'.$label;
2480          return $label;
2481      }
2482  
2483      /**
2484       * Prints a table with extension information in it.
2485       *
2486       * @param    string        Extension key
2487       * @param    array        Extension information array
2488       * @param    boolean        If set, the information array shows information for a remote extension in TER, not a local one.
2489       * @return    string        HTML content.
2490       */
2491  	function extInformationArray($extKey,$extInfo,$remote=0)    {
2492          $lines=array();
2493          $lines[]='<tr class="bgColor5"><td colspan="2"><strong>General information:</strong></td>'.$this->helpCol('').'</tr>';
2494          $lines[]='<tr class="bgColor4"><td>Title:</td><td>'.$extInfo['EM_CONF']['_icon'].$extInfo['EM_CONF']['title'].'</td>'.$this->helpCol('title').'</tr>';
2495          $lines[]='<tr class="bgColor4"><td>Description:</td><td>'.nl2br(htmlspecialchars($extInfo['EM_CONF']['description'])).'</td>'.$this->helpCol('description').'</tr>';
2496          $lines[]='<tr class="bgColor4"><td>Author:</td><td>'.$this->wrapEmail($extInfo['EM_CONF']['author'].($extInfo['EM_CONF']['author_email'] ? ' <'.$extInfo['EM_CONF']['author_email'].'>' : ''),$extInfo['EM_CONF']['author_email']).($extInfo['EM_CONF']['author_company']?', '.$extInfo['EM_CONF']['author_company']:'').
2497          '</td>'.$this->helpCol('description').'</tr>';
2498  
2499          $lines[]='<tr class="bgColor4"><td>Version:</td><td>'.$extInfo['EM_CONF']['version'].'</td>'.$this->helpCol('version').'</tr>';
2500          $lines[]='<tr class="bgColor4"><td>Category:</td><td>'.$this->categories[$extInfo['EM_CONF']['category']].'</td>'.$this->helpCol('category').'</tr>';
2501          $lines[]='<tr class="bgColor4"><td>State:</td><td>'.$this->states[$extInfo['EM_CONF']['state']].'</td>'.$this->helpCol('state').'</tr>';
2502          $lines[]='<tr class="bgColor4"><td>Shy?</td><td>'.($extInfo['EM_CONF']['shy']?'Yes':'').'</td>'.$this->helpCol('shy').'</tr>';
2503          $lines[]='<tr class="bgColor4"><td>Internal?</td><td>'.($extInfo['EM_CONF']['internal']?'Yes':'').'</td>'.$this->helpCol('internal').'</tr>';
2504  
2505          $lines[]='<tr class="bgColor4"><td>Depends on:</td><td>'.$this->depToString($extInfo['EM_CONF']['constraints']).'</td>'.$this->helpCol('dependencies').'</tr>';
2506          $lines[]='<tr class="bgColor4"><td>Conflicts with:</td><td>'.$this->depToString($extInfo['EM_CONF']['constraints'],'conflicts').'</td>'.$this->helpCol('dependencies').'</tr>';
2507          $lines[]='<tr class="bgColor4"><td>Suggests:</td><td>'.$this->depToString($extInfo['EM_CONF']['constraints'],'suggests').'</td>'.$this->helpCol('dependencies').'</tr>';
2508          if (!$remote)    {
2509              $lines[]='<tr class="bgColor4"><td>Priority:</td><td>'.$extInfo['EM_CONF']['priority'].'</td>'.$this->helpCol('priority').'</tr>';
2510              $lines[]='<tr class="bgColor4"><td>Clear cache?</td><td>'.($extInfo['EM_CONF']['clearCacheOnLoad']?'Yes':'').'</td>'.$this->helpCol('clearCacheOnLoad').'</tr>';
2511              $lines[]='<tr class="bgColor4"><td>Includes modules:</td><td>'.$extInfo['EM_CONF']['module'].'</td>'.$this->helpCol('module').'</tr>';
2512              $lines[]='<tr class="bgColor4"><td>Lock Type?</td><td>'.($extInfo['EM_CONF']['lockType']?$extInfo['EM_CONF']['lockType']:'').'</td>'.$this->helpCol('lockType').'</tr>';
2513              $lines[]='<tr class="bgColor4"><td>Modifies tables:</td><td>'.$extInfo['EM_CONF']['modify_tables'].'</td>'.$this->helpCol('modify_tables').'</tr>';
2514  
2515              // Installation status:
2516              $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo,1);
2517              $lines[]='<tr><td>&nbsp;</td><td></td>'.$this->helpCol('').'</tr>';
2518              $lines[]='<tr class="bgColor5"><td colspan="2"><strong>Installation status:</strong></td>'.$this->helpCol('').'</tr>';
2519              $lines[]='<tr class="bgColor4"><td>Type of install:</td><td>'.$this->typeLabels[$extInfo['type']].' - <em>'.$this->typeDescr[$extInfo['type']].'</em></td>'.$this->helpCol('type').'</tr>';
2520              $lines[]='<tr class="bgColor4"><td>Double installs?</td><td>'.$this->extInformationArray_dbInst($extInfo['doubleInstall'],$extInfo['type']).'</td>'.$this->helpCol('doubleInstall').'</tr>';
2521              if (is_array($extInfo['files']))    {
2522                  sort($extInfo['files']);
2523                  $lines[]='<tr class="bgColor4"><td>Root files:</td><td>'.implode('<br />',$extInfo['files']).'</td>'.$this->helpCol('rootfiles').'</tr>';
2524              }
2525  
2526              if ($techInfo['tables']||$techInfo['static']||$techInfo['fields'])    {
2527                  if (!$remote && t3lib_extMgm::isLoaded($extKey))    {
2528                      $tableStatus = $GLOBALS['TBE_TEMPLATE']->rfw(($techInfo['tables_error']?'<strong>Table error!</strong><br />Probably one or more required fields/tables are missing in the database!':'').
2529                      ($techInfo['static_error']?'<strong>Static table error!</strong><br />The static tables are missing or empty!':''));
2530                  } else {
2531                      $tableStatus = $techInfo['tables_error']||$techInfo['static_error'] ? 'The database will need to be updated when this extension is installed.' : 'All required tables are already in the database!';
2532                  }
2533              }
2534  
2535              $lines[]='<tr class="bgColor4"><td>Database requirements:</td><td>'.$this->extInformationArray_dbReq($techInfo,1).'</td>'.$this->helpCol('dbReq').'</tr>';
2536              $lines[]='<tr class="bgColor4"><td>Database status:</td><td>'.$tableStatus.'</td>'.$this->helpCol('dbStatus').'</tr>';
2537              $lines[]='<tr class="bgColor4"><td>Flags:</td><td>'.(is_array($techInfo['flags'])?implode('<br />',$techInfo['flags']):'').'</td>'.$this->helpCol('flags').'</tr>';
2538              $lines[]='<tr class="bgColor4"><td>Config template?</td><td>'.($techInfo['conf']?'Yes':'').'</td>'.$this->helpCol('conf').'</tr>';
2539              $lines[]='<tr class="bgColor4"><td>TypoScript files:</td><td>'.(is_array($techInfo['TSfiles'])?implode('<br />',$techInfo['TSfiles']):'').'</td>'.$this->helpCol('TSfiles').'</tr>';
2540              $lines[]='<tr class="bgColor4"><td>Language files:</td><td>'.(is_array($techInfo['locallang'])?implode('<br />',$techInfo['locallang']):'').'</td>'.$this->helpCol('locallang').'</tr>';
2541              $lines[]='<tr class="bgColor4"><td>Upload folder:</td><td>'.($techInfo['uploadfolder']?$techInfo['uploadfolder']:'').'</td>'.$this->helpCol('uploadfolder').'</tr>';
2542              $lines[]='<tr class="bgColor4"><td>Create directories:</td><td>'.(is_array($techInfo['createDirs'])?implode('<br />',$techInfo['createDirs']):'').'</td>'.$this->helpCol('createDirs').'</tr>';
2543              $lines[]='<tr class="bgColor4"><td>Module names:</td><td>'.(is_array($techInfo['moduleNames'])?implode('<br />',$techInfo['moduleNames']):'').'</td>'.$this->helpCol('moduleNames').'</tr>';
2544              $lines[]='<tr class="bgColor4"><td>Class names:</td><td>'.(is_array($techInfo['classes'])?implode('<br />',$techInfo['classes']):'').'</td>'.$this->helpCol('classNames').'</tr>';
2545              $lines[]='<tr class="bgColor4"><td>Code warnings:<br />(developer-relevant)</td><td>'.(is_array($techInfo['errors'])?$GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />',$techInfo['errors'])):'').'</td>'.$this->helpCol('errors').'</tr>';
2546              $lines[]='<tr class="bgColor4"><td>Naming annoyances:<br />(developer-relevant)</td><td>'.(is_array($techInfo['NSerrors']) ? (!t3lib_div::inList($this->nameSpaceExceptions,$extKey)?t3lib_div::view_array($techInfo['NSerrors']):$GLOBALS['TBE_TEMPLATE']->dfw('[exception]')) : '').'</td>'.$this->helpCol('NSerrors').'</tr>';
2547  
2548              $currentMd5Array = $this->serverExtensionMD5Array($extKey,$extInfo);
2549              $affectedFiles='';
2550  
2551              $msgLines=array();
2552              if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'],serialize($currentMd5Array)))    {
2553                  $msgLines[] = $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>A difference between the originally installed version and the current was detected!</strong>');
2554                  $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($extInfo['EM_CONF']['_md5_values_when_last_written']));
2555                  if (count($affectedFiles))    $msgLines[] = '<br /><strong>Modified files:</strong><br />'.$GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />',$affectedFiles));
2556              }
2557              $lines[]='<tr class="bgColor4"><td>Files changed?</td><td>'.implode('<br />',$msgLines).'</td>'.$this->helpCol('filesChanged').'</tr>';
2558          }
2559  
2560          return '<table border="0" cellpadding="1" cellspacing="2">
2561                      '.implode('
2562                      ',$lines).'
2563                  </table>';
2564      }
2565  
2566      /**
2567       * Returns HTML with information about database requirements
2568       *
2569       * @param    array        Technical information array
2570       * @param    boolean        Table header displayed
2571       * @return    string        HTML content.
2572       */
2573  	function extInformationArray_dbReq($techInfo,$tableHeader=0)    {
2574          return nl2br(trim((is_array($techInfo['tables'])?($tableHeader?"\n\n<strong>Tables:</strong>\n":'').implode(chr(10),$techInfo['tables']):'').
2575          (is_array($techInfo['static'])?"\n\n<strong>Static tables:</strong>\n".implode(chr(10),$techInfo['static']):'').
2576          (is_array($techInfo['fields'])?"\n\n<strong>Additional fields:</strong>\n".implode('<hr />',$techInfo['fields']):'')));
2577      }
2578  
2579      /**
2580       * Double install warning.
2581       *
2582       * @param    string        Double-install string, eg. "LG" etc.
2583       * @param    string        Current scope, eg. "L" or "G" or "S"
2584       * @return    string        Message
2585       */
2586  	function extInformationArray_dbInst($dbInst,$current)    {
2587          if (strlen($dbInst)>1)    {
2588              $others = array();
2589              for($a=0;$a<strlen($dbInst);$a++)    {
2590                  if (substr($dbInst,$a,1)!=$current)    {
2591                      $others[]='"'.$this->typeLabels[substr($dbInst,$a,1)].'"';
2592                  }
2593              }
2594              return $GLOBALS['TBE_TEMPLATE']->rfw('A '.implode(' and ',$others).' extension with this key is also available on the server, but cannot be loaded because the "'.$this->typeLabels[$current].'" version takes precedence.');
2595          } else return '';
2596      }
2597  
2598      /**
2599       * Prints the upload form for extensions
2600       *
2601       * @param    string        Extension key
2602       * @param    array        Extension information array
2603       * @return    string        HTML content.
2604       */
2605  	function getRepositoryUploadForm($extKey,$extInfo)    {
2606          $content.='
2607              <input type="hidden" name="CMD[showExt]" value="'.$extKey.'" />
2608              <input type="hidden" name="em[action]" value="doUpload" />
2609              <table border="0" cellpadding="2" cellspacing="1">
2610                  <tr class="bgColor4">
2611                      <td>Repository Username:</td>
2612                      <td><input'.$this->doc->formWidth(20).' type="text" name="em[user][fe_u]" value="'.$this->fe_user['username'].'" /></td>
2613                  </tr>
2614                  <tr class="bgColor4">
2615                      <td>Repository Password:</td>
2616                      <td><input'.$this->doc->formWidth(20).' type="password" name="em[user][fe_p]" value="'.$this->fe_user['password'].'" /></td>
2617                  </tr>
2618                  <tr class="bgColor4">
2619                      <td>Changelog for upload:</td>
2620                      <td><textarea'.$this->doc->formWidth(30,1).' rows="5" name="em[upload][comment]"></textarea></td>
2621                  </tr>
2622                  <tr class="bgColor4">
2623                      <td>Upload command:</td>
2624                      <td nowrap="nowrap">
2625                          <input type="radio" name="em[upload][mode]" id="new_dev" value="new_dev" checked="checked" /> <label for="new_dev">New development version (latest x.x.<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>)</label><br />
2626                          <input type="radio" name="em[upload][mode]" id="latest" value="latest" /> <label for="latest">Override <em>this</em> development version ('.$extInfo['EM_CONF']['version'].')</label><br />
2627                          <input type="radio" name="em[upload][mode]" id="new_sub" value="new_sub" /> <label for="new_sub">New sub version (latest x.<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>.0)</label><br />
2628                          <input type="radio" name="em[upload][mode]" id="new_main" value="new_main" /> <label for="new_main">New main version (latest <strong>'.$GLOBALS['TBE_TEMPLATE']->rfw('x+1').'</strong>.0.0)</label><br />
2629                          <input type="radio" name="em[upload][mode]" id="custom" value="custom" /> <label for="custom">This version: <input type="text" name="em[upload][version]" /></label><br />
2630                      </td>
2631                  </tr>
2632                  <tr class="bgColor4">
2633                      <td>&nbsp;</td>
2634                      <td><input type="submit" name="submit" value="Upload extension" />
2635                      </td>
2636                  </tr>
2637              </table>
2638              ';
2639  
2640          return $content;
2641      }
2642  
2643  
2644  
2645  
2646  
2647  
2648  
2649  
2650  
2651  
2652      /***********************************
2653      *
2654      * Extension list rendering
2655      *
2656      **********************************/
2657  
2658      /**
2659       * Prints the header row for the various listings
2660       *
2661       * @param    string        Attributes for the <tr> tag
2662       * @param    array        Preset cells in the beginning of the row. Typically a blank cell with a clear-gif
2663       * @param    boolean        If set, the list is coming from remote server.
2664       * @return    string        HTML <tr> table row
2665       */
2666  	function extensionListRowHeader($trAttrib,$cells,$import=0)    {
2667          $cells[] = '<td></td>';
2668          $cells[] = '<td>Title:</td>';
2669  
2670          if (!$this->MOD_SETTINGS['display_details'])    {
2671              $cells[] = '<td>Description:</td>';
2672              $cells[] = '<td>Author:</td>';
2673          } elseif ($this->MOD_SETTINGS['display_details']==2)    {
2674              $cells[] = '<td>Priority:</td>';
2675              $cells[] = '<td>Mod.Tables:</td>';
2676              $cells[] = '<td>Modules:</td>';
2677              $cells[] = '<td>Cl.Cache?</td>';
2678              $cells[] = '<td>Internal?</td>';
2679              $cells[] = '<td>Shy?</td>';
2680          } elseif ($this->MOD_SETTINGS['display_details']==3)    {
2681              $cells[] = '<td>Tables/Fields:</td>';
2682              $cells[] = '<td>TS-files:</td>';
2683              $cells[] = '<td>Affects:</td>';
2684              $cells[] = '<td>Modules:</td>';
2685              $cells[] = '<td>Config?</td>';
2686              $cells[] = '<td>Code warnings:</td>';
2687          } elseif ($this->MOD_SETTINGS['display_details']==4)    {
2688              $cells[] = '<td>locallang:</td>';
2689              $cells[] = '<td>Classes:</td>';
2690              $cells[] = '<td>Code warnings:</td>';
2691              $cells[] = '<td>Nameing annoyances:</td>';
2692          } elseif ($this->MOD_SETTINGS['display_details']==5)    {
2693              $cells[] = '<td>Changed files:</td>';
2694          } else {
2695              $cells[] = '<td>Extension key:</td>';
2696              $cells[] = '<td>Version:</td>';
2697              if (!$import) {
2698                  $cells[] = '<td>DL:</td>';
2699                  $cells[] = '<td>Doc:</td>';
2700                  $cells[] = '<td>Type:</td>';
2701              } else {
2702                  $cells[] = '<td class="bgColor6"'.$this->labelInfo('Current version of the extension on this server. If colored red there is a newer version in repository! Then you should upgrade.').'>Cur. Ver:</td>';
2703                  $cells[] = '<td class="bgColor6"'.$this->labelInfo('Current type of installation of the extension on this server.').'>Cur. Type:</td>';
2704                  $cells[] = '<td'.$this->labelInfo('Number of downloads, all versions/this version').'>DL:</td>';
2705              }
2706              $cells[] = '<td>State:</td>';
2707          }
2708          return '
2709              <tr'.$trAttrib.'>
2710                  '.implode('
2711                  ',$cells).'
2712              </tr>';
2713      }
2714  
2715      /**
2716       * Prints a row with data for the various extension listings
2717       *
2718       * @param    string        Extension key
2719       * @param    array        Extension information array
2720       * @param    array        Preset table cells, eg. install/uninstall icons.
2721       * @param    string        <tr> tag class
2722       * @param    array        Array with installed extension keys (as keys)
2723       * @param    boolean        If set, the list is coming from remote server.
2724       * @param    string        Alternative link URL
2725       * @return    string        HTML <tr> content
2726       */
2727  	function extensionListRow($extKey,$extInfo,$cells,$bgColorClass='',$inst_list=array(),$import=0,$altLinkUrl='')    {
2728  
2729              // Icon:
2730          $imgInfo = @getImageSize($this->getExtPath($extKey,$extInfo['type']).'/ext_icon.gif');
2731          if (is_array($imgInfo))    {
2732              $cells[] = '<td><img src="'.$GLOBALS['BACK_PATH'].$this->typeRelPaths[$extInfo['type']].$extKey.'/ext_icon.gif'.'" '.$imgInfo[3].' alt="" /></td>';
2733          } elseif ($extInfo['_ICON']) {
2734              $cells[] = '<td>'.$extInfo['_ICON'].'</td>';
2735          } else {
2736              $cells[] = '<td><img src="clear.gif" width="1" height="1" alt="" /></td>';
2737          }
2738  
2739              // Extension title:
2740          $cells[] = '<td nowrap="nowrap"><a href="'.htmlspecialchars($altLinkUrl?$altLinkUrl:'index.php?CMD[showExt]='.$extKey.'&SET[singleDetails]=info').'" title="'.$extKey.'"'/*.($extInfo['EM_CONF']['shy'] ? ' style="color:#666;" ' : '')*/.'>'.t3lib_div::fixed_lgd($extInfo['EM_CONF']['title']?$extInfo['EM_CONF']['title']:'<em>'.$extKey.'</em>',40).'</a></td>';
2741  
2742              // Based on which display mode you will see more or less details:
2743          if (!$this->MOD_SETTINGS['display_details'])    {
2744              $cells[] = '<td>'.htmlspecialchars(t3lib_div::fixed_lgd($extInfo['EM_CONF']['description'],400)).'<br /><img src="clear.gif" width="300" height="1" alt="" /></td>';
2745              $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['author_email'] ? '<a href="mailto:'.htmlspecialchars($extInfo['EM_CONF']['author_email']).'">' : '').htmlspecialchars($extInfo['EM_CONF']['author']).($extInfo['EM_CONF']['author_email'] ? '</a>' : '').($extInfo['EM_CONF']['author_company'] ? '<br />'.htmlspecialchars($extInfo['EM_CONF']['author_company']) : '').'</td>';
2746          } elseif ($this->MOD_SETTINGS['display_details']==2)    {
2747              $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['priority'].'</td>';
2748              $cells[] = '<td nowrap="nowrap">'.implode('<br />',t3lib_div::trimExplode(',',$extInfo['EM_CONF']['modify_tables'],1)).'</td>';
2749              $cells[] = '<td nowrap="nowrap">'.$extInfo['EM_CONF']['module'].'</td>';
2750              $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['clearCacheOnLoad'] ? 'Yes' : '').'</td>';
2751              $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['internal'] ? 'Yes' : '').'</td>';
2752              $cells[] = '<td nowrap="nowrap">'.($extInfo['EM_CONF']['shy'] ? 'Yes' : '').'</td>';
2753          } elseif ($this->MOD_SETTINGS['display_details']==3)    {
2754              $techInfo = $this->makeDetailedExtensionAnalysis($extKey,$extInfo);
2755  
2756              $cells[] = '<td>'.$this->extInformationArray_dbReq($techInfo).
2757              '</td>';
2758              $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['TSfiles']) ? implode('<br />',$techInfo['TSfiles']) : '').'</td>';
2759              $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['flags']) ? implode('<br />',$techInfo['flags']) : '').'</td>';
2760              $cells[] = '<td nowrap="nowrap">'.(is_array($techInfo['moduleNames']) ? implode('<br />',$techInfo['moduleNames']) : '').'</td>';
2761              $cells[] = '<td nowrap="nowrap">'.($techInfo['conf'] ? 'Yes' : '').'</td>';
2762              $cells[] = '<td>'.
2763              $GLOBALS['TBE_TEMPLATE']->rfw((t3lib_extMgm::isLoaded($extKey)&&$techInfo['tables_error']?'<strong>Table error!</strong><br />Probably one or more required fields/tables are missing in the database!':'').
2764              (t3lib_extMgm::isLoaded($extKey)&&$techInfo['static_error']?'<strong>Static table error!</strong><br />The static tables are missing or empty!':'')).
2765              '</td>';
2766          } elseif ($this->MOD_SETTINGS['display_details']==4)    {
2767              $techInfo=$this->makeDetailedExtensionAnalysis($extKey,$extInfo,1);
2768  
2769              $cells[] = '<td>'.(is_array($techInfo['locallang']) ? implode('<br />',$techInfo['locallang']) : '').'</td>';
2770              $cells[] = '<td>'.(is_array($techInfo['classes']) ? implode('<br />',$techInfo['classes']) : '').'</td>';
2771              $cells[] = '<td>'.(is_array($techInfo['errors']) ? $GLOBALS['TBE_TEMPLATE']->rfw(implode('<hr />',$techInfo['errors'])) : '').'</td>';
2772              $cells[] = '<td>'.(is_array($techInfo['NSerrors']) ? (!t3lib_div::inList($this->nameSpaceExceptions,$extKey) ? t3lib_div::view_array($techInfo['NSerrors']) : $GLOBALS['TBE_TEMPLATE']->dfw('[exception]')) :'').'</td>';
2773          } elseif ($this->MOD_SETTINGS['display_details']==5)    {
2774              $currentMd5Array = $this->serverExtensionMD5Array($extKey,$extInfo);
2775              $affectedFiles = '';
2776              $msgLines = array();
2777              $msgLines[] = 'Files: '.count($currentMd5Array);
2778              if (strcmp($extInfo['EM_CONF']['_md5_values_when_last_written'],serialize($currentMd5Array)))    {
2779                  $msgLines[] = $GLOBALS['TBE_TEMPLATE']->rfw('<br /><strong>A difference between the originally installed version and the current was detected!</strong>');
2780                  $affectedFiles = $this->findMD5ArrayDiff($currentMd5Array,unserialize($extInfo['EM_CONF']['_md5_values_when_last_written']));
2781                  if (count($affectedFiles))    $msgLines[] = '<br /><strong>Modified files:</strong><br />'.$GLOBALS['TBE_TEMPLATE']->rfw(implode('<br />',$affectedFiles));
2782              }
2783              $cells[] = '<td>'.implode('<br />',$msgLines).'</td>';
2784          } else {
2785                  // Default view:
2786              $verDiff = $inst_list[$extKey] && $this->versionDifference($extInfo['EM_CONF']['version'],$inst_list[$extKey]['EM_CONF']['version'],$this->versionDiffFactor);
2787  
2788              $cells[] = '<td nowrap="nowrap"><em>'.$extKey.'</em></td>';
2789              $cells[] = '<td nowrap="nowrap">'.($verDiff ? '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw(htmlspecialchars($extInfo['EM_CONF']['version'])).'</strong>' : $extInfo['EM_CONF']['version']).'</td>';
2790              if (!$import) {        // Listing extenson on LOCAL server:
2791                      // Extension Download:
2792                  $cells[] = '<td nowrap="nowrap"><a href="'.htmlspecialchars('index.php?CMD[doBackup]=1&SET[singleDetails]=backup&CMD[showExt]='.$extKey).'"><img src="download.png" width="13" height="12" title="Download" alt="" /></a></td>';
2793  
2794                      // Manual download
2795                  $fileP = PATH_site.$this->typePaths[$extInfo['type']].$extKey.'/doc/manual.sxw';
2796                  $cells[] = '<td nowrap="nowrap">'.
2797                  ($this->typePaths[$extInfo['type']] && @is_file($fileP)?'<a href="'.htmlspecialchars(t3lib_div::resolveBackPath($this->doc->backPath.'../'.$this->typePaths[$extInfo['type']].$extKey.'/doc/manual.sxw')).'" target="_blank"><img src="oodoc.gif" width="13" height="16" title="Local Open Office Manual" alt="" /></a>':'').
2798                  '</td>';
2799                  $cells[] = '<td nowrap="nowrap">'.$this->typeLabels[$extInfo['type']].(strlen($extInfo['doubleInstall'])>1?'<strong> '.$GLOBALS['TBE_TEMPLATE']->rfw($extInfo['doubleInstall']).'</strong>':'').'</td>';
2800              } else {    // Listing extensions from REMOTE repository:
2801                  $inst_curVer = $inst_list[$extKey]['EM_CONF']['version'];
2802                  if (isset($inst_list[$extKey]))    {
2803                      if ($verDiff)    $inst_curVer = '<strong>'.$GLOBALS['TBE_TEMPLATE']->rfw($inst_curVer).'</strong>';
2804                  }
2805                  $cells[] = '<td nowrap="nowrap">'.$inst_curVer.'</td>';
2806                  $cells[] = '<td nowrap="nowrap">'.$this->typeLabels[$inst_list[$extKey]['type']].(strlen($inst_list[$extKey]['doubleInstall'])>1?'<strong> '.$GLOBALS['TBE_TEMPLATE']->rfw($inst_list[$extKey]['doubleInstall']).'</strong>':'').'</td>';
2807                  $cells[] = '<td nowrap="nowrap">'.($extInfo['downloadcounter_all']?$extInfo['downloadcounter_all']:'&nbsp;&nbsp;').'/'.($extInfo['downloadcounter']?$extInfo['downloadcounter']:'&nbsp;').'</td>';
2808              }
2809              $cells[] = '<td nowrap="nowrap" class="extstate" style="background-color:'.$this->stateColors[$extInfo['EM_CONF']['state']].';">'.$this->states[$extInfo['EM_CONF']['state']].'</td>';
2810          }
2811  
2812          if($this->xmlhandler->getReviewState($extKey,$extInfo['EM_CONF']['version'])<1) {
2813              $bgclass = ' class="unsupported-ext"';
2814          } else {
2815              $bgclass = ' class="'.($bgColorClass?$bgColorClass:'bgColor4').'"';
2816          }
2817  
2818          return '
2819              <tr'.$bgclass.'>
2820                  '.implode('
2821                  ',$cells).'
2822              </tr>';
2823      }
2824  
2825  
2826  
2827  
2828  
2829  
2830      /************************************
2831      *
2832      * Output helper functions
2833      *
2834      ************************************/
2835  
2836      /**
2837       * Wrapping input string in a link tag with link to email address
2838       *
2839       * @param    string        Input string, being wrapped in <a> tags
2840       * @param    string        Email address for use in link.
2841       * @return    string        Output
2842       */
2843  	function wrapEmail($str,$email)    {
2844          if ($email)    {
2845              $str = '<a href="mailto:'.htmlspecialchars($email).'">'.htmlspecialchars($str).'</a>';
2846          }
2847          return $str;
2848      }
2849  
2850      /**
2851       * Returns help text if applicable.
2852       *
2853       * @param    string        Help text key
2854       * @return    string        HTML table cell
2855       */
2856  	function helpCol($key)    {
2857          global $BE_USER;
2858          if ($BE_USER->uc['edit_showFieldHelp'])    {
2859              $hT = trim(t3lib_BEfunc::helpText($this->descrTable,'emconf_'.$key,$this->doc->backPath));
2860              return '<td>'.($hT?$hT:t3lib_BEfunc::helpTextIcon($this->descrTable,'emconf_'.$key,$this->doc->backPath)).'</td>';
2861          } else {
2862              return '';
2863          }
2864      }
2865  
2866      /**
2867       * Returns title and style attribute for mouseover help text.
2868       *
2869       * @param    string        Help text.
2870       * @return    string        title="" attribute prepended with a single space
2871       */
2872  	function labelInfo($str)    {
2873          return ' title="'.htmlspecialchars($str).'" style="cursor:help;"';
2874      }
2875  
2876      /**
2877       * Returns a header for an extensions including icon if any
2878       *
2879       * @param    string        Extension key
2880       * @param    array        Extension information array
2881       * @param    string        align-attribute value (for <img> tag)
2882       * @return    string        HTML; Extension title and image.
2883       */
2884  	function extensionTitleIconHeader($extKey,$extInfo,$align='top')    {
2885          $imgInfo = @getImageSize($this->getExtPath($extKey,$extInfo['type']).'/ext_icon.gif');
2886          $out = '';
2887          if (is_array($imgInfo))    {
2888              $out.= '<img src="'.$GLOBALS['BACK_PATH'].$this->typeRelPaths[$extInfo['type']].$extKey.'/ext_icon.gif" '.$imgInfo[3].' align="'.$align.'" alt="" />';
2889          }
2890          $out.= $extInfo['EM_CONF']['title'] ? htmlspecialchars(t3lib_div::fixed_lgd($extInfo['EM_CONF']['title'],40)) : '<em>'.$extKey.'</em>';
2891          return $out;
2892      }
2893  
2894      /**
2895       * Returns image tag for "uninstall"
2896       *
2897       * @return    string        <img> tag
2898       */
2899  	function removeButton()    {
2900          return '<img src="uninstall.gif" width="16" height="16" title="Remove extension" align="top" alt="" />';
2901      }
2902  
2903      /**
2904       * Returns image for "install"
2905       *
2906       * @return    string        <img> tag
2907       */
2908  	function installButton()    {
2909          return '<img src="install.gif" width="16" height="16" title="Install extension..." align="top" alt="" />';
2910      }
2911  
2912      /**
2913       * Warning (<img> + text string) message about the impossibility to import extensions (both local and global locations are disabled...)
2914       *
2915       * @return    string        <img> + text string.
2916       */
2917  	function noImportMsg()    {
2918          return '<img src="'.$this->doc->backPath.'gfx/icon_warning2.gif" width="18" height="16" align="top" alt="" /><strong>Import to both local and global path is disabled in TYPO3_CONF_VARS!</strong>';
2919      }
2920  
2921      /**
2922       * Checks whether the passed dependency is TER2-style (array) and returns a single string for displaying the dependencies.
2923       *
2924       * It leaves out all version numbers and the "php" and "typo3" dependencies, as they are implicit and of no interest without the version number.
2925       *
2926       * @param    mixed        $dep Either a string or an array listing dependencies.
2927       * @param    string        $type The dependency type to list if $dep is an array
2928       * @return    string        A simple dependency list for display
2929       */
2930  	function depToString($dep,$type='depends') {
2931          if(is_array($dep)) {
2932              unset($dep[$type]['php']);
2933              unset($dep[$type]['typo3']);
2934              $s = (count($dep[$type])) ? implode(',', array_keys($dep[$type])) : '';
2935              return $s;
2936          }
2937          return '';
2938      }
2939  
2940      /**
2941       * Checks whether the passed dependency is TER-style (string) or TER2-style (array) and returns a single string for displaying the dependencies.
2942       *
2943       * It leaves out all version numbers and the "php" and "typo3" dependencies, as they are implicit and of no interest without the version number.
2944       *
2945       * @param    mixed        $dep Either a string or an array listing dependencies.
2946       * @param    string        $type The dependency type to list if $dep is an array
2947       * @return    string        A simple dependency list for display
2948       */
2949  	function stringToDep($dep) {
2950          $constraint = array();
2951          if(is_string($dep) && strlen($dep)) {
2952              $dep = explode(',',$dep);
2953              foreach($dep as $v) {
2954                  $constraint[$v] = '';
2955              }
2956          }
2957          return $constraint;
2958      }
2959  
2960  
2961  
2962  
2963  
2964  
2965  
2966  
2967      /********************************
2968      *
2969      * Read information about all available extensions
2970      *
2971      *******************************/
2972  
2973      /**
2974       * Returns the list of available (installed) extensions
2975       *
2976       * @return    array        Array with two arrays, list array (all extensions with info) and category index
2977       * @see getInstExtList()
2978       */
2979  	function getInstalledExtensions()    {
2980          $list = array();
2981          $cat = $this->defaultCategories;
2982  
2983          $path = PATH_typo3.'sysext/';
2984          $this->getInstExtList($path,$list,$cat,'S');
2985  
2986          $path = PATH_typo3.'ext/';
2987          $this->getInstExtList($path,$list,$cat,'G');
2988  
2989          $path = PATH_typo3conf.'ext/';
2990          $this->getInstExtList($path,$list,$cat,'L');
2991  
2992          return array($list,$cat);
2993      }
2994  
2995      /**
2996       * Gathers all extensions in $path
2997       *
2998       * @param    string        Absolute path to local, global or system extensions
2999       * @param    array        Array with information for each extension key found. Notice: passed by reference
3000       * @param    array        Categories index: Contains extension titles grouped by various criteria.
3001       * @param    string        Path-type: L, G or S
3002       * @return    void        "Returns" content by reference
3003       * @access private
3004       * @see getInstalledExtensions()
3005       */
3006  	function getInstExtList($path,&$list,&$cat,$type)    {
3007  
3008          if (@is_dir($path))    {
3009              $extList = t3lib_div::get_dirs($path);
3010              if (is_array($extList))    {
3011                  foreach($extList as $extKey)    {
3012                      if (@is_file($path.$extKey.'/ext_emconf.php'))    {
3013                          $emConf = $this->includeEMCONF($path.$extKey.'/ext_emconf.php', $extKey);
3014                          if (is_array($emConf))    {
3015                              if (is_array($list[$extKey]))    {
3016                                  $list[$extKey]=array('doubleInstall'=>$list[$extKey]['doubleInstall']);
3017                              }
3018                              $list[$extKey]['doubleInstall'].= $type;
3019                              $list[$extKey]['type'] = $type;
3020                              $list[$extKey]['EM_CONF'] = $emConf;
3021                              $list[$extKey]['files'] = t3lib_div::getFilesInDir($path.$extKey, '', 0, '', $this->excludeForPackaging);
3022  
3023                              $this->setCat($cat,$list[$extKey], $extKey);
3024                          }
3025                      }
3026                  }
3027              }
3028          }
3029      }
3030  
3031      /**
3032       * Fixes an old style ext_emconf.php array by adding constraints if needed and removing deprecated keys
3033       *
3034       * @param    array        $emConf
3035       * @return    array
3036       */
3037  	function fixEMCONF($emConf) {
3038          if(!isset($emConf['constraints']) || !isset($emConf['constraints']['depends']) || !isset($emConf['constraints']['conflicts']) || !isset($emConf['constraints']['suggests'])) {
3039              if(!isset($emConf['constraints']) || !isset($emConf['constraints']['depends'])) {
3040                  $emConf['constraints']['depends'] = $this->stringToDep($emConf['dependencies']);
3041                  if(strlen($emConf['PHP_version'])) {
3042                      $versionRange = $this->splitVersionRange($emConf['PHP_version']);
3043                      if (version_compare($versionRange[0],'3.0.0','<')) $versionRange[0] = '3.0.0';
3044                      if (version_compare($versionRange[1],'3.0.0','<')) $versionRange[1] = '0.0.0';
3045                      $emConf['constraints']['depends']['php'] = implode('-',$versionRange);
3046                  }
3047                  if(strlen($emConf['TYPO3_version'])) {
3048                      $versionRange = $this->splitVersionRange($emConf['TYPO3_version']);
3049                      if (version_compare($versionRange[0],'3.5.0','<')) $versionRange[0] = '3.5.0';
3050                      if (version_compare($versionRange[1],'3.5.0','<')) $versionRange[1] = '0.0.0';
3051                      $emConf['constraints']['depends']['typo3'] = implode('-',$versionRange);
3052                  }
3053              }
3054              if(!isset($emConf['constraints']) || !isset($emConf['constraints']['conflicts'])) {
3055                  $emConf['constraints']['conflicts'] = $this->stringToDep($emConf['conflicts']);
3056              }
3057              if(!isset($emConf['constraints']) || !isset($emConf['constraints']['suggests'])) {
3058                  $emConf['constraints']['suggests'] = array();
3059              }
3060          } elseif (isset($emConf['constraints']) && isset($emConf['dependencies'])) {
3061              $emConf['suggests'] = isset($emConf['suggests']) ? $emConf['suggests'] : array();
3062              $emConf['dependencies'] = $this->depToString($emConf['constraints']);
3063              $emConf['conflicts'] = $this->depToString($emConf['constraints'], 'conflicts');
3064          }
3065  
3066              // sanity check for version numbers, intentionally only checks php and typo3
3067          if(isset($emConf['constraints']['depends']) && isset($emConf['constraints']['depends']['php'])) {
3068              $versionRange = $this->splitVersionRange($emConf['constraints']['depends']['php']);
3069              if (version_compare($versionRange[0],'3.0.0','<')) $versionRange[0] = '3.0.0';
3070              if (version_compare($versionRange[1],'3.0.0','<')) $versionRange[1] = '0.0.0';
3071              $emConf['constraints']['depends']['php'] = implode('-',$versionRange);
3072          }
3073          if(isset($emConf['constraints']['depends']) && isset($emConf['constraints']['depends']['typo3'])) {
3074              $versionRange = $this->splitVersionRange($emConf['constraints']['depends']['typo3']);
3075              if (version_compare($versionRange[0],'3.5.0','<')) $versionRange[0] = '3.5.0';
3076              if (version_compare($versionRange[1],'3.5.0','<')) $versionRange[1] = '0.0.0';
3077              $emConf['constraints']['depends']['typo3'] = implode('-',$versionRange);
3078          }
3079  
3080          unset($emConf['private']);
3081          unset($emConf['download_password']);
3082          unset($emConf['TYPO3_version']);
3083          unset($emConf['PHP_version']);
3084  
3085          return $emConf;
3086      }
3087  
3088      /**
3089       * Splits a version range into an array.
3090       *
3091       * If a single version number is given, it is considered a minimum value.
3092       * If a dash is found, the numbers left and right are considered as minimum and maximum. Empty values are allowed.
3093       *
3094       * @param    string        $ver A string with a version range.
3095       * @return    array
3096       */
3097  	function splitVersionRange($ver)    {
3098          $versionRange = array();
3099          if (strstr($ver, '-'))    {
3100              $versionRange = explode('-', $ver, 2);
3101          } else {
3102              $versionRange[0] = $ver;
3103              $versionRange[1] = '';
3104          }
3105  
3106          if (!$versionRange[0])    { $versionRange[0] = '0.0.0'; }
3107          if (!$versionRange[1])    { $versionRange[1] = '0.0.0'; }
3108  
3109          return $versionRange;
3110      }
3111  
3112      /**
3113       * Maps remote extensions information into $cat/$list arrays for listing
3114       *
3115       * @param    boolean        If set the info in the internal extensionsXML array will be unset before returning the result.
3116       * @return    array        List array and category index as key 0 / 1 in an array.
3117       */
3118  	function prepareImportExtList($unsetProc = false)    {
3119          $list = array();
3120          $cat = $this->defaultCategories;
3121          $filepath = $this->getMirrorURL();
3122  
3123          reset($this->xmlhandler->extensionsXML);
3124          while (list($extKey, $data) = each($this->xmlhandler->extensionsXML)) {
3125              $GLOBALS['LANG']->csConvObj->convArray($data,'utf-8',$GLOBALS['LANG']->charSet); // is there a better place for conversion?
3126              $list[$extKey]['type'] = '_';
3127              $version = array_keys($data['versions']);
3128              $list[$extKey]['_ICON'] = '<img alt="" src="'.$filepath.$extKey{0}.'/'.$extKey{1}.'/'.$extKey.'_'.end($version).'.gif" />';
3129              $list[$extKey]['downloadcounter'] = $data['downloadcounter'];
3130  
3131              foreach(array_keys($data['versions']) as $version) {
3132                  $list[$extKey]['versions'][$version]['downloadcounter'] = $data['versions'][$version]['downloadcounter'];
3133  
3134                  $list[$extKey]['versions'][$version]['EM_CONF'] = array(
3135                  'version' => $version,
3136                  'title' => $data['versions'][$version]['title'],
3137                  'description' => $data['versions'][$version]['description'],
3138                  'category' => $data['versions'][$version]['category'],
3139                  'constraints' => $data['versions'][$version]['dependencies'],
3140                  'state' => $data['versions'][$version]['state'],
3141                  'reviewstate' => $data['versions'][$version]['reviewstate'],
3142                  'lastuploaddate' => $data['versions'][$version]['lastuploaddate'],
3143                  'author' => $data['versions'][$version]['authorname'],
3144                  'author_email' => $data['versions'][$version]['authoremail'],
3145                  'author_company' => $data['versions'][$version]['authorcompany'],
3146                  );
3147              }
3148              $this->setCat($cat, $list[$extKey]['versions'][$version], $extKey);
3149              if ($unsetProc)    {
3150                  unset($this->xmlhandler->extensionsXML[$extKey]);
3151              }
3152          }
3153  
3154          return array($list,$cat);
3155      }
3156  
3157      /**
3158       * Set category array entries for extension
3159       *
3160       * @param    array        Category index array
3161       * @param    array        Part of list array for extension.
3162       * @param    string        Extension key
3163       * @return    array        Modified category index array
3164       */
3165  	function setCat(&$cat,$listArrayPart,$extKey)    {
3166  
3167          // Getting extension title:
3168          $extTitle = $listArrayPart['EM_CONF']['title'];
3169  
3170          // Category index:
3171          $index = $listArrayPart['EM_CONF']['category'];
3172          $cat['cat'][$index][$extKey] = $extTitle;
3173  
3174          // Author index:
3175          $index = $listArrayPart['EM_CONF']['author'].($listArrayPart['EM_CONF']['author_company']?', '.$listArrayPart['EM_CONF']['author_company']:'');
3176          $cat['author_company'][$index][$extKey] = $extTitle;
3177  
3178          // State index:
3179          $index = $listArrayPart['EM_CONF']['state'];
3180          $cat['state'][$index][$extKey] = $extTitle;
3181  
3182          // Type index:
3183          $index = $listArrayPart['type'];
3184          $cat['type'][$index][$extKey] = $extTitle;
3185  
3186          // Return categories:
3187          return $cat;
3188      }
3189  
3190  
3191  
3192  
3193  
3194  
3195  
3196  
3197  
3198  
3199      /*******************************
3200      *
3201      * Extension analyzing (detailed information)
3202      *
3203      ******************************/
3204  
3205      /**
3206       * Perform a detailed, technical analysis of the available extension on server!
3207       * Includes all kinds of verifications
3208       * Takes some time to process, therfore use with care, in particular in listings.
3209       *
3210       * @param    string        Extension key
3211       * @param    array        Extension information
3212       * @param    boolean        If set, checks for validity of classes etc.
3213       * @return    array        Information in an array.
3214       */
3215  	function makeDetailedExtensionAnalysis($extKey,$extInfo,$validity=0)    {
3216  
3217          // Get absolute path of the extension
3218          $absPath = $this->getExtPath($extKey,$extInfo['type']);
3219  
3220          $infoArray = array();
3221  
3222          $table_class_prefix = substr($extKey,0,5)=='user_' ? 'user_' : 'tx_'.str_replace('_','',$extKey).'_';
3223          $module_prefix = substr($extKey,0,5)=='user_' ? 'u' : 'tx'.str_replace('_','',$extKey);
3224  
3225          // Database status:
3226          $dbInfo = $this->checkDBupdates($extKey,$extInfo,1);
3227  
3228          // Database structure required:
3229          if (is_array($dbInfo['structure']['tables_fields']))    {
3230              $modify_tables = t3lib_div::trimExplode(',',$extInfo['EM_CONF']['modify_tables'],1);
3231              $infoArray['dump_tf'] = array();
3232  
3233              foreach($dbInfo['structure']['tables_fields'] as $tN => $d)    {
3234                  if (in_array($tN,$modify_tables))    {
3235                      $infoArray['fields'][] = $tN.': <i>'.
3236                      (is_array($d['fields']) ? implode(', ',array_keys($d['fields'])) : '').
3237                      (is_array($d['keys']) ? ' + '.count($d['keys']).' keys' : '').
3238                      '</i>';
3239                      if (is_array($d['fields']))    {
3240                          reset($d['fields']);
3241                          while(list($fN) = each($d['fields']))    {
3242                              $infoArray['dump_tf'][] = $tN.'.'.$fN;
3243                              if (!t3lib_div::isFirstPartOfStr($fN,$table_class_prefix))    {
3244                                  $infoArray['NSerrors']['fields'][$fN] = $fN;
3245                              } else {
3246                                  $infoArray['NSok']['fields'][$fN] = $fN;
3247                              }
3248                          }
3249                      }
3250                      if (is_array($d['keys']))    {
3251                          reset($d['keys']);
3252                          while(list($fN)=each($d['keys']))    {
3253                              $infoArray['dump_tf'][] = $tN.'.KEY:'.$fN;
3254                          }
3255                      }
3256                  } else {
3257                      $infoArray['dump_tf'][] = $tN;
3258                      $infoArray['tables'][] = $tN;
3259                      if (!t3lib_div::isFirstPartOfStr($tN,$table_class_prefix))    {
3260                          $infoArray['NSerrors']['tables'][$tN] = $tN;
3261                      } else $infoArray['NSok']['tables'][$tN] = $tN;
3262                  }
3263              }
3264              if (count($dbInfo['structure']['diff']['diff']) || count($dbInfo['structure']['diff']['extra']))    {
3265                  $msg = array();
3266                  if (count($dbInfo['structure']['diff']['diff']))    $msg[] = 'missing';
3267                  if (count($dbInfo['structure']['diff']['extra']))    $msg[] = 'of wrong type';
3268                  $infoArray['tables_error'] = 1;
3269                  if (t3lib_extMgm::isLoaded($extKey))    $infoArray['errors'][] = 'Some tables or fields are '.implode(' and ',$msg).'!';
3270              }
3271          }
3272  
3273          // Static tables?
3274          if (is_array($dbInfo['static']))    {
3275              $infoArray['static'] = array_keys($dbInfo['static']);
3276  
3277              foreach($dbInfo['static'] as $tN => $d)    {
3278                  if (!$d['exists'])    {
3279                      $infoArray['static_error'] = 1;
3280                      if (t3lib_extMgm::isLoaded($extKey))    $infoArray['errors'][] = 'Static table(s) missing!';
3281                      if (!t3lib_div::isFirstPartOfStr($tN,$table_class_prefix))    {
3282                          $infoArray['NSerrors']['tables'][$tN] = $tN;
3283                      } else $infoArray['NSok']['tables'][$tN] = $tN;
3284                  }
3285              }
3286          }
3287  
3288          // Backend Module-check:
3289          $knownModuleList = t3lib_div::trimExplode(',',$extInfo['EM_CONF']['module'],1);
3290          foreach($knownModuleList as $mod)    {
3291              if (@is_dir($absPath.$mod))    {
3292                  if (@is_file($absPath.$mod.'/conf.php'))    {
3293                      $confFileInfo = $this->modConfFileAnalysis($absPath.$mod.'/conf.php');
3294                      if (is_array($confFileInfo['TYPO3_MOD_PATH']))    {
3295                          $shouldBePath = $this->typeRelPaths[$extInfo['type']].$extKey.'/'.$mod.'/';
3296                          if (strcmp($confFileInfo['TYPO3_MOD_PATH'][1][1],$shouldBePath))    {
3297                              $infoArray['errors'][] = 'Configured TYPO3_MOD_PATH "'.$confFileInfo['TYPO3_MOD_PATH'][1][1].'" different from "'.$shouldBePath.'"';
3298                          }
3299                      } else $infoArray['errors'][] = 'No definition of TYPO3_MOD_PATH constant found inside!';
3300                      if (is_array($confFileInfo['MCONF_name']))    {
3301                          $mName = $confFileInfo['MCONF_name'][1][1];
3302                          $mNameParts = explode('_',$mName);
3303                          $infoArray['moduleNames'][] = $mName;
3304                          if (!t3lib_div::isFirstPartOfStr($mNameParts[0],$module_prefix) &&
3305                          (!$mNameParts[1] || !t3lib_div::isFirstPartOfStr($mNameParts[1],$module_prefix)))    {
3306                              $infoArray['NSerrors']['modname'][] = $mName;
3307                          } else $infoArray['NSok']['modname'][] = $mName;
3308                      } else $infoArray['errors'][] = 'No definition of MCONF[name] variable found inside!';
3309                  } else  $infoArray['errors'][] = 'Backend module conf file "'.$mod.'/conf.php" should exist but does not!';
3310              } else $infoArray['errors'][] = 'Backend module folder "'.$mod.'/" should exist but does not!';
3311          }
3312          $dirs = t3lib_div::get_dirs($absPath);
3313          if (is_array($dirs))    {
3314              reset($dirs);
3315              while(list(,$mod) = each($dirs))    {
3316                  if (!in_array($mod,$knownModuleList) && @is_file($absPath.$mod.'/conf.php'))    {
3317                      $confFileInfo = $this->modConfFileAnalysis($absPath.$mod.'/conf.php');
3318                      if (is_array($confFileInfo))    {
3319                          $infoArray['errors'][] = 'It seems like there is a backend module in "'.$mod.'/conf.php" which is not configured in ext_emconf.php';
3320                      }
3321                  }
3322              }
3323          }
3324  
3325          // ext_tables.php:
3326          if (@is_file($absPath.'ext_tables.php'))    {
3327              $content = t3lib_div::getUrl($absPath.'ext_tables.php');
3328              if (stristr($content,'t3lib_extMgm::addModule'))    $infoArray['flags'][] = 'Module';
3329              if (stristr($content,'t3lib_extMgm::insertModuleFunction'))    $infoArray['flags'][] = 'Module+';
3330              if (stristr($content,'t3lib_div::loadTCA'))    $infoArray['flags'][] = 'loadTCA';
3331              if (stristr($content,'$TCA['))    $infoArray['flags'][] = 'TCA';
3332              if (stristr($content,'t3lib_extMgm::addPlugin'))    $infoArray['flags'][] = 'Plugin';
3333          }
3334  
3335          // ext_localconf.php:
3336          if (@is_file($absPath.'ext_localconf.php'))    {
3337              $content = t3lib_div::getUrl($absPath.'ext_localconf.php');
3338              if (stristr($content,'t3lib_extMgm::addPItoST43'))    $infoArray['flags'][]='Plugin/ST43';
3339              if (stristr($content,'t3lib_extMgm::addPageTSConfig'))    $infoArray['flags'][]='Page-TSconfig';
3340              if (stristr($content,'t3lib_extMgm::addUserTSConfig'))    $infoArray['flags'][]='User-TSconfig';
3341              if (stristr($content,'t3lib_extMgm::addTypoScriptSetup'))    $infoArray['flags'][]='TS/Setup';
3342              if (stristr($content,'t3lib_extMgm::addTypoScriptConstants'))    $infoArray['flags'][]='TS/Constants';
3343          }
3344  
3345          if (@is_file($absPath.'ext_typoscript_constants.txt'))    {
3346              $infoArray['TSfiles'][] = 'Constants';
3347          }
3348          if (@is_file($absPath.'ext_typoscript_setup.txt'))    {
3349              $infoArray['TSfiles'][] = 'Setup';
3350          }
3351          if (@is_file($absPath.'ext_conf_template.txt'))    {
3352              $infoArray['conf'] = 1;
3353          }
3354  
3355          // Classes:
3356          if ($validity)    {
3357              $filesInside = $this->getClassIndexLocallangFiles($absPath,$table_class_prefix,$extKey);
3358              if (is_array($filesInside['errors']))    $infoArray['errors'] = array_merge((array)$infoArray['errors'],$filesInside['errors']);
3359              if (is_array($filesInside['NSerrors']))    $infoArray['NSerrors'] = array_merge((array)$infoArray['NSerrors'],$filesInside['NSerrors']);
3360              if (is_array($filesInside['NSok']))    $infoArray['NSok'] = array_merge((array)$infoArray['NSok'],$filesInside['NSok']);
3361              $infoArray['locallang'] = $filesInside['locallang'];
3362              $infoArray['classes'] = $filesInside['classes'];
3363          }
3364  
3365          // Upload folders
3366          if ($extInfo['EM_CONF']['uploadfolder'])    {
3367              $infoArray['uploadfolder'] = $this->ulFolder($extKey);
3368              if (!@is_dir(PATH_site.$infoArray['uploadfolder']))    {
3369                  $infoArray['errors'][] = 'Error: Upload folder "'.$infoArray['uploadfolder'].'" did not exist!';
3370                  $infoArray['uploadfolder'] = '';
3371              }
3372          }
3373  
3374          // Create directories:
3375          if ($extInfo['EM_CONF']['createDirs'])    {
3376              $infoArray['createDirs'] = array_unique(t3lib_div::trimExplode(',',$extInfo['EM_CONF']['createDirs'],1));
3377              foreach($infoArray['createDirs'] as $crDir)    {
3378                  if (!@is_dir(PATH_site.$crDir))    {
3379                      $infoArray['errors'][]='Error: Upload folder "'.$crDir.'" did not exist!';
3380                  }
3381              }
3382          }
3383  
3384          // Return result array:
3385          return $infoArray;
3386      }
3387  
3388      /**
3389       * Analyses the php-scripts of an available extension on server
3390       *
3391       * @param    string        Absolute path to extension
3392       * @param    string        Prefix for tables/classes.
3393       * @param    string        Extension key
3394       * @return    array        Information array.
3395       * @see makeDetailedExtensionAnalysis()
3396       */
3397  	function getClassIndexLocallangFiles($absPath,$table_class_prefix,$extKey)    {
3398          $filesInside = t3lib_div::removePrefixPathFromList(t3lib_div::getAllFilesAndFoldersInPath(array(),$absPath,'php,inc',0,99,$this->excludeForPackaging),$absPath);
3399          $out = array();
3400  
3401          foreach($filesInside as $fileName)    {
3402              if (substr($fileName,0,4)!='ext_' && substr($fileName,0,6)!='tests/')    {    // ignore supposed-to-be unit tests as well
3403                  $baseName = basename($fileName);
3404                  if (substr($baseName,0,9)=='locallang' && substr($baseName,-4)=='.php')    {
3405                      $out['locallang'][] = $fileName;
3406                  } elseif ($baseName!='conf.php')    {
3407                      if (filesize($absPath.$fileName)<500*1024)    {
3408                          $fContent = t3lib_div::getUrl($absPath.$fileName);
3409                          unset($reg);
3410                          if (preg_match('/\n[[:space:]]*class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*)/',$fContent,$reg))    {
3411  
3412                              // Find classes:
3413                              $lines = explode(chr(10),$fContent);
3414                              foreach($lines as $l)    {
3415                                  $line = trim($l);
3416                                  unset($reg);
3417                                  if (preg_match('/^class[[:space:]]*([[:alnum:]_]+)([[:alnum:][:space:]_]*)/',$line,$reg))    {
3418                                      $out['classes'][] = $reg[1];
3419                                      $out['files'][$fileName]['classes'][] = $reg[1];
3420                                      if ($reg[1]!=='ext_update' && substr($reg[1],0,3)!='ux_' && !t3lib_div::isFirstPartOfStr($reg[1],$table_class_prefix) && strcmp(substr($table_class_prefix,0,-1),$reg[1]))    {
3421                                          $out['NSerrors']['classname'][] = $reg[1];
3422                                      } else $out['NSok']['classname'][] = $reg[1];
3423                                  }
3424                              }
3425                              // If class file prefixed 'class.'....
3426                              if (substr($baseName,0,6)=='class.')    {
3427                                  $fI = pathinfo($baseName);
3428                                  $testName=substr($baseName,6,-(1+strlen($fI['extension'])));
3429                                  if ($testName!=='ext_update' && substr($testName,0,3)!='ux_' && !t3lib_div::isFirstPartOfStr($testName,$table_class_prefix) && strcmp(substr($table_class_prefix,0,-1),$testName))    {
3430                                      $out['NSerrors']['classfilename'][] = $baseName;
3431                                  } else {
3432                                      $out['NSok']['classfilename'][] = $baseName;
3433                                      if (is_array($out['files'][$fileName]['classes']) && $this->first_in_array($testName,$out['files'][$fileName]['classes'],1))    {
3434                                          $out['msg'][] = 'Class filename "'.$fileName.'" did contain the class "'.$testName.'" just as it should.';
3435                                      } else $out['errors'][] = 'Class filename "'.$fileName.'" did NOT contain the class "'.$testName.'"!';
3436                                  }
3437                              }
3438                              //
3439                              $XclassParts = split('if \(defined\([\'"]TYPO3_MODE[\'"]\) && \$TYPO3_CONF_VARS\[TYPO3_MODE\]\[[\'"]XCLASS[\'"]\]',$fContent,2);
3440                              if (count($XclassParts)==2)    {
3441                                  unset($reg);
3442                                  preg_match('/^\[[\'"]([[:alnum:]_\/\.]*)[\'"]\]/',$XclassParts[1],$reg);
3443                                  if ($reg[1]) {
3444                                      $cmpF = 'ext/'.$extKey.'/'.$fileName;
3445                                      if (!strcmp($reg[1],$cmpF))    {
3446                                          if (preg_match('/_once[[:space:]]*\(\$TYPO3_.ONF_VARS\[TYPO3_MODE\]\[[\'"]XCLASS[\'"]\]\[[\'"]'.preg_quote($cmpF,'/').'[\'"]\]\);/', $XclassParts[1]))    {
3447                                              $out['msg'][] = 'XCLASS OK in '.$fileName;
3448                                          } else $out['errors'][] = 'Couldn\'t find the include_once statement for XCLASS!';
3449                                      } else $out['errors'][] = 'The XCLASS filename-key "'.$reg[1].'" was different from "'.$cmpF.'" which it should have been!';
3450                                  } else $out['errors'][] = 'No XCLASS filename-key found in file "'.$fileName.'". Maybe a regex coding error here...';
3451                              } elseif (!$this->first_in_array('ux_',$out['files'][$fileName]['classes'])) $out['errors'][] = 'No XCLASS inclusion code found in file "'.$fileName.'"';
3452                          }
3453                      }
3454                  }
3455              }
3456          }
3457          return $out;
3458      }
3459  
3460      /**
3461       * Reads $confFilePath (a module $conf-file) and returns information on the existence of TYPO3_MOD_PATH definition and MCONF_name
3462       *
3463       * @param    string        Absolute path to a "conf.php" file of a module which we are analysing.
3464       * @return    array        Information found.
3465       * @see writeTYPO3_MOD_PATH()
3466       */
3467  	function modConfFileAnalysis($confFilePath)    {
3468          $lines = explode(chr(10),t3lib_div::getUrl($confFilePath));
3469          $confFileInfo = array();
3470          $confFileInfo['lines'] = $lines;
3471  
3472          foreach($lines as $k => $l)    {
3473              $line = trim($l);
3474  
3475              unset($reg);
3476              if (preg_match('/^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;/',$line,$reg))    {
3477                  $confFileInfo['TYPO3_MOD_PATH'] = array($k,$reg);
3478              }
3479  
3480              unset($reg);
3481              if (preg_match('/^\$MCONF\[["\']?name["\']?\][[:space:]]*=[[:space:]]*["\']([[:alnum:]_]+)["\'];/',$line,$reg))    {
3482                  $confFileInfo['MCONF_name'] = array($k,$reg);
3483              }
3484          }
3485          return $confFileInfo;
3486      }
3487  
3488      /**
3489       * Creates a MD5-hash array over the current files in the extension
3490       *
3491       * @param    string        Extension key
3492       * @param    array        Extension information array
3493       * @return    array        MD5-keys
3494       */
3495  	function serverExtensionMD5Array($extKey,$conf)    {
3496  
3497          // Creates upload-array - including filelist.
3498          $mUA = $this->makeUploadArray($extKey,$conf);
3499  
3500          $md5Array = array();
3501          if (is_array($mUA['FILES']))    {
3502  
3503              // Traverse files.
3504              foreach($mUA['FILES'] as $fN => $d)    {
3505                  if ($fN!='ext_emconf.php')    {
3506                      $md5Array[$fN] = substr($d['content_md5'],0,4);
3507                  }
3508              }
3509          } else debug($mUA);
3510          return $md5Array;
3511      }
3512  
3513      /**
3514       * Compares two arrays with MD5-hash values for analysis of which files has changed.
3515       *
3516       * @param    array        Current values
3517       * @param    array        Past values
3518       * @return    array        Affected files
3519       */
3520  	function findMD5ArrayDiff($current,$past)    {
3521          if (!is_array($current))    $current = array();
3522          if (!is_array($past))        $past = array();
3523          $filesInCommon = array_intersect($current,$past);
3524          $diff1 =  array_keys(array_diff($past,$filesInCommon));
3525          $diff2 =  array_keys(array_diff($current,$filesInCommon));
3526          $affectedFiles = array_unique(array_merge($diff1,$diff2));
3527          return $affectedFiles;
3528      }
3529  
3530  
3531  
3532  
3533  
3534  
3535  
3536  
3537  
3538  
3539      /***********************************
3540      *
3541      * File system operations
3542      *
3543      **********************************/
3544  
3545      /**
3546       * Creates directories in $extDirPath
3547       *
3548       * @param    array        Array of directories to create relative to extDirPath, eg. "blabla", "blabla/blabla" etc...
3549       * @param    string        Absolute path to directory.
3550       * @return    mixed        Returns false on success or an error string
3551       */
3552  	function createDirsInPath($dirs,$extDirPath)    {
3553          if (is_array($dirs))    {
3554              foreach($dirs as $dir)    {
3555                  $error = t3lib_div::mkdir_deep($extDirPath,$dir);
3556                  if ($error)    return $error;
3557              }
3558          }
3559  
3560          return false;
3561      }
3562  
3563      /**
3564       * Removes the extension directory (including content)
3565       *
3566       * @param    string        Extension directory to remove (with trailing slash)
3567       * @param    boolean        If set, will leave the extension directory
3568       * @return    boolean        False on success, otherwise error string.
3569       */
3570  	function removeExtDirectory($removePath,$removeContentOnly=0)    {
3571          $errors = array();
3572          if (@is_dir($removePath) && substr($removePath,-1)=='/' && (
3573          t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths['G']) ||
3574          t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths['L']) ||
3575          (t3lib_div::isFirstPartOfStr($removePath,PATH_site.$this->typePaths['S']) && $this->systemInstall) ||
3576          t3lib_div::isFirstPartOfStr($removePath,PATH_site.'fileadmin/_temp_/'))        // Playing-around directory...
3577          ) {
3578  
3579              // All files in extension directory:
3580              $fileArr = t3lib_div::getAllFilesAndFoldersInPath(array(),$removePath,'',1);
3581              if (is_array($fileArr))    {
3582  
3583                  // Remove files in dirs:
3584                  foreach($fileArr as $removeFile)    {
3585                      if (!@is_dir($removeFile))    {
3586                          if (@is_file($removeFile) && t3lib_div::isFirstPartOfStr($removeFile,$removePath) && strcmp($removeFile,$removePath))    {    // ... we are very paranoid, so we check what cannot go wrong: that the file is in fact within the prefix path!
3587                              @unlink($removeFile);
3588                              clearstatcache();
3589                              if (@is_file($removeFile))    {
3590                                  $errors[] = 'Error: "'.$removeFile.'" could not be deleted!';
3591                              }
3592                          } else $errors[] = 'Error: "'.$removeFile.'" was either not a file, or it was equal to the removed directory or simply outside the removed directory "'.$removePath.'"!';
3593                      }
3594                  }
3595  
3596                  // Remove directories:
3597                  $remDirs = $this->extractDirsFromFileList(t3lib_div::removePrefixPathFromList($fileArr,$removePath));
3598                  $remDirs = array_reverse($remDirs);    // Must delete outer directories first...
3599                  foreach($remDirs as $removeRelDir)    {
3600                      $removeDir = $removePath.$removeRelDir;
3601                      if (@is_dir($removeDir))    {
3602                          rmdir($removeDir);
3603                          clearstatcache();
3604                          if (@is_dir($removeDir))    {
3605                              $errors[] = 'Error: "'.$removeDir.'" could not be removed (are there files left?)';
3606                          }
3607                      } else $errors[] = 'Error: "'.$removeDir.'" was not a directory!';
3608                  }
3609  
3610                  // If extension dir should also be removed:
3611                  if (!$removeContentOnly)    {
3612                      rmdir($removePath);
3613                      clearstatcache();
3614                      if (@is_dir($removePath))    {
3615                          $errors[] = 'Error: Extension directory "'.$removePath.'" could not be removed (are there files or folders left?)';
3616                      }
3617                  }
3618              } else $errors[] = 'Error: '.$fileArr;
3619          } else $errors[] = 'Error: Unallowed path to remove: '.$removePath;
3620  
3621          // Return errors if any:
3622          return implode(chr(10),$errors);
3623      }
3624  
3625      /**
3626       * Removes the current extension of $type and creates the base folder for the new one (which is going to be imported)
3627       *
3628       * @param    array        Data for imported extension
3629       * @param    string        Extension installation scope (L,G,S)
3630       * @param    boolean        If set, nothing will be deleted (neither directory nor files)
3631       * @return    mixed        Returns array on success (with extension directory), otherwise an error string.
3632       */
3633  	function clearAndMakeExtensionDir($importedData,$type,$dontDelete=0)    {
3634          if (!$importedData['extKey'])    return 'FATAL ERROR: Extension key was not set for some VERY strange reason. Nothing done...';
3635  
3636          // Setting install path (L, G, S or fileadmin/_temp_/)
3637          $path = '';
3638          switch((string)$type)    {
3639              case 'G':
3640              case 'L':
3641                  $path = PATH_site.$this->typePaths[$type];
3642                  $suffix = '';
3643  
3644                  // Creates the typo3conf/ext/ directory if it does NOT already exist:
3645                  if ((string)$type=='L' && !@is_dir($path))    {
3646                      t3lib_div::mkdir($path);
3647                  }
3648                  break;
3649              default:
3650                  if ($this->systemInstall && (string)$type=='S')    {
3651                      $path = PATH_site.$this->typePaths[$type];
3652                      $suffix = '';
3653                  } else {
3654                      $path = PATH_site.'fileadmin/_temp_/';
3655                      $suffix = '_'.date('dmy-His');
3656                  }
3657                  break;
3658          }
3659  
3660          // If the install path is OK...
3661          if ($path && @is_dir($path))    {
3662  
3663              // Set extension directory:
3664              $extDirPath = $path.$importedData['extKey'].$suffix.'/';
3665  
3666              // Install dir was found, remove it then:
3667              if (@is_dir($extDirPath))    {
3668                  if($dontDelete) return array($extDirPath);
3669                  $res = $this->removeExtDirectory($extDirPath);
3670                  if ($res) {
3671                      return 'ERROR: Could not remove extension directory "'.$extDirPath.'". Reasons:<br /><br />'.nl2br($res);
3672                  }
3673              }
3674  
3675              // We go create...
3676              t3lib_div::mkdir($extDirPath);
3677              if (!is_dir($extDirPath))    return 'ERROR: Could not create extension directory "'.$extDirPath.'"';
3678              return array($extDirPath);
3679          } else return 'ERROR: The extension install path "'.$path.'" was not a directory.';
3680      }
3681  
3682      /**
3683       * Unlink (delete) cache files
3684       *
3685       * @return    integer        Number of deleted files.
3686       */
3687  	function removeCacheFiles()    {
3688          return t3lib_extMgm::removeCacheFiles();
3689      }
3690  
3691      /**
3692       * Extracts the directories in the $files array
3693       *
3694       * @param    array        Array of files / directories
3695       * @return    array        Array of directories from the input array.
3696       */
3697  	function extractDirsFromFileList($files)    {
3698          $dirs = array();
3699  
3700          if (is_array($files))    {
3701              // Traverse files / directories array:
3702              foreach($files as $file)    {
3703                  if (substr($file,-1)=='/')    {
3704                      $dirs[$file] = $file;
3705                  } else {
3706                      $pI = pathinfo($file);
3707                      if (strcmp($pI['dirname'],'') && strcmp($pI['dirname'],'.'))    {
3708                          $dirs[$pI['dirname'].'/'] = $pI['dirname'].'/';
3709                      }
3710                  }
3711              }
3712          }
3713          return $dirs;
3714      }
3715  
3716      /**
3717       * Returns the absolute path where the extension $extKey is installed (based on 'type' (SGL))
3718       *
3719       * @param    string        Extension key
3720       * @param    string        Install scope type: L, G, S
3721       * @return    string        Returns the absolute path to the install scope given by input $type variable. It is checked if the path is a directory. Slash is appended.
3722       */
3723  	function getExtPath($extKey,$type)    {
3724          $typeP = $this->typePaths[$type];
3725          if ($typeP)    {
3726              $path = PATH_site.$typeP.$extKey.'/';
3727              return @is_dir($path) ? $path : '';
3728          } else {
3729              return '';
3730          }
3731      }
3732  
3733  
3734  
3735  
3736  
3737  
3738  
3739  
3740  
3741  
3742      /*******************************
3743      *
3744      * Writing to "conf.php" and "localconf.php" files
3745      *
3746      ******************************/
3747  
3748      /**
3749       * Write new TYPO3_MOD_PATH to "conf.php" file.
3750       *
3751       * @param    string        Absolute path to a "conf.php" file of the backend module which we want to write back to.
3752       * @param    string        Install scope type: L, G, S
3753       * @param    string        Relative path for the module folder in extenson
3754       * @return    string        Returns message about the status.
3755       * @see modConfFileAnalysis()
3756       */
3757  	function writeTYPO3_MOD_PATH($confFilePath,$type,$mP)    {
3758          $lines = explode(chr(10),t3lib_div::getUrl($confFilePath));
3759          $confFileInfo = array();
3760          $confFileInfo['lines'] = $lines;
3761  
3762          $flag_M = 0;
3763          $flag_B = 0;
3764  
3765          foreach($lines as $k => $l)    {
3766              $line = trim($l);
3767  
3768              unset($reg);
3769              if (preg_match('/^define[[:space:]]*\([[:space:]]*["\']TYPO3_MOD_PATH["\'][[:space:]]*,[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*\)[[:space:]]*;/',$line,$reg))    {
3770                  $lines[$k] = str_replace($reg[0], 'define(\'TYPO3_MOD_PATH\', \''.$this->typeRelPaths[$type].$mP.'\');', $lines[$k]);
3771                  $flag_M = $k+1;
3772              }
3773  
3774              unset($reg);
3775              if (preg_match('/^\$BACK_PATH[[:space:]]*=[[:space:]]*["\']([[:alnum:]_\/\.]+)["\'][[:space:]]*;/',$line,$reg))    {
3776                  $lines[$k] = str_replace($reg[0], '$BACK_PATH=\''.$this->typeBackPaths[$type].'\';', $lines[$k]);
3777                  $flag_B = $k+1;
3778              }
3779          }
3780  
3781          if ($flag_B && $flag_M)    {
3782              t3lib_div::writeFile($confFilePath,implode(chr(10),$lines));
3783              return 'TYPO3_MOD_PATH and $BACK_PATH was updated in "'.substr($confFilePath,strlen(PATH_site)).'"';
3784          } else return 'Error: Either TYPO3_MOD_PATH or $BACK_PATH was not found in the "'.$confFilePath.'" file. You must manually configure that!';
3785      }
3786  
3787      /**
3788       * Writes the extension list to "localconf.php" file
3789       * Removes the temp_CACHED* files before return.
3790       *
3791       * @param    string        List of extensions
3792       * @return    void
3793       */
3794  	function writeNewExtensionList($newExtList)    {
3795          global $TYPO3_CONF_VARS;
3796  
3797          // Instance of install tool
3798          $instObj = new t3lib_install;
3799          $instObj->allowUpdateLocalConf =1;
3800          $instObj->updateIdentity = 'TYPO3 Extension Manager';
3801  
3802          // Get lines from localconf file
3803          $lines = $instObj->writeToLocalconf_control();
3804          $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXT\'][\'extList\']', $newExtList);
3805          $instObj->writeToLocalconf_control($lines);
3806  
3807          $TYPO3_CONF_VARS['EXT']['extList'] = $newExtList;
3808          $this->removeCacheFiles();
3809      }
3810  
3811      /**
3812       * Writes the TSstyleconf values to "localconf.php"
3813       * Removes the temp_CACHED* files before return.
3814       *
3815       * @param    string        Extension key
3816       * @param    array        Configuration array to write back
3817       * @return    void
3818       */
3819  	function writeTsStyleConfig($extKey,$arr)    {
3820  
3821          // Instance of install tool
3822          $instObj = new t3lib_install;
3823          $instObj->allowUpdateLocalConf =1;
3824          $instObj->updateIdentity = 'TYPO3 Extension Manager';
3825  
3826          // Get lines from localconf file
3827          $lines = $instObj->writeToLocalconf_control();
3828          $instObj->setValueInLocalconfFile($lines, '$TYPO3_CONF_VARS[\'EXT\'][\'extConf\'][\''.$extKey.'\']', serialize($arr));    // This will be saved only if there are no linebreaks in it !
3829          $instObj->writeToLocalconf_control($lines);
3830  
3831          $this->removeCacheFiles();
3832      }
3833  
3834      /**
3835       * Forces update of local EM_CONF. This will renew the information of changed files.
3836       *
3837       * @param    string        Extension key
3838       * @param    array        Extension information array
3839       * @return    string        Status message
3840       */
3841  	function updateLocalEM_CONF($extKey,$extInfo)    {
3842          $extInfo['EM_CONF']['_md5_values_when_last_written'] = serialize($this->serverExtensionMD5Array($extKey,$extInfo));
3843          $emConfFileContent = $this->construct_ext_emconf_file($extKey,$extInfo['EM_CONF']);
3844  
3845          $absPath = $this->getExtPath($extKey,$extInfo['type']);
3846          $emConfFileName = $absPath.'ext_emconf.php';
3847          if($emConfFileContent)    {
3848  
3849              if(@is_file($emConfFileName))    {
3850                  if(t3lib_div::writeFile($emConfFileName,$emConfFileContent) === true) {
3851                      return '"'.substr($emConfFileName,strlen($absPath)).'" was updated with a cleaned up EM_CONF array.';
3852                  } else {
3853                      return '<strong>Error: "'.$emConfFileName.'" was not writable!</strong>';
3854                  }
3855              } else return('<strong>Error: No file "'.$emConfFileName.'" found. DON\'T PANIC!</strong>');
3856          } else {
3857              return 'No content to write to "'.substr($emConfFileName,strlen($absPath)).'"!';
3858          }
3859      }
3860  
3861  
3862  
3863  
3864  
3865  
3866  
3867  
3868  
3869  
3870      /*******************************************
3871      *
3872      * Compiling upload information, emconf-file etc.
3873      *
3874      *******************************************/
3875  
3876      /**
3877       * Compiles the ext_emconf.php file
3878       *
3879       * @param    string        Extension key
3880       * @param    array        EM_CONF array
3881       * @return    string        PHP file content, ready to write to ext_emconf.php file
3882       */
3883  	function construct_ext_emconf_file($extKey,$EM_CONF)    {
3884  
3885              // clean version number:
3886          $vDat = $this->renderVersion($EM_CONF['version']);
3887          $EM_CONF['version']=$vDat['version'];
3888  
3889          $code = '<?php
3890  
3891  ########################################################################
3892  # Extension Manager/Repository config file for ext: "'.$extKey.'"
3893  #
3894  # Auto generated '.date('d-m-Y H:i').'
3895  #
3896  # Manual updates:
3897  # Only the data in the array - anything else is removed by next write.
3898  # "version" and "dependencies" must not be touched!
3899  ########################################################################
3900  
3901  $EM_CONF[$_EXTKEY] = '.$this->arrayToCode($EM_CONF, 0).';
3902  
3903  ?>';
3904          return str_replace(chr(13), '', $code);
3905      }
3906  
3907      /**
3908       * Enter description here...
3909       *
3910       * @param    unknown_type        $array
3911       * @param    unknown_type        $lines
3912       * @param    unknown_type        $level
3913       * @return    unknown
3914       */
3915  	function arrayToCode($array, $level=0) {
3916          $lines = 'array('.chr(10);
3917          $level++;
3918          foreach($array as $k => $v)    {
3919              if(strlen($k) && is_array($v)) {
3920                  $lines .= str_repeat(chr(9),$level)."'".$k."' => ".$this->arrayToCode($v, $level);
3921              } elseif(strlen($k)) {
3922                  $lines .= str_repeat(chr(9),$level)."'".$k."' => ".(t3lib_div::testInt($v) ? intval($v) : "'".t3lib_div::slashJS(trim($v),1)."'").','.chr(10);
3923              }
3924          }
3925  
3926          $lines .= str_repeat(chr(9),$level-1).')'.($level-1==0 ? '':','.chr(10));
3927          return $lines;
3928      }
3929  
3930      /**
3931       * Make upload array out of extension
3932       *
3933       * @param    string        Extension key
3934       * @param    array        Extension information array
3935       * @return    mixed        Returns array with extension upload array on success, otherwise an error string.
3936       */
3937  	function makeUploadArray($extKey,$conf)    {
3938          $extPath = $this->getExtPath($extKey,$conf['type']);
3939  
3940          if ($extPath)    {
3941  
3942              // Get files for extension:
3943              $fileArr = array();
3944              $fileArr = t3lib_div::getAllFilesAndFoldersInPath($fileArr,$extPath,'',0,99,$this->excludeForPackaging);
3945  
3946              // Calculate the total size of those files:
3947              $totalSize = 0;
3948              foreach($fileArr as $file)    {
3949                  $totalSize+=filesize($file);
3950              }
3951  
3952              // If the total size is less than the upper limit, proceed:
3953              if ($totalSize < $this->maxUploadSize)    {
3954  
3955                  // Initialize output array:
3956                  $uploadArray = array();
3957                  $uploadArray['extKey'] = $extKey;
3958                  $uploadArray['EM_CONF'] = $conf['EM_CONF'];
3959                  $uploadArray['misc']['codelines'] = 0;
3960                  $uploadArray['misc']['codebytes'] = 0;
3961  
3962                  $uploadArray['techInfo'] = $this->makeDetailedExtensionAnalysis($extKey,$conf,1);
3963  
3964                  // Read all files:
3965                  foreach($fileArr as $file)    {
3966                      $relFileName = substr($file,strlen($extPath));
3967                      $fI = pathinfo($relFileName);
3968                      if ($relFileName!='ext_emconf.php')    {        // This file should be dynamically written...
3969                          $uploadArray['FILES'][$relFileName] = array(
3970                          'name' => $relFileName,
3971                          'size' => filesize($file),
3972                          'mtime' => filemtime($file),
3973                          'is_executable' => (TYPO3_OS=='WIN' ? 0 : is_executable($file)),
3974                          'content' => t3lib_div::getUrl($file)
3975                          );
3976                          if (t3lib_div::inList('php,inc',strtolower($fI['extension'])))    {
3977                              $uploadArray['FILES'][$relFileName]['codelines']=count(explode(chr(10),$uploadArray['FILES'][$relFileName]['content']));
3978                              $uploadArray['misc']['codelines']+=$uploadArray['FILES'][$relFileName]['codelines'];
3979                              $uploadArray['misc']['codebytes']+=$uploadArray['FILES'][$relFileName]['size'];
3980  
3981                              // locallang*.php files:
3982                              if (substr($fI['basename'],0,9)=='locallang' && strstr($uploadArray['FILES'][$relFileName]['content'],'$LOCAL_LANG'))    {
3983                                  $uploadArray['FILES'][$relFileName]['LOCAL_LANG']=$this->getSerializedLocalLang($file,$uploadArray['FILES'][$relFileName]['content']);
3984                              }
3985                          }
3986                          $uploadArray['FILES'][$relFileName]['content_md5'] = md5($uploadArray['FILES'][$relFileName]['content']);
3987                      }
3988                  }
3989  
3990                  // Return upload-array:
3991                  return $uploadArray;
3992              } else return 'Error: Total size of uncompressed upload ('.$totalSize.') exceeds '.t3lib_div::formatSize($this->maxUploadSize);
3993          } else {
3994              return 'Error: Extension path for extension "'.$extKey.'" not found';
3995          }
3996      }
3997  
3998      /**
3999       * Include a locallang file and return the $LOCAL_LANG array serialized.
4000       *
4001       * @param    string        Absolute path to locallang file to include.
4002       * @param    string        Old content of a locallang file (keeping the header content)
4003       * @return    array        Array with header/content as key 0/1
4004       * @see makeUploadArray()
4005       */
4006  	function getSerializedLocalLang($file,$content)    {
4007          $returnParts = explode('$LOCAL_LANG',$content,2);
4008  
4009          include($file);
4010          if (is_array($LOCAL_LANG))    {
4011              $returnParts[1] = serialize($LOCAL_LANG);
4012              return $returnParts;
4013          } else {
4014              return array();
4015          }
4016      }
4017  
4018  
4019  
4020  
4021  
4022  
4023  
4024  
4025  
4026  
4027      /********************************
4028      *
4029      * Managing dependencies, conflicts, priorities, load order of extension keys
4030      *
4031      *******************************/
4032  
4033      /**
4034       * Adds extension to extension list and returns new list. If -1 is returned, an error happend.
4035       * Checks dependencies etc.
4036       *
4037       * @param    string        Extension key
4038       * @param    array        Extension information array - information about installed extensions
4039       * @return    string        New list of installed extensions or -1 if error
4040       * @see showExtDetails()
4041       */
4042  	function addExtToList($extKey,$instExtInfo)    {
4043          global $TYPO3_LOADED_EXT;
4044  
4045              // ext_emconf.php information:
4046          $conf = $instExtInfo[$extKey]['EM_CONF'];
4047  
4048              // Get list of installed extensions and add this one.
4049          $listArr = array_keys($TYPO3_LOADED_EXT);
4050          if ($conf['priority']=='top')    {
4051              array_unshift($listArr,$extKey);
4052          } else {
4053              $listArr[]=$extKey;
4054          }
4055  
4056              // Manage other circumstances:
4057          $listArr = $this->managesPriorities($listArr,$instExtInfo);
4058          $listArr = $this->removeRequiredExtFromListArr($listArr);
4059  
4060              // Implode unique list of extensions to load and return:
4061          $list = implode(',',array_unique($listArr));
4062          return $list;
4063      }
4064  
4065      /**
4066       * Enter description here...
4067       *
4068       * @param    string        $extKey
4069       * @param    array        $conf
4070       * @param    array        $instExtInfo
4071       * @return    array
4072       */
4073  	function checkDependencies($extKey, $conf, $instExtInfo) {
4074          $content = '';
4075          $depError = false;
4076          $msg = array();
4077          $depsolver = t3lib_div::_POST('depsolver');
4078  
4079          if (isset($conf['constraints']['depends']) && is_array($conf['constraints']['depends'])) {
4080              foreach($conf['constraints']['depends'] as $depK => $depV)    {
4081                  if($depsolver['ignore'][$depK]) {
4082                      $msg[] = '<br />Dependency on '.$depK.' ignored as requested.
4083                      <input type="hidden" value="1" name="depsolver[ignore]['.$depK.']" />';
4084                      continue;
4085                  }
4086                  if($depK == 'php') {
4087                      if(!$depV) continue;
4088                      $versionRange = $this->splitVersionRange($depV);
4089                      $phpv = strstr(PHP_VERSION,'-') ? substr(PHP_VERSION,0,strpos(PHP_VERSION,'-')) : PHP_VERSION; // Linux distributors like to add suffixes, like in 5.1.2-1. Those must be ignored!
4090                      if ($versionRange[0]!='0.0.0' && version_compare($phpv,$versionRange[0],'<'))    {
4091                          $msg[] = '<br />The running PHP version ('.$phpv.') is lower than required ('.$versionRange[0].')';
4092                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this version requirement</label>';
4093                          $depError = true;
4094                          continue;
4095                      } elseif ($versionRange[1]!='0.0.0' && version_compare($phpv,$versionRange[1],'>'))    {
4096                          $msg[] = '<br />The running PHP version ('.$phpv.') is higher than allowed ('.$versionRange[1].')';
4097                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this version requirement</label>';
4098                          $depError = true;
4099                          continue;
4100                      }
4101  
4102                  } elseif ($depK == 'typo3')    {
4103                      if (!$depV) continue;
4104  
4105                      $versionRange = $this->splitVersionRange($depV);
4106                      if ($versionRange[0]!='0.0.0' && version_compare(TYPO3_version,$versionRange[0],'<'))    {
4107                          $msg[] = '<br />The running TYPO3 version ('.TYPO3_version.') is lower than required ('.$versionRange[0].')';
4108                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this version requirement</label>';
4109                          $depError = true;
4110                          continue;
4111                      } elseif ($versionRange[1]!='0.0.0' && version_compare(TYPO3_version,$versionRange[1],'>'))    {
4112                          $msg[] = '<br />The running TYPO3 version ('.TYPO3_version.') is higher than allowed ('.$versionRange[1].')';
4113                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this version requirement</label>';
4114                          $depError = true;
4115                          continue;
4116                      }
4117                  } elseif (strlen($depK) && !t3lib_extMgm::isLoaded($depK))    {    // strlen check for braindead empty dependencies coming from extensions...
4118                      if(!isset($instExtInfo[$depK]))    {
4119                          $msg[] = '<br />Extension "'.$depK.'" was not available in the system. Please import it from the TYPO3 Extension Repository.';
4120                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<img src="'.$GLOBALS['BACK_PATH'].'gfx/import.gif" width="12" height="12" title="Import this extension to \'local\' dir typo3conf/ext/ from online repository." alt="" />&nbsp;<a href="index.php?CMD[importExt]='.$depK.'&CMD[loc]=L&CMD[standAlone]=1" target="_blank">Import now (opens a new window)</a>';
4121                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this extension requirement</label>';
4122                      } else {
4123                          $msg[] = '<br />Extension "'.$depK.'" ('.$instExtInfo[$depK]['EM_CONF']['title'].') was not installed. Please install it first.';
4124                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;'.$this->installButton().'&nbsp;<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$depK.'&CMD[load]=1&CMD[clrCmd]=1&CMD[standAlone]=1&SET[singleDetails]=info').'" target="_blank">Install now (opens a new window)</a>';
4125                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this extension requirement</label>';
4126                      }
4127                      $depError = true;
4128                  } else {
4129                      $versionRange = $this->splitVersionRange($depV);
4130                      if ($versionRange[0]!='0.0.0' && version_compare($instExtInfo[$depK]['EM_CONF']['version'],$versionRange[0],'<'))    {
4131                          $msg[] = '<br />The running version of extension "'.$depK.'" ('.$instExtInfo[$depK]['EM_CONF']['version'].') is lower than required ('.$versionRange[0].')';
4132                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this version requirement</label>';
4133                          $depError = true;
4134                          continue;
4135                      } elseif ($versionRange[1]!='0.0.0' && version_compare($instExtInfo[$depK]['EM_CONF']['version'],$versionRange[1],'>'))    {
4136                          $msg[] = '<br />The running version of extension "'.$depK.'" ('.$instExtInfo[$depK]['EM_CONF']['version'].') is higher than allowed ('.$versionRange[1].')';
4137                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore]['.$depK.']" id="checkIgnore_'.$depK.'" /> <label for="checkIgnore_'.$depK.'">Ignore this version requirement</label>';
4138                          $depError = true;
4139                          continue;
4140                      }
4141                  }
4142              }
4143          }
4144          if($depError) {
4145              $content.= $this->doc->section('Dependency Error',implode('<br />',$msg),0,1,2);
4146          }
4147  
4148              // Check conflicts with other extensions:
4149          $conflictError = false;
4150          $msg = array();
4151  
4152          if (isset($conf['constraints']['conflicts']) && is_array($conf['constraints']['conflicts'])) {
4153              foreach((array)$conf['constraints']['conflicts'] as $conflictK => $conflictV)    {
4154                  if($depsolver['ignore'][$conflictK]) {
4155                      $msg[] = '<br />Conflict with '.$conflictK.' ignored as requested.
4156                      <input type="hidden" value="1" name="depsolver[ignore]['.$conflictK.']" />';
4157                      continue;
4158                  }
4159                  if (t3lib_extMgm::isLoaded($conflictK))    {
4160                      $msg[] = 'The extensions "'.$extKey.'" and "'.$conflictK.'" ('.$instExtInfo[$conflictK]['EM_CONF']['title'].') will conflict with each other. Please remove "'.$conflictK.'" if you want to install "'.$extKey.'".';
4161                      $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;'.$this->removeButton().'&nbsp;<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$conflictK.'&CMD[remove]=1&CMD[clrCmd]=1&CMD[standAlone]=1&SET[singleDetails]=info').'" target="_blank">Remove now (opens a new window)</a>';
4162                      $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore]['.$conflictK.']" id="checkIgnore_'.$conflictK.'" /> <label for="checkIgnore_'.$conflictK.'">Ignore this conflict error</label>';
4163                      $conflictError = true;
4164                  }
4165              }
4166          }
4167          if($conflictError) {
4168              $content.= $this->doc->section('Conflict Error',implode('<br />',$msg),0,1,2);
4169          }
4170  
4171              // Check suggests on other extensions:
4172          if (isset($conf['constraints']['suggests']) && is_array($conf['constraints']['suggests'])) {
4173              $suggestion = false;
4174              $msg = array();
4175              foreach($conf['constraints']['suggests'] as $suggestK => $suggestV)    {
4176                  if($depsolver['ignore'][$suggestK]) {
4177                      $msg[] = '<br />Suggestion of '.$suggestK.' acknowledged.
4178                  <input type="hidden" value="1" name="depsolver[ignore]['.$suggestK.']" />';
4179                      continue;
4180                  }
4181                  if (!t3lib_extMgm::isLoaded($suggestK))    {
4182                      if (!isset($instExtInfo[$suggestK]))    {
4183                          $msg[] = 'Extension "'.$suggestK.'" was not available in the system. You may want to import it from the TYPO3 Extension Repository.';
4184                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<img src="'.$GLOBALS['BACK_PATH'].'gfx/import.gif" width="12" height="12" title="Import this extension to \'local\' dir typo3conf/ext/ from online repository." alt="" />&nbsp;<a href="index.php?CMD[importExt]='.$depK.'&CMD[loc]=L&CMD[standAlone]=1" target="_blank">Import now (opens a new window)</a>';
4185                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore]['.$suggestK.']" id="checkIgnore_'.$suggestK.'" /> <label for="checkIgnore_'.$suggestK.'">Ignore this suggestion</label>';
4186                      } else {
4187                          $msg[] = 'Extension "'.$suggestK.'" ('.$instExtInfo[$suggestK]['EM_CONF']['title'].') was not installed. You may want to install it.';
4188                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;'.$this->installButton().'&nbsp;<a href="'.htmlspecialchars('index.php?CMD[showExt]='.$suggestK.'&CMD[load]=1&CMD[clrCmd]=1&CMD[standAlone]=1&SET[singleDetails]=info').'" target="_blank">Install now (opens a new window)</a>';
4189                          $msg[] = '&nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" value="1" name="depsolver[ignore]['.$suggestK.']" id="checkIgnore_'.$suggestK.'" /> <label for="checkIgnore_'.$suggestK.'">Ignore this suggestion</label>';
4190                      }
4191                      $suggestion = true;
4192                  }
4193              }
4194              if($suggestion) {
4195                  $content .= $this->doc->section('Extensions suggested by extension "'.$extKey.'"',implode('<br />',$msg),0,1,1);
4196              }
4197          }
4198  
4199          if($depError || $conflictError || $suggestion) {
4200              foreach($this->CMD as $k => $v) {
4201                  $content .= '<input type="hidden" name="CMD['.$k.']" value="'.$v.'" />';
4202              }
4203              $content .= '<br /><br /><input type="submit" value="Try again" />';
4204  
4205              return array('returnCode' => false, 'html' => $content);
4206          }
4207  
4208          return array('returnCode' => true);
4209      }
4210  
4211      /**
4212       * Remove extension key from the list of currently installed extensions and return list. If -1 is returned, an error happend.
4213       * Checks dependencies etc.
4214       *
4215       * @param    string        Extension key
4216       * @param    array        Extension information array - information about installed extensions
4217       * @return    string        New list of installed extensions or -1 if error
4218       * @see showExtDetails()
4219       */
4220  	function removeExtFromList($extKey,$instExtInfo)    {
4221          global $TYPO3_LOADED_EXT;
4222  
4223              // Initialize:
4224          $depList = array();
4225          $listArr = array_keys($TYPO3_LOADED_EXT);
4226  
4227              // 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!
4228          foreach($listArr as $k => $ext)    {
4229              if ($instExtInfo[$ext]['EM_CONF']['dependencies'])    {
4230                  $dep = t3lib_div::trimExplode(',',$instExtInfo[$ext]['EM_CONF']['dependencies'],1);
4231                  if (in_array($extKey,$dep))    {
4232                      $depList[] = $ext;
4233                  }
4234              }
4235              if (!strcmp($ext,$extKey))    unset($listArr[$k]);
4236          }
4237  
4238              // Returns either error or the new list
4239          if (count($depList))    {
4240              $msg = 'The extension(s) "'.implode(', ',$depList).'" depends on the extension you are trying to remove. The operation was not completed.';
4241              $this->content.=$this->doc->section('Dependency Error',$msg,0,1,2);
4242              return -1;
4243          } else {
4244              $listArr = $this->removeRequiredExtFromListArr($listArr);
4245              $list = implode(',',array_unique($listArr));
4246              return $list;
4247          }
4248      }
4249  
4250      /**
4251       * 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
4252       *
4253       * @param    array        Array of extension keys as values
4254       * @return    array        Modified array
4255       * @see removeExtFromList(), addExtToList()
4256       */
4257  	function removeRequiredExtFromListArr($listArr)    {
4258          foreach($listArr as $k => $ext)    {
4259              if (in_array($ext,$this->requiredExt) || !strcmp($ext,'_CACHEFILE'))    unset($listArr[$k]);
4260          }
4261          return $listArr;
4262      }
4263  
4264      /**
4265       * Traverse the array of installed extensions keys and arranges extensions in the priority order they should be in
4266       *
4267       * @param    array        Array of extension keys as values
4268       * @param    array        Extension information array
4269       * @return    array        Modified array of extention keys as values
4270       * @see addExtToList()
4271       */
4272  	function managesPriorities($listArr,$instExtInfo)    {
4273  
4274              // Initialize:
4275          $levels = array(
4276              'top' => array(),
4277              'middle' => array(),
4278              'bottom' => array(),
4279          );
4280  
4281              // Traverse list of extensions:
4282          foreach($listArr as $ext)    {
4283              $prio = trim($instExtInfo[$ext]['EM_CONF']['priority']);
4284              switch((string)$prio)    {
4285                  case 'top':
4286                  case 'bottom':
4287                      $levels[$prio][] = $ext;
4288                      break;
4289                  default:
4290                      $levels['middle'][] = $ext;
4291                      break;
4292              }
4293          }
4294          return array_merge(
4295              $levels['top'],
4296              $levels['middle'],
4297              $levels['bottom']
4298          );
4299      }
4300  
4301  
4302  
4303  
4304  
4305  
4306  
4307  
4308  
4309  
4310      /*******************************
4311      *
4312      * System Update functions (based on extension requirements)
4313      *
4314      ******************************/
4315  
4316      /**
4317       * Check if clear-cache should be performed, otherwise show form (for installation of extension)
4318       * Shown only if the extension has the clearCacheOnLoad flag set.
4319       *
4320       * @param    string        Extension key
4321       * @param    array        Extension information array
4322       * @return    string        HTML output (if form is shown)
4323       */
4324  	function checkClearCache($extInfo)    {
4325          if ($extInfo['EM_CONF']['clearCacheOnLoad'])    {
4326              if (t3lib_div::_POST('_clear_all_cache'))    {        // Action: Clearing the cache
4327                  $tce = t3lib_div::makeInstance('t3lib_TCEmain');
4328                  $tce->stripslashes_values = 0;
4329                  $tce->start(Array(),Array());
4330                  $tce->clear_cacheCmd('all');
4331              } else {    // Show checkbox for clearing cache:
4332                  $content.= '
4333                      <br />
4334                      <h3>Clear cache</h3>
4335                      <p>This extension requests the cache to be cleared when it is installed/removed.<br />
4336                          <label for="check_clear_all_cache">Clear all cache:</label> <input type="checkbox" name="_clear_all_cache" id="check_clear_all_cache" checked="checked" value="1" /><br />
4337                          </p>
4338                  ';
4339              }
4340          }
4341          return $content;
4342      }
4343  
4344      /**
4345       * Check if upload folder / "createDir" directories should be created.
4346       *
4347       * @param    string        Extension key
4348       * @param    array        Extension information array
4349       * @return    string        HTML content.
4350       */
4351  	function checkUploadFolder($extKey,$extInfo)    {
4352  
4353              // Checking for upload folder:
4354          $uploadFolder = PATH_site.$this->ulFolder($extKey);
4355          if ($extInfo['EM_CONF']['uploadfolder'] && !@is_dir($uploadFolder))    {
4356              if (t3lib_div::_POST('_uploadfolder'))    {    // CREATE dir:
4357                  t3lib_div::mkdir($uploadFolder);
4358                  $indexContent = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
4359  <HTML>
4360  <HEAD>
4361      <TITLE></TITLE>
4362  <META http-equiv=Refresh Content="0; Url=../../">
4363  </HEAD>
4364  </HTML>';
4365                  t3lib_div::writeFile($uploadFolder.'index.html',$indexContent);
4366              } else {    // Show checkbox / HTML for creation:
4367                  $content.='
4368                      <br /><h3>Create upload folder</h3>
4369                      <p>The extension requires the upload folder "'.$this->ulFolder($extKey).'" to exist.<br />
4370                  <label for="check_uploadfolder">Create directory "'.$this->ulFolder($extKey).'":</label> <input type="checkbox" name="_uploadfolder" id="check_uploadfolder" checked="checked" value="1" /><br />
4371                  </p>
4372                  ';
4373              }
4374          }
4375  
4376              // Additional directories that should be created:
4377          if ($extInfo['EM_CONF']['createDirs'])    {
4378              $createDirs = array_unique(t3lib_div::trimExplode(',',$extInfo['EM_CONF']['createDirs'],1));
4379  
4380              foreach($createDirs as $crDir)    {
4381                  if (!@is_dir(PATH_site.$crDir))    {
4382                      if (t3lib_div::_POST('_createDir_'.md5($crDir)))    {    // CREATE dir:
4383  
4384                              // Initialize:
4385                          $crDirStart = '';
4386                          $dirs_in_path = explode('/',preg_replace('/\/$/','',$crDir));
4387  
4388                              // Traverse each part of the dir path and create it one-by-one:
4389                          foreach($dirs_in_path as $dirP)    {
4390                              if (strcmp($dirP,''))    {
4391                                  $crDirStart.= $dirP.'/';
4392                                  if (!@is_dir(PATH_site.$crDirStart))    {
4393                                      t3lib_div::mkdir(PATH_site.$crDirStart);
4394                                      $finalDir = PATH_site.$crDirStart;
4395                                  }
4396                              } else {
4397                                  die('ERROR: The path "'.PATH_site.$crDir.'" could not be created.');
4398                              }
4399                          }
4400                          if ($finalDir)    {
4401                              $indexContent = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
4402  <HTML>
4403  <HEAD>
4404      <TITLE></TITLE>
4405  <META http-equiv=Refresh Content="0; Url=/">
4406  </HEAD>
4407  </HTML>';
4408                              t3lib_div::writeFile($finalDir.'index.html',$indexContent);
4409                          }
4410                      } else {    // Show checkbox / HTML for creation:
4411                          $md5CrDir = md5($crDir);
4412                          $content.='
4413                              <br />
4414                              <h3>Create folder</h3>
4415                              <p>The extension requires the folder "'.$crDir.'" to exist.<br />
4416                          <label for="check_createDir_'.$md5CrDir.'">Create directory "'.$crDir.'":</label> <input type="checkbox" name="_createDir_'.$md5CrDir.'" id="check_createDir_'.$md5CrDir.'" checked="checked" value="1" /><br />
4417                          </p>
4418                          ';
4419                      }
4420                  }
4421              }
4422          }
4423  
4424          return $content;
4425      }
4426  
4427      /**
4428       * Validates the database according to extension requirements
4429       * Prints form for changes if any. If none, returns blank. If an update is ordered, empty is returned as well.
4430       * DBAL compliant (based on Install Tool code)
4431       *
4432       * @param    string        Extension key
4433       * @param    array        Extension information array
4434       * @param    boolean        If true, returns array with info.
4435       * @return    mixed        If $infoOnly, returns array with information. Otherwise performs update.
4436       */
4437  	function checkDBupdates($extKey,$extInfo,$infoOnly=0)    {
4438  
4439              // Initializing Install Tool object:
4440          $instObj = new t3lib_install;
4441          $instObj->INSTALL = t3lib_div::_GP('TYPO3_INSTALL');
4442          $dbStatus = array();
4443  
4444              // Updating tables and fields?
4445          if (is_array($extInfo['files']) && in_array('ext_tables.sql',$extInfo['files']))    {
4446              $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables.sql');
4447  
4448              $FDfile = $instObj->getFieldDefinitions_sqlContent($fileContent);
4449              if (count($FDfile))    {
4450                  $FDdb = $instObj->getFieldDefinitions_database(TYPO3_db);
4451                  $diff = $instObj->getDatabaseExtra($FDfile, $FDdb);
4452                  $update_statements = $instObj->getUpdateSuggestions($diff);
4453  
4454                  $dbStatus['structure']['tables_fields'] = $FDfile;
4455                  $dbStatus['structure']['diff'] = $diff;
4456  
4457                      // Updating database...
4458                  if (!$infoOnly && is_array($instObj->INSTALL['database_update']))    {
4459                      $instObj->performUpdateQueries($update_statements['add'],$instObj->INSTALL['database_update']);
4460                      $instObj->performUpdateQueries($update_statements['change'],$instObj->INSTALL['database_update']);
4461                      $instObj->performUpdateQueries($update_statements['create_table'],$instObj->INSTALL['database_update']);
4462                  } else {
4463                      $content.=$instObj->generateUpdateDatabaseForm_checkboxes($update_statements['add'],'Add fields');
4464                      $content.=$instObj->generateUpdateDatabaseForm_checkboxes($update_statements['change'],'Changing fields',1,0,$update_statements['change_currentValue']);
4465                      $content.=$instObj->generateUpdateDatabaseForm_checkboxes($update_statements['create_table'],'Add tables');
4466                  }
4467              }
4468          }
4469  
4470              // Importing static tables?
4471          if (is_array($extInfo['files']) && in_array('ext_tables_static+adt.sql',$extInfo['files']))    {
4472              $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables_static+adt.sql');
4473  
4474              $statements = $instObj->getStatementArray($fileContent,1);
4475              list($statements_table, $insertCount) = $instObj->getCreateTables($statements,1);
4476  
4477                  // Execute import of static table content:
4478              if (!$infoOnly && is_array($instObj->INSTALL['database_import']))    {
4479  
4480                      // Traverse the tables
4481                  foreach($instObj->INSTALL['database_import'] as $table => $md5str)    {
4482                      if ($md5str == md5($statements_table[$table]))    {
4483                          $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS '.$table);
4484                          $GLOBALS['TYPO3_DB']->admin_query($statements_table[$table]);
4485  
4486                          if ($insertCount[$table])    {
4487                              $statements_insert = $instObj->getTableInsertStatements($statements, $table);
4488  
4489                              foreach($statements_insert as $v)    {
4490                                  $GLOBALS['TYPO3_DB']->admin_query($v);
4491                              }
4492                          }
4493                      }
4494                  }
4495              } else {
4496                  $whichTables = $instObj->getListOfTables();
4497                  if (count($statements_table))    {
4498                      $out = '';
4499                      foreach($statements_table as $table => $definition)    {
4500                          $exist = isset($whichTables[$table]);
4501  
4502                          $dbStatus['static'][$table]['exists'] = $exist;
4503                          $dbStatus['static'][$table]['count'] = $insertCount[$table];
4504  
4505                          $out.= '<tr>
4506                              <td><input type="checkbox" name="TYPO3_INSTALL[database_import]['.$table.']" checked="checked" value="'.md5($definition).'" /></td>
4507                              <td><strong>'.$table.'</strong></td>
4508                              <td><img src="clear.gif" width="10" height="1" alt="" /></td>
4509                              <td nowrap="nowrap">'.($insertCount[$table]?'Rows: '.$insertCount[$table]:'').'</td>
4510                              <td><img src="clear.gif" width="10" height="1" alt="" /></td>
4511                              <td nowrap="nowrap">'.($exist?'<img src="'.$GLOBALS['BACK_PATH'].'gfx/icon_warning.gif" width="18" height="16" align="top" alt="" />Table exists!':'').'</td>
4512                              </tr>';
4513                      }
4514                      $content.= '
4515                          <br />
4516                          <h3>Import static data</h3>
4517                          <table border="0" cellpadding="0" cellspacing="0">'.$out.'</table>';
4518                  }
4519              }
4520          }
4521  
4522              // Return array of information if $infoOnly, otherwise content.
4523          return $infoOnly ? $dbStatus : $content;
4524      }
4525  
4526      /**
4527       * Updates the database according to extension requirements
4528       * DBAL compliant (based on Install Tool code)
4529       *
4530       * @param    string        Extension key
4531       * @param    array        Extension information array
4532       * @return    void
4533       */
4534  	function forceDBupdates($extKey, $extInfo)    {
4535          $instObj = new t3lib_install;
4536  
4537              // Updating tables and fields?
4538          if (is_array($extInfo['files']) && in_array('ext_tables.sql',$extInfo['files']))    {
4539              $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables.sql');
4540  
4541              $FDfile = $instObj->getFieldDefinitions_sqlContent($fileContent);
4542              if (count($FDfile))    {
4543                  $FDdb = $instObj->getFieldDefinitions_database(TYPO3_db);
4544                  $diff = $instObj->getDatabaseExtra($FDfile, $FDdb);
4545                  $update_statements = $instObj->getUpdateSuggestions($diff);
4546  
4547                  foreach((array)$update_statements['add'] as $string)    {
4548                      $GLOBALS['TYPO3_DB']->admin_query($string);
4549                  }
4550                  foreach((array)$update_statements['change'] as $string)    {
4551                      $GLOBALS['TYPO3_DB']->admin_query($string);
4552                  }
4553                  foreach((array)$update_statements['create_table'] as $string)    {
4554                      $GLOBALS['TYPO3_DB']->admin_query($string);
4555                  }
4556              }
4557          }
4558  
4559              // Importing static tables?
4560          if (is_array($extInfo['files']) && in_array('ext_tables_static+adt.sql',$extInfo['files']))    {
4561              $fileContent = t3lib_div::getUrl($this->getExtPath($extKey,$extInfo['type']).'ext_tables_static+adt.sql');
4562  
4563              $statements = $instObj->getStatementArray($fileContent,1);
4564              list($statements_table, $insertCount) = $instObj->getCreateTables($statements,1);
4565  
4566                  // Traverse the tables
4567              foreach($statements_table as $table => $query)    {
4568                  $GLOBALS['TYPO3_DB']->admin_query('DROP TABLE IF EXISTS '.$table);
4569                  $GLOBALS['TYPO3_DB']->admin_query($query);
4570  
4571                  if ($insertCount[$table])    {
4572                      $statements_insert = $instObj->getTableInsertStatements($statements, $table);
4573  
4574                      foreach($statements_insert as $v)    {
4575                          $GLOBALS['TYPO3_DB']->admin_query($v);
4576                      }
4577                  }
4578              }
4579          }
4580      }
4581  
4582      /**
4583       * Produces the config form for an extension (if any template file, ext_conf_template.txt is found)
4584       *
4585       * @param    string        Extension key
4586       * @param    array        Extension information array
4587       * @param    boolean        If true, the form HTML content is returned, otherwise the content is set in $this->content.
4588       * @param    string        Submit-to URL (supposedly)
4589       * @param    string        Additional form fields to include.
4590       * @return    string        Depending on $output. Can return the whole form.
4591       */
4592  	function tsStyleConfigForm($extKey,$extInfo,$output=0,$script='',$addFields='')    {
4593          global $TYPO3_CONF_VARS;
4594  
4595              // Initialize:
4596          $absPath = $this->getExtPath($extKey,$extInfo['type']);
4597          $relPath = $this->typeRelPaths[$extInfo['type']].$extKey.'/';
4598  
4599              // Look for template file for form:
4600          if (@is_file($absPath.'ext_conf_template.txt'))    {
4601  
4602                  // Load tsStyleConfig class and parse configuration template:
4603              $tsStyleConfig = t3lib_div::makeInstance('t3lib_tsStyleConfig');
4604              $tsStyleConfig->doNotSortCategoriesBeforeMakingForm = TRUE;
4605              $theConstants = $tsStyleConfig->ext_initTSstyleConfig(
4606              t3lib_div::getUrl($absPath.'ext_conf_template.txt'),
4607              $relPath,
4608              $absPath,
4609              $GLOBALS['BACK_PATH']
4610              );
4611  
4612                  // Load the list of resources.
4613              $tsStyleConfig->ext_loadResources($absPath.'res/');
4614  
4615                  // Load current value:
4616              $arr = unserialize($TYPO3_CONF_VARS['EXT']['extConf'][$extKey]);
4617              $arr = is_array($arr) ? $arr : array();
4618  
4619                  // Call processing function for constants config and data before write and form rendering:
4620              if (is_array($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm']))    {
4621                  $_params = array('fields' => &$theConstants, 'data' => &$arr, 'extKey' => $extKey);
4622                  foreach($TYPO3_CONF_VARS['SC_OPTIONS']['typo3/mod/tools/em/index.php']['tsStyleConfigForm'] as $_funcRef)    {
4623                      t3lib_div::callUserFunction($_funcRef,$_params,$this);
4624                  }
4625                  unset($_params);
4626              }
4627  
4628                  // If saving operation is done:
4629              if (t3lib_div::_POST('submit'))    {
4630                  $tsStyleConfig->ext_procesInput(t3lib_div::_POST(),array(),$theConstants,array());
4631                  $arr = $tsStyleConfig->ext_mergeIncomingWithExisting($arr);
4632                  $this->writeTsStyleConfig($extKey,$arr);
4633              }
4634  
4635                  // Setting value array
4636              $tsStyleConfig->ext_setValueArray($theConstants,$arr);
4637  
4638                  // Getting session data:
4639              $MOD_MENU = array();
4640              $MOD_MENU['constant_editor_cat'] = $tsStyleConfig->ext_getCategoriesForModMenu();
4641              $MOD_SETTINGS = t3lib_BEfunc::getModuleData($MOD_MENU, t3lib_div::_GP('SET'), 'xMod_test');
4642  
4643                  // Resetting the menu (stop)
4644              if (count($MOD_MENU)>1)    {
4645                  $menu = 'Category: '.t3lib_BEfunc::getFuncMenu(0,'SET[constant_editor_cat]',$MOD_SETTINGS['constant_editor_cat'],$MOD_MENU['constant_editor_cat'],'','&CMD[showExt]='.$extKey);
4646                  $this->content.=$this->doc->section('','<span class="nobr">'.$menu.'</span>');
4647                  $this->content.=$this->doc->spacer(10);
4648              }
4649  
4650                  // Category and constant editor config:
4651              $form = '
4652                  <table border="0" cellpadding="0" cellspacing="0" width="600">
4653                      <tr>
4654                          <td>'.$tsStyleConfig->ext_getForm($MOD_SETTINGS['constant_editor_cat'],$theConstants,$script,$addFields).'</td>
4655                      </tr>
4656                  </table>';
4657              if ($output)    {
4658                  return $form;
4659              } else {
4660                  $this->content.=$this->doc->section('','</form>'.$form.'<form>');
4661              }
4662          }
4663      }
4664  
4665  
4666  
4667  
4668  
4669  
4670  
4671  
4672  
4673  
4674      /*******************************
4675      *
4676      * Dumping database (MySQL compliant)
4677      *
4678      ******************************/
4679  
4680      /**
4681       * Makes a dump of the tables/fields definitions for an extension
4682       *
4683       * @param    array        Array with table => field/key definition arrays in
4684       * @return    string        SQL for the table definitions
4685       * @see dumpStaticTables()
4686       */
4687  	function dumpTableAndFieldStructure($arr)    {
4688          $tables = array();
4689  
4690          if (count($arr))    {
4691  
4692              // Get file header comment:
4693              $tables[] = $this->dumpHeader();
4694  
4695              // Traverse tables, write each table/field definition:
4696              foreach($arr as $table => $fieldKeyInfo)    {
4697                  $tables[] = $this->dumpTableHeader($table,$fieldKeyInfo);
4698              }
4699          }
4700  
4701          // Return result:
4702          return implode(chr(10).chr(10).chr(10),$tables);
4703      }
4704  
4705      /**
4706       * Dump content for static tables
4707       *
4708       * @param    string        Comma list of tables from which to dump content
4709       * @return    string        Returns the content
4710       * @see dumpTableAndFieldStructure()
4711       */
4712  	function dumpStaticTables($tableList)    {
4713          $instObj = new t3lib_install;
4714          $dbFields = $instObj->getFieldDefinitions_database(TYPO3_db);
4715  
4716          $out = '';
4717          $parts = t3lib_div::trimExplode(',',$tableList,1);
4718  
4719          // Traverse the table list and dump each:
4720          foreach($parts as $table)    {
4721              if (is_array($dbFields[$table]['fields']))    {
4722                  $dHeader = $this->dumpHeader();
4723                  $header = $this->dumpTableHeader($table,$dbFields[$table],1);
4724                  $insertStatements = $this->dumpTableContent($table,$dbFields[$table]['fields']);
4725  
4726                  $out.= $dHeader.chr(10).chr(10).chr(10).
4727                  $header.chr(10).chr(10).chr(10).
4728                  $insertStatements.chr(10).chr(10).chr(10);
4729              } else {
4730                  die('Fatal error: Table for dump not found in database...');
4731              }
4732          }
4733          return $out;
4734      }
4735  
4736      /**
4737       * Header comments of the SQL dump file
4738       *
4739       * @return    string        Table header
4740       */
4741  	function dumpHeader()    {
4742          return trim('
4743  # TYPO3 Extension Manager dump 1.1
4744  #
4745  # Host: '.TYPO3_db_host.'    Database: '.TYPO3_db.'
4746  #--------------------------------------------------------
4747  ');
4748      }
4749  
4750      /**
4751       * Dump CREATE TABLE definition
4752       *
4753       * @param    string        Table name
4754       * @param    array        Field and key information (as provided from Install Tool class!)
4755       * @param    boolean        If true, add "DROP TABLE IF EXISTS"
4756       * @return    string        Table definition SQL
4757       */
4758  	function dumpTableHeader($table,$fieldKeyInfo,$dropTableIfExists=0)    {
4759          $lines = array();
4760          $dump = '';
4761  
4762          // Create field definitions
4763          if (is_array($fieldKeyInfo['fields']))    {
4764              foreach($fieldKeyInfo['fields'] as $fieldN => $data)    {
4765                  $lines[]='  '.$fieldN.' '.$data;
4766              }
4767          }
4768  
4769          // Create index key definitions
4770          if (is_array($fieldKeyInfo['keys']))    {
4771              foreach($fieldKeyInfo['keys'] as $fieldN => $data)    {
4772                  $lines[]='  '.$data;
4773              }
4774          }
4775  
4776          // Compile final output:
4777          if (count($lines))    {
4778              $dump = trim('
4779  #
4780  # Table structure for table "'.$table.'"
4781  #
4782  '.($dropTableIfExists ? 'DROP TABLE IF EXISTS '.$table.';
4783  ' : '').'CREATE TABLE '.$table.' (
4784  '.implode(','.chr(10),$lines).'
4785  );'
4786  );
4787          }
4788  
4789          return $dump;
4790      }
4791  
4792      /**
4793       * Dump table content
4794       * 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.
4795       *
4796       * @param    string        Table name
4797       * @param    array        Field structure
4798       * @return    string        SQL Content of dump (INSERT statements)
4799       */
4800  	function dumpTableContent($table,$fieldStructure)    {
4801  
4802          // Substitution of certain characters (borrowed from phpMySQL):
4803          $search = array('\\', '\'', "\x00", "\x0a", "\x0d", "\x1a");
4804          $replace = array('\\\\', '\\\'', '\0', '\n', '\r', '\Z');
4805  
4806          $lines = array();
4807  
4808          // Select all rows from the table:
4809          $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', $table, '');
4810  
4811          // Traverse the selected rows and dump each row as a line in the file:
4812          while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
4813              $values = array();
4814              reset($fieldStructure);
4815              while(list($field) = each($fieldStructure))    {
4816                  $values[] = isset($row[$field]) ? "'".str_replace($search, $replace, $row[$field])."'" : 'NULL';
4817              }
4818              $lines[] = 'INSERT INTO '.$table.' VALUES ('.implode(', ',$values).');';
4819          }
4820  
4821          // Free DB result:
4822          $GLOBALS['TYPO3_DB']->sql_free_result($result);
4823  
4824          // Implode lines and return:
4825          return implode(chr(10),$lines);
4826      }
4827  
4828      /**
4829       * Gets the table and field structure from database.
4830       * Which fields and which tables are determined from the ext_tables.sql file
4831       *
4832       * @param    string        Array with table.field values
4833       * @return    array        Array of tables and fields splitted.
4834       */
4835  	function getTableAndFieldStructure($parts)    {
4836          // Instance of install tool
4837          $instObj = new t3lib_install;
4838          $dbFields = $instObj->getFieldDefinitions_database(TYPO3_db);
4839  
4840  
4841          $outTables = array();
4842          foreach($parts as $table)    {
4843              $tP = explode('.',$table);
4844              if ($tP[0] && isset($dbFields[$tP[0]]))    {
4845                  if ($tP[1])    {
4846                      $kfP = explode('KEY:',$tP[1],2);
4847                      if (count($kfP)==2 && !$kfP[0])    {    // key:
4848                          if (isset($dbFields[$tP[0]]['keys'][$kfP[1]]))    $outTables[$tP[0]]['keys'][$kfP[1]] = $dbFields[$tP[0]]['keys'][$kfP[1]];
4849                      } else {
4850                          if (isset($dbFields[$tP[0]]['fields'][$tP[1]]))    $outTables[$tP[0]]['fields'][$tP[1]] = $dbFields[$tP[0]]['fields'][$tP[1]];
4851                      }
4852                  } else {
4853                      $outTables[$tP[0]] = $dbFields[$tP[0]];
4854                  }
4855              }
4856          }
4857  
4858          return $outTables;
4859      }
4860  
4861  
4862  
4863  
4864  
4865  
4866  
4867  
4868  
4869  
4870      /*******************************
4871      *
4872      * TER Communication functions
4873      *
4874      ******************************/
4875  
4876  
4877  
4878      /**
4879       * Processes return-data from online repository.
4880       * Currently only the returned emconf array is written to extension.
4881       *
4882       * @param    array        Command array returned from TER
4883       * @return    string        Message
4884       */
4885  	function uploadExtensionToTER($em)    {
4886          $msg = '';
4887          $response = $this->terConnection->uploadToTER($em);
4888  
4889          if(!is_array($response)) return $response;
4890  
4891          if($response['resultCode']==TX_TER_RESULT_EXTENSIONSUCCESSFULLYUPLOADED) {
4892              $em['extInfo']['EM_CONF']['version'] = $response['version'];
4893              $response['resultMessages'][] = 'The extension is now version: '.$response['version'];
4894              $response['resultMessages'][] = $this->updateLocalEM_CONF($em['extKey'],$em['extInfo']);
4895          }
4896  
4897          $msg = '<ul><li>'.implode('</li><li>',$response['resultMessages']).'</li></ul>';
4898          return $msg;
4899      }
4900  
4901  
4902  
4903  
4904  
4905  
4906  
4907  
4908  
4909  
4910      /************************************
4911      *
4912      * Various helper functions
4913      *
4914      ************************************/
4915  
4916      /**
4917       * Returns subtitles for the extension listings
4918       *
4919       * @param    string        List order type
4920       * @param    string        Key value
4921       * @return    string        output.
4922       */
4923  	function listOrderTitle($listOrder,$key)    {
4924          switch($listOrder)    {
4925              case 'cat':
4926                  return isset($this->categories[$key])?$this->categories[$key]:'<em>['.$key.']</em>';
4927                  break;
4928              case 'author_company':
4929                  return $key;
4930                  break;
4931              case 'state':
4932                  return $this->states[$key];
4933                  break;
4934              case 'type':
4935                  return $this->typeDescr[$key];
4936                  break;
4937          }
4938      }
4939  
4940      /**
4941       * Returns version information
4942       *
4943       * @param    string        Version code, x.x.x
4944       * @param    string        part: "", "int", "main", "sub", "dev"
4945       * @return    string
4946       * @see renderVersion()
4947       */
4948  	function makeVersion($v,$mode)    {
4949          $vDat = $this->renderVersion($v);
4950          return $vDat['version_'.$mode];
4951      }
4952  
4953      /**
4954       * Parses the version number x.x.x and returns an array with the various parts.
4955       *
4956       * @param    string        Version code, x.x.x
4957       * @param    string        Increase version part: "main", "sub", "dev"
4958       * @return    string
4959       */
4960  	function renderVersion($v,$raise='')    {
4961          $parts = t3lib_div::intExplode('.',$v.'..');
4962          $parts[0] = t3lib_div::intInRange($parts[0],0,999);
4963          $parts[1] = t3lib_div::intInRange($parts[1],0,999);
4964          $parts[2] = t3lib_div::intInRange($parts[2],0,999);
4965  
4966          switch((string)$raise)    {
4967              case 'main':
4968                  $parts[0]++;
4969                  $parts[1]=0;
4970                  $parts[2]=0;
4971                  break;
4972              case 'sub':
4973                  $parts[1]++;
4974                  $parts[2]=0;
4975                  break;
4976              case 'dev':
4977                  $parts[2]++;
4978                  break;
4979          }
4980  
4981          $res = array();
4982          $res['version'] = $parts[0].'.'.$parts[1].'.'.$parts[2];
4983          $res['version_int'] = intval($parts[0]*1000000+$parts[1]*1000+$parts[2]);
4984          $res['version_main'] = $parts[0];
4985          $res['version_sub'] = $parts[1];
4986          $res['version_dev'] = $parts[2];
4987  
4988          return $res;
4989      }
4990  
4991      /**
4992       * Returns upload folder for extension
4993       *
4994       * @param    string        Extension key
4995       * @return    string        Upload folder for extension
4996       */
4997  	function ulFolder($extKey)    {
4998          return 'uploads/tx_'.str_replace('_','',$extKey).'/';
4999      }
5000  
5001      /**
5002       * Returns true if global OR local installation of extensions is allowed/possible.
5003       *
5004       * @return    boolean        Returns true if global OR local installation of extensions is allowed/possible.
5005       */
5006  	function importAtAll()    {
5007          return ($GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'] || $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall']);
5008      }
5009  
5010      /**
5011       * Reports back if installation in a certain scope is possible.
5012       *
5013       * @param    string        Scope: G, L, S
5014       * @param    string        Extension lock-type (eg. "L" or "G")
5015       * @return    boolean        True if installation is allowed.
5016       */
5017  	function importAsType($type,$lockType='')    {
5018          switch($type)    {
5019              case 'G':
5020                  return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'] && (!$lockType || !strcmp($lockType,$type));
5021                  break;
5022              case 'L':
5023                  return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall'] && (!$lockType || !strcmp($lockType,$type));
5024                  break;
5025              case 'S':
5026                  return $this->systemInstall;
5027                  break;
5028              default:
5029                  return false;
5030          }
5031      }
5032  
5033      /**
5034       * Returns true if extensions in scope, $type, can be deleted (or installed for that sake)
5035       *
5036       * @param    string        Scope: "G" or "L"
5037       * @return    boolean        True if possible.
5038       */
5039  	function deleteAsType($type)    {
5040          switch($type)    {
5041              case 'G':
5042                  return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowGlobalInstall'];
5043                  break;
5044              case 'L':
5045                  return $GLOBALS['TYPO3_CONF_VARS']['EXT']['allowLocalInstall'];
5046                  break;
5047              default:
5048                  return false;
5049          }
5050      }
5051  
5052      /**
5053       * Evaluates differences in version numbers with three parts, x.x.x. Returns true if $v1 is greater than $v2
5054       *
5055       * @param    string        Version number 1
5056       * @param    string        Version number 2
5057       * @param    integer        Tolerance factor. For instance, set to 1000 to ignore difference in dev-version (third part)
5058       * @return    boolean        True if version 1 is greater than version 2
5059       */
5060  	function versionDifference($v1,$v2,$div=1)    {
5061          return floor($this->makeVersion($v1,'int')/$div) > floor($this->makeVersion($v2,'int')/$div);
5062      }
5063  
5064      /**
5065       * Returns true if the $str is found as the first part of a string in $array
5066       *
5067       * @param    string        String to test with.
5068       * @param    array        Input array
5069       * @param    boolean        If set, the test is case insensitive
5070       * @return    boolean        True if found.
5071       */
5072  	function first_in_array($str,$array,$caseInsensitive=FALSE)    {
5073          if ($caseInsensitive)    $str = strtolower($str);
5074          if (is_array($array))    {
5075              foreach($array as $cl)    {
5076                  if ($caseInsensitive)    $cl = strtolower($cl);
5077                  if (t3lib_div::isFirstPartOfStr($cl,$str))    return true;
5078              }
5079          }
5080          return false;
5081      }
5082  
5083      /**
5084       * Returns the $EM_CONF array from an extensions ext_emconf.php file
5085       *
5086       * @param    string        Absolute path to EMCONF file.
5087       * @param    string        Extension key.
5088       * @return    array        EMconf array values.
5089       */
5090  	function includeEMCONF($path,$_EXTKEY)    {
5091          @include($path);
5092          if(is_array($EM_CONF[$_EXTKEY])) {
5093              return $this->fixEMCONF($EM_CONF[$_EXTKEY]);
5094          }
5095          return false;
5096      }
5097  
5098      /**
5099       * Searches for ->lookUpStr in extension and returns true if found (or if no search string is set)
5100       *
5101       * @param    string        Extension key
5102       * @param    array        Extension content
5103       * @return    boolean        If true, display extension in list
5104       */
5105  	function searchExtension($extKey,$row) {
5106          if ($this->lookUpStr)    {
5107              return (
5108              stristr($extKey,$this->lookUpStr) ||
5109              stristr($row['EM_CONF']['title'],$this->lookUpStr) ||
5110              stristr($row['EM_CONF']['description'],$this->lookUpStr) ||
5111              stristr($row['EM_CONF']['author'],$this->lookUpStr) ||
5112              stristr($row['EM_CONF']['author_company'],$this->lookUpStr)
5113              );
5114          } else return true;
5115      }
5116  }
5117  
5118  // Include extension?
5119  if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/tools/em/index.php'])    {
5120      include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/mod/tools/em/index.php']);
5121  }
5122  
5123  ?>


Généré le : Sun Nov 25 17:13:16 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics