* Modified file description header to use "/** ... */" and added @file
[lhc/web/wiklou.git] / config / Installer.php
index 13ccc25..7485970 100644 (file)
@@ -1,23 +1,27 @@
 <?php
-
-# MediaWiki web-based config/installation
-# Copyright (C) 2004 Brion Vibber <brion@pobox.com>, 2006 Rob Church <robchur@gmail.com>
-# http://www.mediawiki.org/
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-# http://www.gnu.org/copyleft/gpl.html
+/**
+ * MediaWiki web-based config/installation
+ *
+ * Copyright © 2004 Brion Vibber <brion@pobox.com>, 2006 Rob Church <robchur@gmail.com>
+ * http://www.mediawiki.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
 
 if( !defined( 'MEDIAWIKI_INSTALL' ) ) {
        die( 'Not an entry point.' );
@@ -44,6 +48,8 @@ require_once( "$IP/includes/ProfilerStub.php" );
 require_once( "$IP/includes/GlobalFunctions.php" );
 require_once( "$IP/includes/Hooks.php" );
 require_once( "$IP/includes/Exception.php" );
+require_once( "$IP/includes/json/Services_JSON.php" );
+require_once( "$IP/includes/json/FormatJson.php" );
 
 # If we get an exception, the user needs to know
 # all the details
@@ -53,45 +59,55 @@ wfInstallExceptionHandler();
 ## Databases we support:
 
 $ourdb = array();
-$ourdb['mysql']['fullname']      = 'MySQL';
-$ourdb['mysql']['havedriver']    = 0;
-$ourdb['mysql']['compile']       = 'mysql';
-$ourdb['mysql']['bgcolor']       = '#ffe5a7';
-$ourdb['mysql']['rootuser']      = 'root';
-
-$ourdb['postgres']['fullname']   = 'PostgreSQL';
-$ourdb['postgres']['havedriver'] = 0;
-$ourdb['postgres']['compile']    = 'pgsql';
-$ourdb['postgres']['bgcolor']    = '#aaccff';
-$ourdb['postgres']['rootuser']   = 'postgres';
-
-$ourdb['sqlite']['fullname']      = 'SQLite';
-$ourdb['sqlite']['havedriver']    = 0;
-$ourdb['sqlite']['compile']       = 'pdo_sqlite';
-$ourdb['sqlite']['bgcolor']       = '#b1ebb1';
-$ourdb['sqlite']['rootuser']      = '';
-
-$ourdb['mssql']['fullname']      = 'MSSQL';
-$ourdb['mssql']['havedriver']    = 0;
-$ourdb['mssql']['compile']       = 'mssql not ready'; # Change to 'mssql' after includes/DatabaseMssql.php added;
-$ourdb['mssql']['bgcolor']       = '#ffc0cb';
-$ourdb['mssql']['rootuser']      = 'administrator';
-
-$ourdb['ibm_db2']['fullname']   = 'DB2';
-$ourdb['ibm_db2']['havedriver'] = 0;
-$ourdb['ibm_db2']['compile']    = 'ibm_db2';
-$ourdb['ibm_db2']['bgcolor']    = '#ffeba1';
-$ourdb['ibm_db2']['rootuser']   = 'db2admin';
-
-$ourdb['oracle']['fullname']   = 'Oracle';
-$ourdb['oracle']['havedriver'] = 0;
-$ourdb['oracle']['compile']    = 'oci8';
-$ourdb['oracle']['bgcolor']    = '#ffeba1';
-$ourdb['oracle']['rootuser']   = '';
+
+$ourdb['mysql'] = array(
+       'fullname'   => 'MySQL',
+       'havedriver' => 0,
+       'compile'    => 'mysql',
+       'bgcolor'    => '#ffe5a7',
+       'rootuser'   => 'root',
+       'serverless' => false
+);
+
+$ourdb['postgres'] = array(
+       'fullname'   => 'PostgreSQL',
+       'havedriver' => 0,
+       'compile'    => 'pgsql',
+       'bgcolor'    => '#aaccff',
+       'rootuser'   => 'postgres',
+       'serverless' => false
+);
+
+$ourdb['sqlite'] = array(
+       'fullname'   => 'SQLite',
+       'havedriver' => 0,
+       'compile'    => 'pdo_sqlite',
+       'bgcolor'    => '#b1ebb1',
+       'rootuser'   => '',
+       'serverless' =>  true
+);
+
+$ourdb['ibm_db2'] = array(
+       'fullname'   => 'DB2',
+       'havedriver' => 0,
+       'compile'    => 'ibm_db2',
+       'bgcolor'    => '#ffeba1',
+       'rootuser'   => 'db2admin',
+       'serverless' => false
+);
+
+$ourdb['oracle'] = array(
+       'fullname'   => 'Oracle',
+       'havedriver' => 0,
+       'compile'    => 'oci8',
+       'bgcolor'    => '#ffeba1',
+       'rootuser'   => 'sys',
+       'serverless' => false
+);
 
 ?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" dir="ltr">
 <head>
        <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
        <meta name="robots" content="noindex,nofollow"/>
@@ -172,12 +188,13 @@ $ourdb['oracle']['rootuser']   = '';
                        font-size: 85%;
                        padding-top: 3em;
                }
-               
+
                span.success-message {
                        font-weight: bold;
                        font-size: 110%;
                        color: green;
                }
+
                .success-box {
                        font-size: 130%;
                }
@@ -185,23 +202,25 @@ $ourdb['oracle']['rootuser']   = '';
        </style>
        <script type="text/javascript">
        <!--
+       <?php echo 'var databases = ' . FormatJson::encode( $ourdb ) . ';'; ?>
+
+       function show(id, showOrHide) {
+               var i = document.getElementById(id);
+               if (i) i.style.display = showOrHide ? 'block' : 'none';
+       }
        function hideall() {
-               <?php foreach (array_keys($ourdb) as $db) {
-               echo "\n                var i = document.getElementById('$db'); if (i) i.style.display='none';";
+               for (db in databases) {
+                       show(db, false);
                }
-               ?>
-
        }
-       function toggleDBarea(id,defaultroot) {
+       function toggleDBarea(id, defaultroot) {
                hideall();
                var dbarea = document.getElementById(id);
                if (dbarea) dbarea.style.display = (dbarea.style.display == 'none') ? 'block' : 'none';
                var db = document.getElementById('RootUser');
-               if (defaultroot) {
-<?php foreach (array_keys($ourdb) as $db) {
-                       echo "                  if (id == '$db') { db.value = '".$ourdb[$db]['rootuser']."';}\n";
-}?>
-               }
+               db.value = databases[id].rootuser;
+               show('db-server-settings1', !databases[id].serverless);
+               show('db-server-settings2', !databases[id].serverless);
        }
        // -->
        </script>
@@ -245,7 +264,7 @@ if( !is_writable( "." ) ) {
        cd <i>" . htmlspecialchars( dirname( dirname( __FILE__ ) ) ) . "</i>
        chmod a+w config
        </pre>
-       
+
        <p>Afterwards retry to start the <a href=\"\">setup</a>.</p>" );
 }
 
@@ -318,7 +337,7 @@ error_reporting( 0 );
 $phpdatabases = array();
 foreach (array_keys($ourdb) as $db) {
        $compname = $ourdb[$db]['compile'];
-       if( extension_loaded( $compname ) || ( mw_have_dl() && dl( "{$compname}." . PHP_SHLIB_SUFFIX ) ) ) {
+       if( wfDl( $compname ) ) {
                array_push($phpdatabases, $db);
                $ourdb[$db]['havedriver'] = 1;
        }
@@ -395,7 +414,6 @@ if( wfIniGetBool( "zend.ze1_compatibility_mode" ) ) {
        <?php
 }
 
-
 if( $fatal ) {
        dieout( "Cannot install MediaWiki." );
 }
@@ -480,11 +498,6 @@ if( $memlimit == -1 ) {
        print "</li>\n";
 }
 
-$conf->turck = function_exists( 'mmcache_get' );
-if ( $conf->turck ) {
-       print "<li><a href=\"http://turck-mmcache.sourceforge.net/\">Turck MMCache</a> installed</li>\n";
-}
-
 $conf->xcache = function_exists( 'xcache_get' );
 if( $conf->xcache )
        print "<li><a href=\"http://trac.lighttpd.net/xcache/\">XCache</a> installed</li>\n";
@@ -496,37 +509,17 @@ if ($conf->apc ) {
 
 $conf->eaccel = function_exists( 'eaccelerator_get' );
 if ( $conf->eaccel ) {
-       $conf->turck = 'eaccelerator';
        print "<li><a href=\"http://eaccelerator.sourceforge.net/\">eAccelerator</a> installed</li>\n";
 }
 
 $conf->dba = function_exists( 'dba_open' );
 
-if( !( $conf->turck || $conf->eaccel || $conf->apc || $conf->xcache ) ) {
-       echo( '<li>Couldn\'t find <a href="http://turck-mmcache.sourceforge.net">Turck MMCache</a>,
-               <a href="http://eaccelerator.sourceforge.net">eAccelerator</a>,
+if( !( $conf->eaccel || $conf->apc || $conf->xcache ) ) {
+       echo( '<li>Couldn\'t find <a href="http://eaccelerator.sourceforge.net">eAccelerator</a>,
                <a href="http://www.php.net/apc">APC</a> or <a href="http://trac.lighttpd.net/xcache/">XCache</a>;
                cannot use these for object caching.</li>' );
 }
 
-$conf->phpCliPath = false;
-$phpClilocations = array_merge(
-       array(
-               "/usr/bin",
-               "/usr/local/bin",
-               "/opt/csw/bin",
-               "/usr/gnu/bin",
-               "/usr/sfw/bin" ),
-       explode( PATH_SEPARATOR, getenv( "PATH" ) ) );
-$phpClinames = array( "php", "php.exe" );
-foreach ($phpClilocations as $loc) {
-       $exe = locate_executable($loc, $phpClinames);
-       if ($exe !== false) {
-               $conf->phpCliPath= $exe;
-               break;
-       }
-}
-
 $conf->diff3 = false;
 $diff3locations = array_merge(
        array(
@@ -615,36 +608,32 @@ print "<li style='font-weight:bold;color:green;font-size:110%'>Environment check
                $conf->DBtype = $DefaultDBtype;
        }
 
-       $conf->DBserver = importPost( "DBserver", "localhost" );
-       $conf->DBname = importPost( "DBname", "wikidb" );
-       $conf->DBuser = importPost( "DBuser", "wikiuser" );
+       $conf->DBserver = importPost( "DBserver", $wgDBserver );
+       $conf->DBname = importPost( "DBname", $wgDBname );
+       $conf->DBuser = importPost( "DBuser", $wgDBuser );
        $conf->DBpassword = importPost( "DBpassword" );
        $conf->DBpassword2 = importPost( "DBpassword2" );
        $conf->SysopName = importPost( "SysopName", "WikiSysop" );
        $conf->SysopPass = importPost( "SysopPass" );
        $conf->SysopPass2 = importPost( "SysopPass2" );
-       $conf->RootUser = importPost( "RootUser", "root" );
+       $conf->RootUser = importPost( "RootUser" );
        $conf->RootPW = importPost( "RootPW", "" );
        $useRoot = importCheck( 'useroot', false );
        $conf->LanguageCode = importPost( "LanguageCode", "en" );
        ## MySQL specific:
        $conf->DBprefix     = importPost( "DBprefix" );
-       $conf->setSchema( 
-               importPost( "DBschema", "mysql5-binary" ), 
+       $conf->setSchema(
+               importPost( "DBschema", "mysql5-binary" ),
                importPost( "DBengine", "InnoDB" ) );
 
        ## Postgres specific:
-       $conf->DBport      = importPost( "DBport",      "5432" );
+       $conf->DBport      = importPost( "DBport",      $wgDBport );
        $conf->DBts2schema = importPost( "DBts2schema", "public" );
        $conf->DBpgschema  = importPost( "DBpgschema",  "mediawiki" );
-       
+
        ## SQLite specific
-       $conf->SQLiteDataDir = importPost( "SQLiteDataDir", "" );
-       
-       ## MSSQL specific
-       // We need a second field so it doesn't overwrite the MySQL one
-       $conf->DBprefix2 = importPost( "DBprefix2" );
-       
+       $conf->SQLiteDataDir = importPost( "SQLiteDataDir", "$IP/../data" );
+
        ## DB2 specific:
        // New variable in order to have a different default port number
        $conf->DBport_db2   = importPost( "DBport_db2",      "50000" );
@@ -664,17 +653,19 @@ $errs = array();
 if( preg_match( '/^$|^mediawiki$|#/i', $conf->Sitename ) ) {
        $errs["Sitename"] = "Must not be blank or \"MediaWiki\" and may not contain \"#\"";
 }
-if( $conf->DBuser == "" ) {
-       $errs["DBuser"] = "Must not be blank";
-}
-if( ($conf->DBtype == 'mysql') && (strlen($conf->DBuser) > 16) ) {
-       $errs["DBuser"] = "Username too long";
-}
-if( $conf->DBpassword == "" && $conf->DBtype != "postgres" ) {
-       $errs["DBpassword"] = "Must not be blank";
-}
-if( $conf->DBpassword != $conf->DBpassword2 ) {
-       $errs["DBpassword2"] = "Passwords don't match!";
+if( !$ourdb[$conf->DBtype]['serverless'] ) {
+       if( $conf->DBuser == "" ) {
+               $errs["DBuser"] = "Must not be blank";
+       }
+       if( ($conf->DBtype == 'mysql') && (strlen($conf->DBuser) > 16) ) {
+               $errs["DBuser"] = "Username too long";
+       }
+       if( $conf->DBpassword == "" && $conf->DBtype != "postgres" ) {
+               $errs["DBpassword"] = "Must not be blank";
+       }
+       if( $conf->DBpassword != $conf->DBpassword2 ) {
+               $errs["DBpassword2"] = "Passwords don't match!";
+       }
 }
 if( !preg_match( '/^[A-Za-z_0-9]*$/', $conf->DBprefix ) ) {
        $errs["DBprefix"] = "Invalid table prefix";
@@ -785,7 +776,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                $local = writeLocalSettings( $conf );
                echo "<li style=\"list-style: none\">\n";
                echo "<p><b>Generating configuration file...</b></p>\n";
-               echo "</li>\n";         
+               echo "</li>\n";
 
                $wgCommandLineMode = false;
                chdir( ".." );
@@ -831,24 +822,21 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                        $wgDBmwschema = $conf->DBdb2schema;
                }
 
-               if( $conf->DBprefix2 != '' ) {
-                       // For MSSQL
-                       $wgDBprefix = $conf->DBprefix2;
-               } elseif( $conf->DBprefix_ora != '' ) {
+               if( $conf->DBprefix_ora != '' ) {
                        // For Oracle
                        $wgDBprefix = $conf->DBprefix_ora;
                }
 
                ## DB2 specific:
                $wgDBcataloged = $conf->DBcataloged;
-               
+
                $wgCommandLineMode = true;
                if (! defined ( 'STDERR' ) )
                        define( 'STDERR', fopen("php://stderr", "wb"));
                $wgUseDatabaseMessages = false; /* FIXME: For database failure */
                require_once( "$IP/includes/Setup.php" );
                Language::getLocalisationCache()->disableBackend();
