thomascube
2007-08-10 31d9efd97d9da09605d4329457ee218cba48f82f
commit | author | age
4e17e6 1 <?php
T 2
3 /*
4  +-----------------------------------------------------------------------+
5  | rcube_shared.inc                                                      |
6  |                                                                       |
7  | This file is part of the RoundCube PHP suite                          |
f11541 8  | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland                 |
30233b 9  | Licensed under the GNU GPL                                            |
4e17e6 10  |                                                                       |
T 11  | CONTENTS:                                                             |
12  |   Shared functions and classes used in PHP projects                   |
13  |                                                                       |
14  +-----------------------------------------------------------------------+
15  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
16  +-----------------------------------------------------------------------+
17
18  $Id$
19
20 */
21
22
6d969b 23 /**
T 24  * RoundCube shared functions
25  * 
26  * @package Core
27  */
4e17e6 28
a0109c 29
6d969b 30 /**
T 31  * Provide details about the client's browser
32  *
33  * @return array Key-value pairs of browser properties
34  */
4e17e6 35 function rcube_browser()
6d969b 36 {
de2e1e 37   $HTTP_USER_AGENT = $_SERVER['HTTP_USER_AGENT'];
4e17e6 38
T 39   $bw['ver'] = 0;
40   $bw['win'] = stristr($HTTP_USER_AGENT, 'win');
41   $bw['mac'] = stristr($HTTP_USER_AGENT, 'mac');
42   $bw['linux'] = stristr($HTTP_USER_AGENT, 'linux');
43   $bw['unix']  = stristr($HTTP_USER_AGENT, 'unix');
44
45   $bw['ns4'] = stristr($HTTP_USER_AGENT, 'mozilla/4') && !stristr($HTTP_USER_AGENT, 'msie');
46   $bw['ns']  = ($bw['ns4'] || stristr($HTTP_USER_AGENT, 'netscape'));
47   $bw['ie']  = stristr($HTTP_USER_AGENT, 'msie');
48   $bw['mz']  = stristr($HTTP_USER_AGENT, 'mozilla/5');
49   $bw['opera'] = stristr($HTTP_USER_AGENT, 'opera');
50   $bw['safari'] = stristr($HTTP_USER_AGENT, 'safari');
51
52   if($bw['ns'])
6d969b 53   {
4e17e6 54     $test = eregi("mozilla\/([0-9\.]+)", $HTTP_USER_AGENT, $regs);
T 55     $bw['ver'] = $test ? (float)$regs[1] : 0;
6d969b 56   }
4e17e6 57   if($bw['mz'])
6d969b 58   {
4e17e6 59     $test = ereg("rv:([0-9\.]+)", $HTTP_USER_AGENT, $regs);
T 60     $bw['ver'] = $test ? (float)$regs[1] : 0;
6d969b 61   }
4e17e6 62   if($bw['ie'])
6d969b 63   {
4e17e6 64     $test = eregi("msie ([0-9\.]+)", $HTTP_USER_AGENT, $regs);
T 65     $bw['ver'] = $test ? (float)$regs[1] : 0;
6d969b 66   }
4e17e6 67   if($bw['opera'])
6d969b 68   {
4e17e6 69     $test = eregi("opera ([0-9\.]+)", $HTTP_USER_AGENT, $regs);
T 70     $bw['ver'] = $test ? (float)$regs[1] : 0;
6d969b 71   }
4e17e6 72
T 73   if(eregi(" ([a-z]{2})-([a-z]{2})", $HTTP_USER_AGENT, $regs))
74     $bw['lang'] =  $regs[1];
75   else
76     $bw['lang'] =  'en';
77
78   $bw['dom'] = ($bw['mz'] || $bw['safari'] || ($bw['ie'] && $bw['ver']>=5) || ($bw['opera'] && $bw['ver']>=7));
79   $bw['pngalpha'] = $bw['mz'] || $bw['safari'] || ($bw['ie'] && $bw['ver']>=5.5) ||
80                     ($bw['ie'] && $bw['ver']>=5 && $bw['mac']) || ($bw['opera'] && $bw['ver']>=7) ? TRUE : FALSE;
81
82   return $bw;
6d969b 83 }
4e17e6 84
T 85
6d969b 86 /**
T 87  * Get localized text in the desired language
88  *
89  * @param mixed Named parameters array or label name
90  * @return string Localized text
91  */
4e17e6 92 function rcube_label($attrib)
6d969b 93 {
7cc38e 94   global $sess_user_lang, $INSTALL_PATH, $OUTPUT;
a95e0e 95   static $sa_text_data, $s_language, $utf8_decode;
4e17e6 96
T 97   // extract attributes
98   if (is_string($attrib))
99     $attrib = array('name' => $attrib);
100     
101   $nr = is_numeric($attrib['nr']) ? $attrib['nr'] : 1;
102   $vars = isset($attrib['vars']) ? $attrib['vars'] : '';
103
86df15 104   $command_name = !empty($attrib['command']) ? $attrib['command'] : NULL;
4e17e6 105   $alias = $attrib['name'] ? $attrib['name'] : ($command_name && $command_label_map[$command_name] ? $command_label_map[$command_name] : '');
T 106
107
108   // load localized texts
109   if (!$sa_text_data || $s_language != $sess_user_lang)
110     {
111     $sa_text_data = array();
112     
113     // get english labels (these should be complete)
0af7e8 114     @include($INSTALL_PATH.'program/localization/en_US/labels.inc');
T 115     @include($INSTALL_PATH.'program/localization/en_US/messages.inc');
4e17e6 116
T 117     if (is_array($labels))
118       $sa_text_data = $labels;
119     if (is_array($messages))
120       $sa_text_data = array_merge($sa_text_data, $messages);
121     
122     // include user language files
123     if ($sess_user_lang!='en' && is_dir($INSTALL_PATH.'program/localization/'.$sess_user_lang))
6d969b 124     {
4e17e6 125       include_once($INSTALL_PATH.'program/localization/'.$sess_user_lang.'/labels.inc');
T 126       include_once($INSTALL_PATH.'program/localization/'.$sess_user_lang.'/messages.inc');
0af7e8 127
4e17e6 128       if (is_array($labels))
T 129         $sa_text_data = array_merge($sa_text_data, $labels);
130       if (is_array($messages))
131         $sa_text_data = array_merge($sa_text_data, $messages);
6d969b 132     }
4e17e6 133       
T 134     $s_language = $sess_user_lang;
6d969b 135   }
4e17e6 136
T 137   // text does not exist
138   if (!($text_item = $sa_text_data[$alias]))
6d969b 139   {
4e17e6 140     /*
6d969b 141     raise_error(array(
T 142       'code' => 500,
143       'type' => 'php',
144       'line' => __LINE__,
145       'file' => __FILE__,
146       'message' => "Missing localized text for '$alias' in '$sess_user_lang'"), TRUE, FALSE);
4e17e6 147     */
T 148     return "[$alias]";
6d969b 149   }
4e17e6 150
T 151   // make text item array 
152   $a_text_item = is_array($text_item) ? $text_item : array('single' => $text_item);
153
154   // decide which text to use
155   if ($nr==1)
156     $text = $a_text_item['single'];
157   else if ($nr>0)
158     $text = $a_text_item['multiple'];
159   else if ($nr==0)
6d969b 160   {
4e17e6 161     if ($a_text_item['none'])
T 162       $text = $a_text_item['none'];
163     else if ($a_text_item['single'])
164       $text = $a_text_item['single'];
165     else if ($a_text_item['multiple'])
166       $text = $a_text_item['multiple'];
6d969b 167   }
4e17e6 168
T 169   // default text is single
170   if ($text=='')
171     $text = $a_text_item['single'];
172
173   // replace vars in text
174   if (is_array($attrib['vars']))
6d969b 175   {
4e17e6 176     foreach ($attrib['vars'] as $var_key=>$var_value)
T 177       $a_replace_vars[substr($var_key, 0, 1)=='$' ? substr($var_key, 1) : $var_key] = $var_value;
6d969b 178   }
4e17e6 179
T 180   if ($a_replace_vars)
181     $text = preg_replace('/\${?([_a-z]{1}[_a-z0-9]*)}?/ei', '$a_replace_vars["\1"]', $text);
182
183   // remove variables in text which were not available in arg $vars and $nr
184   eval("\$text = <<<EOF
185 $text
186 EOF;
187 ");
a95e0e 188
4e17e6 189   // format output
T 190   if (($attrib['uppercase'] && strtolower($attrib['uppercase']=='first')) || $attrib['ucfirst'])
191     return ucfirst($text);
192   else if ($attrib['uppercase'])
193     return strtoupper($text);
194   else if ($attrib['lowercase'])
195     return strtolower($text);
196
197   return $text;
6d969b 198 }
4e17e6 199
T 200
6d969b 201 /**
T 202  * Send HTTP headers to prevent caching this page
203  */
4e17e6 204 function send_nocacheing_headers()
6d969b 205 {
4e17e6 206   if (headers_sent())
T 207     return;
208
209   header("Expires: ".gmdate("D, d M Y H:i:s")." GMT");
210   header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
211   header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
212   header("Pragma: no-cache");
6d969b 213 }
4e17e6 214
T 215
6d969b 216 /**
T 217  * Send header with expire date 30 days in future
218  *
219  * @param int Expiration time in seconds
220  */
ff52be 221 function send_future_expire_header($offset=2600000)
6d969b 222 {
1a98a6 223   if (headers_sent())
T 224     return;
225
ff52be 226   header("Expires: ".gmdate("D, d M Y H:i:s", mktime()+$offset)." GMT");
T 227   header("Cache-Control: max-age=$offset");
1a98a6 228   header("Pragma: ");
6d969b 229 }
4e17e6 230
T 231
6d969b 232 /**
T 233  * Check request for If-Modified-Since and send an according response.
234  * This will terminate the current script if headers match the given values
235  *
236  * @param int Modified date as unix timestamp
237  * @param string Etag value for caching
238  */
ff52be 239 function send_modified_header($mdate, $etag=null)
T 240 {
241   if (headers_sent())
242     return;
243     
244   $iscached = false;
245   if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $mdate)
246     $iscached = true;
247   
248   $etag = $etag ? "\"$etag\"" : null;
249   if ($etag && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag)
250     $iscached = true;
251   
252   if ($iscached)
253     header("HTTP/1.x 304 Not Modified");
254   else
255     header("Last-Modified: ".gmdate("D, d M Y H:i:s", $mdate)." GMT");
256   
257   header("Cache-Control: max-age=0");
258   header("Expires: ");
259   header("Pragma: ");
260   
261   if ($etag)
262     header("Etag: $etag");
263   
264   if ($iscached)
265     exit;
266 }
267
268
f11541 269 /**
6d969b 270  * Convert a variable into a javascript object notation
T 271  *
272  * @param mixed Input value
273  * @return string Serialized JSON string
f11541 274  */
T 275 function json_serialize($var)
6d969b 276 {
T 277   if (is_object($var))
278     $var = get_object_vars($var);
279
280   if (is_array($var))
4e17e6 281   {
6d969b 282     // empty array
T 283     if (!sizeof($var))
284       return '[]';
f11541 285     else
6d969b 286     {
T 287       $keys_arr = array_keys($var);
288       $is_assoc = $have_numeric = 0;
289
290       for ($i=0; $i<sizeof($keys_arr); ++$i)
291       {
292         if (is_numeric($keys_arr[$i]))
293           $have_numeric = 1;
294         if (!is_numeric($keys_arr[$i]) || $keys_arr[$i] != $i)
295           $is_assoc = 1;
296         if ($is_assoc && $have_numeric)
297           break;
298       }
299       
300       $brackets = $is_assoc ? '{}' : '[]';
301       $pairs = array();
302
303       foreach ($var as $key => $value)
304       {
305         // enclose key with quotes if it is not variable-name conform
306         if (!ereg("^[_a-zA-Z]{1}[_a-zA-Z0-9]*$", $key) /* || is_js_reserved_word($key) */)
307           $key = "'$key'";
308
309         $pairs[] = sprintf("%s%s", $is_assoc ? "$key:" : '', json_serialize($value));
310       }
311
312       return $brackets{0} . implode(',', $pairs) . $brackets{1};
313     }
f11541 314   }
6d969b 315   else if (is_numeric($var) && strval(intval($var)) === strval($var))
T 316     return $var;
317   else if (is_bool($var))
318     return $var ? '1' : '0';
319   else
320     return "'".JQ($var)."'";
321
322 }
f11541 323
T 324 /**
6d969b 325  * Function to convert an array to a javascript array
T 326  * Actually an alias function for json_serialize()
f11541 327  * @deprecated
T 328  */
329 function array2js($arr, $type='')
6d969b 330 {
f11541 331   return json_serialize($arr);
6d969b 332 }
4e17e6 333
T 334
f11541 335 /**
T 336  * Similar function as in_array() but case-insensitive
6d969b 337  *
T 338  * @param mixed Needle value
339  * @param array Array to search in
340  * @return boolean True if found, False if not
f11541 341  */
4e17e6 342 function in_array_nocase($needle, $haystack)
6d969b 343 {
4e17e6 344   foreach ($haystack as $value)
T 345     if (strtolower($needle)===strtolower($value))
6d969b 346       return true;
T 347   
348   return false;
349 }
4e17e6 350
T 351
f11541 352 /**
T 353  * Find out if the string content means TRUE or FALSE
6d969b 354  *
T 355  * @param string Input value
356  * @return boolean Imagine what!
f11541 357  */
4e17e6 358 function get_boolean($str)
6d969b 359 {
4e17e6 360   $str = strtolower($str);
T 361   if(in_array($str, array('false', '0', 'no', 'nein', ''), TRUE))
362     return FALSE;
363   else
364     return TRUE;
6d969b 365 }
4e17e6 366
T 367
6d969b 368 /**
T 369  * Parse a human readable string for a number of bytes
370  *
371  * @param string Input string
372  * @return int Number of bytes
373  */
86df15 374 function parse_bytes($str)
6d969b 375 {
86df15 376   if (is_numeric($str))
T 377     return intval($str);
378     
379   if (preg_match('/([0-9]+)([a-z])/i', $str, $regs))
6d969b 380   {
T 381     $bytes = floatval($regs[1]);
382     switch (strtolower($regs[2]))
86df15 383     {
6d969b 384       case 'g':
T 385         $bytes *= 1073741824;
386         break;
387       case 'm':
388         $bytes *= 1048576;
389         break;
390       case 'k':
391         $bytes *= 1024;
392         break;
86df15 393     }
6d969b 394   }
86df15 395
T 396   return intval($bytes);
6d969b 397 }
86df15 398     
6d969b 399 /**
T 400  * Create a human readable string for a number of bytes
401  *
402  * @param int Number of bytes
403  * @return string Byte string
404  */
3ea0e3 405 function show_bytes($bytes)
6d969b 406 {
3ea0e3 407   if ($bytes > 1073741824)
6d969b 408   {
3ea0e3 409     $gb = $bytes/1073741824;
T 410     $str = sprintf($gb>=10 ? "%d GB" : "%.1f GB", $gb);
6d969b 411   }
3ea0e3 412   else if ($bytes > 1048576)
6d969b 413   {
3ea0e3 414     $mb = $bytes/1048576;
T 415     $str = sprintf($mb>=10 ? "%d MB" : "%.1f MB", $mb);
6d969b 416   }
3ea0e3 417   else if ($bytes > 1024)
T 418     $str = sprintf("%d KB",  round($bytes/1024));
4e17e6 419   else
3ea0e3 420     $str = sprintf('%d B', $bytes);
T 421
422   return $str;
6d969b 423 }
4e17e6 424
T 425
6d969b 426 /**
T 427  * Convert paths like ../xxx to an absolute path using a base url
428  *
429  * @param string Relative path
430  * @param string Base URL
431  * @return string Absolute URL
432  */
4e17e6 433 function make_absolute_url($path, $base_url)
6d969b 434 {
T 435   $host_url = $base_url;
436   $abs_path = $path;
4e17e6 437
6d969b 438   // cut base_url to the last directory
T 439   if (strpos($base_url, '/')>7)
440   {
441     $host_url = substr($base_url, 0, strpos($base_url, '/'));
442     $base_url = substr($base_url, 0, strrpos($base_url, '/'));
443   }
444
445   // $path is absolute
446   if ($path{0}=='/')
447     $abs_path = $host_url.$path;
448   else
449   {
450     // strip './' because its the same as ''
451     $path = preg_replace('/^\.\//', '', $path);
452
453     if (preg_match_all('/\.\.\//', $path, $matches, PREG_SET_ORDER))
454       foreach ($matches as $a_match)
4e17e6 455       {
6d969b 456         if (strrpos($base_url, '/'))
T 457           $base_url = substr($base_url, 0, strrpos($base_url, '/'));
458         
459         $path = substr($path, 3);
4e17e6 460       }
T 461
6d969b 462     $abs_path = $base_url.'/'.$path;
T 463   }
464     
465   return $abs_path;
466 }
4e17e6 467
T 468
6d969b 469 /**
T 470  * Wrapper function for strlen
471  */
86df15 472 function rc_strlen($str)
6d969b 473 {
T 474   if (function_exists('mb_strlen'))
475     return mb_strlen($str);
476   else
477     return strlen($str);
478 }
86df15 479   
6d969b 480 /**
T 481  * Wrapper function for strtolower
482  */
86df15 483 function rc_strtolower($str)
6d969b 484 {
T 485   if (function_exists('mb_strtolower'))
486     return mb_strtolower($str);
487   else
488     return strtolower($str);
489 }
86df15 490
6d969b 491 /**
T 492  * Wrapper function for substr
493  */
f11541 494 function rc_substr($str, $start, $len=null)
6d969b 495 {
86df15 496   if (function_exists('mb_substr'))
T 497     return mb_substr($str, $start, $len);
498   else
499     return substr($str, $start, $len);
6d969b 500 }
86df15 501
6d969b 502 /**
T 503  * Wrapper function for strpos
504  */
86df15 505 function rc_strpos($haystack, $needle, $offset=0)
6d969b 506 {
86df15 507   if (function_exists('mb_strpos'))
T 508     return mb_strpos($haystack, $needle, $offset);
509   else
510     return strpos($haystack, $needle, $offset);
6d969b 511 }
86df15 512
6d969b 513 /**
T 514  * Wrapper function for strrpos
515  */
86df15 516 function rc_strrpos($haystack, $needle, $offset=0)
6d969b 517 {
86df15 518   if (function_exists('mb_strrpos'))
T 519     return mb_strrpos($haystack, $needle, $offset);
520   else
521     return strrpos($haystack, $needle, $offset);
6d969b 522 }
86df15 523
T 524
6d969b 525 /**
T 526  * Replace the middle part of a string with ...
527  * if it is longer than the allowed length
528  *
529  * @param string Input string
530  * @param int    Max. length
531  * @param string Replace removed chars with this
532  * @return string Abbrevated string
533  */
9fee0e 534 function abbrevate_string($str, $maxlength, $place_holder='...')
6d969b 535 {
86df15 536   $length = rc_strlen($str);
T 537   $first_part_length = floor($maxlength/2) - rc_strlen($place_holder);
9fee0e 538   
T 539   if ($length > $maxlength)
6d969b 540   {
9fee0e 541     $second_starting_location = $length - $maxlength + $first_part_length + 1;
86df15 542     $str = rc_substr($str, 0, $first_part_length) . $place_holder . rc_substr($str, $second_starting_location, $length);
6d969b 543   }
9fee0e 544
T 545   return $str;
6d969b 546 }
1cded8 547
T 548
6d969b 549 /**
T 550  * Make sure the string ends with a slash
551  */
bac7d1 552 function slashify($str)
6d969b 553 {
bac7d1 554   return unslashify($str).'/';
6d969b 555 }
bac7d1 556
T 557
6d969b 558 /**
T 559  * Remove slash at the end of the string
560  */
bac7d1 561 function unslashify($str)
6d969b 562 {
bac7d1 563   return preg_replace('/\/$/', '', $str);
6d969b 564 }
bac7d1 565   
T 566
6d969b 567 /**
T 568  * Delete all files within a folder
569  *
570  * @param string Path to directory
571  * @return boolean True on success, False if directory was not found
572  */
1cded8 573 function clear_directory($dir_path)
6d969b 574 {
1cded8 575   $dir = @opendir($dir_path);
T 576   if(!$dir) return FALSE;
577
578   while ($file = readdir($dir))
579     if (strlen($file)>2)
580       unlink("$dir_path/$file");
581
582   closedir($dir);
583   return TRUE;
6d969b 584 }
9fee0e 585
T 586
6d969b 587 /**
T 588  * Create a unix timestamp with a specified offset from now
589  *
590  * @param string String representation of the offset (e.g. 20min, 5h, 2days)
591  * @param int Factor to multiply with the offset
592  * @return int Unix timestamp
593  */
cc9570 594 function get_offset_time($offset_str, $factor=1)
T 595   {
596   if (preg_match('/^([0-9]+)\s*([smhdw])/i', $offset_str, $regs))
6d969b 597   {
cc9570 598     $amount = (int)$regs[1];
T 599     $unit = strtolower($regs[2]);
6d969b 600   }
cc9570 601   else
6d969b 602   {
cc9570 603     $amount = (int)$offset_str;
T 604     $unit = 's';
6d969b 605   }
cc9570 606     
T 607   $ts = mktime();
608   switch ($unit)
6d969b 609   {
cc9570 610     case 'w':
T 611       $amount *= 7;
612     case 'd':
613       $amount *= 24;
614     case 'h':
615       $amount *= 60;
bd4959 616     case 'm':
cc9570 617       $amount *= 60;
T 618     case 's':
619       $ts += $amount * $factor;
6d969b 620   }
cc9570 621
T 622   return $ts;
6d969b 623 }
cc9570 624
T 625
a0109c 626 /**
6d969b 627  * Return the last occurence of a string in another string
a0109c 628  *
S 629  * @param haystack string string in which to search
630  * @param needle string string for which to search
631  * @return index of needle within haystack, or false if not found
632  */
633 function strrstr($haystack, $needle)
6d969b 634 {
T 635   $pver = phpversion();
636   if ($pver[0] >= 5)
637       return strrpos($haystack, $needle);
638   else
a0109c 639   {
6d969b 640     $index = strpos(strrev($haystack), strrev($needle));
T 641     if($index === false)
642         return false;
643     
644     $index = strlen($haystack) - strlen($needle) - $index;
645     return $index;
a0109c 646   }
6d969b 647 }
a0109c 648
S 649
f88d41 650 ?>