alecpl
2008-09-29 bf2f39ea6d2b49c7495a43cca19ab18f27f8292e
commit | author | age
354978 1 <?php
T 2
3 /*
4  +-----------------------------------------------------------------------+
5  | rcube_install.php                                                     |
6  |                                                                       |
7  | This file is part of the RoundCube Webmail package                    |
8  | Copyright (C) 2008, RoundCube Dev. - Switzerland                      |
9  | Licensed under the GNU Public License                                 |
10  +-----------------------------------------------------------------------+
11
12  $Id:  $
13
14 */
15
16
17 /**
18  * Class to control the installation process of the RoundCube Webmail package
19  *
20  * @category Install
21  * @package  RoundCube
22  * @author Thomas Bruederli
23  */
24 class rcube_install
25 {
26   var $step;
237119 27   var $is_post = false;
354978 28   var $failures = 0;
c5042d 29   var $config = array();
b3f9df 30   var $configured = false;
c5042d 31   var $last_error = null;
ad43e6 32   var $email_pattern = '([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9])';
27564f 33   var $config_props = array();
354978 34   
T 35   /**
36    * Constructor
37    */
38   function rcube_install()
39   {
40     $this->step = intval($_REQUEST['_step']);
237119 41     $this->is_post = $_SERVER['REQUEST_METHOD'] == 'POST';
354978 42   }
T 43   
c5042d 44   /**
T 45    * Singleton getter
46    */
47   function get_instance()
48   {
49     static $inst;
50     
51     if (!$inst)
52       $inst = new rcube_install();
53     
54     return $inst;
55   }
354978 56   
T 57   /**
c5042d 58    * Read the default config files and store properties
354978 59    */
190e97 60   function load_defaults()
354978 61   {
c5042d 62     $this->_load_config('.php.dist');
T 63   }
64
65
66   /**
67    * Read the local config files and store properties
68    */
69   function load_config()
70   {
b3f9df 71     $this->config = array();
c5042d 72     $this->_load_config('.php');
b3f9df 73     $this->configured = !empty($this->config);
c5042d 74   }
T 75
76   /**
77    * Read the default config file and store properties
78    * @access private
79    */
80   function _load_config($suffix)
81   {
bba657 82     @include RCMAIL_CONFIG_DIR . '/main.inc' . $suffix;
354978 83     if (is_array($rcmail_config)) {
190e97 84       $this->config += $rcmail_config;
354978 85     }
T 86       
bba657 87     @include RCMAIL_CONFIG_DIR . '/db.inc'. $suffix;
354978 88     if (is_array($rcmail_config)) {
c5042d 89       $this->config += $rcmail_config;
354978 90     }
T 91   }
92   
93   
94   /**
95    * Getter for a certain config property
96    *
97    * @param string Property name
ad43e6 98    * @param string Default value
354978 99    * @return string The property value
T 100    */
fa7539 101   function getprop($name, $default = '')
354978 102   {
b77d0d 103     $value = $this->config[$name];
354978 104     
ccb412 105     if ($name == 'des_key' && !$this->configured && !isset($_REQUEST["_$name"]))
807d17 106       $value = rcube_install::random_key(24);
354978 107     
fa7539 108     return $value !== null && $value !== '' ? $value : $default;
354978 109   }
T 110   
111   
112   /**
113    * Take the default config file and replace the parameters
114    * with the submitted form data
115    *
116    * @param string Which config file (either 'main' or 'db')
117    * @return string The complete config file content
118    */
119   function create_config($which)
120   {
121     $out = file_get_contents("../config/{$which}.inc.php.dist");
122     
123     if (!$out)
124       return '[Warning: could not read the template file]';
0c3bde 125
c5042d 126     foreach ($this->config as $prop => $default) {
27564f 127       $value = (isset($_POST["_$prop"]) || $this->config_props[$prop]) ? $_POST["_$prop"] : $default;
354978 128       
T 129       // convert some form data
b77d0d 130       if ($prop == 'debug_level') {
354978 131         $val = 0;
7d7f67 132         if (is_array($value))
T 133           foreach ($value as $dbgval)
b77d0d 134             $val += intval($dbgval);
7d7f67 135         $value = $val;
354978 136       }
0c3bde 137       else if ($which == 'db' && $prop == 'db_dsnw' && !empty($_POST['_dbtype'])) {
237119 138         if ($_POST['_dbtype'] == 'sqlite')
T 139           $value = sprintf('%s://%s?mode=0646', $_POST['_dbtype'], $_POST['_dbname']{0} == '/' ? '/' . $_POST['_dbname'] : $_POST['_dbname']);
140         else
b61965 141           $value = sprintf('%s://%s:%s@%s/%s', $_POST['_dbtype'], 
7d7f67 142             rawurlencode($_POST['_dbuser']), rawurlencode($_POST['_dbpass']), $_POST['_dbhost'], $_POST['_dbname']);
c5042d 143       }
T 144       else if ($prop == 'smtp_auth_type' && $value == '0') {
145         $value = '';
146       }
147       else if ($prop == 'default_host' && is_array($value)) {
807d17 148         $value = rcube_install::_clean_array($value);
c5042d 149         if (count($value) <= 1)
T 150           $value = $value[0];
151       }
ccb412 152       else if ($prop == 'pagesize') {
T 153         $value = max(2, intval($value));
154       }
c5042d 155       else if ($prop == 'smtp_user' && !empty($_POST['_smtp_user_u'])) {
T 156         $value = '%u';
157       }
158       else if ($prop == 'smtp_pass' && !empty($_POST['_smtp_user_u'])) {
159         $value = '%p';
160       }
161       else if (is_bool($default)) {
27564f 162         $value = (bool)$value;
T 163       }
164       else if (is_numeric($value)) {
165         $value = intval($value);
c5042d 166       }
T 167       
168       // skip this property
169       if ($value == $default)
170         continue;
b77d0d 171
A 172       // save change
173       $this->config[$prop] = $value;
174
354978 175       // replace the matching line in config file
T 176       $out = preg_replace(
177         '/(\$rcmail_config\[\''.preg_quote($prop).'\'\])\s+=\s+(.+);/Uie',
178         "'\\1 = ' . var_export(\$value, true) . ';'",
179         $out);
180     }
0c3bde 181
967b34 182     return trim($out);
c5042d 183   }
T 184   
185   
186   /**
187    * Getter for the last error message
188    *
189    * @return string Error message or null if none exists
190    */
191   function get_error()
192   {
193       return $this->last_error['message'];
354978 194   }
T 195   
196   
197   /**
112c54 198    * Return a list with all imap hosts configured
T 199    *
200    * @return array Clean list with imap hosts
201    */
202   function get_hostlist()
203   {
204     $default_hosts = (array)$this->getprop('default_host');
205     $out = array();
206     
207     foreach ($default_hosts as $key => $name) {
208       if (!empty($name))
209         $out[] = is_numeric($key) ? $name : $key;
210     }
211     
212     return $out;
213   }
214   
215   
216   /**
354978 217    * Display OK status
T 218    *
219    * @param string Test name
220    * @param string Confirm message
221    */
222   function pass($name, $message = '')
223   {
224     echo Q($name) . ':&nbsp; <span class="success">OK</span>';
6557d3 225     $this->_showhint($message);
354978 226   }
T 227   
228   
229   /**
230    * Display an error status and increase failure count
231    *
232    * @param string Test name
233    * @param string Error message
234    * @param string URL for details
235    */
236   function fail($name, $message = '', $url = '')
237   {
238     $this->failures++;
239     
240     echo Q($name) . ':&nbsp; <span class="fail">NOT OK</span>';
6557d3 241     $this->_showhint($message, $url);
354978 242   }
T 243   
244   
245   /**
246    * Display warning status
247    *
248    * @param string Test name
249    * @param string Warning message
250    * @param string URL for details
251    */
6557d3 252   function na($name, $message = '', $url = '')
354978 253   {
6557d3 254     echo Q($name) . ':&nbsp; <span class="na">NOT AVAILABLE</span>';
T 255     $this->_showhint($message, $url);
256   }
257   
258   
259   function _showhint($message, $url = '')
260   {
261     $hint = Q($message);
262     
354978 263     if ($url)
6557d3 264       $hint .= ($hint ? '; ' : '') . 'See <a href="' . Q($url) . '" target="_blank">' . Q($url) . '</a>';
T 265       
266     if ($hint)
267       echo '<span class="indent">(' . $hint . ')</span>';
354978 268   }
T 269   
270   
c5042d 271   function _clean_array($arr)
T 272   {
273     $out = array();
274     
275     foreach (array_unique($arr) as $i => $val)
276       if (!empty($val))
277         $out[] = $val;
278     
279     return $out;
280   }
281   
190e97 282   
T 283   /**
284    * Initialize the database with the according schema
285    *
286    * @param object rcube_db Database connection
287    * @return boolen True on success, False on error
288    */
289   function init_db($DB)
290   {
291     $db_map = array('pgsql' => 'postgres', 'mysqli' => 'mysql');
292     $engine = isset($db_map[$DB->db_provider]) ? $db_map[$DB->db_provider] : $DB->db_provider;
293     
294     // find out db version
295     if ($engine == 'mysql') {
296       $DB->query('SELECT VERSION() AS version');
297       $sql_arr = $DB->fetch_assoc();
298       $version = floatval($sql_arr['version']);
299       
300       if ($version >= 4.1)
301         $engine = 'mysql5';
302     }
303     
304     // read schema file from /SQL/*
305     $fname = "../SQL/$engine.initial.sql";
306     if ($lines = @file($fname, FILE_SKIP_EMPTY_LINES)) {
307       $buff = '';
308       foreach ($lines as $i => $line) {
309         if (eregi('^--', $line))
310           continue;
311           
312         $buff .= $line . "\n";
313         if (eregi(';$', trim($line))) {
314           $DB->query($buff);
315           $buff = '';
c0dc90 316           if ($this->get_error())
T 317             break;
190e97 318         }
T 319       }
320     }
321     else {
322       $this->fail('DB Schema', "Cannot read the schema file: $fname");
323       return false;
324     }
325     
326     if ($err = $this->get_error()) {
327       $this->fail('DB Schema', "Error creating database schema: $err");
328       return false;
329     }
330
331     return true;
332   }
333   
c5042d 334   /**
T 335    * Handler for RoundCube errors
336    */
337   function raise_error($p)
338   {
339       $this->last_error = $p;
340   }
341   
342   
354978 343   /**
T 344    * Generarte a ramdom string to be used as encryption key
345    *
346    * @param int Key length
347    * @return string The generated random string
348    * @static
349    */
350   function random_key($length)
351   {
352     $alpha = 'ABCDEFGHIJKLMNOPQERSTUVXYZabcdefghijklmnopqrtsuvwxyz0123456789+*%&?!$-_=';
353     $out = '';
354     
355     for ($i=0; $i < $length; $i++)
356       $out .= $alpha{rand(0, strlen($alpha)-1)};
357     
358     return $out;
359   }
360   
361 }
362
363
364 /**
365  * Shortcut function for htmlentities()
366  *
367  * @param string String to quote
368  * @return string The html-encoded string
369  */
370 function Q($string)
371 {
372   return htmlentities($string);
373 }
374
c5042d 375
T 376 /**
377  * Fake rinternal error handler to catch errors
378  */
379 function raise_error($p)
380 {
381   $rci = rcube_install::get_instance();
382   $rci->raise_error($p);
383 }
384