thomascube
2012-01-18 7fe3811c65a7c63154f03610e289a6d196f3ae2e
commit | author | age
197601 1 <?php
T 2
3 /*
4  +-----------------------------------------------------------------------+
5  | program/include/rcube_config.php                                      |
6  |                                                                       |
e019f2 7  | This file is part of the Roundcube Webmail client                     |
f5e7b3 8  | Copyright (C) 2008-2010, The Roundcube Dev Team                       |
7fe381 9  |                                                                       |
T 10  | Licensed under the GNU General Public License version 3 or            |
11  | any later version with exceptions for skins & plugins.                |
12  | See the README file for a full license statement.                     |
197601 13  |                                                                       |
T 14  | PURPOSE:                                                              |
15  |   Class to read configuration settings                                |
16  |                                                                       |
17  +-----------------------------------------------------------------------+
18  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
19  +-----------------------------------------------------------------------+
20
1d786c 21  $Id$
197601 22
T 23 */
24
25 /**
e019f2 26  * Configuration class for Roundcube
197601 27  *
T 28  * @package Core
29  */
30 class rcube_config
31 {
2eb794 32     private $prop = array();
A 33     private $errors = array();
34     private $userprefs = array();
197601 35
T 36
2eb794 37     /**
A 38      * Object constructor
39      */
40     public function __construct()
2471d3 41     {
2eb794 42         $this->load();
2471d3 43     }
2eb794 44
A 45
46     /**
47      * Load config from local config file
48      *
49      * @todo Remove global $CONFIG
50      */
51     private function load()
2471d3 52     {
2eb794 53         // load main config file
A 54         if (!$this->load_from_file(RCMAIL_CONFIG_DIR . '/main.inc.php'))
55             $this->errors[] = 'main.inc.php was not found.';
56
57         // load database config
58         if (!$this->load_from_file(RCMAIL_CONFIG_DIR . '/db.inc.php'))
59             $this->errors[] = 'db.inc.php was not found.';
f52c4f 60
2eb794 61         // load host-specific configuration
A 62         $this->load_host_config();
63
64         // set skin (with fallback to old 'skin_path' property)
65         if (empty($this->prop['skin']) && !empty($this->prop['skin_path']))
66             $this->prop['skin'] = str_replace('skins/', '', unslashify($this->prop['skin_path']));
67         else if (empty($this->prop['skin']))
68             $this->prop['skin'] = 'default';
69
70         // fix paths
71         $this->prop['log_dir'] = $this->prop['log_dir'] ? realpath(unslashify($this->prop['log_dir'])) : INSTALL_PATH . 'logs';
72         $this->prop['temp_dir'] = $this->prop['temp_dir'] ? realpath(unslashify($this->prop['temp_dir'])) : INSTALL_PATH . 'temp';
f52c4f 73
2eb794 74         // fix default imap folders encoding
A 75         foreach (array('drafts_mbox', 'junk_mbox', 'sent_mbox', 'trash_mbox') as $folder)
76             $this->prop[$folder] = rcube_charset_convert($this->prop[$folder], RCMAIL_CHARSET, 'UTF7-IMAP');
77
c321a9 78         if (!empty($this->prop['default_folders']))
T 79             foreach ($this->prop['default_folders'] as $n => $folder)
80                 $this->prop['default_folders'][$n] = rcube_charset_convert($folder, RCMAIL_CHARSET, 'UTF7-IMAP');
2eb794 81
A 82         // set PHP error logging according to config
83         if ($this->prop['debug_level'] & 1) {
84             ini_set('log_errors', 1);
85
86             if ($this->prop['log_driver'] == 'syslog') {
87                 ini_set('error_log', 'syslog');
88             }
89             else {
90                 ini_set('error_log', $this->prop['log_dir'].'/errors');
91             }
92         }
23b495 93
A 94         // enable display_errors in 'show' level, but not for ajax requests
95         ini_set('display_errors', intval(empty($_REQUEST['_remote']) && ($this->prop['debug_level'] & 4)));
0829b7 96
65082b 97         // set timezone auto settings values
T 98         if ($this->prop['timezone'] == 'auto') {
5879c0 99           $this->prop['_timezone_value'] = $this->client_timezone();
0829b7 100         }
5879c0 101         else if (is_numeric($this->prop['timezone'])) {
T 102           $this->prop['timezone'] = timezone_name_from_abbr("", $this->prop['timezone'] * 3600, 0);
65082b 103         }
5879c0 104
T 105         // remove deprecated properties
106         unset($this->prop['dst_active']);
2eb794 107
A 108         // export config data
109         $GLOBALS['CONFIG'] = &$this->prop;
2471d3 110     }
1854c4 111
2eb794 112     /**
A 113      * Load a host-specific config file if configured
114      * This will merge the host specific configuration with the given one
115      */
116     private function load_host_config()
117     {
118         $fname = null;
10eedb 119
2eb794 120         if (is_array($this->prop['include_host_config'])) {
A 121             $fname = $this->prop['include_host_config'][$_SERVER['HTTP_HOST']];
122         }
123         else if (!empty($this->prop['include_host_config'])) {
124             $fname = preg_replace('/[^a-z0-9\.\-_]/i', '', $_SERVER['HTTP_HOST']) . '.inc.php';
125         }
2471d3 126
2eb794 127         if ($fname) {
A 128             $this->load_from_file(RCMAIL_CONFIG_DIR . '/' . $fname);
129         }
83a763 130     }
T 131
2eb794 132
A 133     /**
134      * Read configuration from a file
135      * and merge with the already stored config values
136      *
5c461b 137      * @param string $fpath Full path to the config file to be loaded
2eb794 138      * @return booelan True on success, false on failure
A 139      */
140     public function load_from_file($fpath)
141     {
142         if (is_file($fpath) && is_readable($fpath)) {
7c9850 143             // use output buffering, we don't need any output here 
A 144             ob_start();
2eb794 145             include($fpath);
7c9850 146             ob_end_clean();
A 147
2eb794 148             if (is_array($rcmail_config)) {
A 149                 $this->prop = array_merge($this->prop, $rcmail_config, $this->userprefs);
150                 return true;
151             }
152         }
153
154         return false;
155     }
156
157
158     /**
159      * Getter for a specific config parameter
160      *
5c461b 161      * @param  string $name Parameter name
A 162      * @param  mixed  $def  Default value if not set
2eb794 163      * @return mixed  The requested config value
A 164      */
165     public function get($name, $def = null)
166     {
183717 167         $result = isset($this->prop[$name]) ? $this->prop[$name] : $def;
A 168         $rcmail = rcmail::get_instance();
801b69 169         
T 170         if ($name == 'timezone' && isset($this->prop['_timezone_value']))
171             $result = $this->prop['_timezone_value'];
183717 172
A 173         if (is_object($rcmail->plugins)) {
174             $plugin = $rcmail->plugins->exec_hook('config_get', array(
175                 'name' => $name, 'default' => $def, 'result' => $result));
176
177             return $plugin['result'];
178         }
179
180         return $result;
2eb794 181     }
A 182
183
184     /**
185      * Setter for a config parameter
186      *
5c461b 187      * @param string $name  Parameter name
A 188      * @param mixed  $value Parameter value
2eb794 189      */
A 190     public function set($name, $value)
191     {
192         $this->prop[$name] = $value;
193     }
194
195
196     /**
197      * Override config options with the given values (eg. user prefs)
198      *
5c461b 199      * @param array $prefs Hash array with config props to merge over
2eb794 200      */
A 201     public function merge($prefs)
202     {
203         $this->prop = array_merge($this->prop, $prefs, $this->userprefs);
204     }
205
206
207     /**
208      * Merge the given prefs over the current config
209      * and make sure that they survive further merging.
210      *
5c461b 211      * @param array $prefs Hash array with user prefs
2eb794 212      */
A 213     public function set_user_prefs($prefs)
214     {
bfb7d6 215         // Honor the dont_override setting for any existing user preferences
A 216         $dont_override = $this->get('dont_override');
217         if (is_array($dont_override) && !empty($dont_override)) {
218             foreach ($prefs as $key => $pref) {
219                 if (in_array($key, $dont_override)) {
220                     unset($prefs[$key]);
221                 }
222             }
223         }
224
c21d7f 225         // convert user's timezone into the new format
A 226         if (is_numeric($prefs['timezone'])) {
227             $prefs['timezone'] = timezone_name_from_abbr('', $prefs['timezone'] * 3600, 0);
228         }
229
2eb794 230         $this->userprefs = $prefs;
bfb7d6 231         $this->prop      = array_merge($this->prop, $prefs);
65082b 232
T 233         // override timezone settings with client values
801b69 234         if ($this->prop['timezone'] == 'auto') {
5879c0 235             $this->prop['_timezone_value'] = isset($_SESSION['timezone']) ? $this->client_timezone() : $this->prop['_timezone_value'];
65082b 236         }
985e41 237         else if (isset($this->prop['_timezone_value']))
T 238            unset($this->prop['_timezone_value']);
2eb794 239     }
A 240
241
242     /**
243      * Getter for all config options
244      *
245      * @return array  Hash array containg all config properties
246      */
247     public function all()
248     {
249         return $this->prop;
250     }
251
da7178 252     /**
65082b 253      * Special getter for user's timezone offset including DST
T 254      *
255      * @return float  Timezone offset (in hours)
5879c0 256      * @deprecated
da7178 257      */
T 258     public function get_timezone()
259     {
e86a21 260       if ($tz = $this->get('timezone')) {
A 261         try {
262           $tz = new DateTimeZone($tz);
263           return $tz->getOffset(new DateTime('now')) / 3600;
264         }
265         catch (Exception $e) {
266         }
5879c0 267       }
T 268
269       return 0;
da7178 270     }
2eb794 271
A 272     /**
273      * Return requested DES crypto key.
274      *
5c461b 275      * @param string $key Crypto key name
2eb794 276      * @return string Crypto key
A 277      */
278     public function get_crypto_key($key)
279     {
280         // Bomb out if the requested key does not exist
281         if (!array_key_exists($key, $this->prop)) {
282             raise_error(array(
283                 'code' => 500, 'type' => 'php',
284                 'file' => __FILE__, 'line' => __LINE__,
285                 'message' => "Request for unconfigured crypto key \"$key\""
286             ), true, true);
287         }
288
289         $key = $this->prop[$key];
290
291         // Bomb out if the configured key is not exactly 24 bytes long
292         if (strlen($key) != 24) {
293             raise_error(array(
294                 'code' => 500, 'type' => 'php',
295                 'file' => __FILE__, 'line' => __LINE__,
296                 'message' => "Configured crypto key '$key' is not exactly 24 bytes long"
297             ), true, true);
298         }
299
300         return $key;
301     }
302
303
304     /**
305      * Try to autodetect operating system and find the correct line endings
306      *
307      * @return string The appropriate mail header delimiter
308      */
309     public function header_delimiter()
310     {
311         // use the configured delimiter for headers
086767 312         if (!empty($this->prop['mail_header_delimiter'])) {
A 313             $delim = $this->prop['mail_header_delimiter'];
314             if ($delim == "\n" || $delim == "\r\n")
315                 return $delim;
316             else
317                 raise_error(array(
318                     'code' => 500, 'type' => 'php',
319                     'file' => __FILE__, 'line' => __LINE__,
320                     'message' => "Invalid mail_header_delimiter setting"
321                 ), true, false);
322         }
2eb794 323
A 324         $php_os = strtolower(substr(PHP_OS, 0, 3));
325
326         if ($php_os == 'win')
327             return "\r\n";
328
329         if ($php_os == 'mac')
330             return "\r\n";
331
332         return "\n";
333     }
334
335
336     /**
337      * Return the mail domain configured for the given host
338      *
5c461b 339      * @param string  $host   IMAP host
A 340      * @param boolean $encode If true, domain name will be converted to IDN ASCII
2eb794 341      * @return string Resolved SMTP host
A 342      */
e99991 343     public function mail_domain($host, $encode=true)
2eb794 344     {
A 345         $domain = $host;
346
347         if (is_array($this->prop['mail_domain'])) {
348             if (isset($this->prop['mail_domain'][$host]))
349                 $domain = $this->prop['mail_domain'][$host];
350         }
351         else if (!empty($this->prop['mail_domain']))
bb8721 352             $domain = rcube_parse_host($this->prop['mail_domain']);
A 353
e99991 354         if ($encode)
e8d5bd 355             $domain = rcube_idn_to_ascii($domain);
e99991 356
2eb794 357         return $domain;
A 358     }
bb8721 359
A 360
2eb794 361     /**
A 362      * Getter for error state
363      *
364      * @return mixed Error message on error, False if no errors
365      */
366     public function get_error()
367     {
368         return empty($this->errors) ? false : join("\n", $this->errors);
369     }
83a763 370
5879c0 371
T 372     /**
373      * Internal getter for client's (browser) timezone identifier
374      */
375     private function client_timezone()
376     {
377         return isset($_SESSION['timezone']) ? timezone_name_from_abbr("", $_SESSION['timezone'] * 3600, 0) : date_default_timezone_get();
378     }
379
197601 380 }