0byt3m1n1
Path:
/
data
/
applications
/
aps
/
typo3
/
4.2.1-6
/
standard
/
htdocs
/
t3lib
/
[
Home
]
File: class.t3lib_superadmin.php
<?php /*************************************************************** * Copyright notice * * (c) 1999-2008 Kasper Skaarhoj (kasperYYYY@typo3.com) * All rights reserved * * This script is part of the TYPO3 project. The TYPO3 project is * free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * The GNU General Public License can be found at * http://www.gnu.org/copyleft/gpl.html. * A copy is found in the textfile GPL.txt and important notices to the license * from the author is found in LICENSE.txt distributed with these scripts. * * * This script is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ /** * Super Admin class has functions for the administration of multiple TYPO3 sites in folders * See 'misc/superadmin.php' for details on how to use! * * $Id: class.t3lib_superadmin.php 3439 2008-03-16 19:16:51Z flyguide $ * Revised for TYPO3 3.6 February/2004 by Kasper Skaarhoj * XHTML Compliant * * @author Kasper Skaarhoj <kasperYYYY@typo3.com> */ /** * [CLASS/FUNCTION INDEX of SCRIPT] * * 120: function debug($p1,$p2='') * * * 134: class t3lib_superadmin * * SECTION: Initialize stuff * 180: function t3lib_superadmin() * 192: function init($parentDirs) * * SECTION: Main functions * 215: function defaultSet() * 271: function make() * * SECTION: Output preparation * 376: function setMenuItem($code,$label) * 390: function error($str) * 401: function headerParentDir($str) * 412: function headerSiteDir($str) * * SECTION: Collection information * 444: function initProcess() * 482: function processSiteDir($path,$dir) * 524: function includeLocalconf($localconf) * 554: function connectToDatabase($siteInfo) * 576: function getDBInfo($key) * * SECTION: Content: Installation Overview * 626: function makeTable() * * SECTION: Content: Local extensions * 729: function localExtensions() * 902: function getExtensionInfo($path,$extKey,$k) * 956: function getAllFilesAndFoldersInPath($fileArr,$extPath,$extList='',$regDirs=0) * 978: function findMostRecent($fileArr,$extPath) * 996: function removePrefixPathFromList($fileArr,$extPath) * * SECTION: Content: Other * 1033: function singleSite($exp) * 1064: function loginLog($DB) * 1102: function log_getDetails($text,$data) * 1116: function rmCachedFiles($exp) * 1149: function menuContent($exp) * 1221: function makeAdminLogin() * 1295: function changeAdminPasswordsForm() * 1330: function setNewPasswords() * * TOTAL FUNCTIONS: 28 * (This index is automatically created/updated by the extension "extdeveval") * */ // ******************************* // Set error reporting // ******************************* error_reporting (E_ALL ^ E_NOTICE); define('TYPO3_mainDir', 'typo3/'); // This is the directory of the backend administration for the sites of this TYPO3 installation. // Dependency: $path_t3lib = './typo3_src/t3lib/'; include_once($path_t3lib.'class.t3lib_div.php'); include_once($path_t3lib.'class.t3lib_db.php'); $TYPO3_DB = t3lib_div::makeInstance('t3lib_DB'); /** * Debug function. Substitute since no config_default.php file is included anywhere * * @param mixed Debug var * @param string Header string * @return void */ function debug($p1,$p2='') { t3lib_div::debug($p1,$p2); } /** * Super Admin class has functions for the administration of multiple TYPO3 sites in folders * NOTICE: Only compliant with single MySQL database usage per installation! * * @author Kasper Skaarhoj <kasperYYYY@typo3.com> * @package TYPO3 * @subpackage t3lib */ class t3lib_superadmin { // External, static: var $targetWindow = 'superAdminWindow'; var $targetWindowAdmin = 'superAdminWindowAdmin'; var $targetWindowInstall = 'superAdminWindowInstall'; var $scriptName = 'superadmin.php'; // GP vars: var $show; // "menu", "all", "admin", "info", "rmTempCached", "localext" var $type; // "phpinfo", "page" - default renders a frameset var $exp; // Additional parameter, typically a md5-hash pointing to an installation of TYPO3 // Internal, static: var $parentDirs = array(); // Configured directories to search var $globalSiteInfo = array(); // Array with information about found TYPO3 installations var $currentUrl = ''; var $mapDBtoKey = array(); var $collectAdminPasswords = array(); var $changeAdminPasswords = array(); var $collectInstallPasswords = array(); // Control: var $full = 0; // If set, the full information array per site is printed. var $noCVS = 0; // See tools/em/index.php.... /********************************** * * Initialize stuff * **********************************/ /** * Constructor, setting GP vars * * @return void */ function t3lib_superadmin() { $this->show = t3lib_div::_GP('show'); $this->type = t3lib_div::_GP('type'); $this->exp = t3lib_div::_GP('exp'); } /** * Initialize with configuration - from the 'superadmin.php' script. See misc/superadmin.php for example. * * @param array Numerical array with arrays having two keys, 'dir' and 'url' where 'dir' is the absolute path to a directory with TYPO3 installations inside. * @return void */ function init($parentDirs) { $this->parentDirs = $parentDirs; } /************************** * * Main functions * **************************/ /** * Main function, creating HTML content; frameset, menu, content frames. * Outputs the full HTML to browser. * * @return void */ function defaultSet() { // Creating content based on "type" variable: switch($this->type) { case 'phpinfo': phpinfo(); break; case 'page': ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <style type="text/css"> .redclass {color: red;} P {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px} BODY {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px} H1 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 20px; color: #000066;} H2 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 17px; color: #000066;} H3 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; color: #000066;} H4 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: maroon;} TD {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px} </style> <title>TYPO3 Super Admin</title> </head> <body> <?php echo $this->make(); ?> </body> </html> <?php break; default: ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>TYPO3 Super Admin</title> </head> <frameset cols="250,*"> <frame name="TSAmenu" src="superadmin.php?type=page&show=menu" marginwidth="10" marginheight="10" scrolling="auto" frameborder="0"> <frame name="TSApage" src="superadmin.php?type=page" marginwidth="10" marginheight="10" scrolling="auto" frameborder="0"> </frameset> </html> <?php break; } } /** * Main function, creating page content. * * @return string HTML content. */ function make() { $retVal = ''; // Creating information about the sites found: $content = $this->initProcess(); // Output mode: switch($this->show) { case 'menu': $lines=array(); $lines[]=$this->setMenuItem('info','INFO'); $lines[]=$this->setMenuItem('update','UPDATE'); $lines[]=''; $lines[]='<a href="'.htmlspecialchars($this->scriptName.'?type=page').'" target="TSApage">Default</a>'; $lines[]='<a href="'.htmlspecialchars($this->scriptName.'?type=page&show=all').'" target="TSApage">All details</a>'; $lines[]='<a href="'.htmlspecialchars($this->scriptName.'?type=page&show=admin').'" target="TSApage">Admin logins</a>'; $lines[]='<a href="'.htmlspecialchars($this->scriptName.'?type=phpinfo').'" target="TSApage">phpinfo()</a>'; $lines[]='<a href="'.htmlspecialchars($this->scriptName.'?type=page&show=localext').'" target="TSApage">Local extensions</a>'; $lines[]=''; $content = implode('<br />',$lines); $content.= '<hr />'; $content.=$this->menuContent($this->exp); $retVal = '<h2 align="center">TYPO3<br />Super Admin</h2>'.$content; break; case 'all': $retVal = ' <h1>All details:</h1> <h2>Overview:</h2> '.$this->makeTable().' <br /><hr /><br /> <h1>Details per site:</h1> '.$content; break; case 'admin': $content = $this->setNewPasswords(); $this->makeTable(); $retVal = $content.' <h1>Admin options:</h1> <h2>Admin logins:</h2> '.$this->makeAdminLogin().' <br /><hr /><br /> <h2>TBE Admin Passwords:</h2> '.t3lib_div::view_array($this->collectAdminPasswords).' <br /><hr /><br /> <h2>Install Tool Passwords:</h2> '.t3lib_div::view_array($this->collectInstallPasswords).' <br /><hr /><br /> <h2>Change TBE Admin Passwords:</h2> '.$this->changeAdminPasswordsForm().' <br /><hr /><br />'; break; case 'info': $retVal = ' <h1>Single site details</h1> '.$this->singleSite($this->exp). '<br />'; break; case 'rmTempCached': $retVal = ' <h1>Removing temp_CACHED_*.php files</h1> '.$this->rmCachedFiles($this->exp). '<br />'; break; case 'localext': $retVal = ' <h1>Local Extensions Found:</h1> '.$this->localExtensions(). '<br />'; break; default: $retVal = ' <h1>Default info:</h1>'. $content; break; } return $retVal; } /******************************** * * Output preparation * *******************************/ /** * Creates menu item from input. * * @param string Value for "&exp" parameter * @param string The label * @return string Wrapped value */ function setMenuItem($code,$label) { $out = '<a href="'.htmlspecialchars($this->scriptName.'?type=page&show=menu&exp='.$code).'" target="TSAmenu">'.htmlspecialchars($label).'</a>'; if ($code==$this->exp) { $out = '<span style="color:red;">>></span>'.$out; } return $out; } /** * Wrap string in red span tag (for errors) * * @param string Input string * @return string Output string */ function error($str) { $out = '<span style="color:red; font-size: 14px; font-weight: bold;">'.htmlspecialchars($str).'</span>'; return $out; } /** * Wraps input string in <h2> * * @param string Input string * @return string Output string, wrapped in <h2> */ function headerParentDir($str) { $out = '<h2>'.htmlspecialchars($str).'</h2>'; return $out; } /** * Wraps input string in <h3> * * @param string Input string * @return string Output string, wrapped in <h3> */ function headerSiteDir($str) { $out = '<h3>'.htmlspecialchars($str).'</h3>'; return $out; } /******************************** * * Collection information * *******************************/ /** * Traverses the parent dirs, collecting the list of TYPO3 installations into $this->globalSiteInfo * * @return string HTML content (The default view seen when starting the superadmin.php script) */ function initProcess() { $content = ''; foreach($this->parentDirs as $k => $v) { $dir = ereg_replace('/$','',$v['dir']); $baseUrl=ereg_replace('/$','',$v['url']); $content.='<br /><br /><br />'; $content.=$this->headerParentDir($dir); if (@is_dir($dir)) { $in_dirs = t3lib_div::get_dirs($dir); asort($in_dirs); reset($in_dirs); $dirArr=array(); while(list($k,$v)=each($in_dirs)) { if (substr($v,0,9)!='typo3_src') { $this->currentUrl = $baseUrl.'/'.$v; $content.= $this->headerSiteDir($v); $content.= $this->processSiteDir($dir.'/'.$v,$dir); } } } else { $content.=$this->error('"'.$dir.'" was not a directory!'); } } return $content; } /** * Creating information array for a specific TYPO3 installation * Information about site is stored in ->globalSiteInfo array * * @param string Absolute path to installation (PATH_site) * @param string Directory of main directory (level under PATH_site) * @return string HTML content with information about the site. * @access private * @see initProcess() */ function processSiteDir($path,$dir) { if (@is_dir($path)) { $localconf = $path.'/typo3conf/localconf.php'; if (@is_file($localconf)) { $key = md5($localconf); $this->includeLocalconf($localconf); $this->mapDBtoKey[$this->globalSiteInfo[$key]['siteInfo']['TYPO3_db']] = $key; $this->globalSiteInfo[$key]['siteInfo']['MAIN_DIR'] = $dir; $this->globalSiteInfo[$key]['siteInfo']['SA_PATH'] = $path; $this->globalSiteInfo[$key]['siteInfo']['URL'] = $this->currentUrl.'/'; $this->globalSiteInfo[$key]['siteInfo']['ADMIN_URL'] = $this->currentUrl.'/'.TYPO3_mainDir; $this->globalSiteInfo[$key]['siteInfo']['INSTALL_URL'] = $this->currentUrl.'/'.TYPO3_mainDir.'install/'; // Connect to database: $conMsg = $this->connectToDatabase($this->globalSiteInfo[$key]['siteInfo']); if (!$conMsg) { $this->getDBInfo($key); $out.=''; } else { $out = $conMsg; } // Show details: if ($this->full) { $out.=t3lib_div::view_array($this->globalSiteInfo[$key]); } else { $out.=t3lib_div::view_array($this->globalSiteInfo[$key]['siteInfo']); } } else $out = $this->error($localconf.' is not a file!'); } else $out = $this->error($path.' is not a directory!'); return $out; } /** * Includes "localconf" of a TYPO3 installation an loads $this->globalSiteInfo with this information. * * @param string Absolute path to localconf.php file to include. * @return array Array with information about the site. * @access private * @see processSiteDir() */ function includeLocalconf($localconf) { $TYPO3_CONF_VARS = array(); $typo_db = ''; $typo_db_username = ''; $typo_db_password = ''; $typo_db_host = ''; include($localconf); $siteInfo=array(); $siteInfo['sitename'] = $TYPO3_CONF_VARS['SYS']['sitename']; $siteInfo['TYPO3_db'] = $typo_db; $siteInfo['TYPO3_db_username'] = $typo_db_username; $siteInfo['TYPO3_db_password'] = $typo_db_password; $siteInfo['TYPO3_db_host'] = $typo_db_host; $siteInfo['installToolPassword'] = $TYPO3_CONF_VARS['BE']['installToolPassword']; $siteInfo['warningEmailAddress'] = $TYPO3_CONF_VARS['BE']['warning_email_addr']; $siteInfo['warningMode'] = $TYPO3_CONF_VARS['BE']['warning_mode']; $this->globalSiteInfo[md5($localconf)] = array('siteInfo'=>$siteInfo,'TYPO3_CONF_VARS'=>$TYPO3_CONF_VARS); return $siteInfo; } /** * Connects to a MySQL database with the TYPO3 db host/username/password and database as found in the localconf.php file! * This is NOT compatible with DBAL and connection will obviously just fail with an error message if it turns out that the _DEFAULT handler of a site is not in a MySQL database * * @param array $siteInfo array, containing username/password/host/database values. * @return string Array message if any */ function connectToDatabase($siteInfo) { if (@mysql_pconnect($siteInfo['TYPO3_db_host'], $siteInfo['TYPO3_db_username'], $siteInfo['TYPO3_db_password'])) { if (!$siteInfo['TYPO3_db']) { return $this->error('No database selected'); } elseif (!mysql_select_db($siteInfo['TYPO3_db'])) { return $this->error('Cannot connect to the current database, "'.$siteInfo['TYPO3_db'].'"'); } } else { return $this->error('The current username, password or host was not accepted when the connection to the database was attempted to be established!'); } } /** * Get database information, assuming standard tables like "be_users" * Adding the information to ->globalSiteInfo * * @param string Key for site in ->globalSiteInfo * @return void * @access private * @see processSiteDir() */ function getDBInfo($key) { $DB = $this->globalSiteInfo[$key]['siteInfo']['TYPO3_db']; // Non-admin users $query = $GLOBALS['TYPO3_DB']->SELECTquery('count(*)', 'be_users', 'admin=0 AND deleted=0'); $res = mysql($DB, $query); $row = mysql_fetch_row($res); $this->globalSiteInfo[$key]['siteInfo']['BE_USERS_NONADMIN'] = $row[0]; // Admin users $query = $GLOBALS['TYPO3_DB']->SELECTquery('count(*)', 'be_users', 'admin!=0 AND deleted=0'); $res = mysql($DB, $query); $row = mysql_fetch_row($res); $this->globalSiteInfo[$key]['siteInfo']['BE_USERS_ADMIN'] = $row[0]; // Select Admin users $query = $GLOBALS['TYPO3_DB']->SELECTquery('uid,username,password,email,realName,disable', 'be_users', 'admin!=0 AND deleted=0'); $res = mysql($DB, $query); while($row = mysql_fetch_assoc($res)) { $this->globalSiteInfo[$key]['siteInfo']['ADMINS'][] = $row; } } /****************************** * * Content: Installation Overview * ******************************/ /** * Creates big table with information about all installations in ->globalSiteInfo * * @return string HTML table */ function makeTable() { // Header row $info = array(); $info[] = 'Site:'; $info[] = 'Path:'; $info[] = 'Database:'; $info[] = 'Username'; $info[] = 'Password'; $info[] = 'Host'; $info[] = 'Links (new win)'; $info[] = '#Users NA/A'; $info[] = 'Admin be_users Info'; $info[] = 'Install Tool Password'; $info[] = 'Warning email address'; $info[] = 'W.mode'; $mainArrRows[] = ' <tr bgcolor="#eeeeee"> <td nowrap="nowrap" valign="top">'.implode('</td> <td nowrap="nowrap" valign="top">',$info).'</td> </tr>'; // Traverse globalSiteInfo for each site: foreach($this->globalSiteInfo as $k => $all) { $info = array(); // Sitename and Database details: $info[] = htmlspecialchars($all['siteInfo']['sitename']); $info[] = '<span style="color:#666666;">'.htmlspecialchars($all['siteInfo']['MAIN_DIR']).'</span>'.htmlspecialchars(substr($all['siteInfo']['SA_PATH'],strlen($all['siteInfo']['MAIN_DIR']))); $info[] = htmlspecialchars($all['siteInfo']['TYPO3_db']); $info[] = htmlspecialchars($all['siteInfo']['TYPO3_db_username']); $info[] = htmlspecialchars($all['siteInfo']['TYPO3_db_password']); $info[] = htmlspecialchars($all['siteInfo']['TYPO3_db_host']); // URL $info[] = '<a href="'.htmlspecialchars($all['siteInfo']['URL']).'" target="'.$this->targetWindow.'">Site</a>'. ' / <a href="'.htmlspecialchars($all['siteInfo']['ADMIN_URL']).'" target="'.$this->targetWindowAdmin.'">Admin</a>'. ' / <a href="'.htmlspecialchars($all['siteInfo']['INSTALL_URL']).'" target="'.$this->targetWindowInstall.'">Install</a>'; $info[] = htmlspecialchars($all['siteInfo']['BE_USERS_NONADMIN'].'/'.$all['siteInfo']['BE_USERS_ADMIN']); // Admin if (is_array($all['siteInfo']['ADMINS'])) { $lines = array(); foreach($all['siteInfo']['ADMINS'] as $vArr) { $lines[] = htmlspecialchars($vArr['password'].' - '.$vArr['username'].' ('.$vArr['realName'].', '.$vArr['email'].')'); $this->collectAdminPasswords[$vArr['password']][] = array( 'path' => $all['siteInfo']['SA_PATH'], 'site' => $all['siteInfo']['sitename'], 'database' => $all['siteInfo']['TYPO3_db'], 'user' => $vArr['username'], 'name_email' => $vArr['realName'].', '.$vArr['email'] ); $this->changeAdminPasswords[$vArr['password']][] = $all['siteInfo']['TYPO3_db'].':'.$vArr['uid'].':'.$vArr['username']; } $info[] = implode('<br />',$lines); } else { $info[] = $this->error('No DB connection!'); } // Install $info[] = htmlspecialchars($all['siteInfo']['installToolPassword']); $this->collectInstallPasswords[$all['siteInfo']['installToolPassword']][] = $all['siteInfo']['SA_PATH'].' - '.$all['siteInfo']['sitename'].' - ('.$all['siteInfo']['TYPO3_db'].')'; $info[] = htmlspecialchars($all['siteInfo']['warningEmailAddress']); $info[] = htmlspecialchars($all['siteInfo']['warningMode']); // compile $mainArrRows[] = ' <tr> <td nowrap="nowrap" valign="top">'.implode('</td> <td nowrap="nowrap" valign="top">',$info).'</td> </tr>'; } // Compile / return table finally: $table = '<table border="1" cellpadding="1" cellspacing="1">'.implode('',$mainArrRows).'</table>'; return $table; } /****************************** * * Content: Local extensions * ******************************/ /** * Based on the globalSiteInfo array, this prints information about local extensions for each site. * In particular version number and most recent mod-time is interesting! * * @return string HTML */ function localExtensions() { $this->extensionInfoArray=array(); // Traverse $this->globalSiteInfo for local extensions: foreach($this->globalSiteInfo as $k => $all) { if ($all['siteInfo']['SA_PATH']) { $extDir = $all['siteInfo']['SA_PATH'].'/typo3conf/ext/'; if (@is_dir($extDir)) { $this->extensionInfoArray['site'][$k] = array(); // Get extensions in local directory $extensions=t3lib_div::get_dirs($extDir); if (is_array($extensions)) { foreach($extensions as $extKey) { // Getting and setting information for extension: $eInfo = $this->getExtensionInfo($extDir,$extKey,$k); $this->extensionInfoArray['site'][$k][$extKey] = $eInfo; $this->extensionInfoArray['ext'][$extKey][$k] = $eInfo; } } } } } // Display results: $out=''; $headerRow = ' <tr bgcolor="#ccccee" style="font-weight:bold;"> <td>Extension key</td> <td>Path</td> <td>Title</td> <td>Ver.</td> <td>Files</td> <td><span title="If M, then there is a manual.">M</span></td> <td>Last mod. time</td> <td>Hash off all file mod. times:</td> <td>TYPO3 ver. req.</td> <td>CGL compliance</td> </tr> '; // PER EXTENSION: if (is_array($this->extensionInfoArray['ext'])) { $extensionKeysCollect=array(); ksort($this->extensionInfoArray['ext']); reset($this->extensionInfoArray['ext']); $rows=array( 'reg'=>array(), 'user'=>array() ); foreach($this->extensionInfoArray['ext'] as $extKey => $instances) { $mtimes = array(); // Find most recent mtime of the options: reset($instances); while(list($k,$eInfo)=each($instances)) { $mtimes[] = $eInfo['mtime']; } // Max mtime: $maxMtime = max($mtimes); $c = 0; // So, traverse all sites with the extension present: foreach($instances as $k => $eInfo) { // Set background color if mtime matches if ($maxMtime==$eInfo['mtime']) { $this->extensionInfoArray['site'][$k][$extKey]['_highlight']=1; $bgCol = $eInfo['dirtype']=='link' ? ' bgcolor="#ffcccc"' : ' bgcolor="#eeeeee"'; } else { $bgCol = ' style="color: #999999; font-style: italic;"'; } // Make row: $type = substr($extKey,0,5)!='user_' ? 'reg' : 'user'; if ($type=='reg') $extensionKeysCollect[] = $extKey; if (!is_array($eInfo)) { // Standard listing: $rows[$type][] = ' <tr> '.(!$c?'<td rowspan="'.count($instances).'">'.htmlspecialchars($extKey).'</td>':'').' <td nowrap="nowrap" bgcolor="#ccddcc">'.htmlspecialchars($this->globalSiteInfo[$k]['siteInfo']['SA_PATH']).'</td> <td nowrap="nowrap" bgcolor="#ccddcc" colspan="8"><em>'.htmlspecialchars($eInfo).'</em></td> </tr> '; } else { // Standard listing: $rows[$type][] = ' <tr> '.(!$c?'<td rowspan="'.count($instances).'">'.htmlspecialchars($extKey).'</td>':'').' <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($this->globalSiteInfo[$k]['siteInfo']['SA_PATH']).'</td> <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['title']).'</td> <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['version']).'</td> <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['numberfiles']).'</td> <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['manual']?'M':'-').'</td> <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['mtime']?date('d-m-y H:i:s',$eInfo['mtime']):'').'</td> <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['mtime_hash']).'</td> <td'.$bgCol.'>'.htmlspecialchars($eInfo['TYPO3_version']).'</td> <td'.$bgCol.'><img src="clear.gif" width="150" height="1" alt="" /><br />'.htmlspecialchars($eInfo['CGLcompliance'].($eInfo['CGLcompliance_note'] ? ' - '.$eInfo['CGLcompliance_note'] : '')).'</td> </tr> '; } $c++; } } // Extensions with registered extension keys: $out.=' <h3>Registered extensions:</h3> <table border="1">'.$headerRow.implode('',$rows['reg']).'</table>'; // List of those extension keys in a form field: $extensionKeysCollect = array_unique($extensionKeysCollect); asort($extensionKeysCollect); $out.='<form action=""><textarea cols="80" rows="10">'.implode(chr(10),$extensionKeysCollect).'</textarea></form>'; // USER extension (prefixed "user_") $out.='<br /> <h3>User extensions:</h3> <table border="1">'.$headerRow.implode('',$rows['user']).'</table>'; } // PER SITE: if (is_array($this->extensionInfoArray['site'])) { $rows = array(); foreach($this->extensionInfoArray['site'] as $k => $extensions) { // So, traverse all sites with the extension present: $c = 0; foreach($extensions as $extKey => $eInfo) { // Set background color if mtime matches if ($eInfo['_highlight']) { $bgCol = $eInfo['dirtype']=='link' ? ' bgcolor="#ffcccc"' : ' bgcolor="#eeeeee"'; } else { $bgCol = ' style="color: #999999; font-style: italic;"'; } // Make row: $rows[] = ' <tr> '.(!$c?'<td rowspan="'.count($extensions).'">'.htmlspecialchars($this->globalSiteInfo[$k]['siteInfo']['SA_PATH']).'</td>':'').' <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($extKey).'</td> <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['title']).'</td> <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['version']).'</td> <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['numberfiles']).'</td> <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['mtime']?date('d-m-y H:i:s',$eInfo['mtime']):'').'</td> <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['mtime_hash']).'</td> </tr> '; $c++; } } $out.='<br /> <h3>Sites:</h3> <table border="1">'.implode('',$rows).'</table>'; } // Return content return $out; } /** * Gets information for an extension, eg. version and most-recently-edited-script * * @param string Path to local extension folder * @param string Extension key * @param string Key to globalSiteInformation array * @return array Information array (unless an error occured) */ function getExtensionInfo($path,$extKey,$k) { $file = $path.$extKey.'/ext_emconf.php'; if (@is_file($file)) { $_EXTKEY = $extKey; $EM_CONF = array(); include($file); $eInfo = array(); // Info from emconf: $eInfo['title'] = $EM_CONF[$extKey]['title']; $eInfo['version'] = $EM_CONF[$extKey]['version']; $eInfo['CGLcompliance'] = $EM_CONF[$extKey]['CGLcompliance']; $eInfo['CGLcompliance_note'] = $EM_CONF[$extKey]['CGLcompliance_note']; $eInfo['TYPO3_version'] = $EM_CONF[$extKey]['TYPO3_version']; $filesHash = unserialize($EM_CONF[$extKey]['_md5_values_when_last_written']); if (!is_array($filesHash) || count($filesHash)<500) { // Get all files list (may take LOONG time): $extPath = $path.$extKey.'/'; $fileArr = array(); $fileArr = $this->removePrefixPathFromList($this->getAllFilesAndFoldersInPath($fileArr,$extPath),$extPath); if (!is_array($fileArr)) { debug(array($fileArr,$extKey,$extPath,$this->getAllFilesAndFoldersInPath(array(),$extPath)),'ERROR'); } // Number of files: $eInfo['numberfiles'] = count($fileArr); $eInfo['dirtype'] = filetype($path.$extKey); // Most recent modification: $eInfo['mtime_files'] = $this->findMostRecent($fileArr,$extPath); if (count($eInfo['mtime_files'])) $eInfo['mtime'] = max($eInfo['mtime_files']); $eInfo['mtime_hash'] = md5(implode(',',$eInfo['mtime_files'])); } else { $eInfo['mtime_hash'] = 'No calculation done, too many files in extension: '.count($filesHash); } $eInfo['manual'] = @is_file($path.$extKey.'/doc/manual.sxw'); return $eInfo; } else return 'ERROR: No emconf.php file: '.$file; } /** * Recursively gather all files and folders of extension path. * * @param array Array of files to which new files are added * @param string Path to look up files in * @param string List of file extensions to include. Blank = all * @param boolean If set, directories are included as well. * @return array $fileArr with new entries added. */ function getAllFilesAndFoldersInPath($fileArr,$extPath,$extList='',$regDirs=0) { if ($regDirs) $fileArr[] = $extPath; $fileArr = array_merge($fileArr,t3lib_div::getFilesInDir($extPath,$extList,1,1)); $dirs = t3lib_div::get_dirs($extPath); if (is_array($dirs)) { foreach($dirs as $subdirs) { if ($subdirs && (strcmp($subdirs,'CVS') || !$this->noCVS)) { $fileArr = $this->getAllFilesAndFoldersInPath($fileArr,$extPath.$subdirs.'/',$extList,$regDirs); } } } return $fileArr; } /** * Creates an array with modification times of all files in $fileArr * * @param array Files in extension (rel path) * @param string Abs path prefix for files. * @return array Array with modification times of files (filenames are keys) */ function findMostRecent($fileArr,$extPath) { $mtimeArray = array(); foreach($fileArr as $fN) { if ($fN!='ext_emconf.php') { $mtime = filemtime($extPath.$fN); $mtimeArray[$fN] = $mtime; } } return $mtimeArray; } /** * Removes the absolute part of all files/folders in fileArr * * @param array File array * @param string Prefix to remove * @return array Modified file array (or error string) */ function removePrefixPathFromList($fileArr,$extPath) { reset($fileArr); while(list($k,$absFileRef)=each($fileArr)) { if(t3lib_div::isFirstPartOfStr($absFileRef,$extPath)) { $fileArr[$k]=substr($absFileRef,strlen($extPath)); } else return 'ERROR: One or more of the files was NOT prefixed with the prefix-path!'; } return $fileArr; } /****************************** * * Content: Other * ******************************/ /** * Shows detailed information for a single installation of TYPO3 * * @param string KEY pointing to installation * @return string HTML content */ function singleSite($exp) { $all = $this->globalSiteInfo[$exp]; // General information: $content = ' <h2>'.htmlspecialchars($all['siteInfo']['sitename'].' (DB: '.$all['siteInfo']['TYPO3_db']).')</h2> <hr /> <h3>Main details:</h3> LINKS: <a href="'.htmlspecialchars($all['siteInfo']['URL']).'" target="'.$this->targetWindow.'">Site</a> / <a href="'.htmlspecialchars($all['siteInfo']['ADMIN_URL']).'" target="'.$this->targetWindowAdmin.'">Admin</a> / <a href="'.htmlspecialchars($all['siteInfo']['INSTALL_URL']).'" target="'.$this->targetWindowInstall.'">Install</a> <br /><br />'; // Add all information in globalSiteInfo array: $content.= t3lib_div::view_array($all); // Last-login: $content.= ' <h3>Login-Log for last month:</h3>'; $content.= $this->loginLog($all['siteInfo']['TYPO3_db']); // Return content return $content; } /** * Get last-login log for database. * * @param string Database * @return string HTML */ function loginLog($DB) { // Non-admin users //1=login, 2=logout, 3=failed login (+ errorcode 3), 4=failure_warning_email sent $query = $GLOBALS['TYPO3_DB']->SELECTquery( 'sys_log.*, be_users.username AS username, be_users.admin AS admin', 'sys_log,be_users', 'be_users.uid=sys_log.userid AND sys_log.type=255 AND sys_log.tstamp > '.(time()-(60*60*24*30)), '', 'sys_log.tstamp DESC' ); $res = mysql($DB,$query); $dayRef = ''; $lines = array(); while($row = mysql_fetch_assoc($res)) { $day = date('d-m-Y',$row['tstamp']); if ($dayRef!=$day) { $lines[] = ' <h4>'.$day.':</h4>'; $dayRef=$day; } $theLine = date('H:i',$row['tstamp']).': '.str_pad(substr($row['username'],0,10),10).' '.$this->log_getDetails($row['details'],unserialize($row['log_data'])); $theLine = htmlspecialchars($theLine); $lines[]= $row['admin'] ? '<span class="redclass">'.$theLine.'</span>' : $theLine; // debug($row); } return '<pre>'.implode(chr(10),$lines).'</pre>'; } /** * Compile log details into template string * * @param string Log message (template) * @param array Data array to insert in log message * @return string Log details. */ function log_getDetails($text,$data) { // $code is used later on to substitute errormessages with language-corrected values... if (is_array($data)) { return sprintf($text, $data[0],$data[1],$data[2],$data[3],$data[4]); } else return $text; } /** * Removing temp_CACHED files for installation * * @param string KEY pointing to installation * @return string HTML content */ function rmCachedFiles($exp) { $all = $this->globalSiteInfo[$exp]; $content = ' <h2>'.htmlspecialchars($all['siteInfo']['sitename'].' (DB: '.$all['siteInfo']['TYPO3_db']).')</h2> <hr /> <h3>typo3conf/temp_CACHED_* files:</h3>'; $path = $all['siteInfo']['SA_PATH'].'/typo3conf/'; if (@is_dir($path)) { $filesInDir = t3lib_div::getFilesInDir($path,'php',1); foreach($filesInDir as $kk => $vv) { if (t3lib_div::isFirstPartOfStr(basename($vv),'temp_CACHED_')) { if (strstr(basename($vv),'ext_localconf.php') || strstr(basename($vv),'ext_tables.php')) { $content.='REMOVED: '.$vv.'<br />'; unlink($vv); if (file_exists($vv)) $content.= $this->error('ERROR: File still exists, so could not be removed anyways!').'<br />'; } } } } else { $content.= $this->error('ERROR: '.$path.' was not a directory!'); } return $content; } /** * Menu for either update/information, showing links for each installation found * * @param string Action key "update" or "info" * @return string HTML output. */ function menuContent($exp) { if ($exp) { // Initialize: $lines = array(); $head = ''; foreach($this->globalSiteInfo as $k => $all) { // Setting section header, if needed. if ($head!=$all['siteInfo']['MAIN_DIR']) { $lines[] = ' <h4 style="white-space: nowrap;">'.htmlspecialchars(t3lib_div::fixed_lgd_pre($all['siteInfo']['MAIN_DIR'],18)).'</h4>'; $head = $all['siteInfo']['MAIN_DIR']; // Set new head... } // Display mode: switch($exp) { case 'update': // Label: $label = $all['siteInfo']['sitename'] ? $all['siteInfo']['sitename'] : '(DB: '.$all['siteInfo']['TYPO3_db'].')'; $lines[] = ' <hr /> <b>'.htmlspecialchars($label).'</b> ('.htmlspecialchars(substr($all['siteInfo']['SA_PATH'],strlen($all['siteInfo']['MAIN_DIR'])+1)).')<br />'; // To avoid "visited links" display on next hit: $tempVal='&_someUniqueValue='.time(); // Add links for update: $url = $this->scriptName.'?type=page&show=rmTempCached&exp='.$k.$tempVal; $lines[] = '<span style="white-space: nowrap;"><a href="'.htmlspecialchars($url).'" target="TSApage">Remove temp_CACHED files</a></span>'; $url = $all['siteInfo']['INSTALL_URL'].'index.php?TYPO3_INSTALL[type]=database&TYPO3_INSTALL[database_type]=import|CURRENT_STATIC'."&presetWholeTable=1".$tempVal.'#bottom'; $lines[] = '<span style="white-space: nowrap;"><a href="'.htmlspecialchars($url).'" target="TSApage">CURRENT_STATIC</a></span>'; $url = $all['siteInfo']['INSTALL_URL'].'index.php?TYPO3_INSTALL[type]=database&TYPO3_INSTALL[database_type]=cmpFile|CURRENT_TABLES'.$tempVal.'#bottom'; $lines[] = '<span style="white-space: nowrap;"><a href="'.htmlspecialchars($url).'" target="TSApage">CURRENT_TABLES</a></span>'; // Cache $url = $all['siteInfo']['INSTALL_URL'].'index.php?TYPO3_INSTALL[type]=database&TYPO3_INSTALL[database_type]=cache|'. "&PRESET[database_clearcache][cache_pages]=1". '&PRESET[database_clearcache][cache_pagesection]=1'. "&PRESET[database_clearcache][cache_hash]=1". $tempVal. '#bottom'; $lines[] = '<span style="white-space: nowrap;"><a href="'.htmlspecialchars($url).'" target="TSApage">Clear cache</a></span>'; // Admin link $url = $all['siteInfo']['ADMIN_URL'].'index.php'; $lines[] = '<span style="white-space: nowrap;"><a href="'.htmlspecialchars($url).'" target="'.$this->targetWindowAdmin.'">Admin -></a></span>'; break; case 'info': // item $label = $all['siteInfo']['sitename'] ? $all['siteInfo']['sitename'] : '(DB: '.$all['siteInfo']['TYPO3_db'].')'; $url = $this->scriptName.'?type=page&show=info&exp='.$k; $lines[] = '<span style="white-space: nowrap;"><a href="'.htmlspecialchars($url).'" target="TSApage">'.htmlspecialchars($label).'</a> ('.htmlspecialchars(substr($all['siteInfo']['SA_PATH'],strlen($all['siteInfo']['MAIN_DIR'])+1)).'/)</span>'; break; } } // Return result. return implode('<br />',$lines).'<br />'; } } /** * Create list of admin logins. * * @return string HTML table */ function makeAdminLogin() { // Initialize: $lines = array(); $head = ''; // Traverse installations found: foreach($this->globalSiteInfo as $k => $all) { // Setting section header, if needed. if ($head!=$all['siteInfo']['MAIN_DIR']) { $lines[] = ' <tr> <td colspan="2"><br /> <h4>'.htmlspecialchars($all['siteInfo']['MAIN_DIR']).'</h4> </td> </tr>'; $head = $all['siteInfo']['MAIN_DIR']; } // item $label = $all['siteInfo']['sitename'] ? $all['siteInfo']['sitename'] : '(DB: '.$all['siteInfo']['TYPO3_db'].')'; $unique = md5(microtime()); $opts = array(); $defUName = ''; if (is_array($all['siteInfo']['ADMINS'])) { foreach($all['siteInfo']['ADMINS'] as $vArr) { $chalVal = md5($vArr['username'].':'.$vArr['password'].':'.$unique); $opts[] = '<option value="'.$chalVal.'">'.htmlspecialchars($vArr['username'].($vArr['disable']?' [DISABLED]':'')).'</option>'; if (!$defUName) { $defUName = $vArr['username']; } } } if (count($opts)>1) { $userident = ' <select name="userident" onchange="document[\''.$k.'\'].username.value=this.options[this.selectedIndex].text;"> '.implode(' ',$opts).' </select> '; } else { $userident = ' ('.$defUName.')<br /> <input type="hidden" name="userident" value="'.$chalVal.'" />'; } $form=' <form name="'.$k.'" action="'.$all['siteInfo']['ADMIN_URL'].'index.php" target="EXTERnalWindow" method="post"> <input type="submit" name="submit" value="Login" /> <input type="hidden" name="username" value="'.$defUName.'" /> <input type="hidden" name="challenge" value="'.$unique.'" /> <input type="hidden" name="redirect_url" value="" /> <input type="hidden" name="login_status" value="login" /> '.trim($userident).' </form>'; $lines[] = ' <tr> <td><strong>'.htmlspecialchars($label).'</strong></td> <td nowrap="nowrap">'.trim($form).'</td> </tr>'; } // Return login table: return '<table border="1" cellpadding="5" cellspacing="1">'.implode('',$lines).'</table>'; } /** * For for changing admin passwords * * @return string Form content. */ function changeAdminPasswordsForm() { $content=''; foreach($this->changeAdminPasswords as $k => $p) { $content.=' <h3>'.$k.'</h3>'; foreach($p as $kk => $pp) { $content.= '<span style="white-space: nowrap;">'; $content.= '<input type="checkbox" name="SETFIELDS[]" value="'.$pp.'" /> '.$pp.' - '; $content.= htmlspecialchars(implode(' - ',$this->collectAdminPasswords[$k][$kk])); $content.= '</span><br />'; } } $content.='New password: <input type="text" name="NEWPASS" /><br />'; $content.='New password (md5): <input type="text" name="NEWPASS_md5" /><br /> (This overrules any plain password above!) <br />'; $content=' <form action="'.htmlspecialchars($this->scriptName.'?type=page&show=admin').'" method="post"> '.$content.' <input type="submit" name="Set" /> </form> '; return $content; } /** * Setting new passwords * * @return string Status * @see changeAdminPasswordsForm() */ function setNewPasswords() { $whichFields = t3lib_div::_POST('SETFIELDS'); $pass = trim(t3lib_div::_POST('NEWPASS')); $passMD5 = t3lib_div::_POST('NEWPASS_md5'); $updatedFlag = 0; if (($pass || $passMD5) && is_array($whichFields)) { $pass = $passMD5 ? $passMD5 : md5($pass); foreach($whichFields as $values) { $parts = explode(':',$values); if (count($parts)>2) { $key = $this->mapDBtoKey[$parts[0]]; if ($key && isset($this->globalSiteInfo[$key]['siteInfo'])) { $error = $this->connectToDatabase($this->globalSiteInfo[$key]['siteInfo']); if (!$error) { $DB = $this->globalSiteInfo[$key]['siteInfo']['TYPO3_db']; $content.='<h3>Updating '.$DB.':</h3>'; $query = $GLOBALS['TYPO3_DB']->UPDATEquery( 'be_users', 'uid='.intval($parts[1]).' AND username="'.addslashes($parts[2]).'" AND admin!=0', array('password' => $pass) ); // username/admin are added to security. But they are certainly redundant!! mysql($DB,$query); $content.= 'Affected rows: '.mysql_affected_rows().'<br /><hr />'; $updatedFlag = '1'; } } } } } $this->initProcess(); return $content; } } if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_superadmin.php']) { include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_superadmin.php']); } ?>