]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - install.php
Improve url finding more. Properly end urls when a space is caught.
[quix0rs-gnu-social.git] / install.php
1 <?php
2 /**
3  * Laconica - a distributed open-source microblogging tool
4  * Copyright (C) 2009, Control Yourself, 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 function main()
23 {
24     if (!checkPrereqs())
25     {
26         return;
27     }
28
29     if ($_SERVER['REQUEST_METHOD'] == 'POST') {
30         handlePost();
31     } else {
32         showForm();
33     }
34 }
35
36 function checkPrereqs()
37 {
38         $pass = true;
39
40     if (file_exists(INSTALLDIR.'/config.php')) {
41          ?><p class="error">Config file &quot;config.php&quot; already exists.</p>
42          <?php
43         $pass = false;
44     }
45
46     if (version_compare(PHP_VERSION, '5.2.3', '<')) {
47             ?><p class="error">Require PHP version 5.2.3 or greater.</p><?php
48                     $pass = false;
49     }
50
51     $reqs = array('gd', 'curl',
52                   'xmlwriter', 'mbstring');
53
54     foreach ($reqs as $req) {
55         if (!checkExtension($req)) {
56             ?><p class="error">Cannot load required extension: <code><?php echo $req; ?></code></p><?php
57                     $pass = false;
58         }
59     }
60     if (!checkExtension('pgsql') && !checkExtension('mysql')) {
61       ?><p class="error">Cannot find mysql or pgsql extension. You need one or the other: <code><?php echo $req; ?></code></p><?php
62                     $pass = false;
63     }
64
65         if (!is_writable(INSTALLDIR)) {
66          ?><p class="error">Cannot write config file to: <code><?php echo INSTALLDIR; ?></code></p>
67                <p>On your server, try this command: <code>chmod a+w <?php echo INSTALLDIR; ?></code>
68          <?php
69              $pass = false;
70         }
71
72         // Check the subdirs used for file uploads
73         $fileSubdirs = array('avatar', 'background', 'file');
74         foreach ($fileSubdirs as $fileSubdir) {
75                 $fileFullPath = INSTALLDIR."/$fileSubdir/";
76                 if (!is_writable($fileFullPath)) {
77              ?><p class="error">Cannot write <?php echo $fileSubdir; ?> directory: <code><?php echo $fileFullPath; ?></code></p>
78                        <p>On your server, try this command: <code>chmod a+w <?php echo $fileFullPath; ?></code></p>
79              <?php
80                      $pass = false;
81                 }
82         }
83
84         return $pass;
85 }
86
87 function checkExtension($name)
88 {
89     if (!extension_loaded($name)) {
90         if (!dl($name.'.so')) {
91             return false;
92         }
93     }
94     return true;
95 }
96
97 function showForm()
98 {
99     echo<<<E_O_T
100         </ul>
101     </dd>
102 </dl>
103 <dl id="page_notice" class="system_notice">
104     <dt>Page notice</dt>
105     <dd>
106         <div class="instructions">
107             <p>Enter your database connection information below to initialize the database.</p>
108         </div>
109     </dd>
110 </dl>
111 <form method="post" action="install.php" class="form_settings" id="form_install">
112     <fieldset>
113         <legend>Connection settings</legend>
114         <ul class="form_data">
115             <li>
116                 <label for="sitename">Site name</label>
117                 <input type="text" id="sitename" name="sitename" />
118                 <p class="form_guide">The name of your site</p>
119             </li>
120             <li>
121                 <label for="fancy-enable">Fancy URLs</label>
122                 <input type="radio" name="fancy" id="fancy-enable" value="enable" checked='checked' /> enable<br />
123                 <input type="radio" name="fancy" id="fancy-disable" value="" /> disable<br />
124                 <p class="form_guide" id='fancy-form_guide'>Enable fancy (pretty) URLs. Auto-detection failed, it depends on Javascript.</p>
125             </li>
126             <li>
127                 <label for="host">Hostname</label>
128                 <input type="text" id="host" name="host" />
129                 <p class="form_guide">Database hostname</p>
130             </li>
131             <li>
132             
133                 <label for="dbtype">Type</label>
134                 <input type="radio" name="dbtype" id="fancy-mysql" value="mysql" checked='checked' /> MySQL<br />
135                 <input type="radio" name="dbtype" id="dbtype-pgsql" value="pgsql" /> PostgreSQL<br />
136                 <p class="form_guide">Database type</p>
137             </li>
138
139             <li>
140                 <label for="database">Name</label>
141                 <input type="text" id="database" name="database" />
142                 <p class="form_guide">Database name</p>
143             </li>
144             <li>
145                 <label for="username">Username</label>
146                 <input type="text" id="username" name="username" />
147                 <p class="form_guide">Database username</p>
148             </li>
149             <li>
150                 <label for="password">Password</label>
151                 <input type="password" id="password" name="password" />
152                 <p class="form_guide">Database password (optional)</p>
153             </li>
154         </ul>
155         <input type="submit" name="submit" class="submit" value="Submit" />
156     </fieldset>
157 </form>
158
159 E_O_T;
160 }
161
162 function updateStatus($status, $error=false)
163 {
164 ?>
165                 <li <?php echo ($error) ? 'class="error"': ''; ?>><?php echo $status;?></li>
166
167 <?php
168 }
169
170 function handlePost()
171 {
172 ?>
173
174 <?php
175     $host     = $_POST['host'];
176     $dbtype   = $_POST['dbtype'];
177     $database = $_POST['database'];
178     $username = $_POST['username'];
179     $password = $_POST['password'];
180     $sitename = $_POST['sitename'];
181     $fancy    = !empty($_POST['fancy']);
182     $server = $_SERVER['HTTP_HOST'];
183     $path = substr(dirname($_SERVER['PHP_SELF']), 1);
184     
185 ?>
186     <dl class="system_notice">
187         <dt>Page notice</dt>
188         <dd>
189             <ul>
190 <?php
191         $fail = false;
192
193     if (empty($host)) {
194         updateStatus("No hostname specified.", true);
195                 $fail = true;
196     }
197
198     if (empty($database)) {
199         updateStatus("No database specified.", true);
200                 $fail = true;
201     }
202
203     if (empty($username)) {
204         updateStatus("No username specified.", true);
205                 $fail = true;
206     }
207
208 //     if (empty($password)) {
209 //         updateStatus("No password specified.", true);
210 //              $fail = true;
211 //     }
212
213     if (empty($sitename)) {
214         updateStatus("No sitename specified.", true);
215                 $fail = true;
216     }
217
218     if($fail){
219             showForm();
220         return;
221     }
222     
223     switch($dbtype) {
224         case 'mysql':
225             $db = mysql_db_installer($host, $database, $username, $password);
226             break;
227         case 'pgsql':
228             $db = pgsql_db_installer($host, $database, $username, $password);
229             break;
230         default:
231     }
232     
233     if (!$db) {
234         // database connection failed, do not move on to create config file.
235         return false;
236     }
237     
238     updateStatus("Writing config file...");
239     $res = writeConf($sitename, $server, $path, $fancy, $db);
240     
241     if (!$res) {
242         updateStatus("Can't write config file.", true);
243         showForm();
244         return;
245     }
246     
247     /*
248         TODO https needs to be considered
249     */
250     $link = "http://".$server.'/'.$path;
251     
252     updateStatus("Laconica has been installed at $link");
253     updateStatus("You can visit your <a href='$link'>new Laconica site</a>.");
254 ?>
255
256 <?php
257 }
258
259 function pgsql_db_installer($host, $database, $username, $password) {
260   $connstring = "dbname=$database host=$host user=$username";
261
262   //No password would mean trust authentication used.
263   if (!empty($password)) {
264     $connstring .= " password=$password";
265   }
266   updateStatus("Starting installation...");
267   updateStatus("Checking database...");
268   $conn = pg_connect($connstring);
269   
270   if ($conn ===false) {
271     updateStatus("Failed to connect to database: $connstring");
272     showForm();
273     return false;
274   }
275
276   //ensure database encoding is UTF8
277   $record = pg_fetch_object(pg_query($conn, 'SHOW server_encoding'));
278   if ($record->server_encoding != 'UTF8') {
279     updateStatus("Laconica requires UTF8 character encoding. Your database is ". htmlentities($record->server_encoding));
280     showForm();
281     return false;
282   }
283
284   updateStatus("Running database script...");
285   //wrap in transaction;
286   pg_query($conn, 'BEGIN');
287   $res = runDbScript(INSTALLDIR.'/db/laconica_pg.sql', $conn, 'pgsql');
288   
289   if ($res === false) {
290       updateStatus("Can't run database script.", true);
291       showForm();
292       return false;
293   }
294   foreach (array('sms_carrier' => 'SMS carrier',
295                 'notice_source' => 'notice source',
296                 'foreign_services' => 'foreign service')
297           as $scr => $name) {
298       updateStatus(sprintf("Adding %s data to database...", $name));
299       $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn, 'pgsql');
300       if ($res === false) {
301           updateStatus(sprintf("Can't run %d script.", $name), true);
302           showForm();
303           return false;
304       }
305   }
306   pg_query($conn, 'COMMIT');
307
308   if (empty($password)) {
309     $sqlUrl = "pgsql://$username@$host/$database";
310   }
311   else {
312     $sqlUrl = "pgsql://$username:$password@$host/$database";
313   }
314   
315   $db = array('type' => 'pgsql', 'database' => $sqlUrl);
316   
317   return $db;
318 }
319
320 function mysql_db_installer($host, $database, $username, $password) {
321   updateStatus("Starting installation...");
322   updateStatus("Checking database...");
323
324   $conn = mysql_connect($host, $username, $password);
325   if (!$conn) {
326       updateStatus("Can't connect to server '$host' as '$username'.", true);
327       showForm();
328       return false;
329   }
330   updateStatus("Changing to database...");
331   $res = mysql_select_db($database, $conn);
332   if (!$res) {
333       updateStatus("Can't change to database.", true);
334       showForm();
335       return false;
336   }
337   updateStatus("Running database script...");
338   $res = runDbScript(INSTALLDIR.'/db/laconica.sql', $conn);
339   if ($res === false) {
340       updateStatus("Can't run database script.", true);
341       showForm();
342       return false;
343   }
344   foreach (array('sms_carrier' => 'SMS carrier',
345                 'notice_source' => 'notice source',
346                 'foreign_services' => 'foreign service')
347           as $scr => $name) {
348       updateStatus(sprintf("Adding %s data to database...", $name));
349       $res = runDbScript(INSTALLDIR.'/db/'.$scr.'.sql', $conn);
350       if ($res === false) {
351           updateStatus(sprintf("Can't run %d script.", $name), true);
352           showForm();
353           return false;
354       }
355   }
356       
357       $sqlUrl = "mysqli://$username:$password@$host/$database";
358       $db = array('type' => 'mysql', 'database' => $sqlUrl);
359       return $db;
360 }
361
362 function writeConf($sitename, $server, $path, $fancy, $db)
363 {
364     // assemble configuration file in a string
365     $cfg =  "<?php\n".
366             "if (!defined('LACONICA')) { exit(1); }\n\n".
367             
368             // site name
369             "\$config['site']['name'] = '$sitename';\n\n".
370             
371             // site location
372             "\$config['site']['server'] = '$server';\n".
373             "\$config['site']['path'] = '$path'; \n\n".
374             
375             // checks if fancy URLs are enabled
376             ($fancy ? "\$config['site']['fancy'] = true;\n\n":'').
377             
378             // database
379             "\$config['db']['database'] = '{$db['database']}';\n\n".
380             ($db['type'] == 'pgsql' ? "\$config['db']['quote_identifiers'] = true;\n\n":'').
381             "\$config['db']['type'] = '{$db['type']}';\n\n".
382             
383             "?>";
384     // write configuration file out to install directory
385     $res = file_put_contents(INSTALLDIR.'/config.php', $cfg);
386
387     return $res;
388 }
389
390 function runDbScript($filename, $conn, $type = 'mysql')
391 {
392     $sql = trim(file_get_contents($filename));
393     $stmts = explode(';', $sql);
394     foreach ($stmts as $stmt) {
395         $stmt = trim($stmt);
396         if (!mb_strlen($stmt)) {
397             continue;
398         }
399         switch ($type) {
400         case 'mysql':
401             $res = mysql_query($stmt, $conn);
402             break;
403         case 'pgsql':
404             $res = pg_query($conn, $stmt);
405             break;
406         default:
407             updateStatus("runDbScript() error: unknown database type ". $type ." provided.");
408         }
409         if ($res === false) {
410             updateStatus("FAILED SQL: $stmt");
411             return $res;
412         }
413     }
414     return true;
415 }
416
417 ?>
418 <?php echo"<?"; ?> xml version="1.0" encoding="UTF-8" <?php echo "?>"; ?>
419 <!DOCTYPE html>
420 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en_US" lang="en_US">
421     <head>
422         <title>Install Laconica</title>
423         <link rel="shortcut icon" href="favicon.ico"/>
424         <link rel="stylesheet" type="text/css" href="theme/default/css/display.css?version=0.8" media="screen, projection, tv"/>
425         <!--[if IE]><link rel="stylesheet" type="text/css" href="theme/base/css/ie.css?version=0.8" /><![endif]-->
426         <!--[if lte IE 6]><link rel="stylesheet" type="text/css" theme/base/css/ie6.css?version=0.8" /><![endif]-->
427         <!--[if IE]><link rel="stylesheet" type="text/css" href="theme/default/css/ie.css?version=0.8" /><![endif]-->
428         <script src="js/jquery.min.js"></script>
429         <script src="js/install.js"></script>
430     </head>
431     <body id="install">
432         <div id="wrap">
433             <div id="header">
434                 <address id="site_contact" class="vcard">
435                     <a class="url home bookmark" href=".">
436                         <img class="logo photo" src="theme/default/logo.png" alt="Laconica"/>
437                         <span class="fn org">Laconica</span>
438                     </a>
439                 </address>
440             </div>
441             <div id="core">
442                 <div id="content">
443                     <h1>Install Laconica</h1>
444 <?php main(); ?>
445                 </div>
446             </div>
447         </div>
448     </body>
449 </html>