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