Fix per Brion's CR r76342: Avoid spaces get normalized between the 2 different classes
[lhc/web/wiklou.git] / config / Installer.php
1 <?php
2 /**
3 * DO NOT USE ANY OF THIS CODE. BEING RETAINED FOR REFERENCE UNTIL JUST BEFORE
4 * THE 1.17 BRANCH
5 *
6 * @file
7 */
8
9 die( 'Now nearly 100% obsolete!' );
10
11 error_reporting( E_ALL | E_STRICT );
12 header( "Content-type: text/html; charset=utf-8" );
13 @ini_set( "display_errors", true );
14
15 # In case of errors, let output be clean.
16 $wgRequestTime = microtime( true );
17
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();
22
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" );
34
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:
41
42 $ourdb = array();
43
44 $ourdb['mysql'] = array(
45 'fullname' => 'MySQL',
46 'havedriver' => 0,
47 'compile' => 'mysql',
48 'bgcolor' => '#ffe5a7',
49 'rootuser' => 'root',
50 'serverless' => false
51 );
52
53 $ourdb['postgres'] = array(
54 'fullname' => 'PostgreSQL',
55 'havedriver' => 0,
56 'compile' => 'pgsql',
57 'bgcolor' => '#aaccff',
58 'rootuser' => 'postgres',
59 'serverless' => false
60 );
61
62 $ourdb['sqlite'] = array(
63 'fullname' => 'SQLite',
64 'havedriver' => 0,
65 'compile' => 'pdo_sqlite',
66 'bgcolor' => '#b1ebb1',
67 'rootuser' => '',
68 'serverless' => true
69 );
70
71 $ourdb['mssql'] = array(
72 'fullname' => 'Microsoft SQL Server',
73 'havedriver' => 0,
74 'compile' => 'sqlsrv',
75 'bgcolor' => '#cccccc',
76 'rootuser' => 'root',
77 'serverless' => false
78 );
79
80 $ourdb['ibm_db2'] = array(
81 'fullname' => 'DB2',
82 'havedriver' => 0,
83 'compile' => 'ibm_db2',
84 'bgcolor' => '#ffeba1',
85 'rootuser' => 'db2admin',
86 'serverless' => false
87 );
88
89 $ourdb['oracle'] = array(
90 'fullname' => 'Oracle',
91 'havedriver' => 0,
92 'compile' => 'oci8',
93 'bgcolor' => '#ffeba1',
94 'rootuser' => 'sys',
95 'serverless' => false
96 );
97
98 ?>
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">
106
107 @import "../skins/monobook/main.css";
108
109 .env-check {
110 font-size: 90%;
111 margin: 1em 0 1em 2.5em;
112 }
113
114 .config-section {
115 margin-top: 2em;
116 }
117
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;
126 }
127
128 .config-input {
129 clear: left;
130 zoom: 100%; /* IE hack */
131 }
132
133 .config-section .config-desc {
134 clear: left;
135 margin: 0 0 2em 18em;
136 padding-top: 1em;
137 font-size: 85%;
138 }
139
140 .iput-text, .iput-password {
141 width: 14em;
142 margin-right: 1em;
143 }
144
145 .error {
146 color: red;
147 background-color: #fff;
148 font-weight: bold;
149 left: 1em;
150 font-size: 100%;
151 }
152
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;
161 }
162
163 ul.plain {
164 list-style-type: none;
165 list-style-image: none;
166 float: left;
167 margin: 0;
168 padding: 0;
169 }
170
171 .btn-install {
172 font-weight: bold;
173 font-size: 110%;
174 padding: .2em .3em;
175 }
176
177 .license {
178 font-size: 85%;
179 padding-top: 3em;
180 }
181
182 span.success-message {
183 font-weight: bold;
184 font-size: 110%;
185 color: green;
186 }
187
188 .success-box {
189 font-size: 130%;
190 }
191
192 </style>
193 <script type="text/javascript">
194 <!--
195 <?php echo 'var databases = ' . FormatJson::encode( $ourdb ) . ';'; ?>
196
197 function show(id, showOrHide) {
198 var i = document.getElementById(id);
199 if (i) i.style.display = showOrHide ? 'block' : 'none';
200 }
201 function hideall() {
202 for (db in databases) {
203 show(db, false);
204 }
205 }
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);
214 }
215 // -->
216 </script>
217 </head>
218
219 <body>
220 <div id="globalWrapper">
221 <div id="column-content">
222 <div id="content">
223 <div id="bodyContent">
224
225 <h1>MediaWiki <?php print htmlspecialchars( $wgVersion ) ?> Installation</h1>
226
227 <?php
228 $mainListOpened = false; # Is the main list (environement checking) opend ? Used by dieout
229
230 /* Check for existing configurations and bug out! */
231
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>" );
236 }
237
238 if( file_exists( "./LocalSettings.php" ) ) {
239 writeSuccessMessage();
240 dieout( '' );
241 }
242
243 if( !is_writable( "." ) ) {
244 dieout( "<h2>Can't write config file, aborting</h2>
245
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>
250
251 <p>To make the directory writable on a Unix/Linux system:</p>
252
253 <pre>
254 cd <i>" . htmlspecialchars( dirname( dirname( __FILE__ ) ) ) . "</i>
255 chmod a+w config
256 </pre>
257
258 <p>Afterwards retry to start the <a href=\"\">setup</a>.</p>" );
259 }
260
261 class ConfigData {
262 function getEncoded( $data ) {
263 # removing latin1 support, no need...
264 return $data;
265 }
266 function getSitename() { return $this->getEncoded( $this->Sitename ); }
267 function getSysopName() { return $this->getEncoded( $this->SysopName ); }
268 function getSysopPass() { return $this->getEncoded( $this->SysopPass ); }
269
270 function setSchema( $schema, $engine ) {
271 $this->DBschema = $schema;
272 if ( !preg_match( '/^\w*$/', $engine ) ){
273 $engine = 'InnoDB';
274 }
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';
287 }
288 $this->DBengine = $engine;
289
290 # Set the global for use during install
291 global $wgDBTableOptions;
292 $wgDBTableOptions = $this->DBTableOptions;
293 }
294 }
295
296 ?>
297
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>
305
306
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;
312
313 $endl = "
314 ";
315 define( 'MW_NO_OUTPUT_BUFFER', 1 );
316 $conf = new ConfigData;
317
318 install_version_checks();
319 $self = 'Installer'; # Maintenance script name, to please Setup.php
320
321 print "<li>PHP " . htmlspecialchars( phpversion() ) . " installed</li>\n";
322
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;
330 }
331 }
332 error_reporting( E_ALL | E_STRICT );
333
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";
341 }
342 echo '</ul>';
343 dieout( '' );
344 }
345
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;
352 }
353 print " ".$ourdb[$db]['fullname'];
354 }
355 }
356 print "</li>\n";
357
358 if( wfIniGetBool( "register_globals" ) ) {
359 ?>
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
368 }
369
370 $fatal = false;
371
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
378 }
379
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
386 }
387
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
394 }
395
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
402 }
403
404 if( $fatal ) {
405 dieout( "Cannot install MediaWiki." );
406 }
407
408 if( wfIniGetBool( "safe_mode" ) ) {
409 $conf->safeMode = true;
410 ?>
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;
418 }
419
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>)";
427 }
428 print "</li>\n";
429
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." );
437 }
438
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." );
442
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>";
461 }
462
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." );
467
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();
472
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. ";
484 }
485 print "</li>\n";
486 }
487
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";
491
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";
495 }
496
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";
500 }
501
502 $conf->dba = function_exists( 'dba_open' );
503
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>' );
508 }
509
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" );
520
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;
527 }
528 }
529
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>";
534
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;
543 }
544 }
545
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";
551 }
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";
556 }
557 }
558
559 $conf->IP = dirname( dirname( __FILE__ ) );
560 print "<li>Installation directory: <tt>" . htmlspecialchars( $conf->IP ) . "</tt></li>\n";
561
562
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"];
569
570 $conf->ScriptPath = preg_replace( '{^(.*)/config.*$}', '$1', $path );
571 print "<li>Script URI path: <tt>" . htmlspecialchars( $conf->ScriptPath ) . "</tt></li>\n";
572
573
574
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";
582 }
583
584
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");
587
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;
596 }
597
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" ) );
615
616 ## Postgres specific:
617 $conf->DBport = importPost( "DBport", $wgDBport );
618 $conf->DBts2schema = importPost( "DBts2schema", "public" );
619 $conf->DBpgschema = importPost( "DBpgschema", "mediawiki" );
620
621 ## SQLite specific
622 $conf->SQLiteDataDir = importPost( "SQLiteDataDir", "$IP/../data" );
623
624 ## DB2 specific:
625 $conf->DBport_db2 = importPost( "DBport_db2", "50000" );
626 $conf->DBdb2schema = importPost( "DBdb2schema", "mediawiki" );
627
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" );
632
633 $conf->ShellLocale = getShellLocale( $conf->LanguageCode );
634
635 /* Check for validity */
636 $errs = array();
637
638 if( preg_match( '/^$|^mediawiki$|#/i', $conf->Sitename ) ) {
639 $errs["Sitename"] = "Must not be blank or \"MediaWiki\" and may not contain \"#\"";
640 }
641 if( !$ourdb[$conf->DBtype]['serverless'] ) {
642 if( $conf->DBuser == "" ) {
643 $errs["DBuser"] = "Must not be blank";
644 }
645 if( ($conf->DBtype == 'mysql') && (strlen($conf->DBuser) > 16) ) {
646 $errs["DBuser"] = "Username too long";
647 }
648 if( $conf->DBpassword == "" && $conf->DBtype != "postgres" ) {
649 $errs["DBpassword"] = "Must not be blank";
650 }
651 if( $conf->DBpassword != $conf->DBpassword2 ) {
652 $errs["DBpassword2"] = "Passwords don't match!";
653 }
654 }
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 );
659 }
660 if( !preg_match( '/^[A-Za-z_0-9]*$/', $conf->DBprefix_ora ) ) {
661 $errs["DBprefix_ora"] = "Invalid table prefix";
662 }
663
664 error_reporting( E_ALL | E_STRICT );
665
666 /**
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.
671 */
672 $wgContLang = Language::factory( 'en' );
673 $wgLang = $wgContLang;
674
675 /**
676 * We're messing about with users, so we need a stub
677 * authentication plugin...
678 */
679 $wgAuth = new AuthPlugin();
680
681 /**
682 * Validate the initial administrator account; username,
683 * password checks, etc.
684 */
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";
694 }
695 } else {
696 $errs['SysopPass2'] = "Passwords don't match";
697 }
698 } else {
699 $errs['SysopPass'] = "Cannot be blank";
700 }
701 unset( $u );
702 } else {
703 $errs['SysopName'] = "Bad username";
704 }
705 }
706
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", "" );
730 }
731
732 $conf->Shm = importRequest( "Shm", "none" );
733 $conf->MCServers = importRequest( "MCServers" );
734
735 /* Test memcached servers */
736
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;
744 }
745 }
746 } else if ( $conf->Shm == 'memcached' ) {
747 $errs["MCServers"] = "Please specify at least one server if you wish to use memcached";
748 }
749
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");
755
756 if( $conf->posted && ( 0 == count( $errs ) ) ) {
757 do { /* So we can 'continue' to end prematurely */
758 $conf->Root = ($conf->RootPW != "");
759
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";
765
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>" );
776 }
777 $conf->DBtypename = '';
778 foreach (array_keys($ourdb) as $db) {
779 if ($conf->DBtype === $db)
780 $conf->DBtypename = $ourdb[$db]['fullname'];
781 }
782 if ( ! strlen($conf->DBtype)) {
783 $errs["DBpicktype"] = "Please choose a database type";
784 continue;
785 }
786
787 if (! $conf->DBtypename) {
788 $errs["DBtype"] = "Unknown database type '$conf->DBtype'";
789 continue;
790 }
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;
796
797 ## Mysql specific:
798 $wgDBprefix = $conf->DBprefix;
799
800 ## Postgres specific:
801 $wgDBport = $conf->DBport;
802 $wgDBts2schema = $conf->DBts2schema;
803
804 if( $wgDBtype == 'postgres' ) {
805 $wgDBmwschema = $conf->DBpgschema;
806 } elseif ( $wgDBtype == 'ibm_db2' ) {
807 $wgDBmwschema = $conf->DBdb2schema;
808 }
809
810 if( $conf->DBprefix_ora != '' ) {
811 // For Oracle
812 $wgDBprefix = $conf->DBprefix_ora;
813 }
814
815 ## DB2 specific:
816 if ( $conf->DBtype == 'ibm_db2' ) {
817 $wgDBport = $conf->DBport_db2;
818 }
819
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();
826
827 chdir( "config" );
828
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;
834 }
835
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";
843 }
844 $ok = true; # Let's be optimistic
845
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;
854 }
855
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 );
859
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";
886 }
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.
897
898 if( !$ok ) { continue; }
899 }
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,
910 1
911 );
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;
918 }
919 $wgDatabase->initial_setup( $conf->DBname, $conf->DBuser, $conf->DBpassword );
920 }
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,
927 1
928 );
929 if ( !$wgDatabase->isOpen() ) {
930 echo( " error: {$wgDatabase->lastError()} </li>\n" );
931 } else {
932 $myver = $wgDatabase->getServerVersion();
933 }
934 }
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;
942 }
943
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);
950
951 if (!$wgDatabase->isOpen()) {
952 print " error: " . htmlspecialchars( $wgDatabase->lastError() ) . "</li>\n";
953 } else {
954 $myver = $wgDatabase->getServerVersion();
955 }
956 if (is_callable(array($wgDatabase, 'initial_setup'))) $wgDatabase->initial_setup('', $wgDBname);
957
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;
967 }
968 if ( !$ok ) {
969 echo "cannot create data directory</li>";
970 $errs['SQLiteDataDir'] = 'Enter a valid data directory';
971 continue;
972 }
973 }
974 if ( !is_writable( $wgSQLiteDataDir ) ) {
975 echo "data directory not writable</li>";
976 $errs['SQLiteDataDir'] = 'Enter a writable data directory';
977 continue;
978 }
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;
985 }
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;
991 }
992 }
993 try {
994 $wgDatabase = new DatabaseSqlite( false, false, false, $wgDBname, 1 );
995 }
996 catch( MWException $ex ) {
997 echo 'error: ' . htmlspecialchars( $ex->getMessage() ) . "</li>\n";
998 continue;
999 }
1000
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();
1007 }
1008 if ( is_callable( array( $wgDatabase, 'initial_setup' ) ) ) {
1009 $wgDatabase->initial_setup('', $wgDBname);
1010 }
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;
1039 }
1040 }
1041 } else {
1042 echo "<li>Database superuser missing, please supply a valid superuser account.</li>";
1043 $ok = false;
1044 }
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);
1051 }
1052 }
1053 if ($ok) {
1054 $myver = $wgDatabase->getServerVersion();
1055 }
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;
1070 }
1071 $wgDatabase->initial_setup($conf->RootUser, $conf->RootPW, 'postgres');
1072 }
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();
1084 }
1085 if (is_callable(array($wgDatabase, 'initial_setup'))) $wgDatabase->initial_setup('', $wgDBname);
1086 }
1087
1088 if ( !$wgDatabase->isOpen() ) {
1089 $errs["DBserver"] = "Couldn't connect to database";
1090 continue;
1091 }
1092
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." );
1098 }
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>";
1105 }
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>";
1112 }
1113 }
1114 print "</li>\n";
1115
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;
1129 }
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;
1138 }
1139 print "<li>Created database <tt>" . htmlspecialchars( $wgDBname ) . "</tt></li>\n";
1140 }
1141 $wgDatabase->selectDB( $wgDBname );
1142 }
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." );
1146 }
1147 }
1148
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";
1151
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";
1172 }
1173 if ( isset( $row->Engine ) ) {
1174 $existingEngine = $row->Engine;
1175 } else {
1176 $existingEngine = $row->Type;
1177 }
1178 }
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 );
1186 }
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 );
1194 }
1195 }
1196
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>";
1207 }
1208 print "</li>\n";
1209 $res = $wgDatabase->sourceFile( "../maintenance/users.sql" );
1210 if ($res !== true) dieout($res);
1211 }
1212 }
1213 }
1214 print "</ul><pre>\n";
1215 chdir( ".." );
1216 flush();
1217
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() );
1222 }
1223
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;
1237 }
1238 }
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' );
1244 }
1245 }
1246
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" );
1253 }
1254 if ($res === true) {
1255 print " done.</li>\n";
1256 } else {
1257 print " <b>FAILED</b></li>\n";
1258 dieout( htmlspecialchars( $res ) );
1259 }
1260 } elseif (is_callable(array($wgDatabase, 'setup_database'))) {
1261 $wgDatabase->setup_database();
1262 }
1263 else {
1264 $errs["DBtype"] = "Do not know how to handle database type '$conf->DBtype'";
1265 continue;
1266 }
1267
1268
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();
1275 }
1276 else {
1277 print "<li>MediaWiki tables successfully created</li>\n";
1278 $wgDatabase->commit();
1279 }
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();
1284 }
1285
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 ) );
1296
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 );
1314 }
1315 }
1316 }
1317
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";
1322 }
1323 else if ( 0 == $u->idForName() ) {
1324 $u->addToDatabase();
1325 $u->setPassword( $conf->getSysopPass() );
1326 $u->saveSettings();
1327
1328 $u->addGroup( "sysop" );
1329 $u->addGroup( "bureaucrat" );
1330
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";
1335 }
1336 } else {
1337 print "<li>Skipped sysop account creation, no name given.</li>\n";
1338 }
1339
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 );
1352 }
1353
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' );
1361
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" );
1367 }
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" );
1376 }
1377
1378 } while( false );
1379 }
1380
1381 print "</ul>\n";
1382 $mainListOpened = false;
1383
1384 if( count( $errs ) ) {
1385 /* Display options form */
1386
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";
1389 }
1390 ?>
1391
1392 <form action="<?php echo defined('MW_INSTALL_PHP5_EXT') ? 'index.php5' : 'index.php'; ?>" name="config" method="post">
1393
1394 <h2>Site config</h2>
1395
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>
1408
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>";
1418 }
1419 echo "\n";
1420 ?>
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>
1426
1427 <div class="config-input">
1428 <label class='column'>Copyright/license:</label>
1429
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>
1457
1458
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>
1474
1475 <div class="config-input">
1476 <label class='column'>Object caching:</label>
1477
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";
1485 }
1486 if ( $conf->apc ) {
1487 echo "<li>";
1488 aField( $conf, "Shm", "APC", "radio", "apc" );
1489 echo "</li>\n";
1490 }
1491 if ( $conf->eaccel ) {
1492 echo "<li>";
1493 aField( $conf, "Shm", "eAccelerator", "radio", "eaccel" );
1494 echo "</li>\n";
1495 }
1496 if ( $conf->dba ) {
1497 echo "<li>";
1498 aField( $conf, "Shm", "DBA (not recommended)", "radio", "dba" );
1499 echo "</li>";
1500 }
1501 ?>
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>
1517
1518 <h2>E-mail, e-mail notification and authentication setup</h2>
1519
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>
1532
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">
1552 <p>
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>
1556
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>
1559
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>
1571
1572 </div>
1573
1574 <h2>Database config</h2>
1575
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";
1582 }
1583 ?>
1584 <ul class='plain'><?php
1585 database_picker($ourdb, $conf);
1586 ?></ul>
1587 </div>
1588
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>
1597
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>
1610
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>
1618
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>
1625
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>
1632
1633 <p>Avoid exotic characters; something like <tt>mw_</tt> is good.</p>
1634 </div>
1635
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>
1664
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>
1675
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>
1683
1684 <p>This directory must exist and be writable by the web server.</p>
1685 </div>
1686 </fieldset>
1687
1688
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>
1694
1695
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>
1712
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>
1719
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>
1725
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
1740 }
1741
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">
1765 <p>
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;
1773 }
1774 }
1775
1776
1777 function escapePhpString( $string ) {
1778 if ( is_array( $string ) || is_object( $string ) ) {
1779 return false;
1780 }
1781 return strtr( $string,
1782 array(
1783 "\n" => "\\n",
1784 "\r" => "\\r",
1785 "\t" => "\\t",
1786 "\\" => "\\\\",
1787 "\$" => "\\\$",
1788 "\"" => "\\\""
1789 ));
1790 }
1791
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
1801 }
1802 $sqliteDataDir = escapePhpString( $dir );
1803
1804 if ( $conf->ShellLocale ) {
1805 $locale = '';
1806 } else {
1807 $locale = '# ';
1808 $conf->ShellLocale = 'en_US.UTF-8';
1809 }
1810
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()';
1829 }
1830
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';
1847 }
1848 } else {
1849 $enableuseremail = 'false';
1850 $enableemail = 'false';
1851 $eauthent = 'false';
1852 $enotifusertalk = 'false';
1853 $enotifwatchlist = 'false';
1854 }
1855
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));
1864 }
1865 print "<li>Warning: \$wgSecretKey key is insecure, generated with mt_rand(). Consider changing it manually.</li>\n";
1866 }
1867
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;
1873 }
1874
1875 if( $conf->DBtype == 'mysql' ) {
1876 $dbsettings =
1877 "# MySQL specific settings
1878 \$wgDBprefix = \"{$slconf['DBprefix']}\";
1879
1880 # MySQL table options to use during installation or update
1881 \$wgDBTableOptions = \"{$slconf['DBTableOptions']}\";
1882
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 = '';
1908 }
1909
1910
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.
1915 #
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.
1919 #
1920 # Further documentation for configuration settings may be found at:
1921 # http://www.mediawiki.org/wiki/Manual:Configuration_settings
1922
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__ );
1929 }
1930
1931 \$path = array( \$IP, \"\$IP/includes\", \"\$IP/languages\" );
1932 set_include_path( implode( PATH_SEPARATOR, \$path ) . PATH_SEPARATOR . get_include_path() );
1933
1934 require_once( \"\$IP/includes/DefaultSettings.php\" );
1935
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\" );
1939 }
1940 }
1941 ## Uncomment this to disable output compression
1942 # \$wgDisableOutputCompression = true;
1943
1944 \$wgSitename = \"{$slconf['Sitename']}\";
1945
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']}\";
1952
1953 ## The relative URL path to the skins directory
1954 \$wgStylePath = \"\$wgScriptPath/skins\";
1955
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\";
1959
1960 ## UPO means: this is also a user preference option
1961
1962 \$wgEnableEmail = $enableemail;
1963 \$wgEnableUserEmail = $enableuseremail; # UPO
1964
1965 \$wgEmergencyContact = \"{$slconf['EmergencyContact']}\";
1966 \$wgPasswordSender = \"{$slconf['PasswordSender']}\";
1967
1968 \$wgEnotifUserTalk = $enotifusertalk; # UPO
1969 \$wgEnotifWatchlist = $enotifwatchlist; # UPO
1970 \$wgEmailAuthentication = $eauthent;
1971
1972 ## Database settings
1973 \$wgDBtype = \"{$slconf['DBtype']}\";
1974 \$wgDBserver = \"{$slconf['DBserver']}\";
1975 \$wgDBname = \"{$slconf['DBname']}\";
1976 \$wgDBuser = \"{$slconf['DBuser']}\";
1977 \$wgDBpassword = \"{$slconf['DBpassword']}\";
1978
1979 {$dbsettings}
1980
1981 ## Shared memory settings
1982 \$wgMainCacheType = $cacheType;
1983 \$wgMemCachedServers = $mcservers;
1984
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}\";
1990
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']}\";
1995
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;
2001
2002 ## If you have the appropriate support software installed
2003 ## you can enable inline LaTeX equations:
2004 \$wgUseTeX = false;
2005
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\";
2010
2011 \$wgLocalInterwiki = strtolower( \$wgSitename );
2012
2013 \$wgLanguageCode = \"{$slconf['LanguageCode']}\";
2014
2015 \$wgSecretKey = \"$secretKey\";
2016
2017 ## Default skin: you can change the default skin. Use the internal symbolic
2018 ## names, ie 'vector', 'monobook':
2019 \$wgDefaultSkin = 'monobook';
2020
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
2030
2031 \$wgDiff3 = \"{$slconf['diff3']}\";
2032
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
2037
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 );
2041 }
2042
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;
2050 }
2051 die( "\n\n</div>\n</div>\n</div>\n</div>\n</body>\n</html>" );
2052 }
2053
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 );
2059 }
2060 } else {
2061 $retval = $default;
2062 }
2063 taint( $retval );
2064 return $retval;
2065 }
2066
2067 function importPost( $name, $default = "" ) {
2068 return importVar( $_POST, $name, $default );
2069 }
2070
2071 function importCheck( $name ) {
2072 return isset( $_POST[$name] );
2073 }
2074
2075 function importRequest( $name, $default = "" ) {
2076 return importVar( $_REQUEST, $name, $default );
2077 }
2078
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 = "";
2085 }
2086
2087 $id = $field;
2088 $nolabel = ($type == "radio") || ($type == "hidden");
2089
2090 if ($type == 'radio') {
2091 $id .= $radioCount++;
2092 }
2093
2094 if( !$nolabel ) {
2095 echo "<label class='column' for=\"$id\">$text</label>";
2096 }
2097
2098 if( $type == "radio" && $value == $conf->$field ) {
2099 $checked = "checked='checked'";
2100 } else {
2101 $checked = "";
2102 }
2103 echo "<input $xtype name=\"$field\" id=\"$id\" class=\"iput-$type\" $checked ";
2104 if ($onclick) {
2105 echo " onclick='toggleDBarea(\"$value\",1)' " ;
2106 }
2107 echo "value=\"";
2108 if( $type == "radio" ) {
2109 echo htmlspecialchars( $value );
2110 } else {
2111 echo htmlspecialchars( $conf->$field );
2112 }
2113
2114
2115 echo "\" />";
2116 if( $nolabel ) {
2117 echo "<label for=\"$id\">$text</label>";
2118 }
2119
2120 global $errs;
2121 if(isset($errs[$field])) {
2122 echo "<span class='error'>" . htmlspecialchars( $errs[$field] ) . "</span>\n";
2123 }
2124 }
2125
2126 function getLanguageList() {
2127 global $wgDummyLanguageCodes;
2128
2129 $codes = array();
2130 foreach ( Language::getLanguageNames() as $code => $name ) {
2131 if( in_array( $code, $wgDummyLanguageCodes ) ) continue;
2132 $codes[$code] = $code . ' - ' . $name;
2133 }
2134 ksort( $codes );
2135 return $codes;
2136 }
2137
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);
2145
2146 foreach ($names as $name) {
2147 $command = "$loc".DIRECTORY_SEPARATOR."$name";
2148 if (@file_exists($command)) {
2149 if (!$versioninfo)
2150 return $command;
2151
2152 $file = str_replace('$1', $command, $versioninfo[0]);
2153 if (strstr(`$file`, $versioninfo[1]) !== false)
2154 return $command;
2155 }
2156 }
2157 return false;
2158 }
2159
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";
2167 }
2168 if ( !$errstr && count( $hostport ) != 2 ) {
2169 $errstr = 'Please specify host and port';
2170 }
2171 if ( !$errstr ) {
2172 list( $host, $port ) = $hostport;
2173 $errno = 0;
2174 $fsockerr = '';
2175
2176 $fp = @fsockopen( $host, $port, $errno, $fsockerr, 1.0 );
2177 if ( $fp === false ) {
2178 $errstr = "Cannot connect to memcached on $host:$port : $fsockerr";
2179 }
2180 }
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";
2186 }
2187 }
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";
2193 }
2194 }
2195 if ( $fp ) {
2196 fclose( $fp );
2197 }
2198 if ( !$errstr ) {
2199 echo "<li>Connected to memcached on " . htmlspecialchars( "$host:$port" ) ." successfully</li>";
2200 }
2201 return $errstr;
2202 }
2203
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";
2211 }
2212 }
2213 print "\n\t";
2214 }
2215
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";
2220 }
2221
2222 function printListItem( $item ) {
2223 print "<li>$item</li>";
2224 }
2225
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;
2232 }
2233
2234 $os = php_uname( 's' );
2235 $supported = array( 'Linux', 'SunOS', 'HP-UX' ); # Tested these
2236 if ( !in_array( $os, $supported ) ) {
2237 return false;
2238 }
2239
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;
2245 }
2246
2247 $lines = wfArrayMap( 'trim', $lines );
2248 $candidatesByLocale = array();
2249 $candidatesByLang = array();
2250 foreach ( $lines as $line ) {
2251 if ( $line === '' ) {
2252 continue;
2253 }
2254 if ( !preg_match( '/^([a-zA-Z]+)(_[a-zA-Z]+|)\.(utf8|UTF-8)(@[a-zA-Z_]*|)$/i', $line, $m ) ) {
2255 continue;
2256 }
2257 list( $all, $lang, $territory, $charset, $modifier ) = $m;
2258 $candidatesByLocale[$m[0]] = $m;
2259 $candidatesByLang[$lang][] = $m;
2260 }
2261
2262 # Try the current value of LANG
2263 if ( isset( $candidatesByLocale[ getenv( 'LANG' ) ] ) ) {
2264 return getenv( 'LANG' );
2265 }
2266
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;
2272 }
2273 }
2274
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];
2279 }
2280
2281 # Are there any at all?
2282 if ( count( $candidatesByLocale ) ) {
2283 $m = reset( $candidatesByLocale );
2284 return $m[0];
2285 }
2286
2287 # Give up
2288 return false;
2289 }
2290
2291 ?>
2292
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>
2299
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>
2304
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>
2310
2311 </div></div></div>
2312
2313
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>
2335
2336 </div>
2337
2338 </body>
2339 </html>