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