* Updated my email address from "kasper@typo3.com" (which is closed and will stay...
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_superadmin.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2004 Kasper Skaarhoj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Super Admin class has functions for the administration of multiple TYPO3 sites in folders
29 * See 'misc/superadmin.php' for details on how to use!
30 *
31 * $Id$
32 * Revised for TYPO3 3.6 February/2004 by Kasper Skaarhoj
33 * XHTML Compliant
34 *
35 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
36 */
37 /**
38 * [CLASS/FUNCTION INDEX of SCRIPT]
39 *
40 * 119: function debug($p1,$p2='')
41 *
42 *
43 * 133: class t3lib_superadmin
44 *
45 * SECTION: Initialize stuff
46 * 179: function t3lib_superadmin()
47 * 191: function init($parentDirs)
48 *
49 * SECTION: Main functions
50 * 214: function defaultSet()
51 * 270: function make()
52 *
53 * SECTION: Output preparation
54 * 372: function setMenuItem($code,$label)
55 * 386: function error($str)
56 * 397: function headerParentDir($str)
57 * 408: function headerSiteDir($str)
58 *
59 * SECTION: Collection information
60 * 440: function initProcess()
61 * 478: function processSiteDir($path,$dir)
62 * 520: function includeLocalconf($localconf)
63 * 544: function connectToDatabase($siteInfo)
64 * 566: function getDBInfo($key)
65 *
66 * SECTION: Content: Installation Overview
67 * 616: function makeTable()
68 *
69 * SECTION: Content: Local extensions
70 * 719: function localExtensions()
71 * 892: function getExtensionInfo($path,$extKey,$k)
72 * 945: function getAllFilesAndFoldersInPath($fileArr,$extPath,$extList='',$regDirs=0)
73 * 967: function findMostRecent($fileArr,$extPath)
74 * 985: function removePrefixPathFromList($fileArr,$extPath)
75 *
76 * SECTION: Content: Other
77 * 1022: function singleSite($exp)
78 * 1053: function loginLog($DB)
79 * 1091: function log_getDetails($text,$data)
80 * 1105: function rmCachedFiles($exp)
81 * 1138: function menuContent($exp)
82 * 1210: function makeAdminLogin()
83 * 1284: function changeAdminPasswordsForm()
84 * 1319: function setNewPasswords()
85 *
86 * TOTAL FUNCTIONS: 28
87 * (This index is automatically created/updated by the extension "extdeveval")
88 *
89 */
90
91
92
93
94
95
96
97
98
99 // *******************************
100 // Set error reporting
101 // *******************************
102 error_reporting (E_ALL ^ E_NOTICE);
103 define('TYPO3_mainDir', 'typo3/'); // This is the directory of the backend administration for the sites of this TYPO3 installation.
104
105
106 // Dependency:
107 include_once('./typo3_src/t3lib/class.t3lib_div.php');
108 include_once('./typo3_src/t3lib/class.t3lib_db.php');
109 $TYPO3_DB = t3lib_div::makeInstance('t3lib_DB');
110
111
112 /**
113 * Debug function. Substitute since no config_default.php file is included anywhere
114 *
115 * @param mixed Debug var
116 * @param string Header string
117 * @return void
118 */
119 function debug($p1,$p2='') {
120 t3lib_div::debug($p1,$p2);
121 }
122
123
124
125 /**
126 * Super Admin class has functions for the administration of multiple TYPO3 sites in folders
127 * NOTICE: Only compliant with single MySQL database usage per installation!
128 *
129 * @author Kasper Skaarhoj <kasperYYYY@typo3.com>
130 * @package TYPO3
131 * @subpackage t3lib
132 */
133 class t3lib_superadmin {
134
135 // External, static:
136 var $targetWindow = 'superAdminWindow';
137 var $targetWindowAdmin = 'superAdminWindowAdmin';
138 var $targetWindowInstall = 'superAdminWindowInstall';
139 var $scriptName = 'superadmin.php';
140
141 // GP vars:
142 var $show; // "menu", "all", "admin", "info", "rmTempCached", "localext"
143 var $type; // "phpinfo", "page" - default renders a frameset
144 var $exp; // Additional parameter, typically a md5-hash pointing to an installation of TYPO3
145
146 // Internal, static:
147 var $parentDirs = array(); // Configured directories to search
148 var $globalSiteInfo = array(); // Array with information about found TYPO3 installations
149
150 var $currentUrl = '';
151 var $mapDBtoKey = array();
152 var $collectAdminPasswords = array();
153 var $changeAdminPasswords = array();
154 var $collectInstallPasswords = array();
155
156 // Control:
157 var $full = 0; // If set, the full information array per site is printed.
158
159 var $noCVS = 0; // See tools/em/index.php....
160
161
162
163
164
165
166
167
168 /**********************************
169 *
170 * Initialize stuff
171 *
172 **********************************/
173
174 /**
175 * Constructor, setting GP vars
176 *
177 * @return void
178 */
179 function t3lib_superadmin() {
180 $this->show = t3lib_div::_GP('show');
181 $this->type = t3lib_div::_GP('type');
182 $this->exp = t3lib_div::_GP('exp');
183 }
184
185 /**
186 * Initialize with configuration - from the 'superadmin.php' script. See misc/superadmin.php for example.
187 *
188 * @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.
189 * @return void
190 */
191 function init($parentDirs) {
192 $this->parentDirs = $parentDirs;
193 }
194
195
196
197
198
199
200
201
202 /**************************
203 *
204 * Main functions
205 *
206 **************************/
207
208 /**
209 * Main function, creating HTML content; frameset, menu, content frames.
210 * Outputs the full HTML to browser.
211 *
212 * @return void
213 */
214 function defaultSet() {
215
216 // Creating content based on "type" variable:
217 switch($this->type) {
218 case 'phpinfo':
219 phpinfo();
220 break;
221 case 'page':
222 ?>
223 <!DOCTYPE html
224 PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
225 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
226 <html>
227 <head>
228 <style type="text/css">
229 .redclass {color: red;}
230 P {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px}
231 BODY {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px}
232 H1 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 20px; color: #000066;}
233 H2 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 17px; color: #000066;}
234 H3 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; color: #000066;}
235 H4 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: maroon;}
236 TD {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px}
237 </style>
238 <title>TYPO3 Super Admin</title>
239 </head>
240 <body>
241 <?php
242 echo $this->make();
243 ?>
244 </body>
245 </html>
246 <?php
247 break;
248 default:
249 ?>
250 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
251 <html>
252 <head>
253 <title>TYPO3 Super Admin</title>
254 </head>
255 <frameset cols="250,*">
256 <frame name="TSAmenu" src="superadmin.php?type=page&show=menu" marginwidth="10" marginheight="10" scrolling="auto" frameborder="0">
257 <frame name="TSApage" src="superadmin.php?type=page" marginwidth="10" marginheight="10" scrolling="auto" frameborder="0">
258 </frameset>
259 </html>
260 <?php
261 break;
262 }
263 }
264
265 /**
266 * Main function, creating page content.
267 *
268 * @return string HTML content.
269 */
270 function make() {
271
272 // Creating information about the sites found:
273 $content = $this->initProcess();
274
275 // Output mode:
276 switch($this->show) {
277 case 'menu':
278 $lines=array();
279 $lines[]=$this->setMenuItem('info','INFO');
280 $lines[]=$this->setMenuItem('update','UPDATE');
281 $lines[]='';
282 $lines[]='<a href="'.htmlspecialchars($this->scriptName.'?type=page').'" target="TSApage">Default</a>';
283 $lines[]='<a href="'.htmlspecialchars($this->scriptName.'?type=page&show=all').'" target="TSApage">All details</a>';
284 $lines[]='<a href="'.htmlspecialchars($this->scriptName.'?type=page&show=admin').'" target="TSApage">Admin logins</a>';
285 $lines[]='<a href="'.htmlspecialchars($this->scriptName.'?type=phpinfo').'" target="TSApage">phpinfo()</a>';
286 $lines[]='<a href="'.htmlspecialchars($this->scriptName.'?type=page&show=localext').'" target="TSApage">Local extensions</a>';
287 $lines[]='';
288 $content = implode('<br />',$lines);
289 $content.= '<hr />';
290 $content.=$this->menuContent($this->exp);
291 return '<h2 align="center">TYPO3<br />Super Admin</h2>'.$content;
292 break;
293 case 'all':
294 return '
295 <h1>All details:</h1>
296 <h2>Overview:</h2>
297 '.$this->makeTable().'
298 <br /><hr /><br />
299 <h1>Details per site:</h1>
300 '.$content;
301 break;
302 case 'admin':
303 $content = $this->setNewPasswords();
304 $this->makeTable();
305 return $content.'
306 <h1>Admin options:</h1>
307
308 <h2>Admin logins:</h2>
309 '.$this->makeAdminLogin().'
310 <br /><hr /><br />
311
312 <h2>TBE Admin Passwords:</h2>
313 '.t3lib_div::view_array($this->collectAdminPasswords).'
314 <br /><hr /><br />
315
316 <h2>Install Tool Passwords:</h2>
317 '.t3lib_div::view_array($this->collectInstallPasswords).'
318 <br /><hr /><br />
319
320 <h2>Change TBE Admin Passwords:</h2>
321 '.$this->changeAdminPasswordsForm().'
322 <br /><hr /><br />';
323 break;
324 case 'info':
325 return '
326 <h1>Single site details</h1>
327 '.$this->singleSite($this->exp).
328 '<br />';
329 break;
330 case 'rmTempCached':
331 return '
332 <h1>Removing temp_CACHED_*.php files</h1>
333 '.$this->rmCachedFiles($this->exp).
334 '<br />';
335 break;
336 case 'localext':
337 return '
338 <h1>Local Extensions Found:</h1>
339 '.$this->localExtensions().
340 '<br />';
341 break;
342 default:
343 return '
344 <h1>Default info:</h1>'.
345 $content;
346 break;
347 }
348 }
349
350
351
352
353
354
355
356
357
358
359 /********************************
360 *
361 * Output preparation
362 *
363 *******************************/
364
365 /**
366 * Creates menu item from input.
367 *
368 * @param string Value for "&exp" parameter
369 * @param string The label
370 * @return string Wrapped value
371 */
372 function setMenuItem($code,$label) {
373 $out = '<a href="'.htmlspecialchars($this->scriptName.'?type=page&show=menu&exp='.$code).'" target="TSAmenu">'.htmlspecialchars($label).'</a>';
374 if ($code==$this->exp) {
375 $out = '<span style="color:red;">&gt;&gt;</span>'.$out;
376 }
377 return $out;
378 }
379
380 /**
381 * Wrap string in red span tag (for errors)
382 *
383 * @param string Input string
384 * @return string Output string
385 */
386 function error($str) {
387 $out = '<span style="color:red; font-size: 14px; font-weight: bold;">'.htmlspecialchars($str).'</span>';
388 return $out;
389 }
390
391 /**
392 * Wraps input string in <h2>
393 *
394 * @param string Input string
395 * @return string Output string, wrapped in <h2>
396 */
397 function headerParentDir($str) {
398 $out = '<h2>'.htmlspecialchars($str).'</h2>';
399 return $out;
400 }
401
402 /**
403 * Wraps input string in <h3>
404 *
405 * @param string Input string
406 * @return string Output string, wrapped in <h3>
407 */
408 function headerSiteDir($str) {
409 $out = '<h3>'.htmlspecialchars($str).'</h3>';
410 return $out;
411 }
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429 /********************************
430 *
431 * Collection information
432 *
433 *******************************/
434
435 /**
436 * Traverses the parent dirs, collecting the list of TYPO3 installations into $this->globalSiteInfo
437 *
438 * @return string HTML content (The default view seen when starting the superadmin.php script)
439 */
440 function initProcess() {
441 $content = '';
442
443 foreach($this->parentDirs as $k => $v) {
444 $dir = ereg_replace('/$','',$v['dir']);
445 $baseUrl=ereg_replace('/$','',$v['url']);
446 $content.='<br /><br /><br />';
447 $content.=$this->headerParentDir($dir);
448 if (@is_dir($dir)) {
449 $in_dirs = t3lib_div::get_dirs($dir);
450 asort($in_dirs);
451 reset($in_dirs);
452 $dirArr=array();
453 while(list($k,$v)=each($in_dirs)) {
454 if (substr($v,0,9)!='typo3_src') {
455 $this->currentUrl = $baseUrl.'/'.$v;
456 $content.= $this->headerSiteDir($v);
457 $content.= $this->processSiteDir($dir.'/'.$v,$dir);
458 }
459 }
460 } else {
461 $content.=$this->error('"'.$dir.'" was not a directory!');
462 }
463 }
464
465 return $content;
466 }
467
468 /**
469 * Creating information array for a specific TYPO3 installation
470 * Information about site is stored in ->globalSiteInfo array
471 *
472 * @param string Absolute path to installation (PATH_site)
473 * @param string Directory of main directory (level under PATH_site)
474 * @return string HTML content with information about the site.
475 * @access private
476 * @see initProcess()
477 */
478 function processSiteDir($path,$dir) {
479 if (@is_dir($path)) {
480 $localconf = $path.'/typo3conf/localconf.php';
481 if (@is_file($localconf)) {
482 $key = md5($localconf);
483 $this->includeLocalconf($localconf);
484
485 $this->mapDBtoKey[$this->globalSiteInfo[$key]['siteInfo']['TYPO3_db']] = $key;
486 $this->globalSiteInfo[$key]['siteInfo']['MAIN_DIR'] = $dir;
487 $this->globalSiteInfo[$key]['siteInfo']['SA_PATH'] = $path;
488 $this->globalSiteInfo[$key]['siteInfo']['URL'] = $this->currentUrl.'/';
489 $this->globalSiteInfo[$key]['siteInfo']['ADMIN_URL'] = $this->currentUrl.'/'.TYPO3_mainDir;
490 $this->globalSiteInfo[$key]['siteInfo']['INSTALL_URL'] = $this->currentUrl.'/'.TYPO3_mainDir.'install/';
491
492 // Connect to database:
493 $conMsg = $this->connectToDatabase($this->globalSiteInfo[$key]['siteInfo']);
494 if (!$conMsg) {
495 $this->getDBInfo($key);
496 $out.='';
497 } else {
498 $out = $conMsg;
499 }
500
501 // Show details:
502 if ($this->full) {
503 $out.=t3lib_div::view_array($this->globalSiteInfo[$key]);
504 } else {
505 $out.=t3lib_div::view_array($this->globalSiteInfo[$key]['siteInfo']);
506 }
507 } else $out = $this->error($localconf.' is not a file!');
508 } else $out = $this->error($path.' is not a directory!');
509 return $out;
510 }
511
512 /**
513 * Includes "localconf" of a TYPO3 installation an loads $this->globalSiteInfo with this information.
514 *
515 * @param string Absolute path to localconf.php file to include.
516 * @return array Array with information about the site.
517 * @access private
518 * @see processSiteDir()
519 */
520 function includeLocalconf($localconf) {
521 include($localconf);
522
523 $siteInfo=array();
524 $siteInfo['sitename'] = $TYPO3_CONF_VARS['SYS']['sitename'];
525 $siteInfo['TYPO3_db'] = $typo_db;
526 $siteInfo['TYPO3_db_username'] = $typo_db_username;
527 $siteInfo['TYPO3_db_password'] = $typo_db_password;
528 $siteInfo['TYPO3_db_host'] = $typo_db_host;
529 $siteInfo['installToolPassword'] = $TYPO3_CONF_VARS['BE']['installToolPassword'];
530 $siteInfo['warningEmailAddress'] = $TYPO3_CONF_VARS['BE']['warning_email_addr'];
531 $siteInfo['warningMode'] = $TYPO3_CONF_VARS['BE']['warning_mode'];
532
533 $this->globalSiteInfo[md5($localconf)] = array('siteInfo'=>$siteInfo,'TYPO3_CONF_VARS'=>$TYPO3_CONF_VARS);
534 return $siteInfo;
535 }
536
537 /**
538 * Connects to a MySQL database with the TYPO3 db host/username/password and database as found in the localconf.php file!
539 * 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
540 *
541 * @param array $siteInfo array, containing username/password/host/database values.
542 * @return string Array message if any
543 */
544 function connectToDatabase($siteInfo) {
545 if (@mysql_pconnect($siteInfo['TYPO3_db_host'], $siteInfo['TYPO3_db_username'], $siteInfo['TYPO3_db_password'])) {
546 if (!$siteInfo['TYPO3_db']) {
547 return $this->error('No database selected');
548 } elseif (!mysql_select_db($siteInfo['TYPO3_db'])) {
549 return $this->error('Cannot connect to the current database, "'.$siteInfo['TYPO3_db'].'"');
550 }
551 } else {
552 return $this->error('The current username, password or host was not accepted when the connection to the database was attempted to be established!');
553 }
554 }
555
556
557 /**
558 * Get database information, assuming standard tables like "be_users"
559 * Adding the information to ->globalSiteInfo
560 *
561 * @param string Key for site in ->globalSiteInfo
562 * @return void
563 * @access private
564 * @see processSiteDir()
565 */
566 function getDBInfo($key) {
567 $DB = $this->globalSiteInfo[$key]['siteInfo']['TYPO3_db'];
568
569 // Non-admin users
570 $query = $GLOBALS['TYPO3_DB']->SELECTquery('count(*)', 'be_users', 'admin=0 AND NOT deleted');
571 $res = mysql($DB, $query);
572 $row = mysql_fetch_row($res);
573 $this->globalSiteInfo[$key]['siteInfo']['BE_USERS_NONADMIN'] = $row[0];
574
575 // Admin users
576 $query = $GLOBALS['TYPO3_DB']->SELECTquery('count(*)', 'be_users', 'admin!=0 AND NOT deleted');
577 $res = mysql($DB, $query);
578 $row = mysql_fetch_row($res);
579 $this->globalSiteInfo[$key]['siteInfo']['BE_USERS_ADMIN'] = $row[0];
580
581 // Select Admin users
582 $query = $GLOBALS['TYPO3_DB']->SELECTquery('uid,username,password,email,realName,disable', 'be_users', 'admin!=0 AND NOT deleted');
583 $res = mysql($DB, $query);
584 while($row = mysql_fetch_assoc($res)) {
585 $this->globalSiteInfo[$key]['siteInfo']['ADMINS'][] = $row;
586 }
587 }
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605 /******************************
606 *
607 * Content: Installation Overview
608 *
609 ******************************/
610
611 /**
612 * Creates big table with information about all installations in ->globalSiteInfo
613 *
614 * @return string HTML table
615 */
616 function makeTable() {
617
618 // Header row
619 $info = array();
620 $info[] = 'Site:';
621 $info[] = 'Path:';
622 $info[] = 'Database:';
623 $info[] = 'Username';
624 $info[] = 'Password';
625 $info[] = 'Host';
626 $info[] = 'Links (new win)';
627 $info[] = '#Users NA/A';
628 $info[] = 'Admin be_users Info';
629 $info[] = 'Install Tool Password';
630 $info[] = 'Warning email address';
631 $info[] = 'W.mode';
632 $mainArrRows[] = '
633 <tr bgcolor="#eeeeee">
634 <td nowrap="nowrap" valign="top">'.implode('</td>
635 <td nowrap="nowrap" valign="top">',$info).'</td>
636 </tr>';
637
638 // Traverse globalSiteInfo for each site:
639 foreach($this->globalSiteInfo as $k => $all) {
640 $info = array();
641
642 // Sitename and Database details:
643 $info[] = htmlspecialchars($all['siteInfo']['sitename']);
644 $info[] = '<span style="color:#666666;">'.htmlspecialchars($all['siteInfo']['MAIN_DIR']).'</span>'.htmlspecialchars(substr($all['siteInfo']['SA_PATH'],strlen($all['siteInfo']['MAIN_DIR'])));
645 $info[] = htmlspecialchars($all['siteInfo']['TYPO3_db']);
646 $info[] = htmlspecialchars($all['siteInfo']['TYPO3_db_username']);
647 $info[] = htmlspecialchars($all['siteInfo']['TYPO3_db_password']);
648 $info[] = htmlspecialchars($all['siteInfo']['TYPO3_db_host']);
649
650 // URL
651 $info[] = '<a href="'.htmlspecialchars($all['siteInfo']['URL']).'" target="'.$this->targetWindow.'">Site</a>'.
652 ' / <a href="'.htmlspecialchars($all['siteInfo']['ADMIN_URL']).'" target="'.$this->targetWindowAdmin.'">Admin</a>'.
653 ' / <a href="'.htmlspecialchars($all['siteInfo']['INSTALL_URL']).'" target="'.$this->targetWindowInstall.'">Install</a>';
654 $info[] = htmlspecialchars($all['siteInfo']['BE_USERS_NONADMIN'].'/'.$all['siteInfo']['BE_USERS_ADMIN']);
655
656 // Admin
657 if (is_array($all['siteInfo']['ADMINS'])) {
658 $lines = array();
659 foreach($all['siteInfo']['ADMINS'] as $vArr) {
660 $lines[] = htmlspecialchars($vArr['password'].' - '.$vArr['username'].' ('.$vArr['realName'].', '.$vArr['email'].')');
661 $this->collectAdminPasswords[$vArr['password']][] = array(
662 'path' => $all['siteInfo']['SA_PATH'],
663 'site' => $all['siteInfo']['sitename'],
664 'database' => $all['siteInfo']['TYPO3_db'],
665 'user' => $vArr['username'],
666 'name_email' => $vArr['realName'].', '.$vArr['email']
667 );
668 $this->changeAdminPasswords[$vArr['password']][] = $all['siteInfo']['TYPO3_db'].':'.$vArr['uid'].':'.$vArr['username'];
669 }
670 $info[] = implode('<br />',$lines);
671 } else {
672 $info[] = $this->error('No DB connection!');
673 }
674 // Install
675 $info[] = htmlspecialchars($all['siteInfo']['installToolPassword']);
676 $this->collectInstallPasswords[$all['siteInfo']['installToolPassword']][] = $all['siteInfo']['SA_PATH'].' - '.$all['siteInfo']['sitename'].' - ('.$all['siteInfo']['TYPO3_db'].')';
677
678 $info[] = htmlspecialchars($all['siteInfo']['warningEmailAddress']);
679 $info[] = htmlspecialchars($all['siteInfo']['warningMode']);
680
681 // compile
682 $mainArrRows[] = '
683 <tr>
684 <td nowrap="nowrap" valign="top">'.implode('</td>
685 <td nowrap="nowrap" valign="top">',$info).'</td>
686 </tr>';
687 }
688
689 // Compile / return table finally:
690 $table = '<table border="1" cellpadding="1" cellspacing="1">'.implode('',$mainArrRows).'</table>';
691 return $table;
692 }
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707 /******************************
708 *
709 * Content: Local extensions
710 *
711 ******************************/
712
713 /**
714 * Based on the globalSiteInfo array, this prints information about local extensions for each site.
715 * In particular version number and most recent mod-time is interesting!
716 *
717 * @return string HTML
718 */
719 function localExtensions() {
720 $this->extensionInfoArray=array();
721
722 // Traverse $this->globalSiteInfo for local extensions:
723 foreach($this->globalSiteInfo as $k => $all) {
724 if ($all['siteInfo']['SA_PATH']) {
725 $extDir = $all['siteInfo']['SA_PATH'].'/typo3conf/ext/';
726 if (@is_dir($extDir)) {
727 $this->extensionInfoArray['site'][$k] = array();
728
729 // Get extensions in local directory
730 $extensions=t3lib_div::get_dirs($extDir);
731 if (is_array($extensions)) {
732 foreach($extensions as $extKey) {
733 // Getting and setting information for extension:
734 $eInfo = $this->getExtensionInfo($extDir,$extKey,$k);
735 $this->extensionInfoArray['site'][$k][$extKey] = $eInfo;
736 $this->extensionInfoArray['ext'][$extKey][$k] = $eInfo;
737 }
738 }
739 }
740 }
741 }
742
743 // Display results:
744 $out='';
745 $headerRow = '
746 <tr bgcolor="#ccccee" style="font-weight:bold;">
747 <td>Extension key</td>
748 <td>Path</td>
749 <td>Title</td>
750 <td>Ver.</td>
751 <td>Files</td>
752 <td><span title="If M, then there is a manual.">M</span></td>
753 <td>Last mod. time</td>
754 <td>Hash off all file mod. times:</td>
755 <td>TYPO3 ver. req.</td>
756 <td>CGL compliance</td>
757 </tr>
758 ';
759
760 // PER EXTENSION:
761 if (is_array($this->extensionInfoArray['ext'])) {
762 $extensionKeysCollect=array();
763
764 ksort($this->extensionInfoArray['ext']);
765 reset($this->extensionInfoArray['ext']);
766 $rows=array(
767 'reg'=>array(),
768 'user'=>array()
769 );
770
771 foreach($this->extensionInfoArray['ext'] as $extKey => $instances) {
772 $mtimes = array();
773
774 // Find most recent mtime of the options:
775 reset($instances);
776 while(list($k,$eInfo)=each($instances)) {
777 $mtimes[] = $eInfo['mtime'];
778 }
779 // Max mtime:
780 $maxMtime = max($mtimes);
781 $c = 0;
782
783 // So, traverse all sites with the extension present:
784 foreach($instances as $k => $eInfo) {
785 // Set background color if mtime matches
786 if ($maxMtime==$eInfo['mtime']) {
787 $this->extensionInfoArray['site'][$k][$extKey]['_highlight']=1;
788 $bgCol = $eInfo['dirtype']=='link' ? ' bgcolor="#ffcccc"' : ' bgcolor="#eeeeee"';
789 } else {
790 $bgCol = ' style="color: #999999; font-style: italic;"';
791 }
792
793 // Make row:
794 $type = substr($extKey,0,5)!='user_' ? 'reg' : 'user';
795 if ($type=='reg') $extensionKeysCollect[] = $extKey;
796
797 if (!is_array($eInfo)) {
798 // Standard listing:
799 $rows[$type][] = '
800 <tr>
801 '.(!$c?'<td rowspan="'.count($instances).'">'.htmlspecialchars($extKey).'</td>':'').'
802 <td nowrap="nowrap" bgcolor="#ccddcc">'.htmlspecialchars($this->globalSiteInfo[$k]['siteInfo']['SA_PATH']).'</td>
803 <td nowrap="nowrap" bgcolor="#ccddcc" colspan="8"><em>'.htmlspecialchars($eInfo).'</em></td>
804 </tr>
805 ';
806 } else {
807 // Standard listing:
808 $rows[$type][] = '
809 <tr>
810 '.(!$c?'<td rowspan="'.count($instances).'">'.htmlspecialchars($extKey).'</td>':'').'
811 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($this->globalSiteInfo[$k]['siteInfo']['SA_PATH']).'</td>
812 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['title']).'</td>
813 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['version']).'</td>
814 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['numberfiles']).'</td>
815 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['manual']?'M':'-').'</td>
816 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['mtime']?date('d-m-y H:i:s',$eInfo['mtime']):'').'</td>
817 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['mtime_hash']).'</td>
818
819 <td'.$bgCol.'>'.htmlspecialchars($eInfo['TYPO3_version']).'</td>
820 <td'.$bgCol.'><img src="clear.gif" width="150" height="1" alt="" /><br />'.htmlspecialchars($eInfo['CGLcompliance'].($eInfo['CGLcompliance_note'] ? ' - '.$eInfo['CGLcompliance_note'] : '')).'</td>
821 </tr>
822 ';
823 }
824 $c++;
825 }
826 }
827
828 // Extensions with registered extension keys:
829 $out.='
830 <h3>Registered extensions:</h3>
831 <table border="1">'.$headerRow.implode('',$rows['reg']).'</table>';
832
833 // List of those extension keys in a form field:
834 $extensionKeysCollect = array_unique($extensionKeysCollect);
835 asort($extensionKeysCollect);
836 $out.='<form action=""><textarea cols="80" rows="10">'.implode(chr(10),$extensionKeysCollect).'</textarea></form>';
837
838 // USER extension (prefixed "user_")
839 $out.='<br />
840 <h3>User extensions:</h3>
841 <table border="1">'.$headerRow.implode('',$rows['user']).'</table>';
842 }
843
844 // PER SITE:
845 if (is_array($this->extensionInfoArray['site'])) {
846 $rows = array();
847 foreach($this->extensionInfoArray['site'] as $k => $extensions) {
848
849 // So, traverse all sites with the extension present:
850 $c = 0;
851 foreach($extensions as $extKey => $eInfo) {
852
853 // Set background color if mtime matches
854 if ($eInfo['_highlight']) {
855 $bgCol = $eInfo['dirtype']=='link' ? ' bgcolor="#ffcccc"' : ' bgcolor="#eeeeee"';
856 } else {
857 $bgCol = ' style="color: #999999; font-style: italic;"';
858 }
859
860 // Make row:
861 $rows[] = '
862 <tr>
863 '.(!$c?'<td rowspan="'.count($extensions).'">'.htmlspecialchars($this->globalSiteInfo[$k]['siteInfo']['SA_PATH']).'</td>':'').'
864 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($extKey).'</td>
865 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['title']).'</td>
866 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['version']).'</td>
867 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['numberfiles']).'</td>
868 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['mtime']?date('d-m-y H:i:s',$eInfo['mtime']):'').'</td>
869 <td nowrap="nowrap"'.$bgCol.'>'.htmlspecialchars($eInfo['mtime_hash']).'</td>
870 </tr>
871 ';
872 $c++;
873 }
874 }
875 $out.='<br />
876 <h3>Sites:</h3>
877 <table border="1">'.implode('',$rows).'</table>';
878 }
879
880 // Return content
881 return $out;
882 }
883
884 /**
885 * Gets information for an extension, eg. version and most-recently-edited-script
886 *
887 * @param string Path to local extension folder
888 * @param string Extension key
889 * @param string Key to globalSiteInformation array
890 * @return array Information array (unless an error occured)
891 */
892 function getExtensionInfo($path,$extKey,$k) {
893 $file = $path.$extKey.'/ext_emconf.php';
894 if (@is_file($file)) {
895 $_EXTKEY = $extKey;
896 include($file);
897
898 $eInfo = array();
899 // Info from emconf:
900 $eInfo['title'] = $EM_CONF[$extKey]['title'];
901 $eInfo['version'] = $EM_CONF[$extKey]['version'];
902 $eInfo['CGLcompliance'] = $EM_CONF[$extKey]['CGLcompliance'];
903 $eInfo['CGLcompliance_note'] = $EM_CONF[$extKey]['CGLcompliance_note'];
904 $eInfo['TYPO3_version'] = $EM_CONF[$extKey]['TYPO3_version'];
905 $filesHash = unserialize($EM_CONF[$extKey]['_md5_values_when_last_written']);
906
907 if (!is_array($filesHash) || count($filesHash)<500) {
908
909 // Get all files list (may take LOONG time):
910 $extPath = $path.$extKey.'/';
911 $fileArr = array();
912 $fileArr = $this->removePrefixPathFromList($this->getAllFilesAndFoldersInPath($fileArr,$extPath),$extPath);
913
914 if (!is_array($fileArr)) {
915 debug(array($fileArr,$extKey,$extPath,$this->getAllFilesAndFoldersInPath(array(),$extPath)),'ERROR');
916 }
917
918 // Number of files:
919 $eInfo['numberfiles'] = count($fileArr);
920 $eInfo['dirtype'] = filetype($path.$extKey);
921
922 // Most recent modification:
923 $eInfo['mtime_files'] = $this->findMostRecent($fileArr,$extPath);
924 if (count($eInfo['mtime_files'])) $eInfo['mtime'] = max($eInfo['mtime_files']);
925 $eInfo['mtime_hash'] = md5(implode(',',$eInfo['mtime_files']));
926 } else {
927 $eInfo['mtime_hash'] = 'No calculation done, too many files in extension: '.count($filesHash);
928 }
929
930 $eInfo['manual'] = @is_file($path.$extKey.'/doc/manual.sxw');
931
932 return $eInfo;
933 } else return 'ERROR: No emconf.php file: '.$file;
934 }
935
936 /**
937 * Recursively gather all files and folders of extension path.
938 *
939 * @param array Array of files to which new files are added
940 * @param string Path to look up files in
941 * @param string List of file extensions to include. Blank = all
942 * @param boolean If set, directories are included as well.
943 * @return array $fileArr with new entries added.
944 */
945 function getAllFilesAndFoldersInPath($fileArr,$extPath,$extList='',$regDirs=0) {
946 if ($regDirs) $fileArr[] = $extPath;
947 $fileArr = array_merge($fileArr,t3lib_div::getFilesInDir($extPath,$extList,1,1));
948
949 $dirs = t3lib_div::get_dirs($extPath);
950 if (is_array($dirs)) {
951 foreach($dirs as $subdirs) {
952 if ($subdirs && (strcmp($subdirs,'CVS') || !$this->noCVS)) {
953 $fileArr = $this->getAllFilesAndFoldersInPath($fileArr,$extPath.$subdirs.'/',$extList,$regDirs);
954 }
955 }
956 }
957 return $fileArr;
958 }
959
960 /**
961 * Creates an array with modification times of all files in $fileArr
962 *
963 * @param array Files in extension (rel path)
964 * @param string Abs path prefix for files.
965 * @return array Array with modification times of files (filenames are keys)
966 */
967 function findMostRecent($fileArr,$extPath) {
968 $mtimeArray = array();
969 foreach($fileArr as $fN) {
970 if ($fN!='ext_emconf.php') {
971 $mtime = filemtime($extPath.$fN);
972 $mtimeArray[$fN] = $mtime;
973 }
974 }
975 return $mtimeArray;
976 }
977
978 /**
979 * Removes the absolute part of all files/folders in fileArr
980 *
981 * @param array File array
982 * @param string Prefix to remove
983 * @return array Modified file array (or error string)
984 */
985 function removePrefixPathFromList($fileArr,$extPath) {
986 reset($fileArr);
987 while(list($k,$absFileRef)=each($fileArr)) {
988 if(t3lib_div::isFirstPartOfStr($absFileRef,$extPath)) {
989 $fileArr[$k]=substr($absFileRef,strlen($extPath));
990 } else return 'ERROR: One or more of the files was NOT prefixed with the prefix-path!';
991 }
992 return $fileArr;
993 }
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010 /******************************
1011 *
1012 * Content: Other
1013 *
1014 ******************************/
1015
1016 /**
1017 * Shows detailed information for a single installation of TYPO3
1018 *
1019 * @param string KEY pointing to installation
1020 * @return string HTML content
1021 */
1022 function singleSite($exp) {
1023 $all = $this->globalSiteInfo[$exp];
1024
1025 // General information:
1026 $content = '
1027 <h2>'.htmlspecialchars($all['siteInfo']['sitename'].' (DB: '.$all['siteInfo']['TYPO3_db']).')</h2>
1028 <hr />
1029
1030 <h3>Main details:</h3>
1031
1032 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>
1033 <br /><br />';
1034
1035 // Add all information in globalSiteInfo array:
1036 $content.= t3lib_div::view_array($all);
1037
1038 // Last-login:
1039 $content.= '
1040 <h3>Login-Log for last month:</h3>';
1041 $content.= $this->loginLog($all['siteInfo']['TYPO3_db']);
1042
1043 // Return content
1044 return $content;
1045 }
1046
1047 /**
1048 * Get last-login log for database.
1049 *
1050 * @param string Database
1051 * @return string HTML
1052 */
1053 function loginLog($DB) {
1054 // Non-admin users
1055 //1=login, 2=logout, 3=failed login (+ errorcode 3), 4=failure_warning_email sent
1056 $query = $GLOBALS['TYPO3_DB']->SELECTquery(
1057 'sys_log.*, be_users.username AS username, be_users.admin AS admin',
1058 'sys_log,be_users',
1059 'be_users.uid=sys_log.userid AND sys_log.type=255 AND sys_log.tstamp > '.(time()-(60*60*24*30)),
1060 '',
1061 'sys_log.tstamp DESC'
1062 );
1063 $res = mysql($DB,$query);
1064
1065 $dayRef = '';
1066 $lines = array();
1067
1068 while($row = mysql_fetch_assoc($res)) {
1069 $day = date('d-m-Y',$row['tstamp']);
1070 if ($dayRef!=$day) {
1071 $lines[] = '
1072 <h4>'.$day.':</h4>';
1073 $dayRef=$day;
1074 }
1075 $theLine = date('H:i',$row['tstamp']).': '.str_pad(substr($row['username'],0,10),10).' '.$this->log_getDetails($row['details'],unserialize($row['log_data']));
1076 $theLine = htmlspecialchars($theLine);
1077 $lines[]= $row['admin'] ? '<span class="redclass">'.$theLine.'</span>' : $theLine;
1078
1079 // debug($row);
1080 }
1081 return '<pre>'.implode(chr(10),$lines).'</pre>';
1082 }
1083
1084 /**
1085 * Compile log details into template string
1086 *
1087 * @param string Log message (template)
1088 * @param array Data array to insert in log message
1089 * @return string Log details.
1090 */
1091 function log_getDetails($text,$data) {
1092 // $code is used later on to substitute errormessages with language-corrected values...
1093 if (is_array($data)) {
1094 return sprintf($text, $data[0],$data[1],$data[2],$data[3],$data[4]);
1095 } else return $text;
1096 }
1097
1098
1099 /**
1100 * Removing temp_CACHED files for installation
1101 *
1102 * @param string KEY pointing to installation
1103 * @return string HTML content
1104 */
1105 function rmCachedFiles($exp) {
1106 $all = $this->globalSiteInfo[$exp];
1107 $content = '
1108 <h2>'.htmlspecialchars($all['siteInfo']['sitename'].' (DB: '.$all['siteInfo']['TYPO3_db']).')</h2>
1109 <hr />
1110 <h3>typo3conf/temp_CACHED_* files:</h3>';
1111
1112 $path = $all['siteInfo']['SA_PATH'].'/typo3conf/';
1113 if (@is_dir($path)) {
1114 $filesInDir = t3lib_div::getFilesInDir($path,'php',1);
1115
1116 foreach($filesInDir as $kk => $vv) {
1117 if (t3lib_div::isFirstPartOfStr(basename($vv),'temp_CACHED_')) {
1118 if (strstr(basename($vv),'ext_localconf.php') || strstr(basename($vv),'ext_tables.php')) {
1119 $content.='REMOVED: '.$vv.'<br />';
1120 unlink($vv);
1121 if (file_exists($vv)) $content.= $this->error('ERROR: File still exists, so could not be removed anyways!').'<br />';
1122 }
1123 }
1124 }
1125 } else {
1126 $content.= $this->error('ERROR: '.$path.' was not a directory!');
1127 }
1128
1129 return $content;
1130 }
1131
1132 /**
1133 * Menu for either update/information, showing links for each installation found
1134 *
1135 * @param string Action key "update" or "info"
1136 * @return string HTML output.
1137 */
1138 function menuContent($exp) {
1139 if ($exp) {
1140
1141 // Initialize:
1142 $lines = array();
1143 $head = '';
1144
1145 foreach($this->globalSiteInfo as $k => $all) {
1146
1147 // Setting section header, if needed.
1148 if ($head!=$all['siteInfo']['MAIN_DIR']) {
1149 $lines[] = '
1150 <h4 style="white-space: nowrap;">'.htmlspecialchars(t3lib_div::fixed_lgd_pre($all['siteInfo']['MAIN_DIR'],18)).'</h4>';
1151 $head = $all['siteInfo']['MAIN_DIR']; // Set new head...
1152 }
1153
1154 // Display mode:
1155 switch($exp) {
1156 case 'update':
1157
1158 // Label:
1159 $label = $all['siteInfo']['sitename'] ? $all['siteInfo']['sitename'] : '(DB: '.$all['siteInfo']['TYPO3_db'].')';
1160 $lines[] = '
1161 <hr />
1162 <b>'.htmlspecialchars($label).'</b> ('.htmlspecialchars(substr($all['siteInfo']['SA_PATH'],strlen($all['siteInfo']['MAIN_DIR'])+1)).')<br />';
1163
1164 // To avoid "visited links" display on next hit:
1165 $tempVal='&_someUniqueValue='.time();
1166
1167 // Add links for update:
1168 $url = $this->scriptName.'?type=page&show=rmTempCached&exp='.$k.$tempVal;
1169 $lines[] = '<span style="white-space: nowrap;"><a href="'.htmlspecialchars($url).'" target="TSApage">Remove temp_CACHED files</a></span>';
1170
1171 $url = $all['siteInfo']['INSTALL_URL'].'index.php?TYPO3_INSTALL[type]=database&TYPO3_INSTALL[database_type]=import|CURRENT_STATIC'."&presetWholeTable=1".$tempVal.'#bottom';
1172 $lines[] = '<span style="white-space: nowrap;"><a href="'.htmlspecialchars($url).'" target="TSApage">CURRENT_STATIC</a></span>';
1173
1174 $url = $all['siteInfo']['INSTALL_URL'].'index.php?TYPO3_INSTALL[type]=database&TYPO3_INSTALL[database_type]=cmpFile|CURRENT_TABLES'.$tempVal.'#bottom';
1175 $lines[] = '<span style="white-space: nowrap;"><a href="'.htmlspecialchars($url).'" target="TSApage">CURRENT_TABLES</a></span>';
1176
1177 // Cache
1178 $url = $all['siteInfo']['INSTALL_URL'].'index.php?TYPO3_INSTALL[type]=database&TYPO3_INSTALL[database_type]=cache|'.
1179 "&PRESET[database_clearcache][cache_pages]=1".
1180 '&PRESET[database_clearcache][cache_pagesection]=1'.
1181 "&PRESET[database_clearcache][cache_hash]=1".
1182 $tempVal.
1183 '#bottom';
1184 $lines[] = '<span style="white-space: nowrap;"><a href="'.htmlspecialchars($url).'" target="TSApage">Clear cache</a></span>';
1185
1186 // Admin link
1187 $url = $all['siteInfo']['ADMIN_URL'].'index.php';
1188 $lines[] = '<span style="white-space: nowrap;"><a href="'.htmlspecialchars($url).'" target="'.$this->targetWindowAdmin.'">Admin -></a></span>';
1189 break;
1190 case 'info':
1191 // item
1192 $label = $all['siteInfo']['sitename'] ? $all['siteInfo']['sitename'] : '(DB: '.$all['siteInfo']['TYPO3_db'].')';
1193
1194 $url = $this->scriptName.'?type=page&show=info&exp='.$k;
1195 $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>';
1196 break;
1197 }
1198 }
1199
1200 // Return result.
1201 return implode('<br />',$lines).'<br />';
1202 }
1203 }
1204
1205 /**
1206 * Create list of admin logins.
1207 *
1208 * @return string HTML table
1209 */
1210 function makeAdminLogin() {
1211
1212 // Initialize:
1213 $lines = array();
1214 $head = '';
1215
1216 // Traverse installations found:
1217 foreach($this->globalSiteInfo as $k => $all) {
1218
1219 // Setting section header, if needed.
1220 if ($head!=$all['siteInfo']['MAIN_DIR']) {
1221 $lines[] = '
1222 <tr>
1223 <td colspan="2"><br />
1224 <h4>'.htmlspecialchars($all['siteInfo']['MAIN_DIR']).'</h4>
1225 </td>
1226 </tr>';
1227 $head = $all['siteInfo']['MAIN_DIR'];
1228 }
1229
1230 // item
1231 $label = $all['siteInfo']['sitename'] ? $all['siteInfo']['sitename'] : '(DB: '.$all['siteInfo']['TYPO3_db'].')';
1232 $unique = md5(microtime());
1233
1234 $opts = array();
1235 $defUName = '';
1236
1237 if (is_array($all['siteInfo']['ADMINS'])) {
1238
1239 foreach($all['siteInfo']['ADMINS'] as $vArr) {
1240 $chalVal = md5($vArr['username'].':'.$vArr['password'].':'.$unique);
1241 $opts[] = '<option value="'.$chalVal.'">'.htmlspecialchars($vArr['username'].($vArr['disable']?' [DISABLED]':'')).'</option>';
1242 if (!$defUName) { $defUName = $vArr['username']; }
1243 }
1244 }
1245 if (count($opts)>1) {
1246 $userident = '
1247 <select name="userident" onchange="document[\''.$k.'\'].username.value=this.options[this.selectedIndex].text;">
1248 '.implode('
1249 ',$opts).'
1250 </select>
1251 ';
1252 } else {
1253 $userident = '
1254 ('.$defUName.')<br />
1255 <input type="hidden" name="userident" value="'.$chalVal.'" />';
1256 }
1257
1258 $form='
1259 <form name="'.$k.'" action="'.$all['siteInfo']['ADMIN_URL'].'index.php" target="EXTERnalWindow" method="post">
1260 <input type="submit" name="submit" value="Login" />
1261 <input type="hidden" name="username" value="'.$defUName.'" />
1262 <input type="hidden" name="challenge" value="'.$unique.'" />
1263 <input type="hidden" name="redirect_url" value="" />
1264 <input type="hidden" name="login_status" value="login" />
1265 '.trim($userident).'
1266 </form>';
1267
1268 $lines[] = '
1269 <tr>
1270 <td><strong>'.htmlspecialchars($label).'</strong></td>
1271 <td nowrap="nowrap">'.trim($form).'</td>
1272 </tr>';
1273 }
1274
1275 // Return login table:
1276 return '<table border="1" cellpadding="5" cellspacing="1">'.implode('',$lines).'</table>';
1277 }
1278
1279 /**
1280 * For for changing admin passwords
1281 *
1282 * @return string Form content.
1283 */
1284 function changeAdminPasswordsForm() {
1285 $content='';
1286
1287 foreach($this->changeAdminPasswords as $k => $p) {
1288 $content.='
1289 <h3>'.$k.'</h3>';
1290
1291 foreach($p as $kk => $pp) {
1292 $content.= '<span style="white-space: nowrap;">';
1293 $content.= '<input type="checkbox" name="SETFIELDS[]" value="'.$pp.'" /> '.$pp.' - ';
1294 $content.= htmlspecialchars(implode(' - ',$this->collectAdminPasswords[$k][$kk]));
1295 $content.= '</span><br />';
1296 }
1297 }
1298
1299 $content.='New password: <input type="text" name="NEWPASS" /><br />';
1300 $content.='New password (md5): <input type="text" name="NEWPASS_md5" /><br />
1301 (This overrules any plain password above!)
1302 <br />';
1303 $content='
1304 <form action="'.htmlspecialchars($this->scriptName.'?type=page&show=admin').'" method="post">
1305 '.$content.'
1306 <input type="submit" name="Set" />
1307 </form>
1308 ';
1309
1310 return $content;
1311 }
1312
1313 /**
1314 * Setting new passwords
1315 *
1316 * @return string Status
1317 * @see changeAdminPasswordsForm()
1318 */
1319 function setNewPasswords() {
1320 $whichFields = t3lib_div::_POST('SETFIELDS');
1321 $pass = trim(t3lib_div::_POST('NEWPASS'));
1322 $passMD5 = t3lib_div::_POST('NEWPASS_md5');
1323
1324 $updatedFlag = 0;
1325 if (($pass || $passMD5) && is_array($whichFields)) {
1326 $pass = $passMD5 ? $passMD5 : md5($pass);
1327
1328 foreach($whichFields as $values) {
1329 $parts = explode(':',$values);
1330 if (count($parts)>2) {
1331 $key = $this->mapDBtoKey[$parts[0]];
1332 if ($key && isset($this->globalSiteInfo[$key]['siteInfo'])) {
1333 $error = $this->connectToDatabase($this->globalSiteInfo[$key]['siteInfo']);
1334 if (!$error) {
1335 $DB = $this->globalSiteInfo[$key]['siteInfo']['TYPO3_db'];
1336 $content.='<h3>Updating '.$DB.':</h3>';
1337
1338 $query = $GLOBALS['TYPO3_DB']->UPDATEquery(
1339 'be_users',
1340 'uid='.intval($parts[1]).' AND username="'.addslashes($parts[2]).'" AND admin!=0',
1341 array('password' => $pass)
1342 ); // username/admin are added to security. But they are certainly redundant!!
1343 mysql($DB,$query);
1344
1345 $content.= 'Affected rows: '.mysql_affected_rows().'<br /><hr />';
1346 $updatedFlag = '1';
1347 }
1348 }
1349 }
1350 }
1351 }
1352
1353 $this->initProcess();
1354 return $content;
1355 }
1356 }
1357
1358 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_superadmin.php']) {
1359 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_superadmin.php']);
1360 }
1361 ?>