Changeset 6d969b4 in github for program/include/rcube_shared.inc
- Timestamp:
- Aug 7, 2007 5:02:12 PM (6 years ago)
- Branches:
- master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.6, release-0.7, release-0.8
- Children:
- 4b9efbb
- Parents:
- 93be5b7
- File:
-
- 1 edited
-
program/include/rcube_shared.inc (modified) (17 diffs)
Legend:
- Unmodified
- Added
- Removed
-
program/include/rcube_shared.inc
rf115416 r6d969b4 21 21 22 22 23 // ********* round cube schared classes ********* 24 25 class rcube_html_page 26 { 27 var $css; 28 29 var $scripts_path = ''; 30 var $script_files = array(); 31 var $external_scripts = array(); 32 var $scripts = array(); 33 var $charset = 'ISO-8859-1'; 34 35 var $script_tag_file = "<script type=\"text/javascript\" src=\"%s%s\"></script>\n"; 36 var $script_tag = "<script type=\"text/javascript\">\n<!--\n%s\n\n//-->\n</script>\n"; 37 var $default_template = "<html>\n<head><title></title></head>\n<body></body>\n</html>"; 38 var $tag_format_external_script = "<script type=\"text/javascript\" src=\"%s\"></script>\n"; 39 40 var $title = ''; 41 var $header = ''; 42 var $footer = ''; 43 var $body = ''; 44 var $body_attrib = array(); 45 var $meta_tags = array(); 46 47 48 // PHP 5 constructor 49 function __construct() 50 { 51 $this->css = new rcube_css(); 52 } 53 54 // PHP 4 compatibility 55 function rcube_html_page() 56 { 57 $this->__construct(); 58 } 59 60 61 function include_script($file, $position='head') 62 { 63 static $sa_files = array(); 64 65 if (in_array($file, $sa_files)) 66 return; 67 68 if (!is_array($this->script_files[$position])) 69 $this->script_files[$position] = array(); 70 71 $this->script_files[$position][] = $file; 72 } 73 74 function include_external_script($script_location, $position='head') 75 { 76 if (!is_array($this->external_scripts[$position])) 77 { 78 $this->external_scripts[$position] = array(); 79 } 80 81 $this->external_scripts[$position][] = $script_location; 82 } 83 84 function add_script($script, $position='head') 85 { 86 if (!isset($this->scripts[$position])) 87 $this->scripts[$position] = "\n".rtrim($script); 88 else 89 $this->scripts[$position] .= "\n".rtrim($script); 90 } 91 92 function add_header($str) 93 { 94 $this->header .= "\n".$str; 95 } 96 97 function add_footer($str) 98 { 99 $this->footer .= "\n".$str; 100 } 101 102 function set_title($t) 103 { 104 $this->title = $t; 105 } 106 107 108 function set_charset($charset) 109 { 110 global $MBSTRING; 111 112 $this->charset = $charset; 113 114 if ($MBSTRING && function_exists("mb_internal_encoding")) 115 { 116 if(!@mb_internal_encoding($charset)) 117 $MBSTRING = FALSE; 118 } 119 } 120 121 function get_charset() 122 { 123 return $this->charset; 124 } 125 126 127 function reset() 128 { 129 $this->css = new rcube_css(); 130 $this->script_files = array(); 131 $this->scripts = array(); 132 $this->title = ''; 133 $this->header = ''; 134 $this->footer = ''; 135 } 136 137 138 function write($templ='', $base_path='') 139 { 140 $output = empty($templ) ? $this->default_template : trim($templ); 141 142 // set default page title 143 if (empty($this->title)) 144 $this->title = 'RoundCube Mail'; 145 146 // replace specialchars in content 147 $__page_title = Q($this->title, 'show', FALSE); 148 $__page_header = $__page_body = $__page_footer = ''; 149 150 151 // include meta tag with charset 152 if (!empty($this->charset)) 153 { 154 header('Content-Type: text/html; charset='.$this->charset); 155 $__page_header = '<meta http-equiv="content-type" content="text/html; charset='.$this->charset.'" />'."\n"; 156 } 157 158 159 // definition of the code to be placed in the document header and footer 160 if (is_array($this->script_files['head'])) 161 foreach ($this->script_files['head'] as $file) 162 $__page_header .= sprintf($this->script_tag_file, $this->scripts_path, $file); 163 164 if (is_array($this->external_scripts['head'])) 165 foreach ($this->external_scripts['head'] as $xscript) 166 $__page_header .= sprintf($this->tag_format_external_script, $xscript); 167 168 $head_script = $this->scripts['head_top'] . $this->scripts['head']; 169 if (!empty($head_script)) 170 $__page_header .= sprintf($this->script_tag, $head_script); 171 172 if (!empty($this->header)) 173 $__page_header .= $this->header; 174 175 if (is_array($this->script_files['foot'])) 176 foreach ($this->script_files['foot'] as $file) 177 $__page_footer .= sprintf($this->script_tag_file, $this->scripts_path, $file); 178 179 if (!empty($this->scripts['foot'])) 180 $__page_footer .= sprintf($this->script_tag, $this->scripts['foot']); 181 182 if (!empty($this->footer)) 183 $__page_footer .= $this->footer; 184 185 $__page_header .= $this->css->show(); 186 187 // find page header 188 if($hpos = strpos(strtolower($output), '</head>')) 189 $__page_header .= "\n"; 190 else 191 { 192 if (!is_numeric($hpos)) 193 $hpos = strpos(strtolower($output), '<body'); 194 if (!is_numeric($hpos) && ($hpos = strpos(strtolower($output), '<html'))) 195 { 196 while($output[$hpos]!='>') 197 $hpos++; 198 $hpos++; 199 } 200 201 $__page_header = "<head>\n<title>$__page_title</title>\n$__page_header\n</head>\n"; 202 } 203 204 // add page hader 205 if($hpos) 206 $output = substr($output,0,$hpos) . $__page_header . substr($output,$hpos,strlen($output)); 207 else 208 $output = $__page_header . $output; 209 210 211 // find page body 212 if($bpos = strpos(strtolower($output), '<body')) 213 { 214 while($output[$bpos]!='>') $bpos++; 215 $bpos++; 216 } 217 else 218 $bpos = strpos(strtolower($output), '</head>')+7; 219 220 // add page body 221 if($bpos && $__page_body) 222 $output = substr($output,0,$bpos) . "\n$__page_body\n" . substr($output,$bpos,strlen($output)); 223 224 225 // find and add page footer 226 $output_lc = strtolower($output); 227 if(($fpos = strrstr($output_lc, '</body>')) || 228 ($fpos = strrstr($output_lc, '</html>'))) 229 $output = substr($output, 0, $fpos) . "$__page_footer\n" . substr($output, $fpos); 230 else 231 $output .= "\n$__page_footer"; 232 233 234 // reset those global vars 235 $__page_header = $__page_footer = ''; 236 237 238 // correct absolute paths in images and other tags 239 $output = preg_replace('/(src|href|background)=(["\']?)(\/[a-z0-9_\-]+)/Ui', "\\1=\\2$base_path\\3", $output); 240 $output = str_replace('$__skin_path', $base_path, $output); 241 242 print rcube_charset_convert($output, 'UTF-8', $this->charset); 243 } 244 245 246 function _parse($templ) 247 { 248 249 } 250 } 251 252 253 254 255 class rcube_css 256 { 257 var $css_data = array(); 258 259 var $css_groups = array(); 260 261 var $include_files = array(); 262 263 var $grouped_output = TRUE; 264 265 var $content_type = 'text/css'; 266 267 var $base_path = ''; 268 269 var $indent_chars = "\t"; 270 271 272 // add or overwrite a css definition 273 // either pass porperty and value as separate arguments 274 // or provide an associative array as second argument 275 function set_style($selector, $property, $value='') 276 { 277 $a_elements = $this->_parse_selectors($selector); 278 foreach ($a_elements as $element) 279 { 280 if (!is_array($property)) 281 $property = array($property => $value); 282 283 foreach ($property as $name => $value) 284 $this->css_data[$element][strtolower($name)] = $value; 285 } 286 287 // clear goups array 288 $this->css_groups = array(); 289 } 290 291 292 // unset a style property 293 function remove_style($selector, $property) 294 { 295 if (!is_array($property)) 296 $property = array($property); 297 298 foreach ($property as $key) 299 unset($this->css_data[$selector][strtolower($key)]); 300 301 // clear goups array 302 $this->css_groups = array(); 303 } 304 305 306 // define base path for external css files 307 function set_basepath($path) 308 { 309 $this->base_path = preg_replace('/\/$/', '', $path); 310 } 311 312 313 // enable/disable grouped output 314 function set_grouped_output($grouped) 315 { 316 $this->grouped_output = $grouped; 317 } 318 319 320 // add a css file as external source 321 function include_file($filename, $media='') 322 { 323 // include multiple files 324 if (is_array($filename)) 325 { 326 foreach ($filename as $file) 327 $this->include_file($file, $media); 328 } 329 // add single file 330 else if (!in_array($filename, $this->include_files)) 331 $this->include_files[] = array('file' => $filename, 332 'media' => $media); 333 } 334 335 336 // parse css code 337 function import_string($str) 338 { 339 $ret = FALSE; 340 if (strlen($str)) 341 $ret = $this->_parse($str); 342 343 return $ret; 344 } 345 346 347 // open and parse a css file 348 function import_file($file) 349 { 350 $ret = FALSE; 351 352 if (!is_file($file)) 353 return $ret; 354 355 // for php version >= 4.3.0 356 if (function_exists('file_get_contents')) 357 $ret = $this->_parse(file_get_contents($file)); 358 359 // for order php versions 360 else if ($fp = fopen($file, 'r')) 361 { 362 $ret = $this->_parse(fread($fp, filesize($file))); 363 fclose($fp); 364 } 365 366 return $ret; 367 } 368 369 370 // copy all properties inherited from superior styles to a specific selector 371 function copy_inherited_styles($selector) 372 { 373 // get inherited props from body and tag/class selectors 374 $css_props = $this->_get_inherited_styles($selector); 375 376 // write modified props back and clear goups array 377 if (sizeof($css_props)) 378 { 379 $this->css_data[$selector] = $css_props; 380 $this->css_groups = array(); 381 } 382 } 383 384 385 // return css definition for embedding in HTML 386 function show() 387 { 388 $out = ''; 389 390 // include external css files 391 if (sizeof($this->include_files)) 392 foreach ($this->include_files as $file_arr) 393 $out .= sprintf('<link rel="stylesheet" type="%s" href="%s"%s>'."\n", 394 $this->content_type, 395 $this->_get_file_path($file_arr['file']), 396 $file_arr['media'] ? ' media="'.$file_arr['media'].'"' : ''); 397 398 399 // compose css string 400 if (sizeof($this->css_data)) 401 $out .= sprintf("<style type=\"%s\">\n<!--\n\n%s-->\n</style>", 402 $this->content_type, 403 $this->to_string()); 404 405 406 return $out; 407 } 408 409 410 // return valid css code of the current styles grid 411 function to_string($selector=NULL) 412 { 413 // return code for a single selector 414 if ($selector) 415 { 416 $indent_str = $this->indent_chars; 417 $this->indent_chars = ''; 418 419 $prop_arr = $this->to_array($selector); 420 $out = $this->_style2string($prop_arr, TRUE); 421 422 $this->indent_chars = $indent_str; 423 } 424 425 // compose css code for complete data grid 426 else 427 { 428 $out = ''; 429 $css_data = $this->to_array(); 430 431 foreach ($css_data as $key => $prop_arr) 432 $out .= sprintf("%s {\n%s}\n\n", 433 $key, 434 $this->_style2string($prop_arr, TRUE)); 435 } 436 437 return $out; 438 } 439 440 441 // return a single-line string of a css definition 442 function to_inline($selector) 443 { 444 if ($this->css_data[$selector]) 445 return str_replace('"', '\\"', $this->_style2string($this->css_data[$selector], FALSE)); 446 } 447 448 449 // return an associative array with selector(s) as key and styles array as value 450 function to_array($selector=NULL) 451 { 452 if (!$selector && $this->grouped_output) 453 { 454 // build groups if desired 455 if (!sizeof($this->css_groups)) 456 $this->_build_groups(); 457 458 // modify group array to get an array(selector => properties) 459 $out_arr = array(); 460 foreach ($this->css_groups as $group_arr) 461 { 462 $key = join(', ', $group_arr['selectors']); 463 $out_arr[$key] = $group_arr['properties']; 464 } 465 } 466 else 467 $out_arr = $this->css_data; 468 469 return $selector ? $out_arr[$selector] : $out_arr; 470 } 471 472 473 // create a css file 474 function to_file($filepath) 475 { 476 if ($fp = fopen($filepath, 'w')) 477 { 478 fwrite($fp, $this->to_string()); 479 fclose($fp); 480 return TRUE; 481 } 482 483 return FALSE; 484 } 485 486 487 // alias method for import_string() [DEPRECATED] 488 function add($str) 489 { 490 $this->import_string($str); 491 } 492 493 // alias method for to_string() [DEPRECATED] 494 function get() 495 { 496 return $this->to_string(); 497 } 498 499 500 501 // ******** private methods ******** 502 503 504 // parse a string and add styles to internal data grid 505 function _parse($str) 506 { 507 // remove comments 508 $str = preg_replace("/\/\*(.*)?\*\//Usi", '', $str); 509 510 // parse style definitions 511 if (!preg_match_all ('/([a-z0-9\.#*:_][a-z0-9\.\-_#:*,\[\]\(\)\s\"\'\+\|>~=]+)\s*\{([^\}]*)\}/ims', $str, $matches, PREG_SET_ORDER)) 512 return FALSE; 513 514 515 foreach ($matches as $match_arr) 516 { 517 // split selectors into array 518 $a_keys = $this->_parse_selectors(trim($match_arr[1])); 519 520 // parse each property of an element 521 $codes = explode(";", trim($match_arr[2])); 522 foreach ($codes as $code) 523 { 524 if (strlen(trim($code))>0) 525 { 526 // find the property and the value 527 if (!($sep = strpos($code, ':'))) 528 continue; 529 530 $property = strtolower(trim(substr($code, 0, $sep))); 531 $value = trim(substr($code, $sep+1)); 532 533 // add the property to the object array 534 foreach ($a_keys as $key) 535 $this->css_data[$key][$property] = $value; 536 } 537 } 538 } 539 540 // clear goups array 541 if (sizeof($matches)) 542 { 543 $this->css_groups = array(); 544 return TRUE; 545 } 546 547 return FALSE; 548 } 549 550 551 // split selector group 552 function _parse_selectors($selector) 553 { 554 // trim selector and remove multiple spaces 555 $selector = preg_replace('/\s+/', ' ', trim($selector)); 556 557 if (strpos($selector, ',')) 558 return preg_split('/[\t\s\n\r]*,[\t\s\n\r]*/mi', $selector); 559 else 560 return array($selector); 561 } 562 563 564 // compare identical styles and make groups 565 function _build_groups() 566 { 567 // clear group array 568 $this->css_groups = array(); 569 $string_group_map = array(); 570 571 // bulild css string for each selector and check if the same is already defines 572 foreach ($this->css_data as $selector => $prop_arr) 573 { 574 // make shure to compare props in the same order 575 ksort($prop_arr); 576 $compare_str = preg_replace('/[\s\t]+/', '', $this->_style2string($prop_arr, FALSE)); 577 578 // add selector to extisting group 579 if (isset($string_group_map[$compare_str])) 580 { 581 $group_index = $string_group_map[$compare_str]; 582 $this->css_groups[$group_index]['selectors'][] = $selector; 583 } 584 585 // create new group 586 else 587 { 588 $i = sizeof($this->css_groups); 589 $string_group_map[$compare_str] = $i; 590 $this->css_groups[$i] = array('selectors' => array($selector), 591 'properties' => $this->css_data[$selector]); 592 } 593 } 594 } 595 596 597 // convert the prop array into a valid css definition 598 function _style2string($prop_arr, $multiline=TRUE) 599 { 600 $out = ''; 601 $delm = $multiline ? "\n" : ''; 602 $spacer = $multiline ? ' ' : ''; 603 $indent = $multiline ? $this->indent_chars : ''; 604 605 if (is_array($prop_arr)) 606 foreach ($prop_arr as $prop => $value) 607 if (strlen($value)) 608 $out .= sprintf('%s%s:%s%s;%s', 609 $indent, 610 $prop, 611 $spacer, 612 $value, 613 $delm); 614 615 return $out; 616 } 617 618 619 // copy all properties inherited from superior styles to a specific selector 620 function _get_inherited_styles($selector, $loop=FALSE) 621 { 622 $css_props = $this->css_data[$selector] ? $this->css_data[$selector] : array(); 623 624 // get styles from tag selector 625 if (preg_match('/(([a-z0-9]*)(\.[^\s]+)?)$/i', $selector, $regs)) 626 { 627 $sel = $regs[1]; 628 $tagname = $regs[2]; 629 $class = $regs[3]; 630 631 if ($sel && is_array($this->css_data[$sel])) 632 $css_props = $this->_merge_styles($this->css_data[$sel], $css_props); 633 634 if ($class && is_array($this->css_data[$class])) 635 $css_props = $this->_merge_styles($this->css_data[$class], $css_props); 636 637 if ($tagname && is_array($this->css_data[$tagname])) 638 $css_props = $this->_merge_styles($this->css_data[$tagname], $css_props); 639 } 640 641 // analyse inheritance 642 if (strpos($selector, ' ')) 643 { 644 $a_hier = split(' ', $selector); 645 if (sizeof($a_hier)>1) 646 { 647 array_pop($a_hier); 648 $base_selector = join(' ', $a_hier); 649 650 // call this method recursively 651 $new_props = $this->_get_inherited_styles($base_selector, TRUE); 652 $css_props = $this->_merge_styles($new_props, $css_props); 653 } 654 } 655 656 // get body style 657 if (!$loop && is_array($this->css_data['body'])) 658 $css_props = $this->_merge_styles($this->css_data['body'], $css_props); 659 660 return $css_props; 661 } 662 663 664 // merge two arrays with style properties together like a browser would do 665 function _merge_styles($one, $two) 666 { 667 // these properties are additive 668 foreach (array('text-decoration') as $prop) 669 if ($one[$prop] && $two[$prop]) 670 { 671 // if value contains 'none' it's ignored 672 if (strstr($one[$prop], 'none')) 673 continue; 674 else if (strstr($two[$prop], 'none')) 675 unset($two[$prop]); 676 677 $a_values_one = split(' ', $one[$prop]); 678 $a_values_two = split(' ', $two[$prop]); 679 $two[$prop] = join(' ', array_unique(array_merge($a_values_one, $a_values_two))); 680 } 681 682 return array_merge($one, $two); 683 } 684 685 686 // resolve file path 687 function _get_file_path($file) 688 { 689 if (!$this->base_path && $GLOBALS['CSS_PATH']) 690 $this->set_basepath($GLOBALS['CSS_PATH']); 691 692 $base = ($file{0}=='/' || $file{0}=='.' || substr($file, 0, 7)=='http://') ? '' : 693 ($this->base_path ? $this->base_path.'/' : ''); 694 return $base.$file; 695 } 696 697 } 698 699 700 701 class base_form_element 702 { 703 var $uppertags = FALSE; 704 var $upperattribs = FALSE; 705 var $upperprops = FALSE; 706 var $newline = FALSE; 707 708 var $attrib = array(); 709 710 711 // create string with attributes 712 function create_attrib_string($tagname='') 713 { 714 if (!sizeof($this->attrib)) 715 return ''; 716 717 if ($this->name!='') 718 $this->attrib['name'] = $this->name; 719 720 $attrib_arr = array(); 721 foreach ($this->attrib as $key => $value) 722 { 723 // don't output some internally used attributes 724 if (in_array($key, array('form', 'quicksearch'))) 725 continue; 726 727 // skip if size if not numeric 728 if (($key=='size' && !is_numeric($value))) 729 continue; 730 731 // skip empty eventhandlers 732 if ((strpos($key,'on')===0 && $value=='')) 733 continue; 734 735 // encode textarea content 736 if ($key=='value') 737 $value = Q($value, 'strict', FALSE); 738 739 // attributes with no value 740 if (in_array($key, array('checked', 'multiple', 'disabled', 'selected'))) 741 { 742 if ($value) 743 $attrib_arr[] = $key; 744 } 745 // don't convert size of value attribute 746 else if ($key=='value') 747 $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $value, 'value'); 748 749 // regular tag attributes 750 else 751 $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $this->_conv_case($value, 'value')); 752 } 753 754 return sizeof($attrib_arr) ? ' '.implode(' ', $attrib_arr) : ''; 755 } 756 757 758 // convert tags and attributes to upper-/lowercase 759 // $type can either be "tag" or "attrib" 760 function _conv_case($str, $type='attrib') 761 { 762 if ($type == 'tag') 763 return $this->uppertags ? strtoupper($str) : strtolower($str); 764 else if ($type == 'attrib') 765 return $this->upperattribs ? strtoupper($str) : strtolower($str); 766 else if ($type == 'value') 767 return $this->upperprops ? strtoupper($str) : strtolower($str); 768 } 769 } 770 771 772 class input_field extends base_form_element 773 { 774 var $type = 'text'; 775 776 // PHP 5 constructor 777 function __construct($attrib=NULL) 778 { 779 if (is_array($attrib)) 780 $this->attrib = $attrib; 781 782 if ($attrib['type']) 783 $this->type = $attrib['type']; 784 785 if ($attrib['newline']) 786 $this->newline = TRUE; 787 } 788 789 // PHP 4 compatibility 790 function input_field($attrib=array()) 791 { 792 $this->__construct($attrib); 793 } 794 795 // compose input tag 796 function show($value=NULL, $attrib=NULL) 797 { 798 // overwrite object attributes 799 if (is_array($attrib)) 800 $this->attrib = array_merge($this->attrib, $attrib); 801 802 // set value attribute 803 if ($value!==NULL) 804 $this->attrib['value'] = $value; 805 806 $this->attrib['type'] = $this->type; 807 808 // return final tag 809 return sprintf('<%s%s />%s', 810 $this->_conv_case('input', 'tag'), 811 $this->create_attrib_string(), 812 ($this->newline ? "\n" : "")); 813 } 814 } 815 816 817 class textfield extends input_field 818 { 819 var $type = 'text'; 820 } 821 822 class passwordfield extends input_field 823 { 824 var $type = 'password'; 825 } 826 827 class radiobutton extends input_field 828 { 829 var $type = 'radio'; 830 } 831 832 class checkbox extends input_field 833 { 834 var $type = 'checkbox'; 835 836 837 function show($value='', $attrib=NULL) 838 { 839 // overwrite object attributes 840 if (is_array($attrib)) 841 $this->attrib = array_merge($this->attrib, $attrib); 842 843 $this->attrib['type'] = $this->type; 844 845 if ($value && (string)$value==(string)$this->attrib['value']) 846 $this->attrib['checked'] = TRUE; 847 else 848 $this->attrib['checked'] = FALSE; 849 850 // return final tag 851 return sprintf('<%s%s />%s', 852 $this->_conv_case('input', 'tag'), 853 $this->create_attrib_string(), 854 ($this->newline ? "\n" : "")); 855 } 856 } 857 858 859 class textarea extends base_form_element 860 { 861 // PHP 5 constructor 862 function __construct($attrib=array()) 863 { 864 $this->attrib = $attrib; 865 866 if ($attrib['newline']) 867 $this->newline = TRUE; 868 } 869 870 // PHP 4 compatibility 871 function textarea($attrib=array()) 872 { 873 $this->__construct($attrib); 874 } 875 876 function show($value='', $attrib=NULL) 877 { 878 // overwrite object attributes 879 if (is_array($attrib)) 880 $this->attrib = array_merge($this->attrib, $attrib); 881 882 // take value attribute as content 883 if ($value=='') 884 $value = $this->attrib['value']; 885 886 // make shure we don't print the value attribute 887 if (isset($this->attrib['value'])) 888 unset($this->attrib['value']); 889 890 if (!empty($value) && !isset($this->attrib['mce_editable'])) 891 $value = Q($value, 'strict', FALSE); 892 893 // return final tag 894 return sprintf('<%s%s>%s</%s>%s', 895 $this->_conv_case('textarea', 'tag'), 896 $this->create_attrib_string(), 897 $value, 898 $this->_conv_case('textarea', 'tag'), 899 ($this->newline ? "\n" : "")); 900 } 901 } 902 903 904 class hiddenfield extends base_form_element 905 { 906 var $fields_arr = array(); 907 var $newline = TRUE; 908 909 // PHP 5 constructor 910 function __construct($attrib=NULL) 911 { 912 if (is_array($attrib)) 913 $this->add($attrib); 914 } 915 916 // PHP 4 compatibility 917 function hiddenfield($attrib=NULL) 918 { 919 $this->__construct($attrib); 920 } 921 922 // add a hidden field to this instance 923 function add($attrib) 924 { 925 $this->fields_arr[] = $attrib; 926 } 927 928 929 function show() 930 { 931 $out = ''; 932 foreach ($this->fields_arr as $attrib) 933 { 934 $this->attrib = $attrib; 935 $this->attrib['type'] = 'hidden'; 936 937 $out .= sprintf('<%s%s />%s', 938 $this->_conv_case('input', 'tag'), 939 $this->create_attrib_string(), 940 ($this->newline ? "\n" : "")); 941 } 942 943 return $out; 944 } 945 } 946 947 948 class select extends base_form_element 949 { 950 var $options = array(); 951 952 /* 953 syntax: 954 ------- 955 // create instance. arguments are used to set attributes of select-tag 956 $select = new select(array('name' => 'fieldname')); 957 958 // add one option 959 $select->add('Switzerland', 'CH'); 960 961 // add multiple options 962 $select->add(array('Switzerland', 'Germany'), 963 array('CH', 'DE')); 964 965 // add 10 blank options with 50 chars 966 // used to fill with javascript (necessary for 4.x browsers) 967 $select->add_blank(10, 50); 968 969 // generate pulldown with selection 'Switzerland' and return html-code 970 // as second argument the same attributes available to instanciate can be used 971 print $select->show('CH'); 972 */ 973 974 // PHP 5 constructor 975 function __construct($attrib=NULL) 976 { 977 if (is_array($attrib)) 978 $this->attrib = $attrib; 979 980 if ($attrib['newline']) 981 $this->newline = TRUE; 982 } 983 984 // PHP 4 compatibility 985 function select($attrib=NULL) 986 { 987 $this->__construct($attrib); 988 } 989 990 991 function add($names, $values=NULL) 992 { 993 if (is_array($names)) 994 { 995 foreach ($names as $i => $text) 996 $this->options[] = array('text' => $text, 'value' => (string)$values[$i]); 997 } 998 else 999 { 1000 $this->options[] = array('text' => $names, 'value' => (string)$values); 1001 } 1002 } 1003 1004 1005 function add_blank($nr, $width=0) 1006 { 1007 $text = $width ? str_repeat(' ', $width) : ''; 1008 1009 for ($i=0; $i < $nr; $i++) 1010 $this->options[] = array('text' => $text); 1011 } 1012 1013 1014 function show($select=array(), $attrib=NULL) 1015 { 1016 $options_str = "\n"; 1017 $value_str = $this->_conv_case(' value="%s"', 'attrib'); 1018 1019 if (!is_array($select)) 1020 $select = array((string)$select); 1021 1022 foreach ($this->options as $option) 1023 { 1024 $selected = ((isset($option['value']) && 1025 in_array($option['value'], $select, TRUE)) || 1026 (in_array($option['text'], $select, TRUE))) ? 1027 $this->_conv_case(' selected', 'attrib') : ''; 1028 1029 $options_str .= sprintf("<%s%s%s>%s</%s>\n", 1030 $this->_conv_case('option', 'tag'), 1031 !empty($option['value']) ? sprintf($value_str, Q($option['value'])) : '', 1032 $selected, 1033 Q($option['text'], 'strict', FALSE), 1034 $this->_conv_case('option', 'tag')); 1035 } 1036 1037 // return final tag 1038 return sprintf('<%s%s>%s</%s>%s', 1039 $this->_conv_case('select', 'tag'), 1040 $this->create_attrib_string(), 1041 $options_str, 1042 $this->_conv_case('select', 'tag'), 1043 ($this->newline ? "\n" : "")); 1044 } 1045 } 1046 1047 1048 1049 1050 // ********* rcube schared functions ********* 1051 1052 1053 // provide details about the client's browser 23 /** 24 * RoundCube shared functions 25 * 26 * @package Core 27 */ 28 29 30 /** 31 * Provide details about the client's browser 32 * 33 * @return array Key-value pairs of browser properties 34 */ 1054 35 function rcube_browser() 1055 {36 { 1056 37 $HTTP_USER_AGENT = $_SERVER['HTTP_USER_AGENT']; 1057 38 … … 1070 51 1071 52 if($bw['ns']) 1072 {53 { 1073 54 $test = eregi("mozilla\/([0-9\.]+)", $HTTP_USER_AGENT, $regs); 1074 55 $bw['ver'] = $test ? (float)$regs[1] : 0; 1075 }56 } 1076 57 if($bw['mz']) 1077 {58 { 1078 59 $test = ereg("rv:([0-9\.]+)", $HTTP_USER_AGENT, $regs); 1079 60 $bw['ver'] = $test ? (float)$regs[1] : 0; 1080 }61 } 1081 62 if($bw['ie']) 1082 {63 { 1083 64 $test = eregi("msie ([0-9\.]+)", $HTTP_USER_AGENT, $regs); 1084 65 $bw['ver'] = $test ? (float)$regs[1] : 0; 1085 }66 } 1086 67 if($bw['opera']) 1087 {68 { 1088 69 $test = eregi("opera ([0-9\.]+)", $HTTP_USER_AGENT, $regs); 1089 70 $bw['ver'] = $test ? (float)$regs[1] : 0; 1090 }71 } 1091 72 1092 73 if(eregi(" ([a-z]{2})-([a-z]{2})", $HTTP_USER_AGENT, $regs)) … … 1100 81 1101 82 return $bw; 1102 } 1103 1104 1105 // get text in the desired language from the language file 83 } 84 85 86 /** 87 * Get localized text in the desired language 88 * 89 * @param mixed Named parameters array or label name 90 * @return string Localized text 91 */ 1106 92 function rcube_label($attrib) 1107 {93 { 1108 94 global $sess_user_lang, $INSTALL_PATH, $OUTPUT; 1109 95 static $sa_text_data, $s_language, $utf8_decode; … … 1136 122 // include user language files 1137 123 if ($sess_user_lang!='en' && is_dir($INSTALL_PATH.'program/localization/'.$sess_user_lang)) 1138 {124 { 1139 125 include_once($INSTALL_PATH.'program/localization/'.$sess_user_lang.'/labels.inc'); 1140 126 include_once($INSTALL_PATH.'program/localization/'.$sess_user_lang.'/messages.inc'); … … 1144 130 if (is_array($messages)) 1145 131 $sa_text_data = array_merge($sa_text_data, $messages); 1146 }132 } 1147 133 1148 134 $s_language = $sess_user_lang; 1149 }135 } 1150 136 1151 137 // text does not exist 1152 138 if (!($text_item = $sa_text_data[$alias])) 1153 {139 { 1154 140 /* 1155 raise_error(array('code' => 500, 1156 'type' => 'php', 1157 'line' => __LINE__, 1158 'file' => __FILE__, 1159 'message' => "Missing localized text for '$alias' in '$sess_user_lang'"), TRUE, FALSE); 141 raise_error(array( 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); 1160 147 */ 1161 148 return "[$alias]"; 1162 }149 } 1163 150 1164 151 // make text item array … … 1171 158 $text = $a_text_item['multiple']; 1172 159 else if ($nr==0) 1173 {160 { 1174 161 if ($a_text_item['none']) 1175 162 $text = $a_text_item['none']; … … 1178 165 else if ($a_text_item['multiple']) 1179 166 $text = $a_text_item['multiple']; 1180 }167 } 1181 168 1182 169 // default text is single … … 1186 173 // replace vars in text 1187 174 if (is_array($attrib['vars'])) 1188 {175 { 1189 176 foreach ($attrib['vars'] as $var_key=>$var_value) 1190 177 $a_replace_vars[substr($var_key, 0, 1)=='$' ? substr($var_key, 1) : $var_key] = $var_value; 1191 }178 } 1192 179 1193 180 if ($a_replace_vars) … … 1209 196 1210 197 return $text; 1211 } 1212 1213 1214 // send HTTP header for no-cacheing steps 198 } 199 200 201 /** 202 * Send HTTP headers to prevent caching this page 203 */ 1215 204 function send_nocacheing_headers() 1216 {205 { 1217 206 if (headers_sent()) 1218 207 return; … … 1222 211 header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); 1223 212 header("Pragma: no-cache"); 1224 } 1225 1226 1227 // send header with expire date 30 days in future 213 } 214 215 216 /** 217 * Send header with expire date 30 days in future 218 * 219 * @param int Expiration time in seconds 220 */ 1228 221 function send_future_expire_header($offset=2600000) 1229 {222 { 1230 223 if (headers_sent()) 1231 224 return; … … 1234 227 header("Cache-Control: max-age=$offset"); 1235 228 header("Pragma: "); 1236 } 1237 1238 1239 // check request for If-Modified-Since and send an according response 229 } 230 231 232 /** 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 */ 1240 239 function send_modified_header($mdate, $etag=null) 1241 240 { … … 1269 268 1270 269 /** 1271 * Convert a variable into a javascript notation string 270 * Convert a variable into a javascript object notation 271 * 272 * @param mixed Input value 273 * @return string Serialized JSON string 1272 274 */ 1273 275 function json_serialize($var) 1274 { 1275 if (is_object($var)) 1276 $var = get_object_vars($var); 1277 1278 if (is_array($var)) 276 { 277 if (is_object($var)) 278 $var = get_object_vars($var); 279 280 if (is_array($var)) 281 { 282 // empty array 283 if (!sizeof($var)) 284 return '[]'; 285 else 1279 286 { 1280 // empty array1281 if (!sizeof($var))1282 return '[]'; 1283 else287 $keys_arr = array_keys($var); 288 $is_assoc = $have_numeric = 0; 289 290 for ($i=0; $i<sizeof($keys_arr); ++$i) 1284 291 { 1285 $keys_arr = array_keys($var); 1286 $is_assoc = $have_numeric = 0; 1287 1288 for ($i=0; $i<sizeof($keys_arr); ++$i) 1289 { 1290 if (is_numeric($keys_arr[$i])) 1291 $have_numeric = 1; 1292 if (!is_numeric($keys_arr[$i]) || $keys_arr[$i] != $i) 1293 $is_assoc = 1; 1294 if ($is_assoc && $have_numeric) 1295 break; 1296 } 1297 1298 $brackets = $is_assoc ? '{}' : '[]'; 1299 $pairs = array(); 1300 1301 foreach ($var as $key => $value) 1302 { 1303 // enclose key with quotes if it is not variable-name conform 1304 if (!ereg("^[_a-zA-Z]{1}[_a-zA-Z0-9]*$", $key) /* || is_js_reserved_word($key) */) 1305 $key = "'$key'"; 1306 1307 $pairs[] = sprintf("%s%s", $is_assoc ? "$key:" : '', json_serialize($value)); 1308 } 1309 1310 return $brackets{0} . implode(',', $pairs) . $brackets{1}; 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; 1311 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}; 1312 313 } 1313 else if (is_numeric($var) && strval(intval($var)) === strval($var)) 1314 return $var; 1315 else if (is_bool($var)) 1316 return $var ? '1' : '0'; 1317 else 1318 return "'".JQ($var)."'"; 1319 1320 } 1321 1322 /** 1323 * function to convert an array to a javascript array 314 } 315 else if (is_numeric($var) && strval(intval($var)) === strval($var)) 316 return $var; 317 else if (is_bool($var)) 318 return $var ? '1' : '0'; 319 else 320 return "'".JQ($var)."'"; 321 322 } 323 324 /** 325 * Function to convert an array to a javascript array 326 * Actually an alias function for json_serialize() 1324 327 * @deprecated 1325 328 */ 1326 329 function array2js($arr, $type='') 1327 {330 { 1328 331 return json_serialize($arr); 1329 }332 } 1330 333 1331 334 1332 335 /** 1333 336 * Similar function as in_array() but case-insensitive 337 * 338 * @param mixed Needle value 339 * @param array Array to search in 340 * @return boolean True if found, False if not 1334 341 */ 1335 342 function in_array_nocase($needle, $haystack) 1336 {343 { 1337 344 foreach ($haystack as $value) 1338 {1339 345 if (strtolower($needle)===strtolower($value)) 1340 return TRUE; 1341 } 1342 1343 return FALSE; 1344 } 346 return true; 347 348 return false; 349 } 1345 350 1346 351 1347 352 /** 1348 353 * Find out if the string content means TRUE or FALSE 354 * 355 * @param string Input value 356 * @return boolean Imagine what! 1349 357 */ 1350 358 function get_boolean($str) 1351 {359 { 1352 360 $str = strtolower($str); 1353 361 if(in_array($str, array('false', '0', 'no', 'nein', ''), TRUE)) … … 1355 363 else 1356 364 return TRUE; 1357 } 1358 1359 1360 // parse a human readable string for a number of bytes 365 } 366 367 368 /** 369 * Parse a human readable string for a number of bytes 370 * 371 * @param string Input string 372 * @return int Number of bytes 373 */ 1361 374 function parse_bytes($str) 1362 {375 { 1363 376 if (is_numeric($str)) 1364 377 return intval($str); 1365 378 1366 379 if (preg_match('/([0-9]+)([a-z])/i', $str, $regs)) 380 { 381 $bytes = floatval($regs[1]); 382 switch (strtolower($regs[2])) 1367 383 { 1368 $bytes = floatval($regs[1]); 1369 switch (strtolower($regs[2])) 1370 { 1371 case 'g': 1372 $bytes *= 1073741824; 1373 break; 1374 case 'm': 1375 $bytes *= 1048576; 1376 break; 1377 case 'k': 1378 $bytes *= 1024; 1379 break; 1380 } 384 case 'g': 385 $bytes *= 1073741824; 386 break; 387 case 'm': 388 $bytes *= 1048576; 389 break; 390 case 'k': 391 $bytes *= 1024; 392 break; 1381 393 } 394 } 1382 395 1383 396 return intval($bytes); 1384 } 1385 1386 // create a human readable string for a number of bytes 397 } 398 399 /** 400 * Create a human readable string for a number of bytes 401 * 402 * @param int Number of bytes 403 * @return string Byte string 404 */ 1387 405 function show_bytes($bytes) 1388 {406 { 1389 407 if ($bytes > 1073741824) 1390 {408 { 1391 409 $gb = $bytes/1073741824; 1392 410 $str = sprintf($gb>=10 ? "%d GB" : "%.1f GB", $gb); 1393 }411 } 1394 412 else if ($bytes > 1048576) 1395 {413 { 1396 414 $mb = $bytes/1048576; 1397 415 $str = sprintf($mb>=10 ? "%d MB" : "%.1f MB", $mb); 1398 }416 } 1399 417 else if ($bytes > 1024) 1400 418 $str = sprintf("%d KB", round($bytes/1024)); … … 1403 421 1404 422 return $str; 1405 } 1406 1407 1408 // convert paths like ../xxx to an absolute path using a base url 423 } 424 425 426 /** 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 */ 1409 433 function make_absolute_url($path, $base_url) 1410 { 1411 $host_url = $base_url; 1412 $abs_path = $path; 1413 1414 // cut base_url to the last directory 1415 if (strpos($base_url, '/')>7) 434 { 435 $host_url = $base_url; 436 $abs_path = $path; 437 438 // cut base_url to the last directory 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) 1416 455 { 1417 $host_url = substr($base_url, 0, strpos($base_url, '/')); 1418 $base_url = substr($base_url, 0, strrpos($base_url, '/')); 456 if (strrpos($base_url, '/')) 457 $base_url = substr($base_url, 0, strrpos($base_url, '/')); 458 459 $path = substr($path, 3); 1419 460 } 1420 461 1421 // $path is absolute 1422 if ($path{0}=='/') 1423 $abs_path = $host_url.$path; 1424 else 1425 { 1426 // strip './' because its the same as '' 1427 $path = preg_replace('/^\.\//', '', $path); 1428 1429 if(preg_match_all('/\.\.\//', $path, $matches, PREG_SET_ORDER)) 1430 foreach($matches as $a_match) 1431 { 1432 if (strrpos($base_url, '/')) 1433 $base_url = substr($base_url, 0, strrpos($base_url, '/')); 1434 1435 $path = substr($path, 3); 1436 } 1437 1438 $abs_path = $base_url.'/'.$path; 1439 } 1440 1441 return $abs_path; 1442 } 1443 1444 1445 // wrapper function for strlen 462 $abs_path = $base_url.'/'.$path; 463 } 464 465 return $abs_path; 466 } 467 468 469 /** 470 * Wrapper function for strlen 471 */ 1446 472 function rc_strlen($str) 1447 { 1448 if (function_exists('mb_strlen')) 1449 return mb_strlen($str); 1450 else 1451 return strlen($str); 1452 } 1453 1454 // wrapper function for strtolower 473 { 474 if (function_exists('mb_strlen')) 475 return mb_strlen($str); 476 else 477 return strlen($str); 478 } 479 480 /** 481 * Wrapper function for strtolower 482 */ 1455 483 function rc_strtolower($str) 1456 { 1457 if (function_exists('mb_strtolower')) 1458 return mb_strtolower($str); 1459 else 1460 return strtolower($str); 1461 } 1462 1463 // wrapper function for substr 484 { 485 if (function_exists('mb_strtolower')) 486 return mb_strtolower($str); 487 else 488 return strtolower($str); 489 } 490 491 /** 492 * Wrapper function for substr 493 */ 1464 494 function rc_substr($str, $start, $len=null) 1465 {495 { 1466 496 if (function_exists('mb_substr')) 1467 497 return mb_substr($str, $start, $len); 1468 498 else 1469 499 return substr($str, $start, $len); 1470 } 1471 1472 // wrapper function for strpos 500 } 501 502 /** 503 * Wrapper function for strpos 504 */ 1473 505 function rc_strpos($haystack, $needle, $offset=0) 1474 {506 { 1475 507 if (function_exists('mb_strpos')) 1476 508 return mb_strpos($haystack, $needle, $offset); 1477 509 else 1478 510 return strpos($haystack, $needle, $offset); 1479 } 1480 1481 // wrapper function for strrpos 511 } 512 513 /** 514 * Wrapper function for strrpos 515 */ 1482 516 function rc_strrpos($haystack, $needle, $offset=0) 1483 {517 { 1484 518 if (function_exists('mb_strrpos')) 1485 519 return mb_strrpos($haystack, $needle, $offset); 1486 520 else 1487 521 return strrpos($haystack, $needle, $offset); 1488 } 1489 1490 1491 // replace the middle part of a string with ... 1492 // if it is longer than the allowed length 522 } 523 524 525 /** 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 */ 1493 534 function abbrevate_string($str, $maxlength, $place_holder='...') 1494 {535 { 1495 536 $length = rc_strlen($str); 1496 537 $first_part_length = floor($maxlength/2) - rc_strlen($place_holder); 1497 538 1498 539 if ($length > $maxlength) 1499 {540 { 1500 541 $second_starting_location = $length - $maxlength + $first_part_length + 1; 1501 542 $str = rc_substr($str, 0, $first_part_length) . $place_holder . rc_substr($str, $second_starting_location, $length); 1502 }543 } 1503 544 1504 545 return $str; 1505 } 1506 1507 1508 // make sure the string ends with a slash 546 } 547 548 549 /** 550 * Make sure the string ends with a slash 551 */ 1509 552 function slashify($str) 1510 {553 { 1511 554 return unslashify($str).'/'; 1512 } 1513 1514 1515 // remove slash at the end of the string 555 } 556 557 558 /** 559 * Remove slash at the end of the string 560 */ 1516 561 function unslashify($str) 1517 {562 { 1518 563 return preg_replace('/\/$/', '', $str); 1519 } 1520 1521 1522 // delete all files within a folder 564 } 565 566 567 /** 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 */ 1523 573 function clear_directory($dir_path) 1524 {574 { 1525 575 $dir = @opendir($dir_path); 1526 576 if(!$dir) return FALSE; … … 1532 582 closedir($dir); 1533 583 return TRUE; 1534 } 1535 1536 1537 // create a unix timestamp with a specified offset from now 584 } 585 586 587 /** 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 */ 1538 594 function get_offset_time($offset_str, $factor=1) 1539 595 { 1540 596 if (preg_match('/^([0-9]+)\s*([smhdw])/i', $offset_str, $regs)) 1541 {597 { 1542 598 $amount = (int)$regs[1]; 1543 599 $unit = strtolower($regs[2]); 1544 }1545 else 1546 {600 } 601 else 602 { 1547 603 $amount = (int)$offset_str; 1548 604 $unit = 's'; 1549 }605 } 1550 606 1551 607 $ts = mktime(); 1552 608 switch ($unit) 1553 {609 { 1554 610 case 'w': 1555 611 $amount *= 7; … … 1562 618 case 's': 1563 619 $ts += $amount * $factor; 1564 }620 } 1565 621 1566 622 return $ts; 1567 } 1568 1569 1570 /** 1571 * strrstr 1572 * 1573 * return the last occurence of a string in another string 623 } 624 625 626 /** 627 * Return the last occurence of a string in another string 628 * 1574 629 * @param haystack string string in which to search 1575 630 * @param needle string string for which to search … … 1577 632 */ 1578 633 function strrstr($haystack, $needle) 1579 { 1580 $pver = phpversion(); 1581 if ($pver[0] >= 5) 1582 { 1583 return strrpos($haystack, $needle); 1584 } 1585 else 1586 { 1587 $index = strpos(strrev($haystack), strrev($needle)); 1588 if($index === false) { 1589 return false; 1590 } 1591 $index = strlen($haystack) - strlen($needle) - $index; 1592 return $index; 1593 } 1594 } 634 { 635 $pver = phpversion(); 636 if ($pver[0] >= 5) 637 return strrpos($haystack, $needle); 638 else 639 { 640 $index = strpos(strrev($haystack), strrev($needle)); 641 if($index === false) 642 return false; 643 644 $index = strlen($haystack) - strlen($needle) - $index; 645 return $index; 646 } 647 } 1595 648 1596 649
Note: See TracChangeset
for help on using the changeset viewer.
