MTT r63686: Handle realpath errors in SQLite installer
[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 $dir = realpath( $conf->SQLiteDataDir );
1780 if ( !$dir ) {
1781 $dir = $conf->SQLiteDataDir; // dumb realpath sometimes fails
1782 }
1783 $sqliteDataDir = escapePhpString( $dir );
1784
1785 if ( $conf->ShellLocale ) {
1786 $locale = '';
1787 } else {
1788 $locale = '# ';
1789 $conf->ShellLocale = 'en_US.UTF-8';
1790 }
1791
1792 switch ( $conf->Shm ) {
1793 case 'memcached':
1794 $cacheType = 'CACHE_MEMCACHED';
1795 $mcservers = var_export( $conf->MCServerArray, true );
1796 break;
1797 case 'xcache':
1798 case 'apc':
1799 case 'eaccel':
1800 $cacheType = 'CACHE_ACCEL';
1801 $mcservers = 'array()';
1802 break;
1803 case 'dba':
1804 $cacheType = 'CACHE_DBA';
1805 $mcservers = 'array()';
1806 break;
1807 default:
1808 $cacheType = 'CACHE_NONE';
1809 $mcservers = 'array()';
1810 }
1811
1812 if ( $conf->Email == 'email_enabled' ) {
1813 $enableemail = 'true';
1814 $enableuseremail = ( $conf->Emailuser == 'emailuser_enabled' ) ? 'true' : 'false' ;
1815 $eauthent = ( $conf->Eauthent == 'eauthent_enabled' ) ? 'true' : 'false' ;
1816 switch ( $conf->Enotif ) {
1817 case 'enotif_usertalk':
1818 $enotifusertalk = 'true';
1819 $enotifwatchlist = 'false';
1820 break;
1821 case 'enotif_allpages':
1822 $enotifusertalk = 'true';
1823 $enotifwatchlist = 'true';
1824 break;
1825 default:
1826 $enotifusertalk = 'false';
1827 $enotifwatchlist = 'false';
1828 }
1829 } else {
1830 $enableuseremail = 'false';
1831 $enableemail = 'false';
1832 $eauthent = 'false';
1833 $enotifusertalk = 'false';
1834 $enotifwatchlist = 'false';
1835 }
1836
1837 $file = @fopen( "/dev/urandom", "r" );
1838 if ( $file ) {
1839 $secretKey = bin2hex( fread( $file, 32 ) );
1840 fclose( $file );
1841 } else {
1842 $secretKey = "";
1843 for ( $i=0; $i<8; $i++ ) {
1844 $secretKey .= dechex(mt_rand(0, 0x7fffffff));
1845 }
1846 print "<li>Warning: \$wgSecretKey key is insecure, generated with mt_rand(). Consider changing it manually.</li>\n";
1847 }
1848
1849 # Add slashes to strings for double quoting
1850 $slconf = wfArrayMap( "escapePhpString", get_object_vars( $conf ) );
1851 if( $conf->License == 'gfdl1_2' || $conf->License == 'pd' || $conf->License == 'gfdl1_3' ) {
1852 # Needs literal string interpolation for the current style path
1853 $slconf['RightsIcon'] = $conf->RightsIcon;
1854 }
1855
1856 if( $conf->DBtype == 'mysql' ) {
1857 $dbsettings =
1858 "# MySQL specific settings
1859 \$wgDBprefix = \"{$slconf['DBprefix']}\";
1860
1861 # MySQL table options to use during installation or update
1862 \$wgDBTableOptions = \"{$slconf['DBTableOptions']}\";
1863
1864 # Experimental charset support for MySQL 4.1/5.0.
1865 \$wgDBmysql5 = {$conf->DBmysql5};";
1866 } elseif( $conf->DBtype == 'postgres' ) {
1867 $dbsettings =
1868 "# Postgres specific settings
1869 \$wgDBport = \"{$slconf['DBport']}\";
1870 \$wgDBmwschema = \"{$slconf['DBpgschema']}\";
1871 \$wgDBts2schema = \"{$slconf['DBts2schema']}\";";
1872 } elseif( $conf->DBtype == 'sqlite' ) {
1873 $dbsettings =
1874 "# SQLite-specific settings
1875 \$wgSQLiteDataDir = \"{$sqliteDataDir}\";";
1876 } elseif( $conf->DBtype == 'mssql' ) {
1877 $dbsettings =
1878 "# MSSQL specific settings
1879 \$wgDBprefix = \"{$slconf['DBprefix2']}\";";
1880 } elseif( $conf->DBtype == 'ibm_db2' ) {
1881 $dbsettings =
1882 "# DB2 specific settings
1883 \$wgDBport_db2 = \"{$slconf['DBport_db2']}\";
1884 \$wgDBmwschema = \"{$slconf['DBdb2schema']}\";
1885 \$wgDBcataloged = \"{$slconf['DBcataloged']}\";";
1886 } elseif( $conf->DBtype == 'oracle' ) {
1887 $dbsettings =
1888 "# Oracle specific settings
1889 \$wgDBprefix = \"{$slconf['DBprefix']}\";";
1890 } else {
1891 // ummm... :D
1892 $dbsettings = '';
1893 }
1894
1895
1896 $localsettings = "
1897 # This file was automatically generated by the MediaWiki installer.
1898 # If you make manual changes, please keep track in case you need to
1899 # recreate them later.
1900 #
1901 # See includes/DefaultSettings.php for all configurable settings
1902 # and their default values, but don't forget to make changes in _this_
1903 # file, not there.
1904 #
1905 # Further documentation for configuration settings may be found at:
1906 # http://www.mediawiki.org/wiki/Manual:Configuration_settings
1907
1908 # If you customize your file layout, set \$IP to the directory that contains
1909 # the other MediaWiki files. It will be used as a base to locate files.
1910 if( defined( 'MW_INSTALL_PATH' ) ) {
1911 \$IP = MW_INSTALL_PATH;
1912 } else {
1913 \$IP = dirname( __FILE__ );
1914 }
1915
1916 \$path = array( \$IP, \"\$IP/includes\", \"\$IP/languages\" );
1917 set_include_path( implode( PATH_SEPARATOR, \$path ) . PATH_SEPARATOR . get_include_path() );
1918
1919 require_once( \"\$IP/includes/DefaultSettings.php\" );
1920
1921 if ( \$wgCommandLineMode ) {
1922 if ( isset( \$_SERVER ) && array_key_exists( 'REQUEST_METHOD', \$_SERVER ) ) {
1923 die( \"This script must be run from the command line\\n\" );
1924 }
1925 }
1926 ## Uncomment this to disable output compression
1927 # \$wgDisableOutputCompression = true;
1928
1929 \$wgSitename = \"{$slconf['Sitename']}\";
1930
1931 ## The URL base path to the directory containing the wiki;
1932 ## defaults for all runtime URL paths are based off of this.
1933 ## For more information on customizing the URLs please see:
1934 ## http://www.mediawiki.org/wiki/Manual:Short_URL
1935 \$wgScriptPath = \"{$slconf['ScriptPath']}\";
1936 \$wgScriptExtension = \"{$slconf['ScriptExtension']}\";
1937
1938 ## The relative URL path to the skins directory
1939 \$wgStylePath = \"\$wgScriptPath/skins\";
1940
1941 ## The relative URL path to the logo. Make sure you change this from the default,
1942 ## or else you'll overwrite your logo when you upgrade!
1943 \$wgLogo = \"\$wgStylePath/common/images/wiki.png\";
1944
1945 ## UPO means: this is also a user preference option
1946
1947 \$wgEnableEmail = $enableemail;
1948 \$wgEnableUserEmail = $enableuseremail; # UPO
1949
1950 \$wgEmergencyContact = \"{$slconf['EmergencyContact']}\";
1951 \$wgPasswordSender = \"{$slconf['PasswordSender']}\";
1952
1953 \$wgEnotifUserTalk = $enotifusertalk; # UPO
1954 \$wgEnotifWatchlist = $enotifwatchlist; # UPO
1955 \$wgEmailAuthentication = $eauthent;
1956
1957 ## Database settings
1958 \$wgDBtype = \"{$slconf['DBtype']}\";
1959 \$wgDBserver = \"{$slconf['DBserver']}\";
1960 \$wgDBname = \"{$slconf['DBname']}\";
1961 \$wgDBuser = \"{$slconf['DBuser']}\";
1962 \$wgDBpassword = \"{$slconf['DBpassword']}\";
1963
1964 {$dbsettings}
1965
1966 ## Shared memory settings
1967 \$wgMainCacheType = $cacheType;
1968 \$wgMemCachedServers = $mcservers;
1969
1970 ## To enable image uploads, make sure the 'images' directory
1971 ## is writable, then set this to true:
1972 \$wgEnableUploads = false;
1973 {$magic}\$wgUseImageMagick = true;
1974 {$magic}\$wgImageMagickConvertCommand = \"{$convert}\";
1975
1976 ## If you use ImageMagick (or any other shell command) on a
1977 ## Linux server, this will need to be set to the name of an
1978 ## available UTF-8 locale
1979 {$locale}\$wgShellLocale = \"{$slconf['ShellLocale']}\";
1980
1981 ## If you want to use image uploads under safe mode,
1982 ## create the directories images/archive, images/thumb and
1983 ## images/temp, and make them all writable. Then uncomment
1984 ## this, if it's not already uncommented:
1985 {$hashedUploads}\$wgHashedUploadDirectory = false;
1986
1987 ## If you have the appropriate support software installed
1988 ## you can enable inline LaTeX equations:
1989 \$wgUseTeX = false;
1990
1991 ## Set \$wgCacheDirectory to a writable directory on the web server
1992 ## to make your wiki go slightly faster. The directory should not
1993 ## be publically accessible from the web.
1994 #\$wgCacheDirectory = \"\$IP/cache\";
1995
1996 \$wgLocalInterwiki = strtolower( \$wgSitename );
1997
1998 \$wgLanguageCode = \"{$slconf['LanguageCode']}\";
1999
2000 \$wgSecretKey = \"$secretKey\";
2001
2002 ## Default skin: you can change the default skin. Use the internal symbolic
2003 ## names, ie 'vector', 'monobook':
2004 \$wgDefaultSkin = 'monobook';
2005
2006 ## For attaching licensing metadata to pages, and displaying an
2007 ## appropriate copyright notice / icon. GNU Free Documentation
2008 ## License and Creative Commons licenses are supported so far.
2009 {$rights}\$wgEnableCreativeCommonsRdf = true;
2010 \$wgRightsPage = \"\"; # Set to the title of a wiki page that describes your license/copyright
2011 \$wgRightsUrl = \"{$slconf['RightsUrl']}\";
2012 \$wgRightsText = \"{$slconf['RightsText']}\";
2013 \$wgRightsIcon = \"{$slconf['RightsIcon']}\";
2014 # \$wgRightsCode = \"{$slconf['RightsCode']}\"; # Not yet used
2015
2016 \$wgDiff3 = \"{$slconf['diff3']}\";
2017
2018 # When you make changes to this configuration file, this will make
2019 # sure that cached pages are cleared.
2020 \$wgCacheEpoch = max( \$wgCacheEpoch, gmdate( 'YmdHis', @filemtime( __FILE__ ) ) );
2021 "; ## End of setting the $localsettings string
2022
2023 // Keep things in Unix line endings internally;
2024 // the system will write out as local text type.
2025 return str_replace( "\r\n", "\n", $localsettings );
2026 }
2027
2028 function dieout( $text ) {
2029 global $mainListOpened;
2030 if( $mainListOpened ) echo( "</ul>" );
2031 if( $text != '' && substr( $text, 0, 2 ) != '<p' && substr( $text, 0, 2 ) != '<h' ){
2032 echo "<p>$text</p>\n";
2033 } else {
2034 echo $text;
2035 }
2036 die( "\n\n</div>\n</div>\n</div>\n</div>\n</body>\n</html>" );
2037 }
2038
2039 function importVar( &$var, $name, $default = "" ) {
2040 if( isset( $var[$name] ) ) {
2041 $retval = $var[$name];
2042 if ( get_magic_quotes_gpc() ) {
2043 $retval = stripslashes( $retval );
2044 }
2045 } else {
2046 $retval = $default;
2047 }
2048 taint( $retval );
2049 return $retval;
2050 }
2051
2052 function importPost( $name, $default = "" ) {
2053 return importVar( $_POST, $name, $default );
2054 }
2055
2056 function importCheck( $name ) {
2057 return isset( $_POST[$name] );
2058 }
2059
2060 function importRequest( $name, $default = "" ) {
2061 return importVar( $_REQUEST, $name, $default );
2062 }
2063
2064 function aField( &$conf, $field, $text, $type = "text", $value = "", $onclick = '' ) {
2065 static $radioCount = 0;
2066 if( $type != "" ) {
2067 $xtype = "type=\"$type\"";
2068 } else {
2069 $xtype = "";
2070 }
2071
2072 $id = $field;
2073 $nolabel = ($type == "radio") || ($type == "hidden");
2074
2075 if ($type == 'radio')
2076 $id .= $radioCount++;
2077
2078 if( !$nolabel ) {
2079 echo "<label class='column' for=\"$id\">$text</label>";
2080 }
2081
2082 if( $type == "radio" && $value == $conf->$field ) {
2083 $checked = "checked='checked'";
2084 } else {
2085 $checked = "";
2086 }
2087 echo "<input $xtype name=\"$field\" id=\"$id\" class=\"iput-$type\" $checked ";
2088 if ($onclick) {
2089 echo " onclick='toggleDBarea(\"$value\",1)' " ;
2090 }
2091 echo "value=\"";
2092 if( $type == "radio" ) {
2093 echo htmlspecialchars( $value );
2094 } else {
2095 echo htmlspecialchars( $conf->$field );
2096 }
2097
2098
2099 echo "\" />";
2100 if( $nolabel ) {
2101 echo "<label for=\"$id\">$text</label>";
2102 }
2103
2104 global $errs;
2105 if(isset($errs[$field])) {
2106 echo "<span class='error'>" . htmlspecialchars( $errs[$field] ) . "</span>\n";
2107 }
2108 }
2109
2110 function getLanguageList() {
2111 global $wgDummyLanguageCodes;
2112
2113 $codes = array();
2114 foreach ( Language::getLanguageNames() as $code => $name ) {
2115 if( in_array( $code, $wgDummyLanguageCodes ) ) continue;
2116 $codes[$code] = $code . ' - ' . $name;
2117 }
2118 ksort( $codes );
2119 return $codes;
2120 }
2121
2122 #Check for location of an executable
2123 # @param string $loc single location to check
2124 # @param array $names filenames to check for.
2125 # @param mixed $versioninfo array of details to use when checking version, use false for no version checking
2126 function locate_executable($loc, $names, $versioninfo = false) {
2127 if (!is_array($names))
2128 $names = array($names);
2129
2130 foreach ($names as $name) {
2131 $command = "$loc".DIRECTORY_SEPARATOR."$name";
2132 if (@file_exists($command)) {
2133 if (!$versioninfo)
2134 return $command;
2135
2136 $file = str_replace('$1', $command, $versioninfo[0]);
2137 if (strstr(`$file`, $versioninfo[1]) !== false)
2138 return $command;
2139 }
2140 }
2141 return false;
2142 }
2143
2144 # Test a memcached server
2145 function testMemcachedServer( $server ) {
2146 $hostport = explode(":", $server);
2147 $errstr = false;
2148 $fp = false;
2149 if ( !function_exists( 'fsockopen' ) ) {
2150 $errstr = "Can't connect to memcached, fsockopen() not present";
2151 }
2152 if ( !$errstr && count( $hostport ) != 2 ) {
2153 $errstr = 'Please specify host and port';
2154 }
2155 if ( !$errstr ) {
2156 list( $host, $port ) = $hostport;
2157 $errno = 0;
2158 $fsockerr = '';
2159
2160 $fp = @fsockopen( $host, $port, $errno, $fsockerr, 1.0 );
2161 if ( $fp === false ) {
2162 $errstr = "Cannot connect to memcached on $host:$port : $fsockerr";
2163 }
2164 }
2165 if ( !$errstr ) {
2166 $command = "version\r\n";
2167 $bytes = fwrite( $fp, $command );
2168 if ( $bytes != strlen( $command ) ) {
2169 $errstr = "Cannot write to memcached socket on $host:$port";
2170 }
2171 }
2172 if ( !$errstr ) {
2173 $expected = "VERSION ";
2174 $response = fread( $fp, strlen( $expected ) );
2175 if ( $response != $expected ) {
2176 $errstr = "Didn't get correct memcached response from $host:$port";
2177 }
2178 }
2179 if ( $fp ) {
2180 fclose( $fp );
2181 }
2182 if ( !$errstr ) {
2183 echo "<li>Connected to memcached on " . htmlspecialchars( "$host:$port" ) ." successfully</li>";
2184 }
2185 return $errstr;
2186 }
2187
2188 function database_picker($conf) {
2189 global $ourdb;
2190 print "\n";
2191 foreach(array_keys($ourdb) as $db) {
2192 if ($ourdb[$db]['havedriver']) {
2193 print "\t<li>";
2194 aField( $conf, "DBtype", $ourdb[$db]['fullname'], 'radio', $db, 'onclick');
2195 print "</li>\n";
2196 }
2197 }
2198 print "\n\t";
2199 }
2200
2201 function database_switcher($db) {
2202 global $ourdb;
2203 $color = $ourdb[$db]['bgcolor'];
2204 $full = $ourdb[$db]['fullname'];
2205 print "<fieldset id='$db' style='clear:both'><legend>$full-specific options</legend>\n";
2206 }
2207
2208 function printListItem( $item ) {
2209 print "<li>$item</li>";
2210 }
2211
2212 # Determine a suitable value for $wgShellLocale
2213 function getShellLocale( $wikiLang ) {
2214 # Give up now if we're in safe mode or open_basedir
2215 # It's theoretically possible but tricky to work with
2216 if ( wfIniGetBool( "safe_mode" ) || ini_get( 'open_basedir' ) || !function_exists('exec') ) {
2217 return false;
2218 }
2219
2220 $os = php_uname( 's' );
2221 $supported = array( 'Linux', 'SunOS', 'HP-UX' ); # Tested these
2222 if ( !in_array( $os, $supported ) ) {
2223 return false;
2224 }
2225
2226 # Get a list of available locales
2227 $lines = $ret = false;
2228 exec( '/usr/bin/locale -a', $lines, $ret );
2229 if ( $ret ) {
2230 return false;
2231 }
2232
2233 $lines = wfArrayMap( 'trim', $lines );
2234 $candidatesByLocale = array();
2235 $candidatesByLang = array();
2236 foreach ( $lines as $line ) {
2237 if ( $line === '' ) {
2238 continue;
2239 }
2240 if ( !preg_match( '/^([a-zA-Z]+)(_[a-zA-Z]+|)\.(utf8|UTF-8)(@[a-zA-Z_]*|)$/i', $line, $m ) ) {
2241 continue;
2242 }
2243 list( $all, $lang, $territory, $charset, $modifier ) = $m;
2244 $candidatesByLocale[$m[0]] = $m;
2245 $candidatesByLang[$lang][] = $m;
2246 }
2247
2248 # Try the current value of LANG
2249 if ( isset( $candidatesByLocale[ getenv( 'LANG' ) ] ) ) {
2250 return getenv( 'LANG' );
2251 }
2252
2253 # Try the most common ones
2254 $commonLocales = array( 'en_US.UTF-8', 'en_US.utf8', 'de_DE.UTF-8', 'de_DE.utf8' );
2255 foreach ( $commonLocales as $commonLocale ) {
2256 if ( isset( $candidatesByLocale[$commonLocale] ) ) {
2257 return $commonLocale;
2258 }
2259 }
2260
2261 # Is there an available locale in the Wiki's language?
2262 if ( isset( $candidatesByLang[$wikiLang] ) ) {
2263 $m = reset( $candidatesByLang[$wikiLang] );
2264 return $m[0];
2265 }
2266
2267 # Are there any at all?
2268 if ( count( $candidatesByLocale ) ) {
2269 $m = reset( $candidatesByLocale );
2270 return $m[0];
2271 }
2272
2273 # Give up
2274 return false;
2275 }
2276
2277 function wfArrayMap( $function, $input ) {
2278 $ret = array_map( $function, $input );
2279 foreach ( $ret as $key => $value ) {
2280 $taint = istainted( $input[$key] );
2281 if ( $taint ) {
2282 taint( $ret[$key], $taint );
2283 }
2284 }
2285 return $ret;
2286 }
2287
2288 ?>
2289
2290 <div class="license">
2291 <hr/>
2292 <p>This program is free software; you can redistribute it and/or modify
2293 it under the terms of the GNU General Public License as published by
2294 the Free Software Foundation; either version 2 of the License, or
2295 (at your option) any later version.</p>
2296
2297 <p>This program is distributed in the hope that it will be useful,
2298 but WITHOUT ANY WARRANTY; without even the implied warranty of
2299 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2300 GNU General Public License for more details.</p>
2301
2302 <p>You should have received <a href="../COPYING">a copy of the GNU General Public License</a>
2303 along with this program; if not, write to the Free Software
2304 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
2305 or <a href="http://www.gnu.org/copyleft/gpl.html">read it online</a></p>
2306 </div>
2307
2308 </div></div></div>
2309
2310
2311 <div id="column-one">
2312 <div class="portlet" id="p-logo">
2313 <a style="background-image: url(../skins/common/images/mediawiki.png);"
2314 href="../"
2315 title="Main Page"></a>
2316 </div>
2317 <script type="text/javascript"> if (window.isMSIE55) fixalpha(); </script>
2318 <div class='portlet'><div class='pBody'>
2319 <ul>
2320 <li><a href="../README">Readme</a></li>
2321 <li><a href="../RELEASE-NOTES">Release notes</a></li>
2322 <li><a href="../docs/">Documentation</a></li>
2323 <li><a href="http://www.mediawiki.org/wiki/Help:Contents">User's Guide</a></li>
2324 <li><a href="http://www.mediawiki.org/wiki/Manual:Contents">Administrator's Guide</a></li>
2325 <li><a href="http://www.mediawiki.org/wiki/Manual:FAQ">FAQ</a></li>
2326 </ul>
2327 <p style="font-size:90%;margin-top:1em">MediaWiki is Copyright © 2001-2009 by Magnus Manske, Brion Vibber,
2328 Lee Daniel Crocker, Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason, Niklas Laxström,
2329 Domas Mituzas, Rob Church, Yuri Astrakhan, Aryeh Gregor, Aaron Schulz and others.</p>
2330 </div></div>
2331 </div>
2332
2333 </div>
2334
2335 </body>
2336 </html>