*** empty log message ***
[Packages/TYPO3.CMS.git] / t3lib / class.t3lib_superadmin.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2004 Kasper Skaarhoj (kasper@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 *
33 * @author Kasper Skaarhoj <kasper@typo3.com>
34 */
35 /**
36 * [CLASS/FUNCTION INDEX of SCRIPT]
37 *
38 * 104: function debug($p1,$p2='')
39 *
40 *
41 * 117: class t3lib_superadmin
42 * 140: function init($parentDirs)
43 * 149: function initProcess()
44 * 182: function make()
45 * 240: function setMenuItem($code,$label)
46 * 254: function error($str)
47 * 265: function headerParentDir($str)
48 * 276: function headerSiteDir($str)
49 * 288: function processSiteDir($path,$dir)
50 * 322: function includeLocalconf($localconf)
51 * 345: function connectToDatabase($siteInfo)
52 * 363: function getDBInfo($key)
53 * 391: function makeTable()
54 * 454: function localExtensions()
55 * 594: function getExtensionInfo($path,$extKey,$k)
56 * 640: function getAllFilesAndFoldersInPath($fileArr,$extPath,$extList="",$regDirs=0)
57 * 663: function serverExtensionMD5Array($fileArr,$extPath)
58 * 682: function findMostRecent($fileArr,$extPath)
59 * 701: function removePrefixPathFromList($fileArr,$extPath)
60 * 717: function singleSite($exp)
61 * 737: function rmCachedFiles($exp)
62 * 769: function menuContent($exp)
63 * 867: function makeAdminLogin()
64 * 924: function loginLog($DB)
65 * 955: function log_getDetails($text,$data)
66 * 967: function changeAdminPasswordsForm()
67 * 1000: function setNewPasswords()
68 * 1039: function defaultSet()
69 *
70 * TOTAL FUNCTIONS: 28
71 * (This index is automatically created/updated by the extension "extdeveval")
72 *
73 */
74
75
76
77
78
79
80
81
82
83 // *******************************
84 // Set error reporting
85 // *******************************
86 error_reporting (E_ALL ^ E_NOTICE);
87 define('TYPO3_mainDir', 'typo3/'); // This is the directory of the backend administration for the sites of this TYPO3 installation.
88
89
90 // Dependency:
91 include_once('./typo3_src/t3lib/class.t3lib_div.php');
92
93
94
95 /**
96 * Debug function.
97 *
98 * @param [type] $p1: ...
99 * @param [type] $p2: ...
100 * @return [type] ...
101 * @package TYPO3
102 * @subpackage t3lib
103 */
104 function debug($p1,$p2='') {
105 t3lib_div::debug($p1,$p2);
106 }
107
108
109
110 /**
111 * Super Admin class has functions for the administration of multiple TYPO3 sites in folders
112 *
113 * @author Kasper Skaarhoj <kasper@typo3.com>
114 * @package TYPO3
115 * @subpackage t3lib
116 */
117 class t3lib_superadmin {
118 var $parentDirs=array();
119 var $globalSiteInfo=array();
120 var $currentUrl='';
121 var $targetWindow='superAdminWindow';
122 var $targetWindowAdmin='superAdminWindowAdmin';
123 var $targetWindowInstall='superAdminWindowInstall';
124 var $mapDBtoKey=array();
125 var $collectAdminPasswords=array();
126 var $changeAdminPasswords=array();
127 var $collectInstallPasswords=array();
128 var $scriptName="superadmin.php";
129
130 // Control:
131 var $full=0; // If set, the full information array per site is printed.
132
133 var $noCVS=0; // See tools/em/index.php....
134
135
136 /**
137 * @param [type] $parentDirs: ...
138 * @return [type] ...
139 */
140 function init($parentDirs) {
141 $this->parentDirs = $parentDirs;
142 }
143
144 /**
145 * [Describe function...]
146 *
147 * @return [type] ...
148 */
149 function initProcess() {
150 $content="";
151 reset($this->parentDirs);
152 while(list($k,$v)=each($this->parentDirs)) {
153 $dir = ereg_replace("/$","",$v["dir"]);
154 $baseUrl=ereg_replace("/$","",$v["url"]);
155 $content.="<BR><BR><BR>";
156 $content.=$this->headerParentDir($dir);
157 if (@is_dir($dir)) {
158 $in_dirs = t3lib_div::get_dirs($dir);
159 asort($in_dirs);
160 reset($in_dirs);
161 $dirArr=array();
162 while(list($k,$v)=each($in_dirs)) {
163 if (substr($v,0,9)!="typo3_src") {
164 $this->currentUrl=$baseUrl."/".$v;
165 $content.=$this->headerSiteDir($v);
166 $content.=$this->processSiteDir($dir."/".$v,$dir);
167 }
168 }
169 } else {
170 $content.=$this->error("'".$dir."' was not a directory!");
171 }
172 }
173 // debug($this->globalSiteInfo);
174 return $content;
175 }
176
177 /**
178 * [Describe function...]
179 *
180 * @return [type] ...
181 */
182 function make() {
183 reset($this->parentDirs);
184 $content = $this->initProcess();
185
186 // Output mode:
187 $mode=t3lib_div::GPvar("show");
188 //debug($GLOBALS["HTTP_GET_VARS"]);
189 switch($mode) {
190 case "menu":
191 $lines=array();
192 $lines[]=$this->setMenuItem("info","INFO");
193 $lines[]=$this->setMenuItem("update","UPDATE");
194 $lines[]='';
195 $lines[]='<A HREF="'.$this->scriptName.'?type=page" target="TSApage">Default</A>';
196 $lines[]='<a HREF="'.$this->scriptName.'?type=page&show=all" target="TSApage">All details</a>';
197 $lines[]='<a HREF="'.$this->scriptName.'?type=page&show=admin" target="TSApage">Admin logins</a>';
198 $lines[]='<a HREF="'.$this->scriptName.'?type=phpinfo" target="TSApage">phpinfo()</a>';
199 $lines[]='<a HREF="'.$this->scriptName.'?type=localext&show=localext" target="TSApage">Local extensions</a>';
200 $lines[]='';
201 $content = '<font>'.implode("<BR>",$lines).'</font>';
202 $content.= '<HR>';
203 $content.=$this->menuContent(t3lib_div::GPvar("exp"));
204 return '<h2><nobr><div align="center">TYPO3<BR>Super Admin</div></nobr></h2>'.$content;
205 break;
206 case "all":
207 return '<h1>All details:</h1><h2>Overview:</h2>'.$this->makeTable()."<BR><HR><BR>".
208 '<h1>Details per site:</h1>'.$content;
209 break;
210 case "admin":
211 $content = $this->setNewPasswords();
212 $this->makeTable();
213 return $content.'<h1>Admin options:</h1><h2>Admin logins:</h2>'.$this->makeAdminLogin()."<BR><HR><BR>".
214 '<h2>TBE Admin Passwords:</h2>'.t3lib_div::view_array($this->collectAdminPasswords)."<BR><HR><BR>".
215 '<h2>Install Tool Passwords:</h2>'.t3lib_div::view_array($this->collectInstallPasswords)."<BR><HR><BR>".
216 '<h2>Change TBE Admin Passwords:</h2>'.$this->changeAdminPasswordsForm()."<BR><HR><BR>";
217 break;
218 case "info":
219 return '<h1>Single site details</h1>'.$this->singleSite(t3lib_div::GPvar("exp"))."<BR>";
220 break;
221 case "rmTempCached":
222 return '<h1>Removing temp_CACHED_*.php files</h1>'.$this->rmCachedFiles(t3lib_div::GPvar("exp"))."<BR>";
223 break;
224 case "localext":
225 return '<h1>Local Extensions Found:</h1>'.$this->localExtensions()."<BR>";
226 break;
227 default:
228 return '<h1>Default info:</h1>'.$content;
229 break;
230 }
231 }
232
233 /**
234 * [Describe function...]
235 *
236 * @param [type] $code: ...
237 * @param [type] $label: ...
238 * @return [type] ...
239 */
240 function setMenuItem($code,$label) {
241 $out = '<a HREF="'.$this->scriptName.'?type=menu&show=menu&exp='.$code.'" target="TSAmenu">'.$label.'</a>';
242 if ($code==t3lib_div::GPvar("exp")) {
243 $out = '<font color=red>&gt;&gt;</font>'.$out;
244 }
245 return $out;
246 }
247
248 /**
249 * [Describe function...]
250 *
251 * @param [type] $str: ...
252 * @return [type] ...
253 */
254 function error($str) {
255 $out = '<font color=red size=4>'.$str.'</font>';
256 return $out;
257 }
258
259 /**
260 * [Describe function...]
261 *
262 * @param [type] $str: ...
263 * @return [type] ...
264 */
265 function headerParentDir($str) {
266 $out = '<h2>'.$str.'</h2>';
267 return $out;
268 }
269
270 /**
271 * [Describe function...]
272 *
273 * @param [type] $str: ...
274 * @return [type] ...
275 */
276 function headerSiteDir($str) {
277 $out = '<h3>'.$str.'</h3>';
278 return $out;
279 }
280
281 /**
282 * [Describe function...]
283 *
284 * @param [type] $path: ...
285 * @param [type] $dir: ...
286 * @return [type] ...
287 */
288 function processSiteDir($path,$dir) {
289 if (@is_dir($path)) {
290 $localconf = $path."/typo3conf/localconf.php";
291 if (@is_file($localconf)) {
292 $key = md5($localconf);
293 $this->includeLocalconf($localconf);
294
295 $this->mapDBtoKey[$this->globalSiteInfo[$key]["siteInfo"]["TYPO3_db"]]=$key;
296 $this->globalSiteInfo[$key]["siteInfo"]["MAIN_DIR"]=$dir;
297 $this->globalSiteInfo[$key]["siteInfo"]["SA_PATH"]=$path;
298 $this->globalSiteInfo[$key]["siteInfo"]["URL"]=$this->currentUrl."/";
299 $this->globalSiteInfo[$key]["siteInfo"]["ADMIN_URL"]=$this->currentUrl."/".TYPO3_mainDir;
300 $this->globalSiteInfo[$key]["siteInfo"]["INSTALL_URL"]=$this->currentUrl."/".TYPO3_mainDir."install/";
301
302 $conMsg = $this->connectToDatabase($this->globalSiteInfo[$key]["siteInfo"]);
303 if (!$conMsg) {
304 $this->getDBInfo($key);
305 if ($this->full) {
306 $out.=t3lib_div::view_array($this->globalSiteInfo[$key]);
307 } else {
308 $out.=t3lib_div::view_array($this->globalSiteInfo[$key]["siteInfo"]);
309 }
310 } else {$out=$this->error($conMsg);}
311 } else $out=$this->error($localconf." is not a file!");
312 } else $out=$this->error($path." is not a directory!");
313 return $out;
314 }
315
316 /**
317 * [Describe function...]
318 *
319 * @param [type] $localconf: ...
320 * @return [type] ...
321 */
322 function includeLocalconf($localconf) {
323 include($localconf);
324
325 $siteInfo=array();
326 $siteInfo["sitename"] = $TYPO3_CONF_VARS["SYS"]["sitename"];
327 $siteInfo["TYPO3_db"] = $typo_db;
328 $siteInfo["TYPO3_db_username"] = $typo_db_username;
329 $siteInfo["TYPO3_db_password"] = $typo_db_password;
330 $siteInfo["TYPO3_db_host"] = $typo_db_host;
331 $siteInfo["installToolPassword"] = $TYPO3_CONF_VARS["BE"]["installToolPassword"];
332 $siteInfo["warningEmailAddress"] = $TYPO3_CONF_VARS["BE"]["warning_email_addr"];
333 $siteInfo["warningMode"] = $TYPO3_CONF_VARS["BE"]["warning_mode"];
334
335 $this->globalSiteInfo[md5($localconf)]=array("siteInfo"=>$siteInfo,"TYPO3_CONF_VARS"=>$TYPO3_CONF_VARS);
336 return $siteInfo;
337 }
338
339 /**
340 * [Describe function...]
341 *
342 * @param [type] $siteInfo: ...
343 * @return [type] ...
344 */
345 function connectToDatabase($siteInfo) {
346 if (@mysql_pconnect($siteInfo["TYPO3_db_host"], $siteInfo["TYPO3_db_username"], $siteInfo["TYPO3_db_password"])) {
347 if (!$siteInfo["TYPO3_db"]) {
348 return $this->error("No database selected");
349 } elseif (!mysql_select_db($siteInfo["TYPO3_db"])) {
350 return $this->error("Cannot connect to the current database, '".$siteInfo["TYPO3_db"]."'");
351 }
352 } else {
353 return $this->error("The current username, password or host was not accepted when the connection to the database was attempted to be established!");
354 }
355 }
356
357 /**
358 * [Describe function...]
359 *
360 * @param [type] $key: ...
361 * @return [type] ...
362 */
363 function getDBInfo($key) {
364 $DB = $this->globalSiteInfo[$key]["siteInfo"]["TYPO3_db"];
365
366 // Non-admin users
367 $query="SELECT count(*) FROM be_users WHERE admin=0 AND NOT deleted";
368 $res = mysql($DB,$query);
369 $row = mysql_fetch_row($res);
370 $this->globalSiteInfo[$key]["siteInfo"]["BE_USERS_NONADMIN"] = $row[0];
371 // Admin users
372 $query="SELECT count(*) FROM be_users WHERE admin!=0 AND NOT deleted";
373 $res = mysql($DB,$query);
374 $row = mysql_fetch_row($res);
375 $this->globalSiteInfo[$key]["siteInfo"]["BE_USERS_ADMIN"] = $row[0];
376
377 // Select Admin users
378 $query="SELECT uid,username,password,email,realName FROM be_users WHERE admin!=0 AND NOT deleted";
379 $res = mysql($DB,$query);
380 while($row = mysql_fetch_assoc($res)) {
381 // debug($row);
382 $this->globalSiteInfo[$key]["siteInfo"]["ADMINS"][] = $row;
383 }
384 }
385
386 /**
387 * [Describe function...]
388 *
389 * @return [type] ...
390 */
391 function makeTable() {
392 // TITLE:
393 $info=array();
394 $info[]="Site:";
395 $info[]="Database:";
396 $info[]="Username";
397 $info[]="Password";
398 $info[]="Host";
399 $info[]="Links (new win)";
400 $info[]="#Users NA/A";
401 $info[]="Admin be_users Info";
402 $info[]="Install Tool Password";
403 $info[]="Warning email address";
404 $info[]="W.mode";
405 $mainArrRows[]="<TR bgcolor=#eeeeee><TD nowrap valign=top>".implode("</TD><TD nowrap valign=top>",$info)."</TD></TR>";
406
407 reset($this->globalSiteInfo);
408 while(list($k,$all)=each($this->globalSiteInfo)) {
409 $info=array();
410 $info[]=$all["siteInfo"]["sitename"];
411 $info[]=$all["siteInfo"]["TYPO3_db"];
412 $info[]=$all["siteInfo"]["TYPO3_db_username"];
413 $info[]=$all["siteInfo"]["TYPO3_db_password"];
414 $info[]=$all["siteInfo"]["TYPO3_db_host"];
415 // URL
416 $info[]='<A HREF="'.$all["siteInfo"]["URL"].'" target="'.$this->targetWindow.'">Site</A> / <A HREF="'.$all["siteInfo"]["ADMIN_URL"].'" target="'.$this->targetWindowAdmin.'">Admin</A> / <A HREF="'.$all["siteInfo"]["INSTALL_URL"].'" target="'.$this->targetWindowInstall.'">Install</A>';
417 $info[]=$all["siteInfo"]["BE_USERS_NONADMIN"]."/".$all["siteInfo"]["BE_USERS_ADMIN"];
418
419 // Admin
420 if (is_array($all["siteInfo"]["ADMINS"])) {
421 reset($all["siteInfo"]["ADMINS"]);
422 $lines=array();
423 while(list(,$vArr)=each($all["siteInfo"]["ADMINS"])) {
424 $lines[]=$vArr["password"]." - ".$vArr["username"]." (".$vArr["realName"].", ".$vArr["email"].")";
425 $this->collectAdminPasswords[$vArr["password"]][] = $all["siteInfo"]["sitename"]." (".$all["siteInfo"]["TYPO3_db"]."), ".$vArr["username"]." (".$vArr["realName"].", ".$vArr["email"].")";
426 $this->changeAdminPasswords[$vArr["password"]][]=$all["siteInfo"]["TYPO3_db"].":".$vArr["uid"].":".$vArr["username"];
427 }
428 $info[]=implode("<BR>",$lines);
429 } else {
430 $info[]='<font color="red">No DB connection!</font>';
431 }
432 // Install
433 $info[]=$all["siteInfo"]["installToolPassword"];
434 $this->collectInstallPasswords[$all["siteInfo"]["installToolPassword"]][] = $all["siteInfo"]["sitename"]." (".$all["siteInfo"]["TYPO3_db"].")";
435
436 $info[]=$all["siteInfo"]["warningEmailAddress"];
437 $info[]=$all["siteInfo"]["warningMode"];
438 // debug($all["siteInfo"]);
439
440
441 // compile
442 $mainArrRows[]="<TR><TD nowrap valign=top>".implode("</TD><TD nowrap valign=top>",$info)."</TD></TR>";
443 }
444 $table = '<TABLE border=1 cellpadding=1 cellspacing=1>'.implode("",$mainArrRows).'</TABLE>';
445 return $table;
446 }
447
448 /**
449 * Based on the globalSiteInfo array, this prints information about local extensions for each site.
450 * In particular version number and most recent mod-time is interesting!
451 *
452 * @return [type] ...
453 */
454 function localExtensions() {
455 $this->extensionInfoArray=array();
456
457 reset($this->globalSiteInfo);
458 while(list($k,$all)=each($this->globalSiteInfo)) {
459 if ($all["siteInfo"]["SA_PATH"]) {
460 $extDir = $all["siteInfo"]["SA_PATH"]."/typo3conf/ext/";
461 if (@is_dir($extDir)) {
462 $this->extensionInfoArray["site"][$k]=array();
463
464 # debug($extDir,1);
465 $extensions=t3lib_div::get_dirs($extDir);
466 if (is_array($extensions)) {
467
468 # debug($extensions);
469 reset($extensions);
470 while(list(,$extKey)=each($extensions)) {
471 $eInfo = $this->getExtensionInfo($extDir,$extKey,$k);
472
473 $this->extensionInfoArray["site"][$k][$extKey]=$eInfo;
474 $this->extensionInfoArray["ext"][$extKey][$k]=$eInfo;
475 }
476 }
477 }
478 }
479 }
480
481 // Display results:
482 $out="";
483
484 #debug($this->extensionInfoArray);
485 // PER EXTENSION:
486 if (is_array($this->extensionInfoArray["ext"])) {
487 $extensionKeysCollect=array();
488
489 ksort($this->extensionInfoArray["ext"]);
490 reset($this->extensionInfoArray["ext"]);
491 $rows=array(
492 "reg"=>array(),
493 "user"=>array()
494 );
495 while(list($extKey,$instances)=each($this->extensionInfoArray["ext"])) {
496 $mtimes=array();
497
498 // Find most recent mtime of the options:
499 reset($instances);
500 while(list($k,$eInfo)=each($instances)) {
501 $mtimes[]=$eInfo["mtime"];
502 }
503 // Max mtime:
504 $maxMtime=max($mtimes);
505 $c=0;
506
507 // So, traverse all sites with the extension present:
508 reset($instances);
509 while(list($k,$eInfo)=each($instances)) {
510 // Set background color if mtime matches
511 if ($maxMtime==$eInfo["mtime"]) {
512 $this->extensionInfoArray["site"][$k][$extKey]["_highlight"]=1;
513 $bgCol = $eInfo["dirtype"]=='link' ? ' bgcolor="#ffcccc"' : ' bgcolor="#eeeeee"';
514 } else {
515 $bgCol = ' style="color: #999999; font-style: italic;"';
516 }
517
518 // Make row:
519 $type = substr($extKey,0,5)!="user_"?"reg":"user";
520 if ($type=="reg") $extensionKeysCollect[]=$extKey;
521 $rows[$type][]='
522 <tr>
523 '.(!$c?'<td rowspan="'.count($instances).'">'.$extKey.'</td>':'').'
524 <td nowrap'.$bgCol.'>'.$this->globalSiteInfo[$k]["siteInfo"]["SA_PATH"].'</td>
525 <td nowrap'.$bgCol.'>'.$eInfo["title"].'</td>
526 <td nowrap'.$bgCol.'>'.$eInfo["version"].'</td>
527 <td nowrap'.$bgCol.'>'.$eInfo["numberfiles"].'</td>
528 <td nowrap'.$bgCol.'>'.($eInfo["manual"]?'M':'-').'</td>
529 <td nowrap'.$bgCol.'>'.($eInfo["mtime"]?date("d-m-y H:i:s",$eInfo["mtime"]):'').'</td>
530 <td nowrap'.$bgCol.'>'.$eInfo["mtime_hash"].'</td>
531 </tr>
532 ';
533 $c++;
534 }
535 }
536
537 $out.='<h3>Registered extensions:</h3><table border=1>'.implode("",$rows["reg"]).'</table>';
538
539 $extensionKeysCollect = array_unique($extensionKeysCollect);
540 asort($extensionKeysCollect);
541 $out.='<form action=""><textarea cols="80" rows="10">'.implode(chr(10),$extensionKeysCollect).'</textarea></form>';
542
543 $out.='<BR><h3>User extensions:</h3><table border=1>'.implode("",$rows["user"]).'</table>';
544 }
545
546 // PER SITE:
547 if (is_array($this->extensionInfoArray["site"])) {
548 reset($this->extensionInfoArray["site"]);
549 $rows=array();
550 while(list($k,$extensions)=each($this->extensionInfoArray["site"])) {
551 // So, traverse all sites with the extension present:
552 $c=0;
553 reset($extensions);
554 while(list($extKey,$eInfo)=each($extensions)) {
555 // Set background color if mtime matches
556 if ($eInfo["_highlight"]) {
557 $bgCol = $eInfo["dirtype"]=='link' ? ' bgcolor="#ffcccc"' : ' bgcolor="#eeeeee"';
558 } else {
559 $bgCol = ' style="color: #999999; font-style: italic;"';
560 }
561
562 // Make row:
563 $rows[]='
564 <tr>
565 '.(!$c?'<td rowspan="'.count($extensions).'">'.$this->globalSiteInfo[$k]["siteInfo"]["SA_PATH"].'</td>':'').'
566 <td nowrap'.$bgCol.'>'.$extKey.'</td>
567 <td nowrap'.$bgCol.'>'.$eInfo["title"].'</td>
568 <td nowrap'.$bgCol.'>'.$eInfo["version"].'</td>
569 <td nowrap'.$bgCol.'>'.$eInfo["numberfiles"].'</td>
570 <td nowrap'.$bgCol.'>'.($eInfo["mtime"]?date("d-m-y H:i:s",$eInfo["mtime"]):'').'</td>
571 <td nowrap'.$bgCol.'>'.$eInfo["mtime_hash"].'</td>
572 </tr>
573 ';
574 $c++;
575 }
576 }
577 $out.='<BR><h3>Sites:</h3><table border=1>'.implode("",$rows).'</table>';
578 }
579 return $out;
580
581
582 # debug($this->extensionInfoArray);
583 # debug($this->globalSiteInfo);
584 }
585
586 /**
587 * Gets information for an extension, eg. version and most-recently-edited-script
588 *
589 * @param [type] $path: ...
590 * @param [type] $extKey: ...
591 * @param [type] $k: ...
592 * @return [type] ...
593 */
594 function getExtensionInfo($path,$extKey,$k) {
595 $file = $path.$extKey."/ext_emconf.php";
596 if (@is_file($file)) {
597 $_EXTKEY = $extKey;
598 include($file);
599
600 $eInfo=array();
601 // Info from emconf:
602 $eInfo["title"] = $EM_CONF[$extKey]["title"];
603 $eInfo["version"] = $EM_CONF[$extKey]["version"];
604 $filesHash = unserialize($EM_CONF[$extKey]["_md5_values_when_last_written"]);
605
606 # debug(count($filesHash),1);
607 if (!is_array($filesHash) || count($filesHash)<150) {
608 // Get all files list (may take LOONG time):
609 $extPath=$path.$extKey."/";
610 $fileArr = array();
611 $fileArr = $this->removePrefixPathFromList($this->getAllFilesAndFoldersInPath($fileArr,$extPath),$extPath);
612
613 // Number of files:
614 $eInfo["numberfiles"]=count($fileArr);
615 $eInfo["dirtype"]= filetype($path.$extKey);
616
617 // Most recent modification:
618 $eInfo["mtime_files"]=$this->findMostRecent($fileArr,$extPath);
619 if (count($eInfo["mtime_files"])) $eInfo["mtime"]=max($eInfo["mtime_files"]);
620 $eInfo["mtime_hash"] = md5(implode(",",$eInfo["mtime_files"]));
621 }
622
623 $eInfo["manual"] = @is_file($path.$extKey."/doc/manual.sxw");
624
625 return $eInfo;
626 # debug(unserialize($EM_CONF[$extKey]["_md5_values_when_last_written"]));
627 # debug($this->serverExtensionMD5Array($fileArr,$extPath));
628 # debug($fileArr);
629 } else return "ERROR: No emconf.php file: ".$file;
630 }
631
632 /**
633 * Recursively gather all files and folders of extension path.
634 *
635 * @param [type] $fileArr: ...
636 * @param [type] $extPath: ...
637 * @param [type] $extList: ...
638 * @param [type] $regDirs: ...
639 * @return [type] ...
640 */
641 function getAllFilesAndFoldersInPath($fileArr,$extPath,$extList="",$regDirs=0) {
642 if ($regDirs) $fileArr[]=$extPath;
643 $fileArr=array_merge($fileArr,t3lib_div::getFilesInDir($extPath,$extList,1,1)); // Candidate for t3lib_div::array_merge() if integer-keys will some day make trouble...
644
645 $dirs = t3lib_div::get_dirs($extPath);
646 if (is_array($dirs)) {
647 reset($dirs);
648 while(list(,$subdirs)=each($dirs)) {
649 if ($subdirs && (strcmp($subdirs,"CVS") || !$this->noCVS)) {
650 $fileArr = $this->getAllFilesAndFoldersInPath($fileArr,$extPath.$subdirs."/",$extList,$regDirs);
651 }
652 }
653 }
654 return $fileArr;
655 }
656
657 /**
658 * Creates a MD5-hash array over the current files in the extension
659 *
660 * @param [type] $fileArr: ...
661 * @param [type] $extPath: ...
662 * @return [type] ...
663 */
664 function serverExtensionMD5Array($fileArr,$extPath) {
665 reset($fileArr);
666 $md5Array=array();
667 while(list(,$fN)=each($fileArr)) {
668 if ($fN!="ext_emconf.php") {
669 $content_md5 = md5(t3lib_div::getUrl($extPath.$fN));
670 $md5Array[$fN]=substr($content_md5,0,4);
671 }
672 }
673 return $md5Array;
674 }
675
676 /**
677 * Creates a MD5-hash array over the current files in the extension
678 *
679 * @param [type] $fileArr: ...
680 * @param [type] $extPath: ...
681 * @return [type] ...
682 */
683 function findMostRecent($fileArr,$extPath) {
684 reset($fileArr);
685 $mtimeArray=array();
686 while(list(,$fN)=each($fileArr)) {
687 if ($fN!="ext_emconf.php") {
688 $mtime = filemtime($extPath.$fN);
689 $mtimeArray[$fN]=$mtime;
690 }
691 }
692 return $mtimeArray;
693 }
694
695 /**
696 * Removes the absolute part of all files/folders in fileArr
697 *
698 * @param [type] $fileArr: ...
699 * @param [type] $extPath: ...
700 * @return [type] ...
701 */
702 function removePrefixPathFromList($fileArr,$extPath) {
703 reset($fileArr);
704 while(list($k,$absFileRef)=each($fileArr)) {
705 if(t3lib_div::isFirstPartOfStr($absFileRef,$extPath)) {
706 $fileArr[$k]=substr($absFileRef,strlen($extPath));
707 } else return "ERROR: One or more of the files was NOT prefixed with the prefix-path!";
708 }
709 return $fileArr;
710 }
711
712 /**
713 * [Describe function...]
714 *
715 * @param [type] $exp: ...
716 * @return [type] ...
717 */
718 function singleSite($exp) {
719 $all = $this->globalSiteInfo[$exp];
720 $content = '<h2>'.$all["siteInfo"]["sitename"].' (DB: '.$all["siteInfo"]["TYPO3_db"].')</h2>';
721 $content.= '<HR>';
722 $content.= '<h3>Main details:</h3>';
723 $content.= '<font>LINKS: <A HREF="'.$all["siteInfo"]["URL"].'" target="'.$this->targetWindow.'">Site</A> / <A HREF="'.$all["siteInfo"]["ADMIN_URL"].'" target="'.$this->targetWindowAdmin.'">Admin</A> / <A HREF="'.$all["siteInfo"]["INSTALL_URL"].'" target="'.$this->targetWindowInstall.'">Install</A></font><BR><BR>';
724 $content.= t3lib_div::view_array($all);
725
726 $content.= '<h3>Login-Log for last month:</h3>';
727 $content.= $this->loginLog($all["siteInfo"]["TYPO3_db"]);
728
729 return $content;
730 }
731
732 /**
733 * [Describe function...]
734 *
735 * @param [type] $exp: ...
736 * @return [type] ...
737 */
738 function rmCachedFiles($exp) {
739 $all = $this->globalSiteInfo[$exp];
740 $content = '<h2>'.$all["siteInfo"]["sitename"].' (DB: '.$all["siteInfo"]["TYPO3_db"].')</h2>';
741 $content.= '<HR>';
742 $content.= '<h3>typo3conf/temp_CACHED_* files:</h3>';
743
744 $path = $all["siteInfo"]["SA_PATH"]."/typo3conf/";
745 if (@is_dir($path)) {
746 $filesInDir=t3lib_div::getFilesInDir($path,"php",1);
747 reset($filesInDir);
748 while(list($kk,$vv)=each($filesInDir)) {
749 if (t3lib_div::isFirstPartOfStr(basename($vv),"temp_CACHED_")) {
750 if (strstr(basename($vv),"ext_localconf.php") || strstr(basename($vv),"ext_tables.php")) {
751 $content.="REMOVED: ".$vv."<BR>";
752 unlink($vv);
753 if (file_exists($vv)) $content.="<strong><font color=red>ERROR: File still exists, so could not be removed anyways!</font></strong><BR>";
754 }
755 }
756 }
757 } else {
758 $content.='<strong><font color=red>ERROR: '.$path.' was not a directory!</font></strong>';
759 }
760
761 return $content;
762 }
763
764 /**
765 * [Describe function...]
766 *
767 * @param [type] $exp: ...
768 * @return [type] ...
769 */
770 function menuContent($exp) {
771 if ($exp) {
772 reset($this->globalSiteInfo);
773 $lines=array();
774 $head="";
775 while(list($k,$all)=each($this->globalSiteInfo)) {
776 // Setting section header, if needed.
777 if ($head!=$all["siteInfo"]["MAIN_DIR"]) {
778 $lines[]='<h4><nobr>'.t3lib_div::fixed_lgd_pre($all["siteInfo"]["MAIN_DIR"],18).'</nobr></h4>';
779 $head=$all["siteInfo"]["MAIN_DIR"];
780 }
781
782 switch($exp) {
783 case "update":
784 // Label:
785 $label = $all["siteInfo"]["sitename"] ? $all["siteInfo"]["sitename"] : "(DB: ".$all["siteInfo"]["TYPO3_db"].")";
786 $lines[]='<HR><b>'.$label.'</b> ('.substr($all["siteInfo"]["SA_PATH"],strlen($all["siteInfo"]["MAIN_DIR"])+1).')<BR>';
787
788 // Get SQL-files:
789 /* $readPath = $all["siteInfo"]["SA_PATH"]."/typo3/t3lib/stddb/";
790 $fileArr = t3lib_div::getFilesInDir($readPath,"sql",1,"mtime");
791 $file=array();
792 if (is_array($fileArr)) {
793 reset($fileArr);
794 while(list(,$fP)=each($fileArr)) {
795 // if (substr($fP,0,strlen($readPath."static_template"))==$readPath."static_template") {
796 if (substr($fP,0,strlen($readPath."static+"))==$readPath."static+") {
797 $file["static_template.sql"]=$fP;
798 }
799 if (substr($fP,0,strlen($readPath."sys_tabledescr_X"))==$readPath."sys_tabledescr_X") {
800 $file["sys_tabledescr_X.sql"]=$fP;
801 }
802 if (substr($fP,0,strlen($readPath."tables"))==$readPath."tables") {
803 $file["tables.sql"]=$fP;
804 }
805 }
806 }
807 */
808 $tempVal='&_someUniqueValue='.time();
809
810 // $url = $all["siteInfo"]["ADMIN_URL"]."mod/tools/em/index.php";
811 // $lines[]='<nobr><a HREF="'.$url.'" target="TSApage">EM</a></nobr>';
812
813
814
815 $lines[]='<nobr><a HREF="'.$this->scriptName.'?type=page&show=rmTempCached&exp='.$k.$tempVal.'" target="TSApage">Remove temp_CACHED files</a></nobr>';
816
817 $url = $all["siteInfo"]["INSTALL_URL"]."index.php?TYPO3_INSTALL[type]=database&TYPO3_INSTALL[database_type]=cmpFile|CURRENT_TABLES".$tempVal."#bottom";
818 $lines[]='<nobr><a HREF="'.$url.'" target="TSApage">CURRENT_TABLES</a></nobr>';
819
820 $url = $all["siteInfo"]["INSTALL_URL"]."index.php?TYPO3_INSTALL[type]=database&TYPO3_INSTALL[database_type]=import|CURRENT_STATIC"."&presetWholeTable=1".$tempVal."#bottom";
821 $lines[]='<nobr><a HREF="'.$url.'" target="TSApage">CURRENT_STATIC</a></nobr>';
822
823 /*
824 // Link to tables:
825 if ($file["tables.sql"]) {
826 $url = $all["siteInfo"]["INSTALL_URL"]."index.php?TYPO3_INSTALL[type]=database&TYPO3_INSTALL[database_type]=cmpFile|".rawurlencode($file["tables.sql"]).$tempVal."#bottom";
827 $lines[]='<nobr><a HREF="'.$url.'" target="TSApage">'.basename($file["tables.sql"]).'</a></nobr>';
828 }
829 // Link to static_tempalte
830 if ($file["static_template.sql"]) {
831 $url = $all["siteInfo"]["INSTALL_URL"]."index.php?TYPO3_INSTALL[type]=database&TYPO3_INSTALL[database_type]=import|".rawurlencode($file["static_template.sql"])."&presetWholeTable=1".$tempVal."#bottom";
832 $lines[]='<nobr><a HREF="'.$url.'" target="TSApage">'.basename($file["static_template.sql"]).'</a></nobr>';
833 }
834 // Link to language file
835 if ($file["sys_tabledescr_X.sql"]) {
836 $url = $all["siteInfo"]["INSTALL_URL"]."index.php?TYPO3_INSTALL[type]=database&TYPO3_INSTALL[database_type]=import|".rawurlencode($file["sys_tabledescr_X.sql"])."&presetWholeTable=1".$tempVal."#bottom";
837 $lines[]='<nobr><a HREF="'.$url.'" target="TSApage">'.basename($file["sys_tabledescr_X.sql"]).'</a></nobr>';
838 }
839 */
840 // Cache
841 $url = $all["siteInfo"]["INSTALL_URL"]."index.php?TYPO3_INSTALL[type]=database&TYPO3_INSTALL[database_type]=cache|".
842 "&PRESET[database_clearcache][cache_pages]=1".
843 "&PRESET[database_clearcache][cache_pagesection]=1".
844 "&PRESET[database_clearcache][cache_hash]=1".
845 $tempVal.
846 "#bottom";
847 $lines[]='<nobr><a HREF="'.$url.'" target="TSApage">Clear cache</a></nobr>';
848
849
850 $lines[]='<nobr><a HREF="'.$all["siteInfo"]["ADMIN_URL"].'index.php" target="'.$this->targetWindowAdmin.'">Admin -></a></nobr>';
851 break;
852 case "info":
853 // item
854 $label = $all["siteInfo"]["sitename"] ? $all["siteInfo"]["sitename"] : "(DB: ".$all["siteInfo"]["TYPO3_db"].")";
855 $lines[]='<nobr><a HREF="'.$this->scriptName.'?type=page&show=info&exp='.$k.'" target="TSApage">'.$label.'</a> ('.substr($all["siteInfo"]["SA_PATH"],strlen($all["siteInfo"]["MAIN_DIR"])+1).'/)</nobr>';
856 break;
857 }
858 }
859 return "<font>".implode("<BR>",$lines)."<BR></font>";
860 }
861 }
862
863 /**
864 * [Describe function...]
865 *
866 * @return [type] ...
867 */
868 function makeAdminLogin() {
869 reset($this->globalSiteInfo);
870 $lines=array();
871 $head="";
872 while(list($k,$all)=each($this->globalSiteInfo)) {
873 // Setting section header, if needed.
874 if ($head!=$all["siteInfo"]["MAIN_DIR"]) {
875 $lines[]='<tr><td colspan=2><BR><h4>'.$all["siteInfo"]["MAIN_DIR"].'</h4></td></tr>';
876 $head=$all["siteInfo"]["MAIN_DIR"];
877 }
878
879
880
881 // item
882 $label = $all["siteInfo"]["sitename"] ? $all["siteInfo"]["sitename"] : "(DB: ".$all["siteInfo"]["TYPO3_db"].")";
883 $unique=md5(microtime());
884
885 $opts=array();
886
887 $defUName="";
888 if (is_array($all["siteInfo"]["ADMINS"])) {
889 reset($all["siteInfo"]["ADMINS"]);
890 while(list(,$vArr)=each($all["siteInfo"]["ADMINS"])) {
891 $chalVal = md5($vArr["username"].":".$vArr["password"].":".$unique);
892 $opts[]='<option value="'.$chalVal.'">'.$vArr["username"].'</option>';
893 if (!$defUName) {$defUName=$vArr["username"];}
894 }
895 }
896 if (count($opts)>1) {
897 $userident='
898 <select name="userident" onChange="document[\''.$k.'\'].username.value=this.options[this.selectedIndex].text;">'.implode("",$opts).'</select>
899 ';
900 } else {
901 $userident='('.$defUName.')<BR><input type="Hidden" name="userident" value="'.$chalVal.'">';
902 }
903
904 $form='
905 <form name="'.$k.'" action="'.$all["siteInfo"]["ADMIN_URL"].'index.php" target="EXTERnalWindow" method="post">
906 <input type="submit" name="submit" value="Login">
907 <input type="Hidden" name="username" value="'.$defUName.'">
908 <input type="Hidden" name="challenge" value="'.$unique.'">
909 <input type="Hidden" name="redirect_url" value="">
910 <input type="Hidden" name="login_status" value="login">
911 '.trim($userident).'
912 </form>';
913
914 $lines[]='<tr><td><strong>'.$label.'</strong></td><td nowrap>'.trim($form).'</td></tr>';
915 }
916 return "<table border=1 cellpadding=5 cellspacing=1>".implode("",$lines)."</table>";
917 }
918
919 /**
920 * [Describe function...]
921 *
922 * @param [type] $DB: ...
923 * @return [type] ...
924 */
925 function loginLog($DB) {
926 // Non-admin users
927 $query="SELECT sys_log.*, be_users.username AS username, be_users.admin AS admin FROM sys_log,be_users WHERE be_users.uid=sys_log.userid AND sys_log.type=255 AND sys_log.tstamp > ".(time()-(60*60*24*30))." ORDER BY sys_log.tstamp DESC";
928
929 //1=login, 2=logout, 3=failed login (+ errorcode 3), 4=failure_warning_email sent
930 $res = mysql($DB,$query);
931 echo mysql_error();
932 $dayRef="";
933 $lines=array();
934 while($row = mysql_fetch_assoc($res)) {
935 $day = date("d-m-Y",$row["tstamp"]);
936 if ($dayRef!=$day) {
937 $lines[]='
938 <h4>'.$day.':</h4>';
939 $dayRef=$day;
940 }
941 $theLine = date("H:i",$row["tstamp"]).": ".str_pad(substr($row["username"],0,10),10)." ".$this->log_getDetails($row["details"],unserialize($row["log_data"]));
942 $lines[]= $row["admin"] ? '<span class=redclass>'.$theLine.'</span>' : $theLine;
943
944 // debug($row);
945 }
946 return '<pre>'.implode(chr(10),$lines).'</pre>';
947 }
948
949 /**
950 * [Describe function...]
951 *
952 * @param [type] $text: ...
953 * @param [type] $data: ...
954 * @return [type] ...
955 */
956 function log_getDetails($text,$data) {
957 // $code is used later on to substitute errormessages with language-corrected values...
958 if (is_array($data)) {
959 return sprintf($text, $data[0],$data[1],$data[2],$data[3],$data[4]);
960 } else return $text;
961 }
962
963 /**
964 * [Describe function...]
965 *
966 * @return [type] ...
967 */
968 function changeAdminPasswordsForm() {
969 reset($this->changeAdminPasswords);
970 $content="";
971 while(list($k,$p)=each($this->changeAdminPasswords)) {
972 $content.='<h3>'.$k.'</h3>';
973 reset($p);
974 while(list($kk,$pp)=each($p)) {
975 $content.='<nobr>';
976 $content.='<input type="checkbox" name="SETFIELDS[]" value="'.$pp.'"> '.$pp.' - ';
977 $content.=$this->collectAdminPasswords[$k][$kk];
978 $content.='</nobr><BR>';
979 }
980 }
981
982 $content.='New password: <input type="text" name="NEWPASS"><BR>';
983 $content.='New password (md5): <input type="text" name="NEWPASS_md5"><BR>
984 (This overrules any plain password above!)
985 <br>';
986 $content='
987 <form action="'.$this->scriptName.'?type=page&show=admin" method="post">
988 '.$content.'
989 <input type="submit" name="Set">
990 </form>
991 ';
992
993 return $content;
994 }
995
996 /**
997 * [Describe function...]
998 *
999 * @return [type] ...
1000 */
1001 function setNewPasswords() {
1002 $whichFields = t3lib_div::GPvar("SETFIELDS");
1003
1004 $pass = trim(t3lib_div::GPvar("NEWPASS"));
1005 $passMD5 = t3lib_div::GPvar("NEWPASS_md5");
1006 $updatedFlag=0;
1007 if ($pass || $passMD5) {
1008 $pass = $passMD5 ? $passMD5 : md5($pass);
1009
1010 reset($whichFields);
1011 while(list(,$values)=each($whichFields)) {
1012 $parts = explode(":",$values);
1013 if (count($parts)>2) {
1014 $key = $this->mapDBtoKey[$parts[0]];
1015 if ($key && isset($this->globalSiteInfo[$key]["siteInfo"])) {
1016 $error = $this->connectToDatabase($this->globalSiteInfo[$key]["siteInfo"]);
1017 if (!$error) {
1018 $DB = $this->globalSiteInfo[$key]["siteInfo"]["TYPO3_db"];
1019 $content.='<h3>Updating '.$DB.':</h3>';
1020 $query = "UPDATE be_users SET password='".addslashes($pass)."' WHERE uid=".intval($parts[1])." AND username='".addslashes($parts[2])."' AND admin!=0"; // username/admin are added to security. But they are certainly redundant!!
1021 $content.='<i>'.htmlspecialchars($query).'</i><BR>';
1022 $res = mysql($DB,$query);
1023 echo mysql_error();
1024 $content.='Affected rows: '.mysql_affected_rows().'<BR><HR>';
1025 $updatedFlag="1";
1026 }
1027 }
1028 }
1029 }
1030 }
1031 $this->initProcess();
1032 return $content;
1033 }
1034
1035 /**
1036 * [Describe function...]
1037 *
1038 * @return [type] ...
1039 */
1040 function defaultSet() {
1041 $style = '
1042 <style type="text/css">
1043 .redclass {color: red;}
1044 P {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px}
1045 FONT {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px}
1046 H1 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 20px; color: #000066;}
1047 H2 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 17px; color: #000066;}
1048 H3 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; color: #000066;}
1049 H4 {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; color: maroon;}
1050 TD {font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px}
1051 </style>
1052 ';
1053
1054 switch(t3lib_div::GPvar("type")) {
1055 case "phpinfo":
1056 phpinfo();
1057 break;
1058 case "page":
1059 ?>
1060 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
1061 <?php echo $style;?>
1062 <html>
1063 <head>
1064 <title>TYPO3 Super Admin MAIN</title>
1065 </head>
1066 <body>
1067 <br>
1068 <?php
1069 echo $this->make();
1070 ?>
1071 </body>
1072 </html>
1073 <?php
1074 break;
1075 case "menu":
1076 ?>
1077 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
1078 <?php echo $style;?>
1079 <html>
1080 <head>
1081 <title>TYPO3 Super Admin MENU</title>
1082 </head>
1083 <body>
1084 <?php
1085 echo $this->make();
1086 ?>
1087 </body>
1088 </html>
1089 <?php
1090 break;
1091 case "localext":
1092 ?>
1093 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
1094 <?php echo $style;?>
1095 <html>
1096 <head>
1097 <title>TYPO3 Super Admin</title>
1098 </head>
1099 <body>
1100 <?php
1101 echo $this->make();
1102 ?>
1103 </body>
1104 </html>
1105 <?php
1106 break;
1107 default:
1108 ?>
1109 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
1110 <html>
1111 <head>
1112 <title>TYPO3 Super Admin</title>
1113 </head>
1114 <frameset cols="250,*">
1115 <frame name="TSAmenu" src="superadmin.php?type=menu&show=menu" marginwidth="10" marginheight="10" scrolling="auto" frameborder="0">
1116 <frame name="TSApage" src="superadmin.php?type=page" marginwidth="10" marginheight="10" scrolling="auto" frameborder="0">
1117 </frameset>
1118 </html>
1119 <?php
1120 break;
1121 }
1122 }
1123 }
1124
1125 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_superadmin.php']) {
1126 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_superadmin.php']);
1127 }
1128 ?>