]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - install.php
Merge branch '0.8.x' into 0.9.x
[quix0rs-gnu-social.git] / install.php
1
2 <?php
3 /**
4  * StatusNet - the distributed open-source microblogging tool
5  * Copyright (C) 2009, StatusNet, Inc.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as published by
9  * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  * @category Installation
21  * @package  Installation
22  *
23  * @author   Adrian Lang <mail@adrianlang.de>
24  * @author   Brenda Wallace <shiny@cpan.org>
25  * @author   Brett Taylor <brett@webfroot.co.nz>
26  * @author   Brion Vibber <brion@pobox.com>
27  * @author   CiaranG <ciaran@ciarang.com>
28  * @author   Craig Andrews <candrews@integralblue.com>
29  * @author   Eric Helgeson <helfire@Erics-MBP.local>
30  * @author   Evan Prodromou <evan@status.net>
31  * @author   Robin Millette <millette@controlyourself.ca>
32  * @author   Sarven Capadisli <csarven@status.net>
33  * @author   Tom Adams <tom@holizz.com>
34  * @license  GNU Affero General Public License http://www.gnu.org/licenses/
35  * @version  0.9.x
36  * @link     http://status.net
37  */
38
39 define('INSTALLDIR', dirname(__FILE__));
40
41 $external_libraries=array(
42     array(
43         'name'=>'gettext',
44         'url'=>'http://us.php.net/manual/en/book.gettext.php',
45         'check_function'=>'gettext'
46     ),
47     array(
48         'name'=>'PEAR',
49         'url'=>'http://pear.php.net/',
50         'deb'=>'php-pear',
51         'include'=>'PEAR.php',
52         'check_class'=>'PEAR'
53     ),
54     array(
55         'name'=>'DB',
56         'pear'=>'DB',
57         'url'=>'http://pear.php.net/package/DB',
58         'deb'=>'php-db',
59         'include'=>'DB/common.php',
60         'check_class'=>'DB_common'
61     ),
62     array(
63         'name'=>'DB_DataObject',
64         'pear'=>'DB_DataObject',
65         'url'=>'http://pear.php.net/package/DB_DataObject',
66         'include'=>'DB/DataObject.php',
67         'check_class'=>'DB_DataObject'
68     ),
69     array(
70         'name'=>'Console_Getopt',
71         'pear'=>'Console_Getopt',
72         'url'=>'http://pear.php.net/package/Console_Getopt',
73         'include'=>'Console/Getopt.php',
74         'check_class'=>'Console_Getopt'
75     ),
76     array(
77         'name'=>'Facebook API',
78         'url'=>'http://developers.facebook.com/',
79         'include'=>'facebook/facebook.php',
80         'check_class'=>'Facebook'
81     ),
82     array(
83         'name'=>'htmLawed',
84         'url'=>'http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed',
85         'include'=>'htmLawed/htmLawed.php',
86         'check_function'=>'htmLawed'
87     ),
88     array(
89         'name'=>'HTTP_Request',
90         'pear'=>'HTTP_Request',
91         'url'=>'http://pear.php.net/package/HTTP_Request',
92         'deb'=>'php-http-request',
93         'include'=>'HTTP/Request.php',
94         'check_class'=>'HTTP_Request'
95     ),
96     array(
97         'name'=>'HTTP_Request2',
98         'pear'=>'HTTP_Request2',
99         'url'=>'http://pear.php.net/package/HTTP_Request2',
100         'include'=>'HTTP/Request2.php',
101         'check_class'=>'HTTP_Request2'
102     ),
103     array(
104         'name'=>'Mail',
105         'pear'=>'Mail',
106         'url'=>'http://pear.php.net/package/Mail',
107         'deb'=>'php-mail',
108         'include'=>'Mail.php',
109         'check_class'=>'Mail'
110     ),
111     array(
112         'name'=>'Mail_mimeDecode',
113         'pear'=>'Mail_mimeDecode',
114         'url'=>'http://pear.php.net/package/Mail_mimeDecode',
115         'deb'=>'php-mail-mimedecode',
116         'include'=>'Mail/mimeDecode.php',
117         'check_class'=>'Mail_mimeDecode'
118     ),
119     array(
120         'name'=>'Mime_Type',
121         'pear'=>'Mime_Type',
122         'url'=>'http://pear.php.net/package/Mime_Type',
123         'include'=>'MIME/Type.php',
124         'check_class'=>'Mime_Type'
125     ),
126     array(
127         'name'=>'Net_URL_Mapper',
128         'pear'=>'Net_URL_Mapper',
129         'url'=>'http://pear.php.net/package/Net_URL_Mapper',
130         'include'=>'Net/URL/Mapper.php',
131         'check_class'=>'Net_URL_Mapper'
132     ),
133     array(
134         'name'=>'Net_LDAP2',
135         'pear'=>'Net_LDAP2',
136         'url'=>'http://pear.php.net/package/Net_LDAP2',
137         'deb'=>'php-net-ldap2',
138         'include'=>'Net/LDAP2.php',
139         'check_class'=>'Net_LDAP2'
140     ),
141     array(
142         'name'=>'Net_Socket',
143         'pear'=>'Net_Socket',
144         'url'=>'http://pear.php.net/package/Net_Socket',
145         'deb'=>'php-net-socket',
146         'include'=>'Net/Socket.php',
147         'check_class'=>'Net_Socket'
148     ),
149     array(
150         'name'=>'Net_SMTP',
151         'pear'=>'Net_SMTP',
152         'url'=>'http://pear.php.net/package/Net_SMTP',
153         'deb'=>'php-net-smtp',
154         'include'=>'Net/SMTP.php',
155         'check_class'=>'Net_SMTP'
156     ),
157     array(
158         'name'=>'Net_URL',
159         'pear'=>'Net_URL',
160         'url'=>'http://pear.php.net/package/Net_URL',
161         'deb'=>'php-net-url',
162         'include'=>'Net/URL.php',
163         'check_class'=>'Net_URL'
164     ),
165     array(
166         'name'=>'Net_URL2',
167         'pear'=>'Net_URL2',
168         'url'=>'http://pear.php.net/package/Net_URL2',
169         'include'=>'Net/URL2.php',
170         'check_class'=>'Net_URL2'
171     ),
172     array(
173         'name'=>'Services_oEmbed',
174         'pear'=>'Services_oEmbed',
175         'url'=>'http://pear.php.net/package/Services_oEmbed',
176         'include'=>'Services/oEmbed.php',
177         'check_class'=>'Services_oEmbed'
178     ),
179     array(
180         'name'=>'Stomp',
181         'url'=>'http://stomp.codehaus.org/PHP',
182         'include'=>'Stomp.php',
183         'check_class'=>'Stomp'
184     ),
185     array(
186         'name'=>'System_Command',
187         'pear'=>'System_Command',
188         'url'=>'http://pear.php.net/package/System_Command',
189         'include'=>'System/Command.php',
190         'check_class'=>'System_Command'
191     ),
192     array(
193         'name'=>'XMPPHP',
194         'url'=>'http://code.google.com/p/xmpphp',
195         'include'=>'XMPPHP/XMPP.php',
196         'check_class'=>'XMPPHP_XMPP'
197     ),
198     array(
199         'name'=>'PHP Markdown',
200         'url'=>'http://www.michelf.com/projects/php-markdown/',
201         'include'=>'markdown.php',
202         'check_class'=>'Markdown_Parser'
203     ),
204     array(
205         'name'=>'OAuth',
206         'url'=>'http://code.google.com/p/oauth-php',
207         'include'=>'OAuth.php',
208         'check_class'=>'OAuthRequest'
209     ),
210     array(
211         'name'=>'Validate',
212         'pear'=>'Validate',
213         'url'=>'http://pear.php.net/package/Validate',
214         'include'=>'Validate.php',
215         'check_class'=>'Validate'
216     )
217 );
218 $dbModules = array(
219     'mysql' => array(
220         'name' => 'MySQL',
221         'check_module' => 'mysql', // mysqli?
222         'installer' => 'mysql_db_installer',
223     ),
224     'pgsql' => array(
225         'name' => 'PostgreSQL',
226         'check_module' => 'pgsql',
227         'installer' => 'pgsql_db_installer',
228     ),
229 );
230
231 /**
232  * the actual installation.
233  * If call libraries are present, then install
234  *
235  * @return void
236  */
237 function main()
238 {
239     if (!checkPrereqs()) {
240         return;
241     }
242
243     if (!empty($_GET['checklibs'])) {
244         showLibs();
245     } else {
246         if ($_SERVER['REQUEST_METHOD'] == 'POST') {
247             handlePost();
248         } else {
249             showForm();
250         }
251     }
252 }
253
254 /**
255  * checks if an external libary is present
256  *
257  * @param string $external_library Name of library
258  *
259  * @return boolean indicates if library present
260  */
261 function haveExternalLibrary($external_library)
262 {
263     if (isset($external_library['include']) && !haveIncludeFile($external_library['include'])) {
264         return false;
265     }
266     if (isset($external_library['check_function']) && ! function_exists($external_library['check_function'])) {
267         return false;
268     }
269     if (isset($external_library['check_class']) && ! class_exists($external_library['check_class'])) {
270         return false;
271     }
272     return true;
273 }
274
275 // Attempt to include a PHP file and report if it worked, while
276 // suppressing the annoying warning messages on failure.
277 function haveIncludeFile($filename) {
278     $old = error_reporting(error_reporting() & ~E_WARNING);
279     $ok = include_once($filename);
280     error_reporting($old);
281     return $ok;
282 }
283
284 /**
285  * Check if all is ready for installation
286  *
287  * @return void
288  */
289 function checkPrereqs()
290 {
291     $pass = true;
292
293     if (file_exists(INSTALLDIR.'/config.php')) {
294          printf('<p class="error">Config file &quot;config.php&quot; already exists.</p>');
295         $pass = false;
296     }
297
298     if (version_compare(PHP_VERSION, '5.2.3', '<')) {
299         printf('<p class="error">Require PHP version 5.2.3 or greater.</p>');
300         $pass = false;
301     }
302
303     $reqs = array('gd', 'curl',
304                   'xmlwriter', 'mbstring','tidy');
305
306     foreach ($reqs as $req) {
307         if (!checkExtension($req)) {
308             printf('<p class="error">Cannot load required extension: <code>%s</code></p>', $req);
309             $pass = false;
310         }
311     }
312     // Make sure we have at least one database module available
313     global $dbModules;
314     $missingExtensions = array();
315     foreach ($dbModules as $type => $info) {
316         if (!checkExtension($info['check_module'])) {
317             $missingExtensions[] = $info['check_module'];
318         }
319     }
320
321     if (count($missingExtensions) == count($dbModules)) {
322         $req = implode(', ', $missingExtensions);
323         printf('<p class="error">Cannot find mysql or pgsql extension. You need one or the other.');
324         $pass = false;
325     }
326
327     if (!is_writable(INSTALLDIR)) {
328         printf('<p class="error">Cannot write config file to: <code>%s</code></p>', INSTALLDIR);
329         printf('<p>On your server, try this command: <code>chmod a+w %s</code>', INSTALLDIR);
330         $pass = false;
331     }
332
333     // Check the subdirs used for file uploads
334     $fileSubdirs = array('avatar', 'background', 'file');
335     foreach ($fileSubdirs as $fileSubdir) {
336         $fileFullPath = INSTALLDIR."/$fileSubdir/";
337         if (!is_writable($fileFullPath)) {
338             printf('<p class="error">Cannot write to %s directory: <code>%s</code></p>', $fileSubdir, $fileFullPath);
339             printf('<p>On your server, try this command: <code>chmod a+w %s</code></p>', $fileFullPath);
340             $pass = false;
341         }
342     }
343
344     return $pass;
345 }
346
347 /**
348  * Checks if a php extension is both installed and loaded
349  *
350  * @param string $name of extension to check
351  *
352  * @return boolean whether extension is installed and loaded
353  */
354 function checkExtension($name)
355 {
356     if (extension_loaded($name)) {
357         return true;
358     } elseif (function_exists('dl') && ini_get('enable_dl') && !ini_get('safe_mode')) {
359         // dl will throw a fatal error if it's disabled or we're in safe mode.
360         // More fun, it may not even exist under some SAPIs in 5.3.0 or later...
361         $soname = $name . '.' . PHP_SHLIB_SUFFIX;
362         if (PHP_SHLIB_SUFFIX == 'dll') {
363             $soname = "php_" . $soname;
364         }
365         return @dl($soname);
366     } else {
367         return false;
368     }
369 }
370
371 /**
372  * Show list of libraries
373  *
374  * @return void
375  */
376 function showLibs()
377 {
378     global $external_libraries;
379     $present_libraries=array();
380     $absent_libraries=array();
381     foreach ($external_libraries as $external_library) {
382         if (haveExternalLibrary($external_library)) {
383             $present_libraries[]=$external_library;
384         } else {
385             $absent_libraries[]=$external_library;
386         }
387     }
388     echo<<<E_O_T
389     <div class="instructions">
390         <p>StatusNet comes bundled with a number of libraries required for the application to work. However, it is best that you use PEAR or you distribution to manage
391         libraries instead, as they tend to provide security updates faster, and may offer improved performance.</p>
392         <p>On Debian based distributions, such as Ubuntu, use a package manager (such as &quot;aptitude&quot;, &quot;apt-get&quot;, and &quot;synaptic&quot;) to install the package listed.</p>
393         <p>On RPM based distributions, such as Red Hat, Fedora, CentOS, Scientific Linux, Yellow Dog Linux and Oracle Enterprise Linux, use a package manager (such as &quot;yum&quot;, &quot;apt-rpm&quot;, and &quot;up2date&quot;) to install the package listed.</p>
394         <p>On servers without a package manager (such as Windows), or if the library is not packaged for your distribution, you can use PHP's PEAR to install the library. Simply run &quot;pear install &lt;name&gt;&quot;.</p>
395     </div>
396     <h2>Absent Libraries</h2>
397     <ul id="absent_libraries">
398 E_O_T;
399     foreach ($absent_libraries as $library) {
400         echo '<li>';
401         if (isset($library['url'])) {
402             echo '<a href="'.$library['url'].'">'.htmlentities($library['name']).'</a>';
403         } else {
404             echo htmlentities($library['name']);
405         }
406         echo '<ul>';
407         if (isset($library['deb'])) {
408             echo '<li class="deb package">deb: <a href="apt:' . urlencode($library['deb']) . '">' . htmlentities($library['deb']) . '</a></li>';
409         }
410         if (isset($library['rpm'])) {
411             echo '<li class="rpm package">rpm: ' . htmlentities($library['rpm']) . '</li>';
412         }
413         if (isset($library['pear'])) {
414             echo '<li class="pear package">pear: ' . htmlentities($library['pear']) . '</li>';
415         }
416         echo '</ul>';
417     }
418     echo<<<E_O_T
419     </ul>
420     <h2>Installed Libraries</h2>
421     <ul id="present_libraries">
422 E_O_T;
423     foreach ($present_libraries as $library) {
424         echo '<li>';
425         if (isset($library['url'])) {
426             echo '<a href="'.$library['url'].'">'.htmlentities($library['name']).'</a>';
427         } else {
428             echo htmlentities($library['name']);
429         }
430         echo '</li>';
431     }
432     echo<<<E_O_T
433     </ul>
434 E_O_T;
435 }
436
437 function showForm()
438 {
439     global $dbModules;
440     $dbRadios = '';
441     $checked = 'checked="checked" '; // Check the first one which exists
442     foreach ($dbModules as $type => $info) {
443         if (checkExtension($info['check_module'])) {
444             $dbRadios .= "<input type=\"radio\" name=\"dbtype\" id=\"dbtype-$type\" value=\"$type\" $checked/> $info[name]<br />\n";
445             $checked = '';
446         }
447     }
448     echo<<<E_O_T
449         </ul>
450     </dd>
451 </dl>
452 <dl id="page_notice" class="system_notice">
453     <dt>Page notice</dt>
454     <dd>
455         <div class="instructions">
456             <p>Enter your database connection information below to initialize the database.</p>
457             <p>StatusNet bundles a number of libraries for ease of installation. <a href="?checklibs=true">You can see what bundled libraries you are using, versus what libraries are installed on your server.</a>
458         </div>
459     </dd>
460 </dl>
461 <form method="post" action="install.php" class="form_settings" id="form_install">
462     <fieldset>
463         <legend>Connection settings</legend>
464         <ul class="form_data">
465             <li>
466                 <label for="sitename">Site name</label>
467                 <input type="text" id="sitename" name="sitename" />
468                 <p class="form_guide">The name of your site</p>
469             </li>
470             <li>
471                 <label for="fancy-enable">Fancy URLs</label>
472                 <input type="radio" name="fancy" id="fancy-enable" value="enable" checked='checked' /> enable<br />
473                 <input type="radio" name="fancy" id="fancy-disable" value="" /> disable<br />
474                 <p class="form_guide" id='fancy-form_guide'>Enable fancy (pretty) URLs. Auto-detection failed, it depends on Javascript.</p>
475             </li>
476             <li>
477                 <label for="host">Hostname</label>
478                 <input type="text" id="host" name="host" />
479                 <p class="form_guide">Database hostname</p>
480             </li>
481             <li>
482
483                 <label for="dbtype">Type</label>
484                 $dbRadios
485                 <p class="form_guide">Database type</p>
486             </li>
487
488             <li>
489                 <label for="database">Name</label>
490                 <input type="text" id="database" name="database" />
491                 <p class="form_guide">Database name</p>
492             </li>
493             <li>
494                 <label for="username">Username</label>
495                 <input type="text" id="username" name="username" />
496                 <p class="form_guide">Database username</p>
497             </li>
498             <li>
499                 <label for="password">Password</label>
500                 <input type="password" id="password" name="password" />
501                 <p class="form_guide">Database password (optional)</p>
502             </li>
503         </ul>
504         <input type="submit" name="submit" class="submit" value="Submit" />
505     </fieldset>
506 </form>
507
508 E_O_T;
509 }
510
511 function updateStatus($status, $error=false)
512 {
513     echo '<li' . ($error ? ' class="error"': '' ) . ">$status</li>";
514 }
515
516 function handlePost()
517 {
518     $host     = $_POST['host'];
519     $dbtype   = $_POST['dbtype'];
520     $database = $_POST['database'];
521     $username = $_POST['username'];
522     $password = $_POST['password'];
523     $sitename = $_POST['sitename'];
524     $fancy    = !empty($_POST['fancy']);
525     $server = $_SERVER['HTTP_HOST'];
526     $path = substr(dirname($_SERVER['PHP_SELF']), 1);
527
528     echo <<<STR
529     <dl class="system_notice">
530         <dt>Page notice</dt>
531         <dd>
532             <ul>
533 STR;
534     $fail = false;
535
536     if (empty($host)) {
537         updateStatus("No hostname specified.", true);
538         $fail = true;
539     }
540
541     if (empty($database)) {
542         updateStatus("No database specified.", true);
543         $fail = true;
544     }
545
546     if (empty($username)) {
547         updateStatus("No username specified.", true);
548         $fail = true;
549     }
550
551     if (empty($sitename)) {
552         updateStatus("No sitename specified.", true);
553         $fail = true;
554     }
555
556     if ($fail) {
557         showForm();
558         return;
559     }
560
561     global $dbModules;
562     $db = call_user_func($dbModules[$dbtype]['installer'], $host, $database, $username, $password);
563
564     if (!$db) {
565         // database connection failed, do not move on to create config file.
566         return false;
567     }
568
569     updateStatus("Writing config file...");
570     $res = writeConf($sitename, $server, $path, $fancy, $db);
571
572     if (!$res) {
573         updateStatus("Can't write config file.", true);
574         showForm();
575         return;
576     }
577
578     /*
579         TODO https needs to be considered
580     */
581     $link = "http://".$server.'/'.$path;
582
583     updateStatus("StatusNet has been installed at $link");
584     updateStatus("You can visit your <a href='$link'>new StatusNet site</a>.");
585 }
586
587 function Pgsql_Db_installer($host, $database, $username, $password)
588 {
589     $connstring = "dbname=$database host=$host user=$username";
590
591     //No password would mean trust authentication used.
592     if (!empty($password)) {
593         $connstring .= " password=$password";
594     }
595     updateStatus("Starting installation...");
596     updateStatus("Checking database...");
597     $conn = pg_connect($connstring);
598
599     if ($conn ===false) {
600         updateStatus("Failed to connect to database: $connstring");
601         showForm();
602         return false;
603     }
604
605     //ensure database encoding is UTF8
606     $record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding'));
607     if ($record->server_encoding != 'UTF8') {
608         updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
609         showForm();
610         return false;
611     }
612
613     updateStatus("Running database script...");
614     //wrap in transaction;
615     pg_query($conn, 'BEGIN');
616     $res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql');
617
618     if ($res === false) {
619         updateStatus("Can't run database script.", true);
620         showForm();
621         return false;
622     }
623     foreach (array('sms_carrier' => 'SMS carrier',
624                 'notice_source' => 'notice source',
625                 'foreign_services' => 'foreign service')
626           as $scr => $name) {
627         updateStatus(sprintf("Adding %s data to database...", $name));
628         $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql');
629         if ($res === false) {
630             updateStatus(sprintf("Can't run %d script.", $name), true);
631             showForm();
632             return false;
633         }
634     }
635     pg_query($conn, 'COMMIT');
636
637     if (empty($password)) {
638         $sqlUrl = "pgsql://$username@$host/$database";
639     } else {
640         $sqlUrl = "pgsql://$username:$password@$host/$database";
641     }
642
643     $db = array('type' => 'pgsql', 'database' => $sqlUrl);
644
645     return $db;
646 }
647
648 function Mysql_Db_installer($host, $database, $username, $password)
649 {
650     updateStatus("Starting installation...");
651     updateStatus("Checking database...");
652
653     $conn = mysql_connect($host, $username, $password);
654     if (!$conn) {
655         updateStatus("Can't connect to server '$host' as '$username'.", true);
656         showForm();
657         return false;
658     }
659     updateStatus("Changing to database...");
660     $res = mysql_select_db($database, $conn);
661     if (!$res) {
662         updateStatus("Can't change to database.", true);
663         showForm();
664         return false;
665     }
666     updateStatus("Running database script...");
667     $res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn);
668     if ($res === false) {
669         updateStatus("Can't run database script.", true);
670         showForm();
671         return false;
672     }
673     foreach (array('sms_carrier' => 'SMS carrier',
674                 'notice_source' => 'notice source',
675                 'foreign_services' => 'foreign service')
676           as $scr => $name) {
677         updateStatus(sprintf("Adding %s data to database...", $name));
678         $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn);
679         if ($res === false) {
680             updateStatus(sprintf("Can't run %d script.", $name), true);
681             showForm();
682             return false;
683         }
684     }
685
686     $sqlUrl = "mysqli://$username:$password@$host/$database";
687     $db = array('type' => 'mysql', 'database' => $sqlUrl);
688     return $db;
689 }
690
691 function writeConf($sitename, $server, $path, $fancy, $db)
692 {
693     // assemble configuration file in a string
694     $cfg =  "<?php\n".
695             "if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }\n\n".
696
697             // site name
698             "\$config['site']['name'] = '$sitename';\n\n".
699
700             // site location
701             "\$config['site']['server'] = '$server';\n".
702             "\$config['site']['path'] = '$path'; \n\n".
703
704             // checks if fancy URLs are enabled
705             ($fancy ? "\$config['site']['fancy'] = true;\n\n":'').
706
707             // database
708             "\$config['db']['database'] = '{$db['database']}';\n\n".
709             ($db['type'] == 'pgsql' ? "\$config['db']['quote_identifiers'] = true;\n\n":'').
710             "\$config['db']['type'] = '{$db['type']}';\n\n";
711     // write configuration file out to install directory
712     $res = file_put_contents(INSTALLDIR.'/config.php', $cfg);
713
714     return $res;
715 }
716
717 /**
718  * Install schema into the database
719  *
720  * @param string $filename location of database schema file
721  * @param dbconn $conn     connection to database
722  * @param string $type     type of database, currently mysql or pgsql
723  *
724  * @return boolean - indicating success or failure
725  */
726 function runDbScript($filename, $conn, $type = 'mysqli')
727 {
728     $sql = trim(file_get_contents($filename));
729     $stmts = explode(';', $sql);
730     foreach ($stmts as $stmt) {
731         $stmt = trim($stmt);
732         if (!mb_strlen($stmt)) {
733             continue;
734         }
735         // FIXME: use PEAR::DB or PDO instead of our own switch
736         switch ($type) {
737         case 'mysqli':
738             $res = mysql_query($stmt, $conn);
739             if ($res === false) {
740                 $error = mysql_error();
741             }
742             break;
743         case 'pgsql':
744             $res = pg_query($conn, $stmt);
745             if ($res === false) {
746                 $error = pg_last_error();
747             }
748             break;
749         default:
750             updateStatus("runDbScript() error: unknown database type ". $type ." provided.");
751         }
752         if ($res === false) {
753             updateStatus("ERROR ($error) for SQL '$stmt'");
754             return $res;
755         }
756     }
757     return true;
758 }
759
760 ?>
761 <?php echo"<?"; ?> xml version="1.0" encoding="UTF-8" <?php echo "?>"; ?>
762 <!DOCTYPE html
763 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
764        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
765 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
766     <head>
767         <title>Install StatusNet</title>
768         <link rel="shortcut icon" href="favicon.ico"/>
769         <link rel="stylesheet" type="text/css" href="theme/default/css/display.css?version=0.8" media="screen, projection, tv"/>
770         <!--[if IE]><link rel="stylesheet" type="text/css" href="theme/base/css/ie.css?version=0.8" /><![endif]-->
771         <!--[if lte IE 6]><link rel="stylesheet" type="text/css" theme/base/css/ie6.css?version=0.8" /><![endif]-->
772         <!--[if IE]><link rel="stylesheet" type="text/css" href="theme/default/css/ie.css?version=0.8" /><![endif]-->
773         <script src="js/jquery.min.js"></script>
774         <script src="js/install.js"></script>
775     </head>
776     <body id="install">
777         <div id="wrap">
778             <div id="header">
779                 <address id="site_contact" class="vcard">
780                     <a class="url home bookmark" href=".">
781                         <img class="logo photo" src="theme/default/logo.png" alt="StatusNet"/>
782                         <span class="fn org">StatusNet</span>
783                     </a>
784                 </address>
785             </div>
786             <div id="core">
787                 <div id="content">
788                     <h1>Install StatusNet</h1>
789 <?php main(); ?>
790                 </div>
791             </div>
792         </div>
793     </body>
794 </html>