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