]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - install.php
5754c717a17b45693c7a0a3e3ccf32bcee67f6fc
[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 function main()
205 {
206     if (!checkPrereqs())
207     {
208         return;
209     }
210     
211     if( $_GET['checklibs'] ){
212         showLibs();
213     }else{
214         if ($_SERVER['REQUEST_METHOD'] == 'POST') {
215             handlePost();
216         } else {
217             showForm();
218         }
219     }
220 }
221
222 function haveExternalLibrary($external_library)
223 {
224     if(isset($external_library['include']) && ! include_once($external_library['include'])){
225         return false;
226     }
227     if(isset($external_library['check_function']) && ! function_exists($external_library['check_function'])){
228         return false;
229     }
230     if(isset($external_library['check_class']) && ! class_exists($external_library['check_class'])){
231         return false;
232     }
233     return true;
234 }
235
236 function checkPrereqs()
237 {
238         $pass = true;
239
240     if (file_exists(INSTALLDIR.'/config.php')) {
241          ?><p class="error">Config file &quot;config.php&quot; already exists.</p>
242          <?php
243         $pass = false;
244     }
245
246     if (version_compare(PHP_VERSION, '5.2.3', '<')) {
247             ?><p class="error">Require PHP version 5.2.3 or greater.</p><?php
248                     $pass = false;
249     }
250
251     $reqs = array('gd', 'curl',
252                   'xmlwriter', 'mbstring','tidy');
253
254     foreach ($reqs as $req) {
255         if (!checkExtension($req)) {
256             ?><p class="error">Cannot load required extension: <code><?php echo $req; ?></code></p><?php
257                     $pass = false;
258         }
259     }
260     
261     // Make sure we have at least one database module available
262     global $dbModules;
263     $missingExtensions = array();
264     foreach ($dbModules as $type => $info) {
265         if (!checkExtension($info['check_module'])) {
266             $missingExtensions[] = $info['check_module'];
267         }
268     }
269     if (count($missingExtensions) == count($dbModules)) {
270         $req = implode(', ', $missingExtensions);
271       ?><p class="error">Cannot find database support. You need at least one of these PHP extensions installed: <code><?php echo $req; ?></code></p><?php
272                     $pass = false;
273     }
274
275         if (!is_writable(INSTALLDIR)) {
276          ?><p class="error">Cannot write config file to: <code><?php echo INSTALLDIR; ?></code></p>
277                <p>On your server, try this command: <code>chmod a+w <?php echo INSTALLDIR; ?></code>
278          <?php
279              $pass = false;
280         }
281
282         // Check the subdirs used for file uploads
283         $fileSubdirs = array('avatar', 'background', 'file');
284         foreach ($fileSubdirs as $fileSubdir) {
285                 $fileFullPath = INSTALLDIR."/$fileSubdir/";
286                 if (!is_writable($fileFullPath)) {
287              ?><p class="error">Cannot write <?php echo $fileSubdir; ?> directory: <code><?php echo $fileFullPath; ?></code></p>
288                        <p>On your server, try this command: <code>chmod a+w <?php echo $fileFullPath; ?></code></p>
289              <?php
290                      $pass = false;
291                 }
292         }
293
294         return $pass;
295 }
296
297 function checkExtension($name)
298 {
299     if (!extension_loaded($name)) {
300         if (!@dl($name.'.so')) {
301             return false;
302         }
303     }
304     return true;
305 }
306
307 function showLibs()
308 {
309     global $external_libraries;
310     $present_libraries=array();
311     $absent_libraries=array();
312     foreach($external_libraries as $external_library){
313         if(haveExternalLibrary($external_library)){
314             $present_libraries[]=$external_library;
315         }else{
316             $absent_libraries[]=$external_library;
317         }
318     }
319     echo<<<E_O_T
320     <div class="instructions">
321         <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
322         libraries instead, as they tend to provide security updates faster, and may offer improved performance.</p>
323         <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>
324         <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>
325         <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>
326     </div>
327     <h2>Absent Libraries</h2>
328     <ul id="absent_libraries">
329 E_O_T;
330     foreach($absent_libraries as $library)
331     {
332         echo '<li>';
333         if($library['url']){
334             echo '<a href=">'.$library['url'].'">'.htmlentities($library['name']).'</a>';
335         }else{
336             echo htmlentities($library['name']);
337         }
338         echo '<ul>';
339         if($library['deb']){
340             echo '<li class="deb package">deb: <a href="apt:' . urlencode($library['deb']) . '">' . htmlentities($library['deb']) . '</a></li>';
341         }
342         if($library['rpm']){
343             echo '<li class="rpm package">rpm: ' . htmlentities($library['rpm']) . '</li>';
344         }
345         if($library['pear']){
346             echo '<li class="pear package">pear: ' . htmlentities($library['pear']) . '</li>';
347         }
348         echo '</ul>';
349     }
350     echo<<<E_O_T
351     </ul>
352     <h2>Installed Libraries</h2>
353     <ul id="present_libraries">
354 E_O_T;
355     foreach($present_libraries as $library)
356     {
357         echo '<li>';
358         if($library['url']){
359             echo '<a href=">'.$library['url'].'">'.htmlentities($library['name']).'</a>';
360         }else{
361             echo htmlentities($library['name']);
362         }
363         echo '</li>';
364     }
365     echo<<<E_O_T
366     </ul>
367 E_O_T;
368 }
369
370 function showForm()
371 {
372     global $dbModules;
373     $dbRadios = '';
374     $checked = 'checked="checked" '; // Check the first one which exists
375     foreach ($dbModules as $type => $info) {
376         if (checkExtension($info['check_module'])) {
377             $dbRadios .= "<input type=\"radio\" name=\"dbtype\" id=\"dbtype-$type\" value=\"$type\" $checked/> $info[name]<br />\n";
378             $checked = '';
379         }
380     }
381     echo<<<E_O_T
382         </ul>
383     </dd>
384 </dl>
385 <dl id="page_notice" class="system_notice">
386     <dt>Page notice</dt>
387     <dd>
388         <div class="instructions">
389             <p>Enter your database connection information below to initialize the database.</p>
390             <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>
391         </div>
392     </dd>
393 </dl>
394 <form method="post" action="install.php" class="form_settings" id="form_install">
395     <fieldset>
396         <legend>Connection settings</legend>
397         <ul class="form_data">
398             <li>
399                 <label for="sitename">Site name</label>
400                 <input type="text" id="sitename" name="sitename" />
401                 <p class="form_guide">The name of your site</p>
402             </li>
403             <li>
404                 <label for="fancy-enable">Fancy URLs</label>
405                 <input type="radio" name="fancy" id="fancy-enable" value="enable" checked='checked' /> enable<br />
406                 <input type="radio" name="fancy" id="fancy-disable" value="" /> disable<br />
407                 <p class="form_guide" id='fancy-form_guide'>Enable fancy (pretty) URLs. Auto-detection failed, it depends on Javascript.</p>
408             </li>
409             <li>
410                 <label for="host">Hostname</label>
411                 <input type="text" id="host" name="host" />
412                 <p class="form_guide">Database hostname</p>
413             </li>
414             <li>
415
416                 <label for="dbtype">Type</label>
417                 $dbRadios
418                 <p class="form_guide">Database type</p>
419             </li>
420
421             <li>
422                 <label for="database">Name</label>
423                 <input type="text" id="database" name="database" />
424                 <p class="form_guide">Database name</p>
425             </li>
426             <li>
427                 <label for="username">Username</label>
428                 <input type="text" id="username" name="username" />
429                 <p class="form_guide">Database username</p>
430             </li>
431             <li>
432                 <label for="password">Password</label>
433                 <input type="password" id="password" name="password" />
434                 <p class="form_guide">Database password (optional)</p>
435             </li>
436         </ul>
437         <input type="submit" name="submit" class="submit" value="Submit" />
438     </fieldset>
439 </form>
440
441 E_O_T;
442 }
443
444 function updateStatus($status, $error=false)
445 {
446 ?>
447                 <li <?php echo ($error) ? 'class="error"': ''; ?>><?php echo $status;?></li>
448
449 <?php
450 }
451
452 function handlePost()
453 {
454 ?>
455
456 <?php
457     $host     = $_POST['host'];
458     $dbtype   = $_POST['dbtype'];
459     $database = $_POST['database'];
460     $username = $_POST['username'];
461     $password = $_POST['password'];
462     $sitename = $_POST['sitename'];
463     $fancy    = !empty($_POST['fancy']);
464     $server = $_SERVER['HTTP_HOST'];
465     $path = substr(dirname($_SERVER['PHP_SELF']), 1);
466
467 ?>
468     <dl class="system_notice">
469         <dt>Page notice</dt>
470         <dd>
471             <ul>
472 <?php
473         $fail = false;
474
475     if (empty($host)) {
476         updateStatus("No hostname specified.", true);
477                 $fail = true;
478     }
479
480     if (empty($database)) {
481         updateStatus("No database specified.", true);
482                 $fail = true;
483     }
484
485     if (empty($username)) {
486         updateStatus("No username specified.", true);
487                 $fail = true;
488     }
489
490 //     if (empty($password)) {
491 //         updateStatus("No password specified.", true);
492 //              $fail = true;
493 //     }
494
495     if (empty($sitename)) {
496         updateStatus("No sitename specified.", true);
497                 $fail = true;
498     }
499
500     if($fail){
501             showForm();
502         return;
503     }
504
505     global $dbModules;
506     $db = call_user_func($dbModules[$dbtype]['installer'],
507         $host, $database, $username, $password);
508
509     if (!$db) {
510         // database connection failed, do not move on to create config file.
511         return false;
512     }
513
514     updateStatus("Writing config file...");
515     $res = writeConf($sitename, $server, $path, $fancy, $db);
516
517     if (!$res) {
518         updateStatus("Can't write config file.", true);
519         showForm();
520         return;
521     }
522
523     /*
524         TODO https needs to be considered
525     */
526     $link = "http://".$server.'/'.$path;
527
528     updateStatus("StatusNet has been installed at $link");
529     updateStatus("You can visit your <a href='$link'>new StatusNet site</a>.");
530 ?>
531
532 <?php
533 }
534
535 function pgsql_db_installer($host, $database, $username, $password) {
536   $connstring = "dbname=$database host=$host user=$username";
537
538   //No password would mean trust authentication used.
539   if (!empty($password)) {
540     $connstring .= " password=$password";
541   }
542   updateStatus("Starting installation...");
543   updateStatus("Checking database...");
544   $conn = pg_connect($connstring);
545
546   if ($conn ===false) {
547     updateStatus("Failed to connect to database: $connstring");
548     showForm();
549     return false;
550   }
551
552   //ensure database encoding is UTF8
553   $record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding'));
554   if ($record->server_encoding != 'UTF8') {
555     updateStatus("StatusNet requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
556     showForm();
557     return false;
558   }
559
560   updateStatus("Running database script...");
561   //wrap in transaction;
562   pg_query($conn, 'BEGIN');
563   $res = runDbScript(INSTALLDIR.'/db/statusnet_pg.sql', $conn, 'pgsql');
564
565   if ($res === false) {
566       updateStatus("Can't run database script.", true);
567       showForm();
568       return false;
569   }
570   foreach (array('sms_carrier' => 'SMS carrier',
571                 'notice_source' => 'notice source',
572                 'foreign_services' => 'foreign service')
573           as $scr => $name) {
574       updateStatus(sprintf("Adding %s data to database...", $name));
575       $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql');
576       if ($res === false) {
577           updateStatus(sprintf("Can't run %d script.", $name), true);
578           showForm();
579           return false;
580       }
581   }
582   pg_query($conn, 'COMMIT');
583
584   if (empty($password)) {
585     $sqlUrl = "pgsql://$username@$host/$database";
586   }
587   else {
588     $sqlUrl = "pgsql://$username:$password@$host/$database";
589   }
590
591   $db = array('type' => 'pgsql', 'database' => $sqlUrl);
592
593   return $db;
594 }
595
596 function mysql_db_installer($host, $database, $username, $password) {
597   updateStatus("Starting installation...");
598   updateStatus("Checking database...");
599
600   $conn = mysql_connect($host, $username, $password);
601   if (!$conn) {
602       updateStatus("Can't connect to server '$host' as '$username'.", true);
603       showForm();
604       return false;
605   }
606   updateStatus("Changing to database...");
607   $res = mysql_select_db($database, $conn);
608   if (!$res) {
609       updateStatus("Can't change to database.", true);
610       showForm();
611       return false;
612   }
613   updateStatus("Running database script...");
614   $res = runDbScript(INSTALLDIR.'/db/statusnet.sql', $conn);
615   if ($res === false) {
616       updateStatus("Can't run database script.", true);
617       showForm();
618       return false;
619   }
620   foreach (array('sms_carrier' => 'SMS carrier',
621                 'notice_source' => 'notice source',
622                 'foreign_services' => 'foreign service')
623           as $scr => $name) {
624       updateStatus(sprintf("Adding %s data to database...", $name));
625       $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn);
626       if ($res === false) {
627           updateStatus(sprintf("Can't run %d script.", $name), true);
628           showForm();
629           return false;
630       }
631   }
632
633       $sqlUrl = "mysqli://$username:$password@$host/$database";
634       $db = array('type' => 'mysql', 'database' => $sqlUrl);
635       return $db;
636 }
637
638 function writeConf($sitename, $server, $path, $fancy, $db)
639 {
640     // assemble configuration file in a string
641     $cfg =  "<?php\n".
642             "if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); }\n\n".
643
644             // site name
645             "\$config['site']['name'] = '$sitename';\n\n".
646
647             // site location
648             "\$config['site']['server'] = '$server';\n".
649             "\$config['site']['path'] = '$path'; \n\n".
650
651             // checks if fancy URLs are enabled
652             ($fancy ? "\$config['site']['fancy'] = true;\n\n":'').
653
654             // database
655             "\$config['db']['database'] = '{$db['database']}';\n\n".
656             ($db['type'] == 'pgsql' ? "\$config['db']['quote_identifiers'] = true;\n\n":'').
657             "\$config['db']['type'] = '{$db['type']}';\n\n".
658
659             "?>";
660     // write configuration file out to install directory
661     $res = file_put_contents(INSTALLDIR.'/config.php', $cfg);
662
663     return $res;
664 }
665
666 function runDbScript($filename, $conn, $type = 'mysql')
667 {
668     $sql = trim(file_get_contents($filename));
669     $stmts = explode(';', $sql);
670     foreach ($stmts as $stmt) {
671         $stmt = trim($stmt);
672         if (!mb_strlen($stmt)) {
673             continue;
674         }
675         // FIXME: use PEAR::DB or PDO instead of our own switch
676         switch ($type) {
677         case 'mysql':
678             $res = mysql_query($stmt, $conn);
679             if ($res === false) {
680                 $error = mysql_error();
681             }
682             break;
683         case 'pgsql':
684             $res = pg_query($conn, $stmt);
685             if ($res === false) {
686                 $error = pg_last_error();
687             }
688             break;
689         default:
690             updateStatus("runDbScript() error: unknown database type ". $type ." provided.");
691         }
692         if ($res === false) {
693             updateStatus("ERROR ($error) for SQL '$stmt'");
694             return $res;
695         }
696     }
697     return true;
698 }
699
700 ?>
701 <?php echo"<?"; ?> xml version="1.0" encoding="UTF-8" <?php echo "?>"; ?>
702 <!DOCTYPE html
703 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
704        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
705 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
706     <head>
707         <title>Install StatusNet</title>
708         <link rel="shortcut icon" href="favicon.ico"/>
709         <link rel="stylesheet" type="text/css" href="theme/default/css/display.css?version=0.8" media="screen, projection, tv"/>
710         <!--[if IE]><link rel="stylesheet" type="text/css" href="theme/base/css/ie.css?version=0.8" /><![endif]-->
711         <!--[if lte IE 6]><link rel="stylesheet" type="text/css" theme/base/css/ie6.css?version=0.8" /><![endif]-->
712         <!--[if IE]><link rel="stylesheet" type="text/css" href="theme/default/css/ie.css?version=0.8" /><![endif]-->
713         <script src="js/jquery.min.js"></script>
714         <script src="js/install.js"></script>
715     </head>
716     <body id="install">
717         <div id="wrap">
718             <div id="header">
719                 <address id="site_contact" class="vcard">
720                     <a class="url home bookmark" href=".">
721                         <img class="logo photo" src="theme/default/logo.png" alt="StatusNet"/>
722                         <span class="fn org">StatusNet</span>
723                     </a>
724                 </address>
725             </div>
726             <div id="core">
727                 <div id="content">
728                     <h1>Install StatusNet</h1>
729 <?php main(); ?>
730                 </div>
731             </div>
732         </div>
733     </body>
734 </html>