-               
+
                chdir( "config" );
 
                $wgTitle = Title::newFromText( "Installation script" );
@@ -930,14 +918,14 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                                $db_user = $wgDBuser;
                                $db_pass = $wgDBpassword;
                        }
-                       
-                       echo( "<li>Attempting to connect to database \"" . htmlspecialchars( $wgDBname ) . 
+
+                       echo( "<li>Attempting to connect to database \"" . htmlspecialchars( $wgDBname ) .
                                "\" as \"" . htmlspecialchars( $db_user ) . "\"..." );
                        $wgDatabase = $dbc->newFromParams($wgDBserver, $db_user, $db_pass, $wgDBname, 1);
                        // enable extra debug messages
                        $dbc->setMode(DatabaseIbm_db2::INSTALL_MODE);
                        $wgDatabase->setMode(DatabaseIbm_db2::INSTALL_MODE);
-                       
+
                        if (!$wgDatabase->isOpen()) {
                                print " error: " . htmlspecialchars( $wgDatabase->lastError() ) . "</li>\n";
                        } else {
@@ -946,11 +934,9 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                        if (is_callable(array($wgDatabase, 'initial_setup'))) $wgDatabase->initial_setup('', $wgDBname);
 
                } elseif ( $conf->DBtype == 'sqlite' ) {
-                       if ("$wgSQLiteDataDir" == '') {
-                               $wgSQLiteDataDir = dirname($_SERVER['DOCUMENT_ROOT']).'/data';
-                       }
-                       echo "<li>Attempting to connect to SQLite database at \"" . 
-                               htmlspecialchars( $wgSQLiteDataDir ) .  "\"";
+                       $wgSQLiteDataDir = $conf->SQLiteDataDir;
+                       echo '<li>Attempting to connect to SQLite database at "' .
+                               htmlspecialchars( $wgSQLiteDataDir ) . '": ';
                        if ( !is_dir( $wgSQLiteDataDir ) ) {
                                if ( is_writable( dirname( $wgSQLiteDataDir ) ) ) {
                                        $ok = wfMkdirParents( $wgSQLiteDataDir, $wgSQLiteDataDirMode );
@@ -958,35 +944,55 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                                        $ok = false;
                                }
                                if ( !$ok ) {
-                                       echo "cannot create data directory</li>";
+                                       echo "cannot create data directory</li>";
                                        $errs['SQLiteDataDir'] = 'Enter a valid data directory';
                                        continue;
                                }
                        }
                        if ( !is_writable( $wgSQLiteDataDir ) ) {
-                               echo "data directory not writable</li>";
+                               echo "data directory not writable</li>";
                                $errs['SQLiteDataDir'] = 'Enter a writable data directory';
                                continue;
                        }
-                       $dataFile = "$wgSQLiteDataDir/$wgDBname.sqlite";
-                       if ( file_exists( $dataFile ) && !is_writable( $dataFile ) ) {
-                               echo ": data file not writable</li>";
-                               $errs['SQLiteDataDir'] = "$wgDBname.sqlite is not writable";
+                       $dataFile = DatabaseSqlite::generateFileName( $wgSQLiteDataDir, $wgDBname );
+                       if ( file_exists( $dataFile ) ) {
+                               if ( !is_writable( $dataFile ) ) {
+                                       echo "data file not writable</li>";
+                                       $errs['SQLiteDataDir'] = basename( $dataFile ) . " is not writable";
+                                       continue;
+                               }
+                       } else {
+                               if ( file_put_contents( $dataFile, '' ) === false ) {
+                                       echo 'could not create database file "' . htmlspecialchars( basename( $dataFile ) ) . "\"</li>\n";
+                                       $errs['SQLiteDataDir'] = "couldn't create " . basename( $dataFile );
+                                       continue;
+                               }
+                       }
+                       try {
+                               $wgDatabase = new DatabaseSqlite( false, false, false, $wgDBname, 1 );
+                       }
+                       catch( MWException $ex ) {
+                               echo 'error: ' . htmlspecialchars( $ex->getMessage() ) . "</li>\n";
                                continue;
                        }
-                       $wgDatabase = new DatabaseSqlite( false, false, false, $wgDBname, 1 );
+
                        if (!$wgDatabase->isOpen()) {
-                               print "error: " . htmlspecialchars( $wgDatabase->lastError() ) . "</li>\n";
+                               print "error: " . htmlspecialchars( $wgDatabase->lastError() ) . "</li>\n";
                                $errs['SQLiteDataDir'] = 'Could not connect to database';
                                continue;
                        } else {
                                $myver = $wgDatabase->getServerVersion();
                        }
-                       if (is_callable(array($wgDatabase, 'initial_setup'))) $wgDatabase->initial_setup('', $wgDBname);
+                       if ( is_callable( array( $wgDatabase, 'initial_setup' ) ) ) {
+                               $wgDatabase->initial_setup('', $wgDBname);
+                       }
                        echo "ok</li>\n";
                } elseif ( $conf->DBtype == 'oracle' ) {
                        echo "<li>Attempting to connect to database \"" . htmlspecialchars( $wgDBname ) ."\"</li>";
+                       $old_error_level = error_reporting();
+                       wfSuppressWarnings();
                        $wgDatabase = $dbc->newFromParams('DUMMY', $wgDBuser, $wgDBpassword, $wgDBname, 1);
+                       wfRestoreWarnings();
                        if (!$wgDatabase->isOpen()) {
                                $ok = true;
                                echo "<li>Connect failed.</li>";
@@ -1002,7 +1008,8 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                                                if ($wgDatabase->isOpen()) {
                                                        $wgDBOracleDefTS = $conf->DBdefTS_ora;
                                                        $wgDBOracleTempTS = $conf->DBtempTS_ora;
-                                                       $wgDatabase->sourceFile( "../maintenance/ora/user.sql"  );
+                                                       $res = $wgDatabase->sourceFile( "../maintenance/ora/user.sql"  );
+                                                       if ($res !== true) dieout($res);
                                                } else {
                                                        echo "<li>Invalid database superuser, please supply a valid superuser account.</li>";
                                                        echo "<li>ERR: ".print_r(oci_error(), true)."</li>";
@@ -1030,10 +1037,9 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                        ## Possible connect as a superuser
                        // Changed !mysql to postgres check since it seems to only apply to postgres
                        if( $useRoot && $conf->DBtype == 'postgres' ) {
-                               $wgDBsuperuser = $conf->RootUser;
-                               echo( "<li>Attempting to connect to database \"postgres\" as superuser \"" . 
-                                       htmlspecialchars( $wgDBsuperuser ) . "\"..." );
-                               $wgDatabase = $dbc->newFromParams($wgDBserver, $wgDBsuperuser, $conf->RootPW, "postgres", 1);
+                               echo( "<li>Attempting to connect to database \"postgres\" as superuser \"" .
+                                       htmlspecialchars( $conf->RootUser ) . "\"..." );
+                               $wgDatabase = $dbc->newFromParams($wgDBserver, $conf->RootUser, $conf->RootPW, "postgres", 1);
                                if (!$wgDatabase->isOpen()) {
                                        print " error: " . htmlspecialchars( $wgDatabase->lastError() ) . "</li>\n";
                                        $errs["DBserver"] = "Could not connect to database as superuser";
@@ -1041,9 +1047,9 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                                        $errs["RootPW"] = "and password";
                                        continue;
                                }
-                               $wgDatabase->initial_setup($conf->RootPW, 'postgres');
+                               $wgDatabase->initial_setup($conf->RootUser, $conf->RootPW, 'postgres');
                        }
-                       echo( "<li>Attempting to connect to database \"" . htmlspecialchars( $wgDBname ) . 
+                       echo( "<li>Attempting to connect to database \"" . htmlspecialchars( $wgDBname ) .
                                "\" as \"" . htmlspecialchars( $wgDBuser ) . "\"..." );
                        $wgDatabase = $dbc->newFromParams($wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, 1);
                        if (!$wgDatabase->isOpen()) {
@@ -1056,7 +1062,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                                $myver = $wgDatabase->getServerVersion();
                        }
                        if (is_callable(array($wgDatabase, 'initial_setup'))) $wgDatabase->initial_setup('', $wgDBname);
-               } 
+               }
 
                if ( !$wgDatabase->isOpen() ) {
                        $errs["DBserver"] = "Couldn't connect to database";
@@ -1153,7 +1159,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                                                $encExisting = htmlspecialchars( $existingSchema );
                                                $encRequested = htmlspecialchars( $conf->DBschema );
                                                print "<li><strong>Warning:</strong> you requested the $encRequested schema, " .
-                                                       "but the existing database has the $encExisting schema. This upgrade script ". 
+                                                       "but the existing database has the $encExisting schema. This upgrade script ".
                                                        "can't convert it, so it will remain $encExisting.</li>\n";
                                                $conf->setSchema( $existingSchema, $conf->DBengine );
                                        }
@@ -1179,7 +1185,8 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                                                        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>";
                                                }
                                                print "</li>\n";
-                                               $wgDatabase->sourceFile( "../maintenance/users.sql" );
+                                               $res = $wgDatabase->sourceFile( "../maintenance/users.sql" );
+                                               if ($res !== true) dieout($res);
                                        }
                                }
                        }
