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