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