@@ -1204,18 +1211,26 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                                }
                                $wgDatabase->freeResult( $res );
                                if ( !$found && $conf->DBengine != 'MyISAM' ) {
-                                       echo "<li><strong>Warning:</strong> " . htmlspecialchars( $conf->DBengine ) . 
+                                       echo "<li><strong>Warning:</strong> " . htmlspecialchars( $conf->DBengine ) .
                                                " storage engine not available, " .
                                                "using MyISAM instead</li>\n";
                                        $conf->setSchema( $conf->DBschema, 'MyISAM' );
                                }
                        }
 
-                       # FIXME: Check for errors
                        print "<li>Creating tables...";
                        if ($conf->DBtype == 'mysql') {
-                               $wgDatabase->sourceFile( "../maintenance/tables.sql" );
-                               $wgDatabase->sourceFile( "../maintenance/interwiki.sql" );
+                               $res = $wgDatabase->sourceFile( "../maintenance/tables.sql" );
+                               if ($res === true) {
+                                       print " done.</li>\n<li>Populating interwiki table... \n";
+                                       $res = $wgDatabase->sourceFile( "../maintenance/interwiki.sql" );
+                               }
+                               if ($res === true) {
+                                       print " done.</li>\n";
+                               } else {
+                                       print " <b>FAILED</b></li>\n";
+                                       dieout( htmlspecialchars( $res ) );
+                               }
                        } elseif (is_callable(array($wgDatabase, 'setup_database'))) {
                                $wgDatabase->setup_database();
                        }
