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