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