@@ -1224,10 +1239,8 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                                continue;
                        }
 
-                       print " done.</li>\n";
-                       
-               
-                       if ($conf->DBtype == 'ibm_db2') {
+
+                       if ( $conf->DBtype == 'ibm_db2' ) {
                                // Now that table creation is done, make sure everything is committed
                                // Do this before doing inserts through API
                                if ($wgDatabase->lastError()) {
@@ -1238,6 +1251,10 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                                        print "<li>MediaWiki tables successfully created</li>\n";
                                        $wgDatabase->commit();
                                }
+                       } elseif ( $conf->DBtype == 'sqlite' ) {
+                               // Ensure proper searchindex format. We have to do that separately because
+                               // if SQLite is compiled without the FTS3 module, table creation syntax will be invalid.
+                               sqlite_setup_searchindex();
                        }
 
                        print "<li>Initializing statistics...</li>\n";
@@ -1262,8 +1279,13 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                                } else {
                                        # Yes, so run the grants
                                        echo( "<li>" . htmlspecialchars( "Granting user permissions to $wgDBuser on $wgDBname..." ) );
-                                       $wgDatabase->sourceFile( "../maintenance/users.sql" );
-                                       echo( "success.</li>\n" );
+                                       $res = $wgDatabase->sourceFile( "../maintenance/users.sql" );
+                                       if ( $res === true ) {
+                                               echo( " success.</li>\n" );
+                                       } else {
+                                               echo( " <b>FAILED</b>.</li>\n" );
+                                               dieout( $res );
+                                       }
                                }
                        }
 
