Thomas Bruederli
2013-04-25 ddfdd8938d78b40842a984d310e3c35af30ece0a
commit | author | age
4e17e6 1 <?php
T 2
3 /*
4  +-----------------------------------------------------------------------+
e019f2 5  | This file is part of the Roundcube PHP suite                          |
18e23a 6  | Copyright (C) 2005-2013, The Roundcube Dev Team                       |
7fe381 7  |                                                                       |
T 8  | Licensed under the GNU General Public License version 3 or            |
9  | any later version with exceptions for skins & plugins.                |
10  | See the README file for a full license statement.                     |
4e17e6 11  |                                                                       |
T 12  | CONTENTS:                                                             |
f707fe 13  |   Roundcube Framework Initialization                                  |
4e17e6 14  +-----------------------------------------------------------------------+
T 15  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
f707fe 16  | Author: Aleksander Machniak <alec@alec.pl>                            |
4e17e6 17  +-----------------------------------------------------------------------+
T 18 */
19
20
6d969b 21 /**
f707fe 22  * Roundcube Framework Initialization
9e54e6 23  *
9ab346 24  * @package    Framework
AM 25  * @subpackage Core
6d969b 26  */
f707fe 27
AM 28 $config = array(
29     'error_reporting'         => E_ALL &~ (E_NOTICE | E_STRICT),
30     // Some users are not using Installer, so we'll check some
31     // critical PHP settings here. Only these, which doesn't provide
32     // an error/warning in the logs later. See (#1486307).
33     'mbstring.func_overload'  => 0,
34     'magic_quotes_runtime'    => 0,
35     'magic_quotes_sybase'     => 0, // #1488506
36 );
589083 37
TB 38 // check these additional ini settings if not called via CLI
39 if (php_sapi_name() != 'cli') {
40     $config += array(
41         'suhosin.session.encrypt' => 0,
42         'session.auto_start'      => 0,
43         'file_uploads'            => 1,
44     );
45 }
46
f707fe 47 foreach ($config as $optname => $optval) {
AM 48     if ($optval != ini_get($optname) && @ini_set($optname, $optval) === false) {
49         die("ERROR: Wrong '$optname' option value and it wasn't possible to set it to required value ($optval).\n"
50             ."Check your PHP configuration (including php_admin_flag).");
51     }
52 }
53
fdbe5a 54 // framework constants
3d525f 55 define('RCUBE_VERSION', '1.0-git');
a92beb 56 define('RCUBE_CHARSET', 'UTF-8');
f707fe 57
9be2f4 58 if (!defined('RCUBE_LIB_DIR')) {
TB 59     define('RCUBE_LIB_DIR', dirname(__FILE__).'/');
f707fe 60 }
AM 61
9be2f4 62 if (!defined('RCUBE_INSTALL_PATH')) {
TB 63     define('RCUBE_INSTALL_PATH', RCUBE_LIB_DIR);
64 }
65
66 if (!defined('RCUBE_CONFIG_DIR')) {
592668 67     define('RCUBE_CONFIG_DIR', RCUBE_INSTALL_PATH . 'config/');
9be2f4 68 }
TB 69
70 if (!defined('RCUBE_PLUGINS_DIR')) {
71     define('RCUBE_PLUGINS_DIR', RCUBE_INSTALL_PATH . 'plugins/');
72 }
73
74 if (!defined('RCUBE_LOCALIZATION_DIR')) {
75     define('RCUBE_LOCALIZATION_DIR', RCUBE_INSTALL_PATH . 'localization/');
f707fe 76 }
AM 77
78 // set internal encoding for mbstring extension
79 if (extension_loaded('mbstring')) {
a92beb 80     mb_internal_encoding(RCUBE_CHARSET);
AM 81     @mb_regex_encoding(RCUBE_CHARSET);
f707fe 82 }
AM 83
84 // Register autoloader
85 spl_autoload_register('rcube_autoload');
86
87 // set PEAR error handling (will also load the PEAR main class)
88 PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'rcube_pear_error');
89
4e17e6 90
a0109c 91
6d969b 92 /**
f11541 93  * Similar function as in_array() but case-insensitive
6d969b 94  *
0c2596 95  * @param string $needle    Needle value
A 96  * @param array  $heystack  Array to search in
97  *
6d969b 98  * @return boolean True if found, False if not
f11541 99  */
4e17e6 100 function in_array_nocase($needle, $haystack)
6d969b 101 {
0c2596 102     $needle = mb_strtolower($needle);
be9840 103     foreach ((array)$haystack as $value) {
0c2596 104         if ($needle === mb_strtolower($value)) {
A 105             return true;
106         }
107     }
9e54e6 108
0c2596 109     return false;
6d969b 110 }
4e17e6 111
T 112
6d969b 113 /**
0c2596 114  * Parse a human readable string for a number of bytes.
6d969b 115  *
0c2596 116  * @param string $str  Input string
A 117  *
47f072 118  * @return float Number of bytes
6d969b 119  */
86df15 120 function parse_bytes($str)
6d969b 121 {
0c2596 122     if (is_numeric($str)) {
A 123         return floatval($str);
86df15 124     }
T 125
0c2596 126     if (preg_match('/([0-9\.]+)\s*([a-z]*)/i', $str, $regs)) {
A 127         $bytes = floatval($regs[1]);
128         switch (strtolower($regs[2])) {
129         case 'g':
130         case 'gb':
131             $bytes *= 1073741824;
132             break;
133         case 'm':
134         case 'mb':
135             $bytes *= 1048576;
136             break;
137         case 'k':
138         case 'kb':
139             $bytes *= 1024;
140             break;
7145e0 141         }
A 142     }
0c2596 143
A 144     return floatval($bytes);
7145e0 145 }
86df15 146
0c2596 147
6d969b 148 /**
T 149  * Make sure the string ends with a slash
150  */
bac7d1 151 function slashify($str)
6d969b 152 {
bac7d1 153   return unslashify($str).'/';
6d969b 154 }
bac7d1 155
T 156
6d969b 157 /**
e8be30 158  * Remove slashes at the end of the string
6d969b 159  */
bac7d1 160 function unslashify($str)
6d969b 161 {
e8be30 162   return preg_replace('/\/+$/', '', $str);
6d969b 163 }
9fee0e 164
T 165
6d969b 166 /**
5d66a4 167  * Returns number of seconds for a specified offset string.
6d969b 168  *
5d66a4 169  * @param string $str  String representation of the offset (e.g. 20min, 5h, 2days, 1week)
0c2596 170  *
5d66a4 171  * @return int Number of seconds
6d969b 172  */
5d66a4 173 function get_offset_sec($str)
9e54e6 174 {
5d66a4 175     if (preg_match('/^([0-9]+)\s*([smhdw])/i', $str, $regs)) {
A 176         $amount = (int) $regs[1];
0c2596 177         $unit   = strtolower($regs[2]);
734584 178     }
bf13ba 179     else {
5d66a4 180         $amount = (int) $str;
0c2596 181         $unit   = 's';
bf13ba 182     }
734584 183
0c2596 184     switch ($unit) {
A 185     case 'w':
186         $amount *= 7;
187     case 'd':
188         $amount *= 24;
189     case 'h':
190         $amount *= 60;
191     case 'm':
192         $amount *= 60;
193     }
194
5d66a4 195     return $amount;
A 196 }
197
198
199 /**
200  * Create a unix timestamp with a specified offset from now.
201  *
202  * @param string $offset_str  String representation of the offset (e.g. 20min, 5h, 2days)
203  * @param int    $factor      Factor to multiply with the offset
204  *
205  * @return int Unix timestamp
206  */
207 function get_offset_time($offset_str, $factor=1)
208 {
209     return time() + get_offset_sec($offset_str) * $factor;
734584 210 }
T 211
0501b6 212
T 213 /**
0c2596 214  * Truncate string if it is longer than the allowed length.
A 215  * Replace the middle or the ending part of a string with a placeholder.
0501b6 216  *
0c2596 217  * @param string $str         Input string
A 218  * @param int    $maxlength   Max. length
219  * @param string $placeholder Replace removed chars with this
220  * @param bool   $ending      Set to True if string should be truncated from the end
221  *
222  * @return string Abbreviated string
0501b6 223  */
0c2596 224 function abbreviate_string($str, $maxlength, $placeholder='...', $ending=false)
0501b6 225 {
0c2596 226     $length = mb_strlen($str);
0501b6 227
0c2596 228     if ($length > $maxlength) {
A 229         if ($ending) {
230             return mb_substr($str, 0, $maxlength) . $placeholder;
231         }
232
233         $placeholder_length = mb_strlen($placeholder);
234         $first_part_length  = floor(($maxlength - $placeholder_length)/2);
235         $second_starting_location = $length - $maxlength + $first_part_length + $placeholder_length;
236
237         $str = mb_substr($str, 0, $first_part_length) . $placeholder . mb_substr($str, $second_starting_location);
238     }
239
240     return $str;
0501b6 241 }
T 242
243
b54121 244 /**
0c2596 245  * Get all keys from array (recursive).
A 246  *
247  * @param array $array  Input array
248  *
249  * @return array List of array keys
f52c93 250  */
T 251 function array_keys_recursive($array)
252 {
0c2596 253     $keys = array();
9e54e6 254
e8be30 255     if (!empty($array) && is_array($array)) {
0c2596 256         foreach ($array as $key => $child) {
A 257             $keys[] = $key;
258             foreach (array_keys_recursive($child) as $val) {
259                 $keys[] = $val;
260             }
261         }
f52c93 262     }
0c2596 263
A 264     return $keys;
265 }
266
267
268 /**
269  * Remove all non-ascii and non-word chars except ., -, _
270  */
271 function asciiwords($str, $css_id = false, $replace_with = '')
272 {
273     $allowed = 'a-z0-9\_\-' . (!$css_id ? '\.' : '');
274     return preg_replace("/[^$allowed]/i", $replace_with, $str);
275 }
276
277
278 /**
a04a74 279  * Check if a string contains only ascii characters
AM 280  *
281  * @param string $str           String to check
282  * @param bool   $control_chars Includes control characters
283  *
284  * @return bool
285  */
286 function is_ascii($str, $control_chars = true)
287 {
288     $regexp = $control_chars ? '/[^\x00-\x7F]/' : '/[^\x20-\x7E]/';
289     return preg_match($regexp, $str) ? false : true;
290 }
291
292
293 /**
e8be30 294  * Remove single and double quotes from a given string
0c2596 295  *
A 296  * @param string Input value
297  *
298  * @return string Dequoted string
299  */
300 function strip_quotes($str)
301 {
302     return str_replace(array("'", '"'), '', $str);
303 }
304
305
306 /**
307  * Remove new lines characters from given string
308  *
309  * @param string $str  Input value
310  *
311  * @return string Stripped string
312  */
313 function strip_newlines($str)
314 {
315     return preg_replace('/[\r\n]/', '', $str);
316 }
317
318
319 /**
320  * Compose a valid representation of name and e-mail address
321  *
322  * @param string $email  E-mail address
323  * @param string $name   Person name
324  *
325  * @return string Formatted string
326  */
327 function format_email_recipient($email, $name = '')
328 {
329     $email = trim($email);
330
331     if ($name && $name != $email) {
332         // Special chars as defined by RFC 822 need to in quoted string (or escaped).
333         if (preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $name)) {
334             $name = '"'.addcslashes($name, '"').'"';
335         }
336
337         return "$name <$email>";
338     }
339
340     return $email;
f52c93 341 }
T 342
343
344 /**
6ab936 345  * Format e-mail address
AM 346  *
347  * @param string $email E-mail address
348  *
349  * @return string Formatted e-mail address
350  */
351 function format_email($email)
352 {
353     $email = trim($email);
354     $parts = explode('@', $email);
355     $count = count($parts);
356
357     if ($count > 1) {
358         $parts[$count-1] = mb_strtolower($parts[$count-1]);
359
360         $email = implode('@', $parts);
361     }
362
363     return $email;
364 }
365
366
367 /**
a07926 368  * Fix version number so it can be used correctly in version_compare()
AM 369  *
370  * @param string $version Version number string
371  *
372  * @param return Version number string
373  */
374 function version_parse($version)
375 {
376     return str_replace(
377         array('-stable', '-git'),
378         array('.0', '.99'),
379         $version);
380 }
381
382
383 /**
ee258c 384  * mbstring replacement functions
A 385  */
8f6a46 386 if (!extension_loaded('mbstring'))
A 387 {
ee258c 388     function mb_strlen($str)
A 389     {
0c2596 390         return strlen($str);
ee258c 391     }
A 392
393     function mb_strtolower($str)
394     {
395         return strtolower($str);
396     }
397
398     function mb_strtoupper($str)
399     {
400         return strtoupper($str);
401     }
402
403     function mb_substr($str, $start, $len=null)
404     {
405         return substr($str, $start, $len);
406     }
407
408     function mb_strpos($haystack, $needle, $offset=0)
409     {
410         return strpos($haystack, $needle, $offset);
411     }
412
413     function mb_strrpos($haystack, $needle, $offset=0)
414     {
415         return strrpos($haystack, $needle, $offset);
416     }
417 }
418
e99991 419 /**
A 420  * intl replacement functions
421  */
422
423 if (!function_exists('idn_to_utf8'))
424 {
425     function idn_to_utf8($domain, $flags=null)
426     {
427         static $idn, $loaded;
428
429         if (!$loaded) {
430             $idn = new Net_IDNA2();
431             $loaded = true;
432         }
433
e8d5bd 434         if ($idn && $domain && preg_match('/(^|\.)xn--/i', $domain)) {
e99991 435             try {
A 436                 $domain = $idn->decode($domain);
437             }
438             catch (Exception $e) {
439             }
440         }
441         return $domain;
442     }
443 }
444
445 if (!function_exists('idn_to_ascii'))
446 {
447     function idn_to_ascii($domain, $flags=null)
448     {
449         static $idn, $loaded;
450
451         if (!$loaded) {
452             $idn = new Net_IDNA2();
453             $loaded = true;
454         }
455
456         if ($idn && $domain && preg_match('/[^\x20-\x7E]/', $domain)) {
457             try {
458                 $domain = $idn->encode($domain);
459             }
460             catch (Exception $e) {
461             }
462         }
463         return $domain;
464     }
465 }
466
0c2596 467 /**
A 468  * Use PHP5 autoload for dynamic class loading
469  *
470  * @todo Make Zend, PEAR etc play with this
471  * @todo Make our classes conform to a more straight forward CS.
472  */
473 function rcube_autoload($classname)
474 {
475     $filename = preg_replace(
476         array(
477             '/Mail_(.+)/',
478             '/Net_(.+)/',
479             '/Auth_(.+)/',
480             '/^html_.+/',
ba6f21 481             '/^rcube(.*)/',
2187b2 482             '/^utf8$/',
0c2596 483         ),
A 484         array(
485             'Mail/\\1',
486             'Net/\\1',
487             'Auth/\\1',
2187b2 488             'Roundcube/html',
AM 489             'Roundcube/rcube\\1',
0c2596 490             'utf8.class',
A 491         ),
492         $classname
493     );
494
495     if ($fp = @fopen("$filename.php", 'r', true)) {
496         fclose($fp);
1aceb9 497         include_once "$filename.php";
0c2596 498         return true;
A 499     }
500
501     return false;
502 }
503
504 /**
505  * Local callback function for PEAR errors
506  */
507 function rcube_pear_error($err)
508 {
509     error_log(sprintf("%s (%s): %s",
510         $err->getMessage(),
511         $err->getCode(),
512         $err->getUserinfo()), 0);
513 }