Removed MMCache support, this thing is dead. Partially implements bug 19193
[lhc/web/wiklou.git] / config / Installer.php
1 <?php
2
3 # MediaWiki web-based config/installation
4 # Copyright (C) 2004 Brion Vibber <brion@pobox.com>, 2006 Rob Church <robchur@gmail.com>
5 # http://www.mediawiki.org/
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License along
18 # with this program; if not, write to the Free Software Foundation, Inc.,
19 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 # http://www.gnu.org/copyleft/gpl.html
21
22 if( !defined( 'MEDIAWIKI_INSTALL' ) ) {
23 die( 'Not an entry point.' );
24 }
25
26 error_reporting( E_ALL | E_STRICT );
27 header( "Content-type: text/html; charset=utf-8" );
28 @ini_set( "display_errors", true );
29
30 # In case of errors, let output be clean.
31 $wgRequestTime = microtime( true );
32
33 // Run version checks before including other files
34 // so people don't see a scary parse error.
35 require_once( "$IP/maintenance/install-utils.inc" );
36 install_version_checks();
37
38 require_once( "$IP/includes/Defines.php" );
39 require_once( "$IP/includes/DefaultSettings.php" );
40 require_once( "$IP/includes/AutoLoader.php" );
41 require_once( "$IP/includes/MagicWord.php" );
42 require_once( "$IP/includes/Namespace.php" );
43 require_once( "$IP/includes/ProfilerStub.php" );
44 require_once( "$IP/includes/GlobalFunctions.php" );
45 require_once( "$IP/includes/Hooks.php" );
46 require_once( "$IP/includes/Exception.php" );
47 require_once( "$IP/includes/json/Services_JSON.php" );
48 require_once( "$IP/includes/json/FormatJson.php" );
49
50 # If we get an exception, the user needs to know
51 # all the details
52 $wgShowExceptionDetails = true;
53 $wgShowSQLErrors = true;
54 wfInstallExceptionHandler();
55 ## Databases we support:
56
57 $ourdb = array();
58
59 $ourdb['mysql'] = array(
60 'fullname' => 'MySQL',
61 'havedriver' => 0,
62 'compile' => 'mysql',
63 'bgcolor' => '#ffe5a7',
64 'rootuser' => 'root',
65 'serverless' => false
66 );
67
68 $ourdb['postgres'] = array(
69 'fullname' => 'PostgreSQL',
70 'havedriver' => 0,
71 'compile' => 'pgsql',
72 'bgcolor' => '#aaccff',
73 'rootuser' => 'postgres',
74 'serverless' => false
75 );
76
77 $ourdb['sqlite'] = array(
78 'fullname' => 'SQLite',
79 'havedriver' => 0,
80 'compile' => 'pdo_sqlite',
81 'bgcolor' => '#b1ebb1',
82 'rootuser' => '',
83 'serverless' => true
84 );
85
86 $ourdb['mssql'] = array(
87 'fullname' => 'MSSQL',
88 'havedriver' => 0,
89 'compile' => 'mssql_not_ready', # Change to 'mssql' after includes/DatabaseMssql.php added;
90 'bgcolor' => '#ffc0cb',
91 'rootuser' => 'administrator',
92 'serverless' => false
93 );
94
95 $ourdb['ibm_db2'] = array(
96 'fullname' => 'DB2',
97 'havedriver' => 0,
98 'compile' => 'ibm_db2',
99 'bgcolor' => '#ffeba1',
100 'rootuser' => 'db2admin',
101 'serverless' => false
102 );
103
104 $ourdb['oracle'] = array(
105 'fullname' => 'Oracle',
106 'havedriver' => 0,
107 'compile' => 'oci8',
108 'bgcolor' => '#ffeba1',
109 'rootuser' => 'sys',
110 'serverless' => false
111 );
112
113 ?>
114 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
115 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" dir="ltr">
116 <head>
117 <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
118 <meta name="robots" content="noindex,nofollow"/>
119 <title>MediaWiki <?php echo htmlspecialchars( $wgVersion ); ?> Installation</title>
120 <style type="text/css">
121
122 @import "../skins/monobook/main.css";
123
124 .env-check {
125 font-size: 90%;
126 margin: 1em 0 1em 2.5em;
127 }
128
129 .config-section {
130 margin-top: 2em;
131 }
132
133 .config-section label.column {
134 clear: left;
135 font-weight: bold;
136 width: 13em;
137 float: left;
138 text-align: right;
139 padding-right: 1em;
140 padding-top: .2em;
141 }
142
143 .config-input {
144 clear: left;
145 zoom: 100%; /* IE hack */
146 }
147
148 .config-section .config-desc {
149 clear: left;
150 margin: 0 0 2em 18em;
151 padding-top: 1em;
152 font-size: 85%;
153 }
154
155 .iput-text, .iput-password {
156 width: 14em;
157 margin-right: 1em;
158 }
159
160 .error {
161 color: red;
162 background-color: #fff;
163 font-weight: bold;
164 left: 1em;
165 font-size: 100%;
166 }
167
168 .error-top {
169 color: red;
170 background-color: #FFF0F0;
171 border: 2px solid red;
172 font-size: 130%;
173 font-weight: bold;
174 padding: 1em 1.5em;
175 margin: 2em 0 1em;
176 }
177
178 ul.plain {
179 list-style-type: none;
180 list-style-image: none;
181 float: left;
182 margin: 0;
183 padding: 0;
184 }
185
186 .btn-install {
187 font-weight: bold;
188 font-size: 110%;
189 padding: .2em .3em;
190 }
191
192 .license {
193 font-size: 85%;
194 padding-top: 3em;
195 }
196
197 span.success-message {
198 font-weight: bold;
199 font-size: 110%;
200 color: green;
201 }
202
203 .success-box {
204 font-size: 130%;
205 }
206
207 </style>
208 <script type="text/javascript">
209 <!--
210 <?php echo 'var databases = ' . FormatJson::encode( $ourdb ) . ';'; ?>
211
212 function show(id, showOrHide) {
213 var i = document.getElementById(id);
214 if (i) i.style.display = showOrHide ? 'block' : 'none';
215 }
216 function hideall() {
217 for (db in databases) {
218 show(db, false);
219 }
220 }
221 function toggleDBarea(id, defaultroot) {
222 hideall();
223 var dbarea = document.getElementById(id);
224 if (dbarea) dbarea.style.display = (dbarea.style.display == 'none') ? 'block' : 'none';
225 var db = document.getElementById('RootUser');
226 db.value = databases[id].rootuser;
227 show('db-server-settings1', !databases[id].serverless);
228 show('db-server-settings2', !databases[id].serverless);
229 }
230 // -->
231 </script>
232 </head>
233
234 <body>
235 <div id="globalWrapper">
236 <div id="column-content">
237 <div id="content">
238 <div id="bodyContent">
239
240 <h1>MediaWiki <?php print htmlspecialchars( $wgVersion ) ?> Installation</h1>
241
242 <?php
243 $mainListOpened = false; # Is the main list (environement checking) opend ? Used by dieout
244
245 /* Check for existing configurations and bug out! */
246
247 if( file_exists( "../LocalSettings.php" ) ) {
248 $script = defined('MW_INSTALL_PHP5_EXT') ? 'index.php5' : 'index.php';
249 dieout( "<p><strong>Setup has completed, <a href='../$script'>your wiki</a> is configured.</strong></p>
250 <p>Please delete the /config directory for extra security.</p>" );
251 }
252
253 if( file_exists( "./LocalSettings.php" ) ) {
254 writeSuccessMessage();
255 dieout( '' );
256 }
257
258 if( !is_writable( "." ) ) {
259 dieout( "<h2>Can't write config file, aborting</h2>
260
261 <p>In order to configure the wiki you have to make the <tt>config</tt> subdirectory
262 writable by the web server. Once configuration is done you'll move the created
263 <tt>LocalSettings.php</tt> to the parent directory, and for added safety you can
264 then remove the <tt>config</tt> subdirectory entirely.</p>
265
266 <p>To make the directory writable on a Unix/Linux system:</p>
267
268 <pre>
269 cd <i>" . htmlspecialchars( dirname( dirname( __FILE__ ) ) ) . "</i>
270 chmod a+w config
271 </pre>
272
273 <p>Afterwards retry to start the <a href=\"\">setup</a>.</p>" );
274 }
275
276
277 require_once( "$IP/maintenance/updaters.inc" );
278
279 class ConfigData {
280 function getEncoded( $data ) {
281 # removing latin1 support, no need...
282 return $data;
283 }
284 function getSitename() { return $this->getEncoded( $this->Sitename ); }
285 function getSysopName() { return $this->getEncoded( $this->SysopName ); }
286 function getSysopPass() { return $this->getEncoded( $this->SysopPass ); }
287
288 function setSchema( $schema, $engine ) {
289 $this->DBschema = $schema;
290 if ( !preg_match( '/^\w*$/', $engine ) ){
291 $engine = 'InnoDB';
292 }
293 switch ( $this->DBschema ) {
294 case 'mysql5':
295 $this->DBTableOptions = "ENGINE=$engine, DEFAULT CHARSET=utf8";
296 $this->DBmysql5 = 'true';
297 break;
298 case 'mysql5-binary':
299 $this->DBTableOptions = "ENGINE=$engine, DEFAULT CHARSET=binary";
300 $this->DBmysql5 = 'true';
301 break;
302 default:
303 $this->DBTableOptions = "TYPE=$engine";
304 $this->DBmysql5 = 'false';
305 }
306 $this->DBengine = $engine;
307
308 # Set the global for use during install
309 global $wgDBTableOptions;
310 $wgDBTableOptions = $this->DBTableOptions;
311 }
312 }
313
314 ?>
315
316 <ul>
317 <li>
318 <b>Don't forget security updates!</b> Keep an eye on the
319 <a href="http://lists.wikimedia.org/mailman/listinfo/mediawiki-announce">low-traffic
320 release announcements mailing list</a>.
321 </li>
322 </ul>
323
324
325 <h2>Checking environment...</h2>
326 <p><em>Please include all of the lines below when reporting installation problems.</em></p>
327 <ul class="env-check">
328 <?php
329 $mainListOpened = true;
330
331 $endl = "
332 ";
333 define( 'MW_NO_OUTPUT_BUFFER', 1 );
334 $conf = new ConfigData;
335
336 install_version_checks();
337 $self = 'Installer'; # Maintenance script name, to please Setup.php
338
339 print "<li>PHP " . htmlspecialchars( phpversion() ) . " installed</li>\n";
340
341 error_reporting( 0 );
342 $phpdatabases = array();
343 foreach (array_keys($ourdb) as $db) {
344 $compname = $ourdb[$db]['compile'];
345 if( extension_loaded( $compname ) || ( mw_have_dl() && dl( "{$compname}." . PHP_SHLIB_SUFFIX ) ) ) {
346 array_push($phpdatabases, $db);
347 $ourdb[$db]['havedriver'] = 1;
348 }
349 }
350 error_reporting( E_ALL | E_STRICT );
351
352 if (!$phpdatabases) {
353 print "Could not find a suitable database driver!<ul>";
354 foreach (array_keys($ourdb) AS $db) {
355 $comp = $ourdb[$db]['compile'];
356 $full = $ourdb[$db]['fullname'];
357 print "<li>For <b>$full</b>, compile PHP using <b>--with-$comp</b>, "
358 ."or install the $comp.so module</li>\n";
359 }
360 echo '</ul>';
361 dieout( '' );
362 }
363
364 print "<li>Found database drivers for:";
365 $DefaultDBtype = '';
366 foreach (array_keys($ourdb) AS $db) {
367 if ($ourdb[$db]['havedriver']) {
368 if ( $DefaultDBtype == '' ) {
369 $DefaultDBtype = $db;
370 }
371 print " ".$ourdb[$db]['fullname'];
372 }
373 }
374 print "</li>\n";
375
376 if( wfIniGetBool( "register_globals" ) ) {
377 ?>
378 <li>
379 <div style="font-size:110%">
380 <strong class="error">Warning:</strong>
381 <strong>PHP's <tt><a href="http://php.net/register_globals">register_globals</a></tt> option is enabled. Disable it if you can.</strong>
382 </div>
383 MediaWiki will work, but your server is more exposed to PHP-based security vulnerabilities.
384 </li>
385 <?php
386 }
387
388 $fatal = false;
389
390 if( wfIniGetBool( "magic_quotes_runtime" ) ) {
391 $fatal = true;
392 ?><li class='error'><strong>Fatal: <a href='http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime'>magic_quotes_runtime</a> is active!</strong>
393 This option corrupts data input unpredictably; you cannot install or use
394 MediaWiki unless this option is disabled.</li>
395 <?php
396 }
397
398 if( wfIniGetBool( "magic_quotes_sybase" ) ) {
399 $fatal = true;
400 ?><li class='error'><strong>Fatal: <a href='http://www.php.net/manual/en/ref.sybase.php#ini.magic-quotes-sybase'>magic_quotes_sybase</a> is active!</strong>
401 This option corrupts data input unpredictably; you cannot install or use
402 MediaWiki unless this option is disabled.</li>
403 <?php
404 }
405
406 if( wfIniGetBool( "mbstring.func_overload" ) ) {
407 $fatal = true;
408 ?><li class='error'><strong>Fatal: <a href='http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload'>mbstring.func_overload</a> is active!</strong>
409 This option causes errors and may corrupt data unpredictably;
410 you cannot install or use MediaWiki unless this option is disabled.</li>
411 <?php
412 }
413
414 if( wfIniGetBool( "zend.ze1_compatibility_mode" ) ) {
415 $fatal = true;
416 ?><li class="error"><strong>Fatal: <a href="http://www.php.net/manual/en/ini.core.php">zend.ze1_compatibility_mode</a> is active!</strong>
417 This option causes horrible bugs with MediaWiki; you cannot install or use
418 MediaWiki unless this option is disabled.</li>
419 <?php
420 }
421
422 if( $fatal ) {
423 dieout( "Cannot install MediaWiki." );
424 }
425
426 if( wfIniGetBool( "safe_mode" ) ) {
427 $conf->safeMode = true;
428 ?>
429 <li><b class='error'>Warning:</b> <strong>PHP's
430 <a href='http://www.php.net/features.safe-mode'>safe mode</a> is active.</strong>
431 You may have problems caused by this, particularly if using image uploads.
432 </li>
433 <?php
434 } else {
435 $conf->safeMode = false;
436 }
437
438 $sapi = htmlspecialchars( php_sapi_name() );
439 print "<li>PHP server API is $sapi; ";
440 $script = defined('MW_INSTALL_PHP5_EXT') ? 'index.php5' : 'index.php';
441 if( $wgUsePathInfo ) {
442 print "ok, using pretty URLs (<tt>$script/Page_Title</tt>)";
443 } else {
444 print "using ugly URLs (<tt>$script?title=Page_Title</tt>)";
445 }
446 print "</li>\n";
447
448 $conf->xml = function_exists( "utf8_encode" );
449 if( $conf->xml ) {
450 print "<li>Have XML / Latin1-UTF-8 conversion support.</li>\n";
451 } else {
452 dieout( "PHP's XML module is missing; the wiki requires functions in
453 this module and won't work in this configuration.
454 If you're running Mandrake, install the php-xml package." );
455 }
456
457 # Check for session support
458 if( !function_exists( 'session_name' ) )
459 dieout( "PHP's session module is missing. MediaWiki requires session support in order to function." );
460
461 # session.save_path doesn't *have* to be set, but if it is, and it's
462 # not valid/writable/etc. then it can cause problems
463 $sessionSavePath = mw_get_session_save_path();
464 $ssp = htmlspecialchars( $sessionSavePath );
465 # Warn the user if it's not set, but let them proceed
466 if( !$sessionSavePath ) {
467 print "<li><strong>Warning:</strong> A value for <tt>session.save_path</tt>
468 has not been set in PHP.ini. If the default value causes problems with
469 saving session data, set it to a valid path which is read/write/execute
470 for the user your web server is running under.</li>";
471 } elseif ( is_dir( $sessionSavePath ) && is_writable( $sessionSavePath ) ) {
472 # All good? Let the user know
473 print "<li>Session save path (<tt>{$ssp}</tt>) appears to be valid.</li>";
474 } else {
475 # Something not right? Warn the user, but let them proceed
476 print "<li><strong>Warning:</strong> Your <tt>session.save_path</tt> value (<tt>{$ssp}</tt>)
477 appears to be invalid or is not writable. PHP needs to be able to save data to
478 this location for correct session operation.</li>";
479 }
480
481 # Check for PCRE support
482 if( !function_exists( 'preg_match' ) )
483 dieout( "The PCRE support module appears to be missing. MediaWiki requires the
484 Perl-compatible regular expression functions." );
485
486 # The installer can take a while, and we really don't want it to time out
487 wfSuppressWarnings();
488 set_time_limit( 0 );
489 wfRestoreWarnings();
490
491 $memlimit = ini_get( "memory_limit" );
492 if( $memlimit == -1 ) {
493 print "<li>PHP is configured with no <tt>memory_limit</tt>.</li>\n";
494 } else {
495 print "<li>PHP's <tt>memory_limit</tt> is " . htmlspecialchars( $memlimit ). " bytes. ";
496 $newlimit = wfMemoryLimit();
497 $memlimit = wfShorthandToInteger( $memlimit );
498 if( $newlimit < $memlimit ) {
499 print "<b>Failed raising limit, installation may fail.</b>";
500 } elseif ( $newlimit > $memlimit ) {
501 print "Raised <tt>memory_limit</tt> to " . htmlspecialchars( $newlimit ) . " bytes. ";
502 }
503 print "</li>\n";
504 }
505
506 $conf->xcache = function_exists( 'xcache_get' );
507 if( $conf->xcache )
508 print "<li><a href=\"http://trac.lighttpd.net/xcache/\">XCache</a> installed</li>\n";
509
510 $conf->apc = function_exists('apc_fetch');
511 if ($conf->apc ) {
512 print "<li><a href=\"http://www.php.net/apc\">APC</a> installed</li>\n";
513 }
514
515 $conf->eaccel = function_exists( 'eaccelerator_get' );
516 if ( $conf->eaccel ) {
517 print "<li><a href=\"http://eaccelerator.sourceforge.net/\">eAccelerator</a> installed</li>\n";
518 }
519
520 $conf->dba = function_exists( 'dba_open' );
521
522 if( !( $conf->eaccel || $conf->apc || $conf->xcache ) ) {
523 echo( '<li>Couldn\'t find <a href="http://eaccelerator.sourceforge.net">eAccelerator</a>,
524 <a href="http://www.php.net/apc">APC</a> or <a href="http://trac.lighttpd.net/xcache/">XCache</a>;
525 cannot use these for object caching.</li>' );
526 }
527
528 $conf->diff3 = false;
529 $diff3locations = array_merge(
530 array(
531 "/usr/bin",
532 "/usr/local/bin",
533 "/opt/csw/bin",
534 "/usr/gnu/bin",
535 "/usr/sfw/bin" ),
536 explode( PATH_SEPARATOR, getenv( "PATH" ) ) );
537 $diff3names = array( "gdiff3", "diff3", "diff3.exe" );
538
539 $diff3versioninfo = array( '$1 --version 2>&1', 'diff3 (GNU diffutils)' );
540 foreach ($diff3locations as $loc) {
541 $exe = locate_executable($loc, $diff3names, $diff3versioninfo);
542 if ($exe !== false) {
543 $conf->diff3 = $exe;
544 break;
545 }
546 }
547
548 if ($conf->diff3)
549 print "<li>Found GNU diff3: <tt>$conf->diff3</tt>.</li>";
550 else
551 print "<li>GNU diff3 not found.</li>";
552
553 $conf->ImageMagick = false;
554 $imcheck = array( "/usr/bin", "/opt/csw/bin", "/usr/local/bin", "/sw/bin", "/opt/local/bin" );
555 foreach( $imcheck as $dir ) {
556 $im = "$dir/convert";
557 if( @file_exists( $im ) ) {
558 print "<li>Found ImageMagick: <tt>$im</tt>; image thumbnailing will be enabled if you enable uploads.</li>\n";
559 $conf->ImageMagick = $im;
560 break;
561 }
562 }
563
564 $conf->HaveGD = function_exists( "imagejpeg" );
565 if( $conf->HaveGD ) {
566 print "<li>Found GD graphics library built-in";
567 if( !$conf->ImageMagick ) {
568 print ", image thumbnailing will be enabled if you enable uploads";
569 }
570 print ".</li>\n";
571 } else {
572 if( !$conf->ImageMagick ) {
573 print "<li>Couldn't find GD library or ImageMagick; image thumbnailing disabled.</li>\n";
574 }
575 }
576
577 $conf->IP = dirname( dirname( __FILE__ ) );
578 print "<li>Installation directory: <tt>" . htmlspecialchars( $conf->IP ) . "</tt></li>\n";
579
580
581 // PHP_SELF isn't available sometimes, such as when PHP is CGI but
582 // cgi.fix_pathinfo is disabled. In that case, fall back to SCRIPT_NAME
583 // to get the path to the current script... hopefully it's reliable. SIGH
584 $path = ($_SERVER["PHP_SELF"] === '')
585 ? $_SERVER["SCRIPT_NAME"]
586 : $_SERVER["PHP_SELF"];
587
588 $conf->ScriptPath = preg_replace( '{^(.*)/config.*$}', '$1', $path );
589 print "<li>Script URI path: <tt>" . htmlspecialchars( $conf->ScriptPath ) . "</tt></li>\n";
590
591
592
593 // We may be installing from *.php5 extension file, if so, print message
594 $conf->ScriptExtension = '.php';
595 if (defined('MW_INSTALL_PHP5_EXT')) {
596 $conf->ScriptExtension = '.php5';
597 print "<li>Installing MediaWiki with <tt>php5</tt> file extensions</li>\n";
598 } else {
599 print "<li>Installing MediaWiki with <tt>php</tt> file extensions</li>\n";
600 }
601
602
603 print "<li style='font-weight:bold;color:green;font-size:110%'>Environment checked. You can install MediaWiki.</li>\n";
604 $conf->posted = ($_SERVER["REQUEST_METHOD"] == "POST");
605
606 $conf->Sitename = ucfirst( importPost( "Sitename", "" ) );
607 $defaultEmail = empty( $_SERVER["SERVER_ADMIN"] )
608 ? 'root@localhost'
609 : $_SERVER["SERVER_ADMIN"];
610 $conf->EmergencyContact = importPost( "EmergencyContact", $defaultEmail );
611 $conf->DBtype = importPost( "DBtype", $DefaultDBtype );
612 if ( !isset( $ourdb[$conf->DBtype] ) ) {
613 $conf->DBtype = $DefaultDBtype;
614 }
615
616 $conf->DBserver = importPost( "DBserver", "localhost" );
617 $conf->DBname = importPost( "DBname", "wikidb" );
618 $conf->DBuser = importPost( "DBuser", "wikiuser" );
619 $conf->DBpassword = importPost( "DBpassword" );
620 $conf->DBpassword2 = importPost( "DBpassword2" );
621 $conf->SysopName = importPost( "SysopName", "WikiSysop" );
622 $conf->SysopPass = importPost( "SysopPass" );
623 $conf->SysopPass2 = importPost( "SysopPass2" );
624 $conf->RootUser = importPost( "RootUser" );
625 $conf->RootPW = importPost( "RootPW", "" );
626 $useRoot = importCheck( 'useroot', false );
627 $conf->LanguageCode = importPost( "LanguageCode", "en" );
628 ## MySQL specific:
629 $conf->DBprefix = importPost( "DBprefix" );
630 $conf->setSchema(
631 importPost( "DBschema", "mysql5-binary" ),
632 importPost( "DBengine", "InnoDB" ) );
633
634 ## Postgres specific:
635 $conf->DBport = importPost( "DBport", "5432" );
636 $conf->DBts2schema = importPost( "DBts2schema", "public" );
637 $conf->DBpgschema = importPost( "DBpgschema", "mediawiki" );
638
639 ## SQLite specific
640 $conf->SQLiteDataDir = importPost( "SQLiteDataDir", "$IP/../data" );
641
642 ## MSSQL specific
643 // We need a second field so it doesn't overwrite the MySQL one
644 $conf->DBprefix2 = importPost( "DBprefix2" );
645
646 ## DB2 specific:
647 // New variable in order to have a different default port number
648 $conf->DBport_db2 = importPost( "DBport_db2", "50000" );
649 $conf->DBcataloged = importPost( "DBcataloged", "cataloged" );
650 $conf->DBdb2schema = importPost( "DBdb2schema", "mediawiki" );
651
652 // Oracle specific
653 $conf->DBprefix_ora = importPost( "DBprefix_ora" );
654 $conf->DBdefTS_ora = importPost( "DBdefTS_ora", "USERS" );
655 $conf->DBtempTS_ora = importPost( "DBtempTS_ora", "TEMP" );
656
657 $conf->ShellLocale = getShellLocale( $conf->LanguageCode );
658
659 /* Check for validity */
660 $errs = array();
661
662 if( preg_match( '/^$|^mediawiki$|#/i', $conf->Sitename ) ) {
663 $errs["Sitename"] = "Must not be blank or \"MediaWiki\" and may not contain \"#\"";
664 }
665 if( !$ourdb[$conf->DBtype]['serverless'] ) {
666 if( $conf->DBuser == "" ) {
667 $errs["DBuser"] = "Must not be blank";
668 }
669 if( ($conf->DBtype == 'mysql') && (strlen($conf->DBuser) > 16) ) {
670 $errs["DBuser"] = "Username too long";
671 }
672 if( $conf->DBpassword == "" && $conf->DBtype != "postgres" ) {
673 $errs["DBpassword"] = "Must not be blank";
674 }
675 if( $conf->DBpassword != $conf->DBpassword2 ) {
676 $errs["DBpassword2"] = "Passwords don't match!";
677 }
678 }
679 if( !preg_match( '/^[A-Za-z_0-9]*$/', $conf->DBprefix ) ) {
680 $errs["DBprefix"] = "Invalid table prefix";
681 } else {
682 untaint( $conf->DBprefix, TC_MYSQL );
683 }
684 if( !preg_match( '/^[A-Za-z_0-9]*$/', $conf->DBprefix_ora ) ) {
685 $errs["DBprefix_ora"] = "Invalid table prefix";
686 }
687
688 error_reporting( E_ALL | E_STRICT );
689
690 /**
691 * Initialise $wgLang and $wgContLang to something so we can
692 * call case-folding methods. Per Brion, this is English for
693 * now, although we could be clever and initialise to the
694 * user-selected language.
695 */
696 $wgContLang = Language::factory( 'en' );
697 $wgLang = $wgContLang;
698
699 /**
700 * We're messing about with users, so we need a stub
701 * authentication plugin...
702 */
703 $wgAuth = new AuthPlugin();
704
705 /**
706 * Validate the initial administrator account; username,
707 * password checks, etc.
708 */
709 if( $conf->SysopName ) {
710 # Check that the user can be created
711 $u = User::newFromName( $conf->SysopName );
712 if( $u instanceof User ) {
713 # Various password checks
714 if( $conf->SysopPass != '' ) {
715 if( $conf->SysopPass == $conf->SysopPass2 ) {
716 if( !$u->isValidPassword( $conf->SysopPass ) ) {
717 $errs['SysopPass'] = "Bad password";
718 }
719 } else {
720 $errs['SysopPass2'] = "Passwords don't match";
721 }
722 } else {
723 $errs['SysopPass'] = "Cannot be blank";
724 }
725 unset( $u );
726 } else {
727 $errs['SysopName'] = "Bad username";
728 }
729 }
730
731 $conf->License = importRequest( "License", "none" );
732 if( $conf->License == "gfdl1_2" ) {
733 $conf->RightsUrl = "http://www.gnu.org/licenses/old-licenses/fdl-1.2.txt";
734 $conf->RightsText = "GNU Free Documentation License 1.2";
735 $conf->RightsCode = "gfdl1_2";
736 $conf->RightsIcon = '${wgScriptPath}/skins/common/images/gnu-fdl.png';
737 } elseif( $conf->License == "gfdl1_3" ) {
738 $conf->RightsUrl = "http://www.gnu.org/copyleft/fdl.html";
739 $conf->RightsText = "GNU Free Documentation License 1.3";
740 $conf->RightsCode = "gfdl1_3";
741 $conf->RightsIcon = '${wgScriptPath}/skins/common/images/gnu-fdl.png';
742 } elseif( $conf->License == "none" ) {
743 $conf->RightsUrl = $conf->RightsText = $conf->RightsCode = $conf->RightsIcon = "";
744 } elseif( $conf->License == "pd" ) {
745 $conf->RightsUrl = "http://creativecommons.org/licenses/publicdomain/";
746 $conf->RightsText = "Public Domain";
747 $conf->RightsCode = "pd";
748 $conf->RightsIcon = '${wgScriptPath}/skins/common/images/public-domain.png';
749 } else {
750 $conf->RightsUrl = importRequest( "RightsUrl", "" );
751 $conf->RightsText = importRequest( "RightsText", "" );
752 $conf->RightsCode = importRequest( "RightsCode", "" );
753 $conf->RightsIcon = importRequest( "RightsIcon", "" );
754 }
755
756 $conf->Shm = importRequest( "Shm", "none" );
757 $conf->MCServers = importRequest( "MCServers" );
758
759 /* Test memcached servers */
760
761 if ( $conf->Shm == 'memcached' && $conf->MCServers ) {
762 $conf->MCServerArray = wfArrayMap( 'trim', explode( ',', $conf->MCServers ) );
763 foreach ( $conf->MCServerArray as $server ) {
764 $error = testMemcachedServer( $server );
765 if ( $error ) {
766 $errs["MCServers"] = $error;
767 break;
768 }
769 }
770 } else if ( $conf->Shm == 'memcached' ) {
771 $errs["MCServers"] = "Please specify at least one server if you wish to use memcached";
772 }
773
774 /* default values for installation */
775 $conf->Email = importRequest("Email", "email_enabled");
776 $conf->Emailuser = importRequest("Emailuser", "emailuser_enabled");
777 $conf->Enotif = importRequest("Enotif", "enotif_allpages");
778 $conf->Eauthent = importRequest("Eauthent", "eauthent_enabled");
779
780 if( $conf->posted && ( 0 == count( $errs ) ) ) {
781 do { /* So we can 'continue' to end prematurely */
782 $conf->Root = ($conf->RootPW != "");
783
784 /* Load up the settings and get installin' */
785 $local = writeLocalSettings( $conf );
786 echo "<li style=\"list-style: none\">\n";
787 echo "<p><b>Generating configuration file...</b></p>\n";
788 echo "</li>\n";
789
790 $wgCommandLineMode = false;
791 chdir( ".." );
792 $ok = eval( $local );
793 if( $ok === false ) {
794 dieout( "<p>Errors in generated configuration; " .
795 "most likely due to a bug in the installer... " .
796 "Config file was: </p>" .
797 "<pre>" .
798 htmlspecialchars( $local ) .
799 "</pre>" );
800 }
801 $conf->DBtypename = '';
802 foreach (array_keys($ourdb) as $db) {
803 if ($conf->DBtype === $db)
804 $conf->DBtypename = $ourdb[$db]['fullname'];
805 }
806 if ( ! strlen($conf->DBtype)) {
807 $errs["DBpicktype"] = "Please choose a database type";
808 continue;
809 }
810
811 if (! $conf->DBtypename) {
812 $errs["DBtype"] = "Unknown database type '$conf->DBtype'";
813 continue;
814 }
815 print "<li>Database type: " . htmlspecialchars( $conf->DBtypename ) . "</li>\n";
816 $dbclass = 'Database'.ucfirst($conf->DBtype);
817 $wgDBtype = $conf->DBtype;
818 $wgDBadminuser = "root";
819 $wgDBadminpassword = $conf->RootPW;
820
821 ## Mysql specific:
822 $wgDBprefix = $conf->DBprefix;
823
824 ## Postgres specific:
825 $wgDBport = $conf->DBport;
826 $wgDBts2schema = $conf->DBts2schema;
827
828 if( $wgDBtype == 'postgres' ) {
829 $wgDBmwschema = $conf->DBpgschema;
830 } elseif ( $wgDBtype == 'ibm_db2' ) {
831 $wgDBmwschema = $conf->DBdb2schema;
832 }
833
834 if( $conf->DBprefix2 != '' ) {
835 // For MSSQL
836 $wgDBprefix = $conf->DBprefix2;
837 } elseif( $conf->DBprefix_ora != '' ) {
838 // For Oracle
839 $wgDBprefix = $conf->DBprefix_ora;
840 }
841
842 ## DB2 specific:
843 $wgDBcataloged = $conf->DBcataloged;
844
845 $wgCommandLineMode = true;
846 if (! defined ( 'STDERR' ) )
847 define( 'STDERR', fopen("php://stderr", "wb"));
848 $wgUseDatabaseMessages = false; /* FIXME: For database failure */
849 require_once( "$IP/includes/Setup.php" );
850 Language::getLocalisationCache()->disableBackend();
851
852 chdir( "config" );
853
854 $wgTitle = Title::newFromText( "Installation script" );
855 error_reporting( E_ALL | E_STRICT );
856 print "<li>Loading class: " . htmlspecialchars( $dbclass ) . "</li>\n";
857 if ( $conf->DBtype != 'sqlite' ) {
858 $dbc = new $dbclass;
859 }
860
861 if( $conf->DBtype == 'mysql' ) {
862 $mysqlOldClient = version_compare( mysql_get_client_info(), "4.1.0", "lt" );
863 if( $mysqlOldClient ) {
864 print "<li><b>PHP is linked with old MySQL client libraries. If you are
865 using a MySQL 4.1 server and have problems connecting to the database,
866 see <a href='http://dev.mysql.com/doc/mysql/en/old-client.html'
867 >http://dev.mysql.com/doc/mysql/en/old-client.html</a> for help.</b></li>\n";
868 }
869 $ok = true; # Let's be optimistic
870
871 # Decide if we're going to use the superuser or the regular database user
872 $conf->Root = $useRoot;
873 if( $conf->Root ) {
874 $db_user = $conf->RootUser;
875 $db_pass = $conf->RootPW;
876 } else {
877 $db_user = $wgDBuser;
878 $db_pass = $wgDBpassword;
879 }
880
881 # Attempt to connect
882 echo( "<li>Attempting to connect to database server as " . htmlspecialchars( $db_user ) . "..." );
883 $wgDatabase = Database::newFromParams( $wgDBserver, $db_user, $db_pass, '', 1 );
884
885 # Check the connection and respond to errors
886 if( $wgDatabase->isOpen() ) {
887 # Seems OK
888 $ok = true;
889 $wgDBadminuser = $db_user;
890 $wgDBadminpassword = $db_pass;
891 echo( "success.</li>\n" );
892 $wgDatabase->ignoreErrors( true );
893 $myver = $wgDatabase->getServerVersion();
894 } else {
895 # There were errors, report them and back out
896 $ok = false;
897 $errno = mysql_errno();
898 $errtx = htmlspecialchars( mysql_error() );
899 switch( $errno ) {
900 case 1045:
901 case 2000:
902 echo( "failed due to authentication errors. Check passwords.</li>" );
903 if( $conf->Root ) {
904 # The superuser details are wrong
905 $errs["RootUser"] = "Check username";
906 $errs["RootPW"] = "and password";
907 } else {
908 # The regular user details are wrong
909 $errs["DBuser"] = "Check username";
910 $errs["DBpassword"] = "and password";
911 }
912 break;
913 case 2002:
914 case 2003:
915 default:
916 # General connection problem
917 echo( htmlspecialchars( "failed with error [$errno] $errtx." ) . "</li>\n" );
918 $errs["DBserver"] = "Connection failed";
919 break;
920 } # switch
921 } #conn. att.
922
923 if( !$ok ) { continue; }
924 }
925 else if( $conf->DBtype == 'ibm_db2' ) {
926 if( $useRoot ) {
927 $db_user = $conf->RootUser;
928 $db_pass = $conf->RootPW;
929 } else {
930 $db_user = $wgDBuser;
931 $db_pass = $wgDBpassword;
932 }
933
934 echo( "<li>Attempting to connect to database \"" . htmlspecialchars( $wgDBname ) .
935 "\" as \"" . htmlspecialchars( $db_user ) . "\"..." );
936 $wgDatabase = $dbc->newFromParams($wgDBserver, $db_user, $db_pass, $wgDBname, 1);
937 // enable extra debug messages
938 $dbc->setMode(DatabaseIbm_db2::INSTALL_MODE);
939 $wgDatabase->setMode(DatabaseIbm_db2::INSTALL_MODE);
940
941 if (!$wgDatabase->isOpen()) {
942 print " error: " . htmlspecialchars( $wgDatabase->lastError() ) . "</li>\n";
943 } else {
944 $myver = $wgDatabase->getServerVersion();
945 }
946 if (is_callable(array($wgDatabase, 'initial_setup'))) $wgDatabase->initial_setup('', $wgDBname);
947
948 } elseif ( $conf->DBtype == 'sqlite' ) {
949 $wgSQLiteDataDir = $conf->SQLiteDataDir;
950 echo '<li>Attempting to connect to SQLite database at "' .
951 htmlspecialchars( $wgSQLiteDataDir ) . '": ';
952 if ( !is_dir( $wgSQLiteDataDir ) ) {
953 if ( is_writable( dirname( $wgSQLiteDataDir ) ) ) {
954 $ok = wfMkdirParents( $wgSQLiteDataDir, $wgSQLiteDataDirMode );
955 } else {
956 $ok = false;
957 }
958 if ( !$ok ) {
959 echo "cannot create data directory</li>";
960 $errs['SQLiteDataDir'] = 'Enter a valid data directory';
961 continue;
962 }
963 }
964 if ( !is_writable( $wgSQLiteDataDir ) ) {
965 echo "data directory not writable</li>";
966 $errs['SQLiteDataDir'] = 'Enter a writable data directory';
967 continue;
968 }
969 $dataFile = DatabaseSqlite::generateFileName( $wgSQLiteDataDir, $wgDBname );
970 if ( file_exists( $dataFile ) ) {
971 if ( !is_writable( $dataFile ) ) {
972 echo "data file not writable</li>";
973 $errs['SQLiteDataDir'] = basename( $dataFile ) . " is not writable";
974 continue;
975 }
976 } else {
977 if ( file_put_contents( $dataFile, '' ) === false ) {
978 echo 'could not create database file "' . htmlspecialchars( basename( $dataFile ) ) . "\"</li>\n";
979 $errs['SQLiteDataDir'] = "couldn't create " . basename( $dataFile );
980 continue;
981 }
982 }
983 try {
984 $wgDatabase = new DatabaseSqlite( false, false, false, $wgDBname, 1 );
985 }
986 catch( MWException $ex ) {
987 echo 'error: ' . htmlspecialchars( $ex->getMessage() ) . "</li>\n";
988 continue;
989 }
990
991 if (!$wgDatabase->isOpen()) {
992 print "error: " . htmlspecialchars( $wgDatabase->lastError() ) . "</li>\n";
993 $errs['SQLiteDataDir'] = 'Could not connect to database';
994 continue;
995 } else {
996 $myver = $wgDatabase->getServerVersion();
997 }
998 if ( is_callable( array( $wgDatabase, 'initial_setup' ) ) ) {
999 $wgDatabase->initial_setup('', $wgDBname);
1000 }
1001 echo "ok</li>\n";
1002 } elseif ( $conf->DBtype == 'oracle' ) {
1003 echo "<li>Attempting to connect to database \"" . htmlspecialchars( $wgDBname ) ."\"</li>";
1004 $old_error_level = error_reporting();
1005 wfSuppressWarnings();
1006 $wgDatabase = $dbc->newFromParams('DUMMY', $wgDBuser, $wgDBpassword, $wgDBname, 1);
1007 wfRestoreWarnings();
1008 if (!$wgDatabase->isOpen()) {
1009 $ok = true;
1010 echo "<li>Connect failed.</li>";
1011 if ($useRoot) {
1012 if (ini_get('oci8.privileged_connect') === false) {
1013 echo "<li>Privileged connect disabled, please set oci8.privileged_connect or run maintenance/ora/user.sql script manually prior to continuing.</li>";
1014 $ok = false;
1015 } else {
1016 $wgDBadminuser = $conf->RootUser;
1017 $wgDBadminpassword = $conf->RootPW;
1018 echo "<li>Attempting to create DB user.</li>";
1019 $wgDatabase = $dbc->newFromParams('DUMMY', $wgDBadminuser, $wgDBadminpassword, $wgDBname, 1, 64);
1020 if ($wgDatabase->isOpen()) {
1021 $wgDBOracleDefTS = $conf->DBdefTS_ora;
1022 $wgDBOracleTempTS = $conf->DBtempTS_ora;
1023 $wgDatabase->sourceFile( "../maintenance/ora/user.sql" );
1024 } else {
1025 echo "<li>Invalid database superuser, please supply a valid superuser account.</li>";
1026 echo "<li>ERR: ".print_r(oci_error(), true)."</li>";
1027 $ok = false;
1028 }
1029 }
1030 } else {
1031 echo "<li>Database superuser missing, please supply a valid superuser account.</li>";
1032 $ok = false;
1033 }
1034 if (!$ok) {
1035 $errs["RootUser"] = "Check username";
1036 $errs["RootPW"] = "and password";
1037 } else {
1038 echo "<li>Attempting to connect to database with new user \"" . htmlspecialchars( $wgDBname ) ."\"</li>";
1039 $wgDatabase = $dbc->newFromParams('DUMMY', $wgDBuser, $wgDBpassword, $wgDBname, 1);
1040 }
1041 }
1042 if ($ok) {
1043 $myver = $wgDatabase->getServerVersion();
1044 }
1045 } else { # not mysql
1046 error_reporting( E_ALL | E_STRICT );
1047 $wgSuperUser = '';
1048 ## Possible connect as a superuser
1049 // Changed !mysql to postgres check since it seems to only apply to postgres
1050 if( $useRoot && $conf->DBtype == 'postgres' ) {
1051 $wgDBsuperuser = $conf->RootUser;
1052 echo( "<li>Attempting to connect to database \"postgres\" as superuser \"" .
1053 htmlspecialchars( $wgDBsuperuser ) . "\"..." );
1054 $wgDatabase = $dbc->newFromParams($wgDBserver, $wgDBsuperuser, $conf->RootPW, "postgres", 1);
1055 if (!$wgDatabase->isOpen()) {
1056 print " error: " . htmlspecialchars( $wgDatabase->lastError() ) . "</li>\n";
1057 $errs["DBserver"] = "Could not connect to database as superuser";
1058 $errs["RootUser"] = "Check username";
1059 $errs["RootPW"] = "and password";
1060 continue;
1061 }
1062 $wgDatabase->initial_setup($conf->RootPW, 'postgres');
1063 }
1064 echo( "<li>Attempting to connect to database \"" . htmlspecialchars( $wgDBname ) .
1065 "\" as \"" . htmlspecialchars( $wgDBuser ) . "\"..." );
1066 $wgDatabase = $dbc->newFromParams($wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, 1);
1067 if (!$wgDatabase->isOpen()) {
1068 print " error: " . htmlspecialchars( $wgDatabase->lastError() ) . "</li>\n";
1069 $errs["DBserver"] = "Could not connect to database as user";
1070 $errs["DBuser"] = "Check username";
1071 $errs["DBpassword"] = "and password";
1072 continue;
1073 } else {
1074 $myver = $wgDatabase->getServerVersion();
1075 }
1076 if (is_callable(array($wgDatabase, 'initial_setup'))) $wgDatabase->initial_setup('', $wgDBname);
1077 }
1078
1079 if ( !$wgDatabase->isOpen() ) {
1080 $errs["DBserver"] = "Couldn't connect to database";
1081 continue;
1082 }
1083
1084 print "<li>Connected to " . htmlspecialchars( "{$conf->DBtype} $myver" );
1085 if ($conf->DBtype == 'mysql') {
1086 if( version_compare( $myver, "4.0.14" ) < 0 ) {
1087 print "</li>\n";
1088 dieout( "-- mysql 4.0.14 or later required. Aborting." );
1089 }
1090 $mysqlNewAuth = version_compare( $myver, "4.1.0", "ge" );
1091 if( $mysqlNewAuth && $mysqlOldClient ) {
1092 print "; <b class='error'>You are using MySQL 4.1 server, but PHP is linked
1093 to old client libraries; if you have trouble with authentication, see
1094 <a href='http://dev.mysql.com/doc/mysql/en/old-client.html'
1095 >http://dev.mysql.com/doc/mysql/en/old-client.html</a> for help.</b>";
1096 }
1097 if( $wgDBmysql5 ) {
1098 if( $mysqlNewAuth ) {
1099 print "; enabling MySQL 4.1/5.0 charset mode";
1100 } else {
1101 print "; <b class='error'>MySQL 4.1/5.0 charset mode enabled,
1102 but older version detected; will likely fail.</b>";
1103 }
1104 }
1105 print "</li>\n";
1106
1107 @$sel = $wgDatabase->selectDB( $wgDBname );
1108 if( $sel ) {
1109 print "<li>Database <tt>" . htmlspecialchars( $wgDBname ) . "</tt> exists</li>\n";
1110 } else {
1111 $err = mysql_errno();
1112 $databaseSafe = htmlspecialchars( $wgDBname );
1113 if( $err == 1102 /* Invalid database name */ ) {
1114 print "<ul><li><strong>{$databaseSafe}</strong> is not a valid database name.</li></ul>";
1115 continue;
1116 } elseif( $err != 1049 /* Database doesn't exist */ ) {
1117 print "<ul><li>Error selecting database <strong>{$databaseSafe}</strong>: {$err} ";
1118 print htmlspecialchars( mysql_error() ) . "</li></ul>";
1119 continue;
1120 }
1121 print "<li>Attempting to create database...</li>";
1122 $res = $wgDatabase->query( "CREATE DATABASE `$wgDBname`" );
1123 if( !$res ) {
1124 print "<li>Couldn't create database <tt>" .
1125 htmlspecialchars( $wgDBname ) .
1126 "</tt>; try with root access or check your username/pass.</li>\n";
1127 $errs["RootPW"] = "<- Enter";
1128 continue;
1129 }
1130 print "<li>Created database <tt>" . htmlspecialchars( $wgDBname ) . "</tt></li>\n";
1131 }
1132 $wgDatabase->selectDB( $wgDBname );
1133 }
1134 else if ($conf->DBtype == 'postgres') {
1135 if( version_compare( $myver, "8.0" ) < 0 ) {
1136 dieout( "<b>Postgres 8.0 or later is required</b>. Aborting." );
1137 }
1138 }
1139
1140 if( $wgDatabase->tableExists( "cur" ) || $wgDatabase->tableExists( "revision" ) ) {
1141 print "<li>There are already MediaWiki tables in this database. Checking if updates are needed...</li>\n";
1142
1143 if ( $conf->DBtype == 'mysql') {
1144 # Determine existing default character set
1145 if ( $wgDatabase->tableExists( "revision" ) ) {
1146 $revision = $wgDatabase->escapeLike( $conf->DBprefix . 'revision' );
1147 $res = $wgDatabase->query( "SHOW TABLE STATUS LIKE '$revision'" );
1148 $row = $wgDatabase->fetchObject( $res );
1149 if ( !$row ) {
1150 echo "<li>SHOW TABLE STATUS query failed!</li>\n";
1151 $existingSchema = false;
1152 $existingEngine = false;
1153 } else {
1154 if ( preg_match( '/^latin1/', $row->Collation ) ) {
1155 $existingSchema = 'mysql4';
1156 } elseif ( preg_match( '/^utf8/', $row->Collation ) ) {
1157 $existingSchema = 'mysql5';
1158 } elseif ( preg_match( '/^binary/', $row->Collation ) ) {
1159 $existingSchema = 'mysql5-binary';
1160 } else {
1161 $existingSchema = false;
1162 echo "<li><strong>Warning:</strong> Unrecognised existing collation</li>\n";
1163 }
1164 if ( isset( $row->Engine ) ) {
1165 $existingEngine = $row->Engine;
1166 } else {
1167 $existingEngine = $row->Type;
1168 }
1169 }
1170 if ( $existingSchema && $existingSchema != $conf->DBschema ) {
1171 $encExisting = htmlspecialchars( $existingSchema );
1172 $encRequested = htmlspecialchars( $conf->DBschema );
1173 print "<li><strong>Warning:</strong> you requested the $encRequested schema, " .
1174 "but the existing database has the $encExisting schema. This upgrade script ".
1175 "can't convert it, so it will remain $encExisting.</li>\n";
1176 $conf->setSchema( $existingSchema, $conf->DBengine );
1177 }
1178 if ( $existingEngine && $existingEngine != $conf->DBengine ) {
1179 $encExisting = htmlspecialchars( $existingEngine );
1180 $encRequested = htmlspecialchars( $conf->DBengine );
1181 print "<li><strong>Warning:</strong> you requested the $encRequested storage " .
1182 "engine, but the existing database uses the $encExisting engine. This upgrade " .
1183 "script can't convert it, so it will remain $encExisting.</li>\n";
1184 $conf->setSchema( $conf->DBschema, $existingEngine );
1185 }
1186 }
1187
1188 # Create user if required
1189 if ( $conf->Root ) {
1190 $conn = $dbc->newFromParams( $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, 1 );
1191 if ( $conn->isOpen() ) {
1192 print "<li>DB user account ok</li>\n";
1193 $conn->close();
1194 } else {
1195 print "<li>Granting user permissions...";
1196 if( $mysqlOldClient && $mysqlNewAuth ) {
1197 print " <b class='error'>If the next step fails, see <a href='http://dev.mysql.com/doc/mysql/en/old-client.html'>http://dev.mysql.com/doc/mysql/en/old-client.html</a> for help.</b>";
1198 }
1199 print "</li>\n";
1200 $wgDatabase->sourceFile( "../maintenance/users.sql" );
1201 }
1202 }
1203 }
1204 print "</ul><pre>\n";
1205 chdir( ".." );
1206 flush();
1207 do_all_updates();
1208 chdir( "config" );
1209 print "</pre>\n";
1210 print "<ul><li>Finished update checks.</li>\n";
1211 // if tables don't yet exist
1212 } else {
1213 # Determine available storage engines if possible
1214 if ( $conf->DBtype == 'mysql' && version_compare( $myver, "4.1.2", "ge" ) ) {
1215 $res = $wgDatabase->query( 'SHOW ENGINES' );
1216 $found = false;
1217 while ( $row = $wgDatabase->fetchObject( $res ) ) {
1218 if ( $row->Engine == $conf->DBengine && ( $row->Support == 'YES' || $row->Support == 'DEFAULT' ) ) {
1219 $found = true;
1220 break;
1221 }
1222 }
1223 $wgDatabase->freeResult( $res );
1224 if ( !$found && $conf->DBengine != 'MyISAM' ) {
1225 echo "<li><strong>Warning:</strong> " . htmlspecialchars( $conf->DBengine ) .
1226 " storage engine not available, " .
1227 "using MyISAM instead</li>\n";
1228 $conf->setSchema( $conf->DBschema, 'MyISAM' );
1229 }
1230 }
1231
1232 # FIXME: Check for errors
1233 print "<li>Creating tables...";
1234 if ($conf->DBtype == 'mysql') {
1235 $wgDatabase->sourceFile( "../maintenance/tables.sql" );
1236 $wgDatabase->sourceFile( "../maintenance/interwiki.sql" );
1237 } elseif (is_callable(array($wgDatabase, 'setup_database'))) {
1238 $wgDatabase->setup_database();
1239 }
1240 else {
1241 $errs["DBtype"] = "Do not know how to handle database type '$conf->DBtype'";
1242 continue;
1243 }
1244
1245 print " done.</li>\n";
1246
1247
1248 if ( $conf->DBtype == 'ibm_db2' ) {
1249 // Now that table creation is done, make sure everything is committed
1250 // Do this before doing inserts through API
1251 if ($wgDatabase->lastError()) {
1252 print "<li>Errors encountered during table creation -- rolled back</li>\n";
1253 $wgDatabase->rollback();
1254 }
1255 else {
1256 print "<li>MediaWiki tables successfully created</li>\n";
1257 $wgDatabase->commit();
1258 }
1259 } elseif ( $conf->DBtype == 'sqlite' ) {
1260 // Ensure proper searchindex format. We have to do that separately because
1261 // if SQLite is compiled without the FTS3 module, table creation syntax will be invalid.
1262 sqlite_setup_searchindex();
1263 }
1264
1265 print "<li>Initializing statistics...</li>\n";
1266 $wgDatabase->insert( 'site_stats',
1267 array ( 'ss_row_id' => 1,
1268 'ss_total_views' => 0,
1269 'ss_total_edits' => 1, # Main page first edit
1270 'ss_good_articles' => 0, # Main page is not a good article - no internal link
1271 'ss_total_pages' => 1, # Main page
1272 'ss_users' => $conf->SysopName ? 1 : 0, # Sysop account, if created
1273 'ss_admins' => $conf->SysopName ? 1 : 0, # Sysop account, if created
1274 'ss_images' => 0 ) );
1275
1276 # Set up the "regular user" account *if we can, and if we need to*
1277 if( $conf->Root and $conf->DBtype == 'mysql') {
1278 # See if we need to
1279 $wgDatabase2 = $dbc->newFromParams( $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, 1 );
1280 if( $wgDatabase2->isOpen() ) {
1281 # Nope, just close the test connection and continue
1282 $wgDatabase2->close();
1283 echo( "<li>User " . htmlspecialchars( $wgDBuser ) . " exists. Skipping grants.</li>\n" );
1284 } else {
1285 # Yes, so run the grants
1286 echo( "<li>" . htmlspecialchars( "Granting user permissions to $wgDBuser on $wgDBname..." ) );
1287 $wgDatabase->sourceFile( "../maintenance/users.sql" );
1288 echo( "success.</li>\n" );
1289 }
1290 }
1291
1292 if( $conf->SysopName ) {
1293 $u = User::newFromName( $conf->getSysopName() );
1294 if ( !$u ) {
1295 print "<li><strong class=\"error\">Warning:</strong> Skipped sysop account creation - invalid username!</li>\n";
1296 }
1297 else if ( 0 == $u->idForName() ) {
1298 $u->addToDatabase();
1299 $u->setPassword( $conf->getSysopPass() );
1300 $u->saveSettings();
1301
1302 $u->addGroup( "sysop" );
1303 $u->addGroup( "bureaucrat" );
1304
1305 print "<li>Created sysop account <tt>" .
1306 htmlspecialchars( $conf->SysopName ) . "</tt>.</li>\n";
1307 } else {
1308 print "<li>Could not create user - already exists!</li>\n";
1309 }
1310 } else {
1311 print "<li>Skipped sysop account creation, no name given.</li>\n";
1312 }
1313
1314 $titleobj = Title::newFromText( wfMsgNoDB( "mainpage" ) );
1315 $article = new Article( $titleobj );
1316 $newid = $article->insertOn( $wgDatabase );
1317 $revision = new Revision( array(
1318 'page' => $newid,
1319 'text' => wfMsg( 'mainpagetext' ) . "\n\n" . wfMsgNoTrans( 'mainpagedocfooter' ),
1320 'comment' => '',
1321 'user' => 0,
1322 'user_text' => 'MediaWiki default',
1323 ) );
1324 $revid = $revision->insertOn( $wgDatabase );
1325 $article->updateRevisionOn( $wgDatabase, $revision );
1326 }
1327
1328 /* Write out the config file now that all is well */
1329 print "<li style=\"list-style: none\">\n";
1330 print "<p>Creating LocalSettings.php...</p>\n\n";
1331 $localSettings = "<" . "?php$endl$local";
1332 // Fix up a common line-ending problem (due to CVS on Windows)
1333 $localSettings = str_replace( "\r\n", "\n", $localSettings );
1334 $f = fopen( "LocalSettings.php", 'xt' );
1335
1336 if( $f == false ) {
1337 print( "</li>\n" );
1338 dieout( "<p>Couldn't write out LocalSettings.php. Check that the directory permissions are correct and that there isn't already a file of that name here...</p>\n" .
1339 "<p>Here's the file that would have been written, try to paste it into place manually:</p>\n" .
1340 "<pre>\n" . htmlspecialchars( $localSettings ) . "</pre>\n" );
1341 }
1342 if(fwrite( $f, $localSettings ) ) {
1343 fclose( $f );
1344 print "<hr/>\n";
1345 writeSuccessMessage();
1346 print "</li>\n";
1347 } else {
1348 fclose( $f );
1349 dieout( "<p class='error'>An error occured while writing the config/LocalSettings.php file. Check user rights and disk space then try again.</p></li>\n" );
1350 }
1351
1352 } while( false );
1353 }
1354
1355 print "</ul>\n";
1356 $mainListOpened = false;
1357
1358 if( count( $errs ) ) {
1359 /* Display options form */
1360
1361 if( $conf->posted ) {
1362 echo "<p class='error-top'>Something's not quite right yet; make sure everything below is filled out correctly.</p>\n";
1363 }
1364 ?>
1365
1366 <form action="<?php echo defined('MW_INSTALL_PHP5_EXT') ? 'index.php5' : 'index.php'; ?>" name="config" method="post">
1367
1368 <h2>Site config</h2>
1369
1370 <div class="config-section">
1371 <div class="config-input">
1372 <?php aField( $conf, "Sitename", "Wiki name:" ); ?>
1373 </div>
1374 <p class="config-desc">
1375 Preferably a short word without punctuation, i.e. "Wikipedia".<br />
1376 Will appear as the namespace name for "meta" pages, and throughout the interface.
1377 </p>
1378 <div class="config-input"><?php aField( $conf, "EmergencyContact", "Contact e-mail:" ); ?></div>
1379 <p class="config-desc">
1380 Displayed to users in some error messages, used as the return address for password reminders, and used as the default sender address of e-mail notifications.
1381 </p>
1382
1383 <div class="config-input">
1384 <label class='column' for="LanguageCode">Language:</label>
1385 <select id="LanguageCode" name="LanguageCode"><?php
1386 $list = getLanguageList();
1387 foreach( $list as $code => $name ) {
1388 $sel = ($code == $conf->LanguageCode) ? 'selected="selected"' : '';
1389 $encCode = htmlspecialchars( $code );
1390 $encName = htmlspecialchars( $name );
1391 echo "\n\t\t<option value=\"$encCode\" $sel>$encName</option>";
1392 }
1393 echo "\n";
1394 ?>
1395 </select>
1396 </div>
1397 <p class="config-desc">
1398 Select the language for your wiki's interface. Some localizations aren't fully complete. Unicode (UTF-8) is used for all localizations.
1399 </p>
1400
1401 <div class="config-input">
1402 <label class='column'>Copyright/license:</label>
1403
1404 <ul class="plain">
1405 <li><?php aField( $conf, "License", "No license metadata", "radio", "none" ); ?></li>
1406 <li><?php aField( $conf, "License", "Public Domain", "radio", "pd" ); ?></li>
1407 <li><?php aField( $conf, "License", "GNU Free Documentation License 1.2", "radio", "gfdl1_2" ); ?></li>
1408 <li><?php aField( $conf, "License", "GNU Free Documentation License 1.3", "radio", "gfdl1_3" ); ?></li>
1409 <li><?php
1410 aField( $conf, "License", "A Creative Commons license - ", "radio", "cc" );
1411 $partner = "MediaWiki";
1412 $script = defined('MW_INSTALL_PHP5_EXT') ? 'index.php5' : 'index.php';
1413 $exit = urlencode( "$wgServer{$conf->ScriptPath}/config/$script?License=cc&RightsUrl=[license_url]&RightsText=[license_name]&RightsCode=[license_code]&RightsIcon=[license_button]" );
1414 $icon = urlencode( "$wgServer$wgUploadPath/wiki.png" );
1415 $ccApp = htmlspecialchars( "http://creativecommons.org/license/?partner=$partner&exit_url=$exit&partner_icon_url=$icon" );
1416 print "<a href=\"$ccApp\" target='_blank'>choose</a>";
1417 if( $conf->License == "cc" ) { ?>
1418 <ul>
1419 <li><?php aField( $conf, "RightsIcon", "<img src=\"" . htmlspecialchars( $conf->RightsIcon ) . "\" alt='(Creative Commons icon)' />", "hidden" ); ?></li>
1420 <li><?php aField( $conf, "RightsText", htmlspecialchars( $conf->RightsText ), "hidden" ); ?></li>
1421 <li><?php aField( $conf, "RightsCode", "code: " . htmlspecialchars( $conf->RightsCode ), "hidden" ); ?></li>
1422 <li><?php aField( $conf, "RightsUrl", "<a href=\"" . htmlspecialchars( $conf->RightsUrl ) . "\">" . htmlspecialchars( $conf->RightsUrl ) . "</a>", "hidden" ); ?></li>
1423 </ul>
1424 <?php } ?>
1425 </li>
1426 </ul>
1427 </div>
1428 <p class="config-desc">
1429 A notice, icon, and machine-readable copyright metadata will be displayed for the license you pick.
1430 </p>
1431
1432
1433 <div class="config-input">
1434 <?php aField( $conf, "SysopName", "Admin username:" ) ?>
1435 </div>
1436 <div class="config-input">
1437 <?php aField( $conf, "SysopPass", "Password:", "password" ) ?>
1438 </div>
1439 <div class="config-input">
1440 <?php aField( $conf, "SysopPass2", "Password confirm:", "password" ) ?>
1441 </div>
1442 <p class="config-desc">
1443 An admin can lock/delete pages, block users from editing, and do other maintenance tasks.<br />
1444 A new account will be added only when creating a new wiki database.
1445 <br /><br />
1446 The password cannot be the same as the username.
1447 </p>
1448
1449 <div class="config-input">
1450 <label class='column'>Object caching:</label>
1451
1452 <ul class="plain">
1453 <li><?php aField( $conf, "Shm", "No caching", "radio", "none" ); ?></li>
1454 <?php
1455 if( $conf->xcache ) {
1456 echo "<li>";
1457 aField( $conf, 'Shm', 'XCache', 'radio', 'xcache' );
1458 echo "</li>\n";
1459 }
1460 if ( $conf->apc ) {
1461 echo "<li>";
1462 aField( $conf, "Shm", "APC", "radio", "apc" );
1463 echo "</li>\n";
1464 }
1465 if ( $conf->eaccel ) {
1466 echo "<li>";
1467 aField( $conf, "Shm", "eAccelerator", "radio", "eaccel" );
1468 echo "</li>\n";
1469 }
1470 if ( $conf->dba ) {
1471 echo "<li>";
1472 aField( $conf, "Shm", "DBA (not recommended)", "radio", "dba" );
1473 echo "</li>";
1474 }
1475 ?>
1476 <li><?php aField( $conf, "Shm", "Memcached", "radio", "memcached" ); ?></li>
1477 </ul>
1478 <div style="clear:left"><?php aField( $conf, "MCServers", "Memcached servers:", "text" ) ?></div>
1479 </div>
1480 <p class="config-desc">
1481 An object caching system such as memcached will provide a significant performance boost,
1482 but needs to be installed. Provide the server addresses and ports in a comma-separated list.
1483 <br /><br />
1484 MediaWiki can also detect and support eAccelerator, APC, and XCache, but
1485 these should not be used if the wiki will be running on multiple application servers.
1486 <br /><br />
1487 DBA (Berkeley-style DB) is generally slower than using no cache at all, and is only
1488 recommended for testing.
1489 </p>
1490 </div>
1491
1492 <h2>E-mail, e-mail notification and authentication setup</h2>
1493
1494 <div class="config-section">
1495 <div class="config-input">
1496 <label class='column'>E-mail features (global):</label>
1497 <ul class="plain">
1498 <li><?php aField( $conf, "Email", "Enabled", "radio", "email_enabled" ); ?></li>
1499 <li><?php aField( $conf, "Email", "Disabled", "radio", "email_disabled" ); ?></li>
1500 </ul>
1501 </div>
1502 <p class="config-desc">
1503 Use this to disable all e-mail functions (password reminders, user-to-user e-mail, and e-mail notifications)
1504 if sending mail doesn't work on your server.
1505 </p>
1506
1507 <div class="config-input">
1508 <label class='column'>User-to-user e-mail:</label>
1509 <ul class="plain">
1510 <li><?php aField( $conf, "Emailuser", "Enabled", "radio", "emailuser_enabled" ); ?></li>
1511 <li><?php aField( $conf, "Emailuser", "Disabled", "radio", "emailuser_disabled" ); ?></li>
1512 </ul>
1513 </div>
1514 <p class="config-desc">
1515 The user-to-user e-mail feature (Special:Emailuser) lets the wiki act as a relay to allow users to exchange e-mail without publicly advertising their e-mail address.
1516 </p>
1517 <div class="config-input">
1518 <label class='column'>E-mail notification about changes:</label>
1519 <ul class="plain">
1520 <li><?php aField( $conf, "Enotif", "Disabled", "radio", "enotif_disabled" ); ?></li>
1521 <li><?php aField( $conf, "Enotif", "Enabled for changes to user discussion pages only", "radio", "enotif_usertalk" ); ?></li>
1522 <li><?php aField( $conf, "Enotif", "Enabled for changes to user discussion pages, and to pages on watchlists (not recommended for large wikis)", "radio", "enotif_allpages" ); ?></li>
1523 </ul>
1524 </div>
1525 <div class="config-desc">
1526 <p>
1527 For this feature to work, an e-mail address must be present for the user account, and the notification
1528 options in the user's preferences must be enabled. Also note the
1529 authentication option below. When testing the feature, keep in mind that your own changes will never trigger notifications to be sent to yourself.</p>
1530
1531 <p>There are additional options for fine tuning in /includes/DefaultSettings.php; copy these to your LocalSettings.php and edit them there to change them.</p>
1532 </div>
1533
1534 <div class="config-input">
1535 <label class='column'>E-mail address authentication:</label>
1536 <ul class="plain">
1537 <li><?php aField( $conf, "Eauthent", "Disabled", "radio", "eauthent_disabled" ); ?></li>
1538 <li><?php aField( $conf, "Eauthent", "Enabled", "radio", "eauthent_enabled" ); ?></li>
1539 </ul>
1540 </div>
1541 <div class="config-desc">
1542 <p>If this option is enabled, users have to confirm their e-mail address using a magic link sent to them whenever they set or change it, and only authenticated e-mail addresses can receive mails from other users and/or
1543 change notification mails. Setting this option is <b>recommended</b> for public wikis because of potential abuse of the e-mail features above.</p>
1544 </div>
1545
1546 </div>
1547
1548 <h2>Database config</h2>
1549
1550 <div class="config-section">
1551 <div class="config-input">
1552 <label class='column'>Database type:</label>
1553 <?php
1554 if (isset($errs['DBpicktype'])) {
1555 print "\t<span class='error'>" . htmlspecialchars( $errs['DBpicktype'] ) . "</span>\n";
1556 }
1557 ?>
1558 <ul class='plain'><?php
1559 database_picker($conf);
1560 ?></ul>
1561 </div>
1562
1563 <div id="db-server-settings1">
1564 <div class="config-input" style="clear:left">
1565 <?php aField( $conf, "DBserver", "Database host:" ); ?>
1566 </div>
1567 <p class="config-desc">
1568 If your database server isn't on your web server, enter the name or IP address here.
1569 </p>
1570 </div>
1571
1572 <div class="config-input"><?php aField( $conf, "DBname", "Database name:" ); ?></div>
1573 <div id="db-server-settings2">
1574 <div class="config-input"><?php aField( $conf, "DBuser", "DB username:" ); ?></div>
1575 <div class="config-input"><?php aField( $conf, "DBpassword", "DB password:", "password" ); ?></div>
1576 <div class="config-input"><?php aField( $conf, "DBpassword2", "DB password confirm:", "password" ); ?></div>
1577 <p class="config-desc">
1578 If you only have a single user account and database available,
1579 enter those here. If you have database root access (see below)
1580 you can specify new accounts/databases to be created. This account
1581 will not be created if it pre-exists. If this is the case, ensure that it
1582 has SELECT, INSERT, UPDATE, and DELETE permissions on the MediaWiki database.
1583 </p>
1584
1585 <div class="config-input">
1586 <label class="column">Superuser account:</label>
1587 <input type="checkbox" name="useroot" id="useroot" <?php if( $useRoot ) { ?>checked="checked" <?php } ?> />
1588 &nbsp;<label for="useroot">Use superuser account</label>
1589 </div>
1590 <div class="config-input"><?php aField( $conf, "RootUser", "Superuser name:", "text" ); ?></div>
1591 <div class="config-input"><?php aField( $conf, "RootPW", "Superuser password:", "password" ); ?></div>
1592
1593 <p class="config-desc">
1594 If the database user specified above does not exist, or does not have access to create
1595 the database (if needed) or tables within it, please check the box and provide details
1596 of a superuser account, such as <strong>root</strong>, which does.
1597 </p>
1598 </div>
1599
1600 <?php database_switcher('mysql'); ?>
1601 <div class="config-input"><?php aField( $conf, "DBprefix", "Database table prefix:" ); ?></div>
1602 <div class="config-desc">
1603 <p>If you need to share one database between multiple wikis, or
1604 between MediaWiki and another web application, you may choose to
1605 add a prefix to all the table names to avoid conflicts.</p>
1606
1607 <p>Avoid exotic characters; something like <tt>mw_</tt> is good.</p>
1608 </div>
1609
1610 <div class="config-input"><label class="column">Storage Engine</label>
1611 <div>Select one:</div>
1612 <ul class="plain">
1613 <li><?php aField( $conf, "DBengine", "InnoDB", "radio", "InnoDB" ); ?></li>
1614 <li><?php aField( $conf, "DBengine", "MyISAM", "radio", "MyISAM" ); ?></li>
1615 </ul>
1616 </div>
1617 <p class="config-desc">
1618 InnoDB is best for public web installations, since it has good concurrency
1619 support. MyISAM may be faster in single-user installations. MyISAM databases
1620 tend to get corrupted more often than InnoDB databases.
1621 </p>
1622 <div class="config-input"><label class="column">Database character set</label>
1623 <div>Select one:</div>
1624 <ul class="plain">
1625 <li><?php aField( $conf, "DBschema", "MySQL 4.1/5.0 binary", "radio", "mysql5-binary" ); ?></li>
1626 <li><?php aField( $conf, "DBschema", "MySQL 4.1/5.0 UTF-8", "radio", "mysql5" ); ?></li>
1627 <li><?php aField( $conf, "DBschema", "MySQL 4.0 backwards-compatible UTF-8", "radio", "mysql4" ); ?></li>
1628 </ul>
1629 </div>
1630 <p class="config-desc">
1631 This option is ignored on upgrade, the same character set will be kept.
1632 <br /><br />
1633 <b>WARNING:</b> If you use <b>backwards-compatible UTF-8</b> on MySQL 4.1+, and subsequently back up the database with <tt>mysqldump</tt>, it may destroy all non-ASCII characters, irreversibly corrupting your backups!.
1634 <br /><br />
1635 In <b>binary mode</b>, MediaWiki stores UTF-8 text to the database in binary fields. This is more efficient than MySQL's UTF-8 mode, and allows you to use the full range of Unicode characters. In <b>UTF-8 mode</b>, MySQL will know what character set your data is in, and can present and convert it appropriately, but it won't let you store characters above the <a target="_blank" href="http://en.wikipedia.org/wiki/Mapping_of_Unicode_character_planes">Basic Multilingual Plane</a>.
1636 </p>
1637 </fieldset>
1638
1639 <?php database_switcher('postgres'); ?>
1640 <div class="config-input"><?php aField( $conf, "DBport", "Database port:" ); ?></div>
1641 <div class="config-input"><?php aField( $conf, "DBpgschema", "Schema for mediawiki:" ); ?></div>
1642 <div class="config-input"><?php aField( $conf, "DBts2schema", "Schema for tsearch2:" ); ?></div>
1643 <div class="config-desc">
1644 <p>The username specified above (at "DB username") will have its search path set to the above schemas,
1645 so it is recommended that you create a new user. The above schemas are generally correct:
1646 only change them if you are sure you need to.</p>
1647 </div>
1648 </fieldset>
1649
1650 <?php database_switcher('sqlite'); ?>
1651 <div class="config-input"><?php
1652 aField( $conf, "SQLiteDataDir", "SQLite data directory:" );
1653 ?></div>
1654 <div class="config-desc">
1655 <p>SQLite stores table data into files in the
1656 filesystem.</p>
1657
1658 <p>This directory must exist and be writable by the web server.</p>
1659 </div>
1660 </fieldset>
1661
1662 <?php database_switcher('mssql'); ?>
1663 <div class="config-input"><?php
1664 aField( $conf, "DBprefix2", "Database table prefix:" );
1665 ?></div>
1666 <div class="config-desc">
1667 <p>If you need to share one database between multiple wikis, or
1668 between MediaWiki and another web application, you may choose to
1669 add a prefix to all the table names to avoid conflicts.</p>
1670
1671 <p>Avoid exotic characters; something like <tt>mw_</tt> is good.</p>
1672 </div>
1673 </fieldset>
1674
1675 <?php database_switcher('ibm_db2'); ?>
1676 <div class="config-input"><?php
1677 aField( $conf, "DBport_db2", "Database port:" );
1678 ?></div>
1679 <div class="config-input"><?php
1680 aField( $conf, "DBdb2schema", "Schema for mediawiki:" );
1681 ?></div>
1682 <div>Select one:</div>
1683 <ul class="plain">
1684 <li><?php aField( $conf, "DBcataloged", "Cataloged (DB2 installed locally)", "radio", "cataloged" ); ?></li>
1685 <li><?php aField( $conf, "DBcataloged", "Uncataloged (remote DB2 through ODBC)", "radio", "uncataloged" ); ?></li>
1686 </ul>
1687 <div class="config-desc">
1688 <p>If you need to share one database between multiple wikis, or
1689 between MediaWiki and another web application, you may specify
1690 a different schema to avoid conflicts.</p>
1691 </div>
1692 </fieldset>
1693
1694 <?php database_switcher('oracle'); ?>
1695 <div class="config-input"><?php aField( $conf, "DBprefix_ora", "Database table prefix:" ); ?></div>
1696 <div class="config-desc">
1697 <p>If you need to share one database between multiple wikis, or
1698 between MediaWiki and another web application, you may choose to
1699 add a prefix to all the table names to avoid conflicts.</p>
1700
1701 <p>Avoid exotic characters; something like <tt>mw_</tt> is good.</p>
1702 </div>
1703 <div class="config-input"><?php aField( $conf, "DBdefTS_ora", "Default tablespace:" ); ?></div>
1704 <div class="config-input"><?php aField( $conf, "DBtempTS_ora", "Temporary tablespace:" ); ?></div>
1705 </fieldset>
1706
1707 <div class="config-input" style="padding:2em 0 3em">
1708 <label class='column'>&nbsp;</label>
1709 <input type="submit" value="Install MediaWiki!" class="btn-install" />
1710 </div>
1711 </div>
1712 </form>
1713 <script type="text/javascript">
1714 window.onload = toggleDBarea( <?php echo Xml::encodeJsVar( $conf->DBtype ); ?>,
1715 <?php
1716 ## If they passed in a root user name, don't populate it on page load
1717 echo strlen(importPost('RootUser', '')) ? 0 : 1;
1718 ?>);
1719 </script>
1720 <?php
1721 }
1722
1723 /* -------------------------------------------------------------------------------------- */
1724 function writeSuccessMessage() {
1725 $script = defined('MW_INSTALL_PHP5_EXT') ? 'index.php5' : 'index.php';
1726 if ( wfIniGetBool( 'safe_mode' ) && !ini_get( 'open_basedir' ) ) {
1727 echo <<<HTML
1728 <div class="success-box">
1729 <p>Installation successful!</p>
1730 <p>To complete the installation, please do the following:
1731 <ol>
1732 <li>Download config/LocalSettings.php with your FTP client or file manager</li>
1733 <li>Upload it to the parent directory</li>
1734 <li>Delete config/LocalSettings.php</li>
1735 <li>Start using <a href='../$script'>your wiki</a>!
1736 </ol>
1737 <p>If you are in a shared hosting environment, do <strong>not</strong> just move LocalSettings.php
1738 remotely. LocalSettings.php is currently owned by the user your webserver is running under,
1739 which means that anyone on the same server can read your database password! Downloading
1740 it and uploading it again will hopefully change the ownership to a user ID specific to you.</p>
1741 </div>
1742 HTML;
1743 } else {
1744 echo <<<HTML
1745 <div class="success-box">
1746 <p>
1747 <span class="success-message">Installation successful!</span>
1748 Move the <tt>config/LocalSettings.php</tt> file to the parent directory, then follow
1749 <a href="../$script"> this link</a> to your wiki.</p>
1750 <p>You should change file permissions for <tt>LocalSettings.php</tt> as required to
1751 prevent other users on the server reading passwords and altering configuration data.</p>
1752 </div>
1753 HTML;
1754 }
1755 }
1756
1757
1758 function escapePhpString( $string ) {
1759 if ( is_array( $string ) || is_object( $string ) ) {
1760 return false;
1761 }
1762 return strtr( $string,
1763 array(
1764 "\n" => "\\n",
1765 "\r" => "\\r",
1766 "\t" => "\\t",
1767 "\\" => "\\\\",
1768 "\$" => "\\\$",
1769 "\"" => "\\\""
1770 ));
1771 }
1772
1773 function writeLocalSettings( $conf ) {
1774 $conf->PasswordSender = $conf->EmergencyContact;
1775 $magic = ($conf->ImageMagick ? "" : "# ");
1776 $convert = ($conf->ImageMagick ? $conf->ImageMagick : "/usr/bin/convert" );
1777 $rights = ($conf->RightsUrl) ? "" : "# ";
1778 $hashedUploads = $conf->safeMode ? '' : '# ';
1779 $sqliteDataDir = escapePhpString( realpath($conf->SQLiteDataDir) );
1780 if ( substr_compare( $conf->IP, $sqliteDataDir, 0 ) ) {
1781 $sqliteDataDir = substr_replace( $sqliteDataDir, '$IP', 0, strlen($conf->IP) );
1782 }
1783
1784 if ( $conf->ShellLocale ) {
1785 $locale = '';
1786 } else {
1787 $locale = '# ';
1788 $conf->ShellLocale = 'en_US.UTF-8';
1789 }
1790
1791 switch ( $conf->Shm ) {
1792 case 'memcached':
1793 $cacheType = 'CACHE_MEMCACHED';
1794 $mcservers = var_export( $conf->MCServerArray, true );
1795 break;
1796 case 'xcache':
1797 case 'apc':
1798 case 'eaccel':
1799 $cacheType = 'CACHE_ACCEL';
1800 $mcservers = 'array()';
1801 break;
1802 case 'dba':
1803 $cacheType = 'CACHE_DBA';
1804 $mcservers = 'array()';
1805 break;
1806 default:
1807 $cacheType = 'CACHE_NONE';
1808 $mcservers = 'array()';
1809 }
1810
1811 if ( $conf->Email == 'email_enabled' ) {
1812 $enableemail = 'true';
1813 $enableuseremail = ( $conf->Emailuser == 'emailuser_enabled' ) ? 'true' : 'false' ;
1814 $eauthent = ( $conf->Eauthent == 'eauthent_enabled' ) ? 'true' : 'false' ;
1815 switch ( $conf->Enotif ) {
1816 case 'enotif_usertalk':
1817 $enotifusertalk = 'true';
1818 $enotifwatchlist = 'false';
1819 break;
1820 case 'enotif_allpages':
1821 $enotifusertalk = 'true';
1822 $enotifwatchlist = 'true';
1823 break;
1824 default:
1825 $enotifusertalk = 'false';
1826 $enotifwatchlist = 'false';
1827 }
1828 } else {
1829 $enableuseremail = 'false';
1830 $enableemail = 'false';
1831 $eauthent = 'false';
1832 $enotifusertalk = 'false';
1833 $enotifwatchlist = 'false';
1834 }
1835
1836 $file = @fopen( "/dev/urandom", "r" );
1837 if ( $file ) {
1838 $secretKey = bin2hex( fread( $file, 32 ) );
1839 fclose( $file );
1840 } else {
1841 $secretKey = "";
1842 for ( $i=0; $i<8; $i++ ) {
1843 $secretKey .= dechex(mt_rand(0, 0x7fffffff));
1844 }
1845 print "<li>Warning: \$wgSecretKey key is insecure, generated with mt_rand(). Consider changing it manually.</li>\n";
1846 }
1847
1848 # Add slashes to strings for double quoting
1849 $slconf = wfArrayMap( "escapePhpString", get_object_vars( $conf ) );
1850 if( $conf->License == 'gfdl1_2' || $conf->License == 'pd' || $conf->License == 'gfdl1_3' ) {
1851 # Needs literal string interpolation for the current style path
1852 $slconf['RightsIcon'] = $conf->RightsIcon;
1853 }
1854
1855 if( $conf->DBtype == 'mysql' ) {
1856 $dbsettings =
1857 "# MySQL specific settings
1858 \$wgDBprefix = \"{$slconf['DBprefix']}\";
1859
1860 # MySQL table options to use during installation or update
1861 \$wgDBTableOptions = \"{$slconf['DBTableOptions']}\";
1862
1863 # Experimental charset support for MySQL 4.1/5.0.
1864 \$wgDBmysql5 = {$conf->DBmysql5};";
1865 } elseif( $conf->DBtype == 'postgres' ) {
1866 $dbsettings =
1867 "# Postgres specific settings
1868 \$wgDBport = \"{$slconf['DBport']}\";
1869 \$wgDBmwschema = \"{$slconf['DBpgschema']}\";
1870 \$wgDBts2schema = \"{$slconf['DBts2schema']}\";";
1871 } elseif( $conf->DBtype == 'sqlite' ) {
1872 $dbsettings =
1873 "# SQLite-specific settings
1874 \$wgSQLiteDataDir = \"{$sqliteDataDir}\";";
1875 } elseif( $conf->DBtype == 'mssql' ) {
1876 $dbsettings =
1877 "# MSSQL specific settings
1878 \$wgDBprefix = \"{$slconf['DBprefix2']}\";";
1879 } elseif( $conf->DBtype == 'ibm_db2' ) {
1880 $dbsettings =
1881 "# DB2 specific settings
1882 \$wgDBport_db2 = \"{$slconf['DBport_db2']}\";
1883 \$wgDBmwschema = \"{$slconf['DBdb2schema']}\";
1884 \$wgDBcataloged = \"{$slconf['DBcataloged']}\";";
1885 } elseif( $conf->DBtype == 'oracle' ) {
1886 $dbsettings =
1887 "# Oracle specific settings
1888 \$wgDBprefix = \"{$slconf['DBprefix']}\";";
1889 } else {
1890 // ummm... :D
1891 $dbsettings = '';
1892 }
1893
1894
1895 $localsettings = "
1896 # This file was automatically generated by the MediaWiki installer.
1897 # If you make manual changes, please keep track in case you need to
1898 # recreate them later.
1899 #
1900 # See includes/DefaultSettings.php for all configurable settings
1901 # and their default values, but don't forget to make changes in _this_
1902 # file, not there.
1903 #
1904 # Further documentation for configuration settings may be found at:
1905 # http://www.mediawiki.org/wiki/Manual:Configuration_settings
1906
1907 # If you customize your file layout, set \$IP to the directory that contains
1908 # the other MediaWiki files. It will be used as a base to locate files.
1909 if( defined( 'MW_INSTALL_PATH' ) ) {
1910 \$IP = MW_INSTALL_PATH;
1911 } else {
1912 \$IP = dirname( __FILE__ );
1913 }
1914
1915 \$path = array( \$IP, \"\$IP/includes\", \"\$IP/languages\" );
1916 set_include_path( implode( PATH_SEPARATOR, \$path ) . PATH_SEPARATOR . get_include_path() );
1917
1918 require_once( \"\$IP/includes/DefaultSettings.php\" );
1919
1920 if ( \$wgCommandLineMode ) {
1921 if ( isset( \$_SERVER ) && array_key_exists( 'REQUEST_METHOD', \$_SERVER ) ) {
1922 die( \"This script must be run from the command line\\n\" );
1923 }
1924 }
1925 ## Uncomment this to disable output compression
1926 # \$wgDisableOutputCompression = true;
1927
1928 \$wgSitename = \"{$slconf['Sitename']}\";
1929
1930 ## The URL base path to the directory containing the wiki;
1931 ## defaults for all runtime URL paths are based off of this.
1932 ## For more information on customizing the URLs please see:
1933 ## http://www.mediawiki.org/wiki/Manual:Short_URL
1934 \$wgScriptPath = \"{$slconf['ScriptPath']}\";
1935 \$wgScriptExtension = \"{$slconf['ScriptExtension']}\";
1936
1937 ## The relative URL path to the skins directory
1938 \$wgStylePath = \"\$wgScriptPath/skins\";
1939
1940 ## The relative URL path to the logo. Make sure you change this from the default,
1941 ## or else you'll overwrite your logo when you upgrade!
1942 \$wgLogo = \"\$wgStylePath/common/images/wiki.png\";
1943
1944 ## UPO means: this is also a user preference option
1945
1946 \$wgEnableEmail = $enableemail;
1947 \$wgEnableUserEmail = $enableuseremail; # UPO
1948
1949 \$wgEmergencyContact = \"{$slconf['EmergencyContact']}\";
1950 \$wgPasswordSender = \"{$slconf['PasswordSender']}\";
1951
1952 \$wgEnotifUserTalk = $enotifusertalk; # UPO
1953 \$wgEnotifWatchlist = $enotifwatchlist; # UPO
1954 \$wgEmailAuthentication = $eauthent;
1955
1956 ## Database settings
1957 \$wgDBtype = \"{$slconf['DBtype']}\";
1958 \$wgDBserver = \"{$slconf['DBserver']}\";
1959 \$wgDBname = \"{$slconf['DBname']}\";
1960 \$wgDBuser = \"{$slconf['DBuser']}\";
1961 \$wgDBpassword = \"{$slconf['DBpassword']}\";
1962
1963 {$dbsettings}
1964
1965 ## Shared memory settings
1966 \$wgMainCacheType = $cacheType;
1967 \$wgMemCachedServers = $mcservers;
1968
1969 ## To enable image uploads, make sure the 'images' directory
1970 ## is writable, then set this to true:
1971 \$wgEnableUploads = false;
1972 {$magic}\$wgUseImageMagick = true;
1973 {$magic}\$wgImageMagickConvertCommand = \"{$convert}\";
1974
1975 ## If you use ImageMagick (or any other shell command) on a
1976 ## Linux server, this will need to be set to the name of an
1977 ## available UTF-8 locale
1978 {$locale}\$wgShellLocale = \"{$slconf['ShellLocale']}\";
1979
1980 ## If you want to use image uploads under safe mode,
1981 ## create the directories images/archive, images/thumb and
1982 ## images/temp, and make them all writable. Then uncomment
1983 ## this, if it's not already uncommented:
1984 {$hashedUploads}\$wgHashedUploadDirectory = false;
1985
1986 ## If you have the appropriate support software installed
1987 ## you can enable inline LaTeX equations:
1988 \$wgUseTeX = false;
1989
1990 ## Set \$wgCacheDirectory to a writable directory on the web server
1991 ## to make your wiki go slightly faster. The directory should not
1992 ## be publically accessible from the web.
1993 #\$wgCacheDirectory = \"\$IP/cache\";
1994
1995 \$wgLocalInterwiki = strtolower( \$wgSitename );
1996
1997 \$wgLanguageCode = \"{$slconf['LanguageCode']}\";
1998
1999 \$wgSecretKey = \"$secretKey\";
2000
2001 ## Default skin: you can change the default skin. Use the internal symbolic
2002 ## names, ie 'standard', 'nostalgia', 'cologneblue', 'monobook':
2003 \$wgDefaultSkin = 'monobook';
2004
2005 ## For attaching licensing metadata to pages, and displaying an
2006 ## appropriate copyright notice / icon. GNU Free Documentation
2007 ## License and Creative Commons licenses are supported so far.
2008 {$rights}\$wgEnableCreativeCommonsRdf = true;
2009 \$wgRightsPage = \"\"; # Set to the title of a wiki page that describes your license/copyright
2010 \$wgRightsUrl = \"{$slconf['RightsUrl']}\";
2011 \$wgRightsText = \"{$slconf['RightsText']}\";
2012 \$wgRightsIcon = \"{$slconf['RightsIcon']}\";
2013 # \$wgRightsCode = \"{$slconf['RightsCode']}\"; # Not yet used
2014
2015 \$wgDiff3 = \"{$slconf['diff3']}\";
2016
2017 # When you make changes to this configuration file, this will make
2018 # sure that cached pages are cleared.
2019 \$wgCacheEpoch = max( \$wgCacheEpoch, gmdate( 'YmdHis', @filemtime( __FILE__ ) ) );
2020 "; ## End of setting the $localsettings string
2021
2022 // Keep things in Unix line endings internally;
2023 // the system will write out as local text type.
2024 return str_replace( "\r\n", "\n", $localsettings );
2025 }
2026
2027 function dieout( $text ) {
2028 global $mainListOpened;
2029 if( $mainListOpened ) echo( "</ul>" );
2030 if( $text != '' && substr( $text, 0, 2 ) != '<p' && substr( $text, 0, 2 ) != '<h' ){
2031 echo "<p>$text</p>\n";
2032 } else {
2033 echo $text;
2034 }
2035 die( "\n\n</div>\n</div>\n</div>\n</div>\n</body>\n</html>" );
2036 }
2037
2038 function importVar( &$var, $name, $default = "" ) {
2039 if( isset( $var[$name] ) ) {
2040 $retval = $var[$name];
2041 if ( get_magic_quotes_gpc() ) {
2042 $retval = stripslashes( $retval );
2043 }
2044 } else {
2045 $retval = $default;
2046 }
2047 taint( $retval );
2048 return $retval;
2049 }
2050
2051 function importPost( $name, $default = "" ) {
2052 return importVar( $_POST, $name, $default );
2053 }
2054
2055 function importCheck( $name ) {
2056 return isset( $_POST[$name] );
2057 }
2058
2059 function importRequest( $name, $default = "" ) {
2060 return importVar( $_REQUEST, $name, $default );
2061 }
2062
2063 function aField( &$conf, $field, $text, $type = "text", $value = "", $onclick = '' ) {
2064 static $radioCount = 0;
2065 if( $type != "" ) {
2066 $xtype = "type=\"$type\"";
2067 } else {
2068 $xtype = "";
2069 }
2070
2071 $id = $field;
2072 $nolabel = ($type == "radio") || ($type == "hidden");
2073
2074 if ($type == 'radio')
2075 $id .= $radioCount++;
2076
2077 if( !$nolabel ) {
2078 echo "<label class='column' for=\"$id\">$text</label>";
2079 }
2080
2081 if( $type == "radio" && $value == $conf->$field ) {
2082 $checked = "checked='checked'";
2083 } else {
2084 $checked = "";
2085 }
2086 echo "<input $xtype name=\"$field\" id=\"$id\" class=\"iput-$type\" $checked ";
2087 if ($onclick) {
2088 echo " onclick='toggleDBarea(\"$value\",1)' " ;
2089 }
2090 echo "value=\"";
2091 if( $type == "radio" ) {
2092 echo htmlspecialchars( $value );
2093 } else {
2094 echo htmlspecialchars( $conf->$field );
2095 }
2096
2097
2098 echo "\" />";
2099 if( $nolabel ) {
2100 echo "<label for=\"$id\">$text</label>";
2101 }
2102
2103 global $errs;
2104 if(isset($errs[$field])) {
2105 echo "<span class='error'>" . htmlspecialchars( $errs[$field] ) . "</span>\n";
2106 }
2107 }
2108
2109 function getLanguageList() {
2110 global $wgDummyLanguageCodes;
2111
2112 $codes = array();
2113 foreach ( Language::getLanguageNames() as $code => $name ) {
2114 if( in_array( $code, $wgDummyLanguageCodes ) ) continue;
2115 $codes[$code] = $code . ' - ' . $name;
2116 }
2117 ksort( $codes );
2118 return $codes;
2119 }
2120
2121 #Check for location of an executable
2122 # @param string $loc single location to check
2123 # @param array $names filenames to check for.
2124 # @param mixed $versioninfo array of details to use when checking version, use false for no version checking
2125 function locate_executable($loc, $names, $versioninfo = false) {
2126 if (!is_array($names))
2127 $names = array($names);
2128
2129 foreach ($names as $name) {
2130 $command = "$loc".DIRECTORY_SEPARATOR."$name";
2131 if (@file_exists($command)) {
2132 if (!$versioninfo)
2133 return $command;
2134
2135 $file = str_replace('$1', $command, $versioninfo[0]);
2136 if (strstr(`$file`, $versioninfo[1]) !== false)
2137 return $command;
2138 }
2139 }
2140 return false;
2141 }
2142
2143 # Test a memcached server
2144 function testMemcachedServer( $server ) {
2145 $hostport = explode(":", $server);
2146 $errstr = false;
2147 $fp = false;
2148 if ( !function_exists( 'fsockopen' ) ) {
2149 $errstr = "Can't connect to memcached, fsockopen() not present";
2150 }
2151 if ( !$errstr && count( $hostport ) != 2 ) {
2152 $errstr = 'Please specify host and port';
2153 }
2154 if ( !$errstr ) {
2155 list( $host, $port ) = $hostport;
2156 $errno = 0;
2157 $fsockerr = '';
2158
2159 $fp = @fsockopen( $host, $port, $errno, $fsockerr, 1.0 );
2160 if ( $fp === false ) {
2161 $errstr = "Cannot connect to memcached on $host:$port : $fsockerr";
2162 }
2163 }
2164 if ( !$errstr ) {
2165 $command = "version\r\n";
2166 $bytes = fwrite( $fp, $command );
2167 if ( $bytes != strlen( $command ) ) {
2168 $errstr = "Cannot write to memcached socket on $host:$port";
2169 }
2170 }
2171 if ( !$errstr ) {
2172 $expected = "VERSION ";
2173 $response = fread( $fp, strlen( $expected ) );
2174 if ( $response != $expected ) {
2175 $errstr = "Didn't get correct memcached response from $host:$port";
2176 }
2177 }
2178 if ( $fp ) {
2179 fclose( $fp );
2180 }
2181 if ( !$errstr ) {
2182 echo "<li>Connected to memcached on " . htmlspecialchars( "$host:$port" ) ." successfully</li>";
2183 }
2184 return $errstr;
2185 }
2186
2187 function database_picker($conf) {
2188 global $ourdb;
2189 print "\n";
2190 foreach(array_keys($ourdb) as $db) {
2191 if ($ourdb[$db]['havedriver']) {
2192 print "\t<li>";
2193 aField( $conf, "DBtype", $ourdb[$db]['fullname'], 'radio', $db, 'onclick');
2194 print "</li>\n";
2195 }
2196 }
2197 print "\n\t";
2198 }
2199
2200 function database_switcher($db) {
2201 global $ourdb;
2202 $color = $ourdb[$db]['bgcolor'];
2203 $full = $ourdb[$db]['fullname'];
2204 print "<fieldset id='$db' style='clear:both'><legend>$full-specific options</legend>\n";
2205 }
2206
2207 function printListItem( $item ) {
2208 print "<li>$item</li>";
2209 }
2210
2211 # Determine a suitable value for $wgShellLocale
2212 function getShellLocale( $wikiLang ) {
2213 # Give up now if we're in safe mode or open_basedir
2214 # It's theoretically possible but tricky to work with
2215 if ( wfIniGetBool( "safe_mode" ) || ini_get( 'open_basedir' ) || !function_exists('exec') ) {
2216 return false;
2217 }
2218
2219 $os = php_uname( 's' );
2220 $supported = array( 'Linux', 'SunOS', 'HP-UX' ); # Tested these
2221 if ( !in_array( $os, $supported ) ) {
2222 return false;
2223 }
2224
2225 # Get a list of available locales
2226 $lines = $ret = false;
2227 exec( '/usr/bin/locale -a', $lines, $ret );
2228 if ( $ret ) {
2229 return false;
2230 }
2231
2232 $lines = wfArrayMap( 'trim', $lines );
2233 $candidatesByLocale = array();
2234 $candidatesByLang = array();
2235 foreach ( $lines as $line ) {
2236 if ( $line === '' ) {
2237 continue;
2238 }
2239 if ( !preg_match( '/^([a-zA-Z]+)(_[a-zA-Z]+|)\.(utf8|UTF-8)(@[a-zA-Z_]*|)$/i', $line, $m ) ) {
2240 continue;
2241 }
2242 list( $all, $lang, $territory, $charset, $modifier ) = $m;
2243 $candidatesByLocale[$m[0]] = $m;
2244 $candidatesByLang[$lang][] = $m;
2245 }
2246
2247 # Try the current value of LANG
2248 if ( isset( $candidatesByLocale[ getenv( 'LANG' ) ] ) ) {
2249 return getenv( 'LANG' );
2250 }
2251
2252 # Try the most common ones
2253 $commonLocales = array( 'en_US.UTF-8', 'en_US.utf8', 'de_DE.UTF-8', 'de_DE.utf8' );
2254 foreach ( $commonLocales as $commonLocale ) {
2255 if ( isset( $candidatesByLocale[$commonLocale] ) ) {
2256 return $commonLocale;
2257 }
2258 }
2259
2260 # Is there an available locale in the Wiki's language?
2261 if ( isset( $candidatesByLang[$wikiLang] ) ) {
2262 $m = reset( $candidatesByLang[$wikiLang] );
2263 return $m[0];
2264 }
2265
2266 # Are there any at all?
2267 if ( count( $candidatesByLocale ) ) {
2268 $m = reset( $candidatesByLocale );
2269 return $m[0];
2270 }
2271
2272 # Give up
2273 return false;
2274 }
2275
2276 function wfArrayMap( $function, $input ) {
2277 $ret = array_map( $function, $input );
2278 foreach ( $ret as $key => $value ) {
2279 $taint = istainted( $input[$key] );
2280 if ( $taint ) {
2281 taint( $ret[$key], $taint );
2282 }
2283 }
2284 return $ret;
2285 }
2286
2287 ?>
2288
2289 <div class="license">
2290 <hr/>
2291 <p>This program is free software; you can redistribute it and/or modify
2292 it under the terms of the GNU General Public License as published by
2293 the Free Software Foundation; either version 2 of the License, or
2294 (at your option) any later version.</p>
2295
2296 <p>This program is distributed in the hope that it will be useful,
2297 but WITHOUT ANY WARRANTY; without even the implied warranty of
2298 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2299 GNU General Public License for more details.</p>
2300
2301 <p>You should have received <a href="../COPYING">a copy of the GNU General Public License</a>
2302 along with this program; if not, write to the Free Software
2303 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2304 or <a href="http://www.gnu.org/copyleft/gpl.html">read it online</a></p>
2305 </div>
2306
2307 </div></div></div>
2308
2309
2310 <div id="column-one">
2311 <div class="portlet" id="p-logo">
2312 <a style="background-image: url(../skins/common/images/mediawiki.png);"
2313 href="../"
2314 title="Main Page"></a>
2315 </div>
2316 <script type="text/javascript"> if (window.isMSIE55) fixalpha(); </script>
2317 <div class='portlet'><div class='pBody'>
2318 <ul>
2319 <li><a href="../README">Readme</a></li>
2320 <li><a href="../RELEASE-NOTES">Release notes</a></li>
2321 <li><a href="../docs/">Documentation</a></li>
2322 <li><a href="http://www.mediawiki.org/wiki/Help:Contents">User's Guide</a></li>
2323 <li><a href="http://www.mediawiki.org/wiki/Manual:Contents">Administrator's Guide</a></li>
2324 <li><a href="http://www.mediawiki.org/wiki/Manual:FAQ">FAQ</a></li>
2325 </ul>
2326 <p style="font-size:90%;margin-top:1em">MediaWiki is Copyright © 2001-2009 by Magnus Manske, Brion Vibber,
2327 Lee Daniel Crocker, Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason, Niklas Laxström,
2328 Domas Mituzas, Rob Church, Yuri Astrakhan, Aryeh Gregor, Aaron Schulz and others.</p>
2329 </div></div>
2330 </div>
2331
2332 </div>
2333
2334 </body>
2335 </html>