@@ -1311,7 +1333,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) {
                $localSettings = str_replace( "\r\n", "\n", $localSettings );
                $f = fopen( "LocalSettings.php", 'xt' );
 
-               if( $f == false ) {
+               if( !$f ) {
                        print( "</li>\n" );
                        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" .
                        "<p>Here's the file that would have been written, try to paste it into place manually:</p>\n" .
@@ -1430,11 +1452,6 @@ if( count( $errs ) ) {
                <ul class="plain">
                <li><?php aField( $conf, "Shm", "No caching", "radio", "none" ); ?></li>
                <?php
-                       if ( $conf->turck ) {
-                               echo "<li>";
-                               aField( $conf, "Shm", "Turck MMCache", "radio", "turck" );
-                               echo "</li>\n";
-                       }
                        if( $conf->xcache ) {
                                echo "<li>";
                                aField( $conf, 'Shm', 'XCache', 'radio', 'xcache' );
@@ -1464,10 +1481,10 @@ if( count( $errs ) ) {
                An object caching system such as memcached will provide a significant performance boost,
                but needs to be installed. Provide the server addresses and ports in a comma-separated list.
                <br /><br />
-               MediaWiki can also detect and support eAccelerator, Turck MMCache, APC, and XCache, but
+               MediaWiki can also detect and support eAccelerator, APC, and XCache, but
                these should not be used if the wiki will be running on multiple application servers.
-               <br/><br/>
-               DBA (Berkeley-style DB) is generally slower than using no cache at all, and is only 
+               <br /><br />
+               DBA (Berkeley-style DB) is generally slower than using no cache at all, and is only
                recommended for testing.
        </p>
 </div>
@@ -1501,14 +1518,14 @@ if( count( $errs ) ) {
                <label class='column'>E-mail notification about changes:</label>
                <ul class="plain">
                <li><?php aField( $conf, "Enotif", "Disabled", "radio", "enotif_disabled" ); ?></li>
-               <li><?php aField( $conf, "Enotif", "Enabled for changes to user discussion pages only", "radio", "enotif_usertalk" ); ?></li>
-               <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>
+               <li><?php aField( $conf, "Enotif", "Changes to user discussion pages only", "radio", "enotif_usertalk" ); ?></li>
+               <li><?php aField( $conf, "Enotif", "Changes to user discussion pages, and to pages on watchlists (not recommended for large wikis)", "radio", "enotif_allpages" ); ?></li>
                </ul>
        </div>
        <div class="config-desc">
                <p>
                For this feature to work, an e-mail address must be present for the user account, and the notification
-               options in the user's preferences must be enabled. Also note the 
+               options in the user's preferences must be enabled. Also note the
                authentication option below. When testing the feature, keep in mind that your own changes will never trigger notifications to be sent to yourself.</p>
 
                <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>
@@ -1533,48 +1550,52 @@ if( count( $errs ) ) {
 <div class="config-section">
 <div class="config-input">
        <label class='column'>Database type:</label>
-<?php 
+<?php
        if (isset($errs['DBpicktype'])) {
                print "\t<span class='error'>" . htmlspecialchars( $errs['DBpicktype'] ) . "</span>\n";
        }
 ?>
-       <ul class='plain'><?php 
-               database_picker($conf); 
+       <ul class='plain'><?php
+               database_picker($conf);
        ?></ul>
        </div>
 
-       <div class="config-input" style="clear:left">
-       <?php aField( $conf, "DBserver", "Database host:" ); ?>
+       <div id="db-server-settings1">
+               <div class="config-input" style="clear:left">
+               <?php aField( $conf, "DBserver", "Database host:" ); ?>
+               </div>
+               <p class="config-desc">
+                       If your database server isn't on your web server, enter the name or IP address here.
+               </p>
        </div>
-       <p class="config-desc">
-               If your database server isn't on your web server, enter the name or IP address here.
-       </p>
 
-       <div class="config-input"><?php aField( $conf, "DBname", "Database name:" ); ?></div>
-       <div class="config-input"><?php aField( $conf, "DBuser", "DB username:" ); ?></div>
-       <div class="config-input"><?php aField( $conf, "DBpassword", "DB password:", "password" ); ?></div>
-       <div class="config-input"><?php aField( $conf, "DBpassword2", "DB password confirm:", "password" ); ?></div>
-       <p class="config-desc">
-               If you only have a single user account and database available,
-               enter those here. If you have database root access (see below)
-               you can specify new accounts/databases to be created. This account 
-               will not be created if it pre-exists. If this is the case, ensure that it
-               has SELECT, INSERT, UPDATE, and DELETE permissions on the MediaWiki database.
-       </p>
-
-       <div class="config-input">
-               <label class="column">Superuser account:</label>
-               <input type="checkbox" name="useroot" id="useroot" <?php if( $useRoot ) { ?>checked="checked" <?php } ?> />
-               &nbsp;<label for="useroot">Use superuser account</label>
+               <div class="config-input"><?php aField( $conf, "DBname", "Database name:" ); ?></div>
+       <div id="db-server-settings2">
+               <div class="config-input"><?php aField( $conf, "DBuser", "DB username:" ); ?></div>
+               <div class="config-input"><?php aField( $conf, "DBpassword", "DB password:", "password" ); ?></div>
+               <div class="config-input"><?php aField( $conf, "DBpassword2", "DB password confirm:", "password" ); ?></div>
+               <p class="config-desc">
+                       If you only have a single user account and database available,
+                       enter those here. If you have database root access (see below)
+                       you can specify new accounts/databases to be created. This account
+                       will not be created if it pre-exists. If this is the case, ensure that it
+                       has SELECT, INSERT, UPDATE, and DELETE permissions on the MediaWiki database.
+               </p>
+
+               <div class="config-input">
+                       <label class="column">Superuser account:</label>
+                       <input type="checkbox" name="useroot" id="useroot" <?php if( $useRoot ) { ?>checked="checked" <?php } ?> />
+                       &#160;<label for="useroot">Use superuser account</label>
+               </div>
+               <div class="config-input"><?php aField( $conf, "RootUser", "Superuser name:", "text" ); ?></div>
+               <div class="config-input"><?php aField( $conf, "RootPW", "Superuser password:", "password" ); ?></div>
+
+               <p class="config-desc">
+                       If the database user specified above does not exist, or does not have access to create
+                       the database (if needed) or tables within it, please check the box and provide details
+                       of a superuser account, such as <strong>root</strong>, which does.
+               </p>
        </div>
-       <div class="config-input"><?php aField( $conf, "RootUser", "Superuser name:", "text" ); ?></div>
-       <div class="config-input"><?php aField( $conf, "RootPW", "Superuser password:", "password" ); ?></div>
-
-       <p class="config-desc">
-               If the database user specified above does not exist, or does not have access to create
-               the database (if needed) or tables within it, please check the box and provide details
-               of a superuser account, such as <strong>root</strong>, which does.
-       </p>
 
        <?php database_switcher('mysql'); ?>
        <div class="config-input"><?php aField( $conf, "DBprefix", "Database table prefix:" ); ?></div>
@@ -1594,8 +1615,8 @@ if( count( $errs ) ) {
                </ul>
        </div>
        <p class="config-desc">
-               InnoDB is best for public web installations, since it has good concurrency 
-               support. MyISAM may be faster in single-user installations. MyISAM databases 
+               InnoDB is best for public web installations, since it has good concurrency
+               support. MyISAM may be faster in single-user installations. MyISAM databases
                tend to get corrupted more often than InnoDB databases.
        </p>
        <div class="config-input"><label class="column">Database character set</label>
@@ -1607,10 +1628,10 @@ if( count( $errs ) ) {
                </ul>
        </div>
        <p class="config-desc">
-               This option is ignored on upgrade, the same character set will be kept. 
-               <br/><br/>
+               This option is ignored on upgrade, the same character set will be kept.
+               <br /><br />
                <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!.
-               <br/><br/>
+               <br /><br />
                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>.
        </p>
        </fieldset>
@@ -1620,41 +1641,24 @@ if( count( $errs ) ) {
        <div class="config-input"><?php aField( $conf, "DBpgschema", "Schema for mediawiki:" ); ?></div>
        <div class="config-input"><?php aField( $conf, "DBts2schema", "Schema for tsearch2:" ); ?></div>
        <div class="config-desc">
-               <p>The username specified above (at "DB username") will have its search path set to the above schemas, 
-               so it is recommended that you create a new user. The above schemas are generally correct: 
+               <p>The username specified above (at "DB username") will have its search path set to the above schemas,
+               so it is recommended that you create a new user. The above schemas are generally correct:
         only change them if you are sure you need to.</p>
        </div>
        </fieldset>
 
        <?php database_switcher('sqlite'); ?>
-       <div class="config-desc">
-               <b>NOTE:</b> SQLite only uses the <i>Database name</i> setting above, the user, password and root settings are ignored.
-       </div>
        <div class="config-input"><?php
                aField( $conf, "SQLiteDataDir", "SQLite data directory:" );
        ?></div>
        <div class="config-desc">
-               <p>SQLite stores table data into files in the filesystem.
-               If you do not provide an explicit path, a "data" directory in
-               the parent of your document root will be used.</p>
-               
+               <p>SQLite stores table data into files in the
+               filesystem.</p>
+
                <p>This directory must exist and be writable by the web server.</p>
        </div>
        </fieldset>
 
-       <?php database_switcher('mssql'); ?>
-       <div class="config-input"><?php
-               aField( $conf, "DBprefix2", "Database table prefix:" );
-       ?></div>
-       <div class="config-desc">
-               <p>If you need to share one database between multiple wikis, or
-               between MediaWiki and another web application, you may choose to
-               add a prefix to all the table names to avoid conflicts.</p>
-
-               <p>Avoid exotic characters; something like <tt>mw_</tt> is good.</p>
-       </div>
-       </fieldset>
-       
        <?php database_switcher('ibm_db2'); ?>
        <div class="config-input"><?php
                aField( $conf, "DBport_db2", "Database port:" );
@@ -1688,7 +1692,7 @@ if( count( $errs ) ) {
        </fieldset>
 
        <div class="config-input" style="padding:2em 0 3em">
-               <label class='column'>&nbsp;</label>
+               <label class='column'>&#160;</label>
                <input type="submit" value="Install MediaWiki!" class="btn-install" />
        </div>
 </div>
@@ -1707,7 +1711,7 @@ window.onload = toggleDBarea( <?php echo Xml::encodeJsVar( $conf->DBtype ); ?>,
 function writeSuccessMessage() {
  $script = defined('MW_INSTALL_PHP5_EXT') ? 'index.php5' : 'index.php';
        if ( wfIniGetBool( 'safe_mode' ) && !ini_get( 'open_basedir' ) ) {
-               echo <<<EOT
+               echo <<<HTML
 <div class="success-box">
 <p>Installation successful!</p>
 <p>To complete the installation, please do the following:
@@ -1722,9 +1726,9 @@ remotely. LocalSettings.php is currently owned by the user your webserver is run
 which means that anyone on the same server can read your database password! Downloading
 it and uploading it again will hopefully change the ownership to a user ID specific to you.</p>
 </div>
-EOT;
+HTML;
        } else {
-               echo <<<EOT
+               echo <<<HTML
 <div class="success-box">
 <p>
 <span class="success-message">Installation successful!</span>
@@ -1733,7 +1737,7 @@ Move the <tt>config/LocalSettings.php</tt> file to the parent directory, then fo
 <p>You should change file permissions for <tt>LocalSettings.php</tt> as required to
 prevent other users on the server reading passwords and altering configuration data.</p>
 </div>
-EOT;
+HTML;
        }
 }
 
@@ -1759,6 +1763,11 @@ function writeLocalSettings( $conf ) {
        $convert = ($conf->ImageMagick ? $conf->ImageMagick : "/usr/bin/convert" );
        $rights = ($conf->RightsUrl) ? "" : "# ";
        $hashedUploads = $conf->safeMode ? '' : '# ';
+       $dir = realpath( $conf->SQLiteDataDir );
+       if ( !$dir ) {
+               $dir = $conf->SQLiteDataDir; // dumb realpath sometimes fails
+       }
+       $sqliteDataDir = escapePhpString( $dir );
 
        if ( $conf->ShellLocale ) {
                $locale = '';
@@ -1772,7 +1781,6 @@ function writeLocalSettings( $conf ) {
                        $cacheType = 'CACHE_MEMCACHED';
                        $mcservers = var_export( $conf->MCServerArray, true );
                        break;
-               case 'turck':
                case 'xcache':
                case 'apc':
                case 'eaccel':
@@ -1851,21 +1859,17 @@ function writeLocalSettings( $conf ) {
        } elseif( $conf->DBtype == 'sqlite' ) {
                $dbsettings =
 "# SQLite-specific settings
-\$wgSQLiteDataDir    = \"{$slconf['SQLiteDataDir']}\";";
-       } elseif( $conf->DBtype == 'mssql' ) {
-               $dbsettings =
-"# MSSQL specific settings
-\$wgDBprefix         = \"{$slconf['DBprefix2']}\";";
+\$wgSQLiteDataDir    = \"{$sqliteDataDir}\";";
        } elseif( $conf->DBtype == 'ibm_db2' ) {
                $dbsettings =
 "# DB2 specific settings
-\$wgDBport_db2       = \"{$slconf['DBport_db2']}\";
+\$wgDBport       = \"{$slconf['DBport_db2']}\";
 \$wgDBmwschema       = \"{$slconf['DBdb2schema']}\";
 \$wgDBcataloged      = \"{$slconf['DBcataloged']}\";";
        } elseif( $conf->DBtype == 'oracle' ) {
                $dbsettings =
 "# Oracle specific settings
-\$wgDBprefix         = \"{$slconf['DBprefix']}\";";
+\$wgDBprefix         = \"{$slconf['DBprefix_ora']}\";";
        } else {
                // ummm... :D
                $dbsettings = '';
@@ -1914,6 +1918,13 @@ if ( \$wgCommandLineMode ) {
 \$wgScriptPath       = \"{$slconf['ScriptPath']}\";
 \$wgScriptExtension  = \"{$slconf['ScriptExtension']}\";
 
+## The relative URL path to the skins directory
+\$wgStylePath        = \"\$wgScriptPath/skins\";
+
+## The relative URL path to the logo.  Make sure you change this from the default,
+## or else you'll overwrite your logo when you upgrade!
+\$wgLogo             = \"\$wgStylePath/common/images/wiki.png\";
+
 ## UPO means: this is also a user preference option
 
 \$wgEnableEmail      = $enableemail;
@@ -1972,7 +1983,7 @@ if ( \$wgCommandLineMode ) {
 \$wgSecretKey = \"$secretKey\";
 
 ## Default skin: you can change the default skin. Use the internal symbolic
-## names, ie 'standard', 'nostalgia', 'cologneblue', 'monobook':
+## names, ie 'vector', 'monobook':
 \$wgDefaultSkin = 'monobook';
 
 ## For attaching licensing metadata to pages, and displaying an
@@ -1987,8 +1998,6 @@ if ( \$wgCommandLineMode ) {
 
 \$wgDiff3 = \"{$slconf['diff3']}\";
 
-\$wgPhpCliPath = \"{$slconf['phpCliPath']}\";
-
 # When you make changes to this configuration file, this will make
 # sure that cached pages are cleared.
 \$wgCacheEpoch = max( \$wgCacheEpoch, gmdate( 'YmdHis', @filemtime( __FILE__ ) ) );
@@ -2082,31 +2091,13 @@ function aField( &$conf, $field, $text, $type = "text", $value = "", $onclick =
 }
 
 function getLanguageList() {
-       global $wgLanguageNames, $IP;
-       if( !isset( $wgLanguageNames ) ) {
-               require_once( "$IP/languages/Names.php" );
-       }
+       global $wgDummyLanguageCodes;
 
        $codes = array();
-
-       $d = opendir( "../languages/messages" );
-       /* In case we are called from the root directory */
-       if (!$d)
-               $d = opendir( "languages/messages");
-       while( false !== ($f = readdir( $d ) ) ) {
-               $m = array();
-               if( preg_match( '/Messages([A-Z][a-z_]+)\.php$/', $f, $m ) ) {
-                       $code = str_replace( '_', '-', strtolower( $m[1] ) );
-                       if( $code == 'qqq' ) continue;
-                       if( isset( $wgLanguageNames[$code] ) ) {
-                               $name = wfBCP47( $code ) . ' - ' . $wgLanguageNames[$code];
-                       } else {
-                               $name = $code;
-                       }
-                       $codes[$code] = $name;
-               }
+       foreach ( Language::getLanguageNames() as $code => $name ) {
+               if( in_array( $code, $wgDummyLanguageCodes ) ) continue;
+               $codes[$code] = $code . ' - ' . $name;
        }
-       closedir( $d );
        ksort( $codes );
        return $codes;
 }
@@ -2194,7 +2185,7 @@ function database_switcher($db) {
        global $ourdb;
        $color = $ourdb[$db]['bgcolor'];
        $full = $ourdb[$db]['fullname'];
-       print "<fieldset id='$db'><legend>$full specific options</legend>\n";
+       print "<fieldset id='$db' style='clear:both'><legend>$full-specific options</legend>\n";
 }
 
 function printListItem( $item ) {
@@ -2266,17 +2257,6 @@ function getShellLocale( $wikiLang ) {
        return false;
 }
 
-function wfArrayMap( $function, $input ) {
-       $ret = array_map( $function, $input );
-       foreach ( $ret as $key => $value ) {
-               $taint = istainted( $input[$key] );
-               if ( $taint ) {
-                       taint( $ret[$key], $taint );
-               }
-       }
-       return $ret;
-}
-
 ?>
 
        <div class="license">
@@ -2316,7 +2296,7 @@ function wfArrayMap( $function, $input ) {
                        <li><a href="http://www.mediawiki.org/wiki/Manual:Contents">Administrator's Guide</a></li>
                        <li><a href="http://www.mediawiki.org/wiki/Manual:FAQ">FAQ</a></li>
                </ul>
-               <p style="font-size:90%;margin-top:1em">MediaWiki is Copyright © 2001-2009 by Magnus Manske, Brion Vibber,
+               <p style="font-size:90%;margin-top:1em">MediaWiki is Copyright © 2001-2010 by Magnus Manske, Brion Vibber,
                 Lee Daniel Crocker, Tim Starling, Erik Möller, Gabriel Wicke, Ævar Arnfjörð Bjarmason, Niklas Laxström,
                 Domas Mituzas, Rob Church, Yuri Astrakhan, Aryeh Gregor, Aaron Schulz and others.</p>
        </div></div>