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', 'xml', 'dom', 'simplexml');
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>