source: github/program/include/rcube_shared.inc @ 3f9edb4

HEADcourier-fixdev-browser-capabilitiespdorelease-0.6release-0.7release-0.8
Last change on this file since 3f9edb4 was 3f9edb4, checked in by thomascube <thomas@…>, 7 years ago

Switched to full UTF-8 support

  • Property mode set to 100644
File size: 34.7 KB
Line 
1<?php
2
3/*
4 +-----------------------------------------------------------------------+
5 | rcube_shared.inc                                                      |
6 |                                                                       |
7 | This file is part of the RoundCube PHP suite                          |
8 | Copyright (C) 2005, RoundCube Dev. - Switzerland                      |
9 | Licensed under the GNU GPL                                            |
10 |                                                                       |
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
23// ********* round cube schared classes *********
24
25class rcube_html_page
26  {
27  var $css;
28 
29  var $scripts_path = '';
30  var $script_files = array();
31  var $scripts = array();
32  var $charset = 'ISO-8859-1';
33 
34  var $script_tag_file = "<script type=\"text/javascript\" src=\"%s%s\"></script>\n";
35  var $script_tag      = "<script type=\"text/javascript\">\n<!--\n%s\n\n//-->\n</script>\n";
36 
37  var $title = '';
38  var $header = '';
39  var $footer = '';
40  var $body = '';
41  var $body_attrib = array();
42  var $meta_tags = array();
43
44
45  // PHP 5 constructor
46  function __construct()
47    {
48    $this->css = new rcube_css();
49    }
50
51  // PHP 4 compatibility
52  function rcube_html_page()
53    {
54    $this->__construct();
55    }
56
57
58  function include_script($file, $position='head')
59    {
60    static $sa_files = array();
61   
62    if (in_array($file, $sa_files))
63      return;
64     
65    if (!is_array($this->script_files[$position]))
66      $this->script_files[$position] = array();
67     
68    $this->script_files[$position][] = $file;
69    }
70   
71 
72  function add_script($script, $position='head')
73    {
74    if (!isset($this->scripts[$position]))
75      $this->scripts[$position] = '';
76
77    $this->scripts[$position] .= "\n$script";
78    }
79
80
81  function set_title()
82    {
83   
84    }
85
86  function set_charset($charset)
87    {
88    $this->charset = $charset;
89    }
90   
91  function get_charset()
92    {
93    return $this->charset;
94    }
95
96
97  function write($templ='', $base_path='')
98    {
99    $output = trim($templ);
100 
101    // set default page title
102    if (!strlen($this->title))
103      $this->title = 'RoundCube|Mail';
104 
105    // replace specialchars in content
106    $__page_title = rep_specialchars_output($this->title, 'html', 'show', FALSE);
107    $__page_header = $__page_body = $__page_footer = '';
108   
109   
110    // include meta tag with charset
111    if (!empty($this->charset))
112      $__page_header = '<meta http-equiv="content-type" content="text/html; charset='.$this->charset.'" />'."\n";;
113 
114 
115    // definition of the code to be placed in the document header and footer
116    if (is_array($this->script_files['head']))
117      foreach ($this->script_files['head'] as $file)
118        $__page_header .= sprintf($this->script_tag_file, $this->scripts_path, $file);
119
120    if (strlen($this->scripts['head']))
121      $__page_header .= sprintf($this->script_tag, $this->scripts['head']);
122         
123    if (is_array($this->script_files['foot']))
124      foreach ($this->script_files['foot'] as $file)
125        $__page_footer .= sprintf($this->script_tag_file, $this->scripts_path, $file);
126
127    if (strlen($this->scripts['foot']))
128      $__page_footer .= sprintf($this->script_tag, $this->scripts['foot']);
129
130
131    $__page_header .= $this->css->show();
132
133 
134    // find page header
135    if($hpos = strpos(strtolower($output), '</head>'))
136      $__page_header .= "\n";
137    else
138      {
139      if (!is_numeric($hpos))
140        $hpos = strpos(strtolower($output), '<body');
141      if (!is_numeric($hpos) && ($hpos = strpos(strtolower($output), '<html')))
142        {
143        while($output[$hpos]!='>')
144        $hpos++;
145        $hpos++;
146        }
147 
148      $__page_header = "<head>\n<title>$__page_title</title>\n$__page_header\n</head>\n";
149      }
150 
151    // add page hader
152    if($hpos)
153      $output = substr($output,0,$hpos) . $__page_header . substr($output,$hpos,strlen($output));
154    else
155      $output = $__page_header . $output;
156 
157 
158    // find page body
159    if($bpos = strpos(strtolower($output), '<body'))
160      {
161      while($output[$bpos]!='>') $bpos++;
162      $bpos++;
163      }
164    else
165      $bpos = strpos(strtolower($output), '</head>')+7;
166 
167    // add page body
168    if($bpos && $__page_body)
169      $output = substr($output,0,$bpos) . "\n$__page_body\n" . substr($output,$bpos,strlen($output));
170 
171 
172    // find and add page footer
173    if(($fpos = strpos(strtolower($output), '</body>')) || ($fpos = strpos(strtolower($output), '</html>')))
174      $output = substr($output,0,$fpos) . "$__page_footer\n" . substr($output,$fpos,strlen($output));
175    else
176      $output .= "\n$__page_footer";
177 
178 
179    // reset those global vars
180    $__page_header = $__page_footer = '';
181 
182 
183    // correct absolute pathes in images and other tags
184    $output = preg_replace('/(src|href|background)=(["\']?)(\/[a-z0-9_\-]+)/Ui', "\\1=\\2$base_path\\3", $output);
185 
186    print rcube_charset_convert($output, 'UTF-8', $this->charset);
187    }
188   
189   
190  function _parse($templ)
191    {
192   
193    }
194  }
195
196
197
198
199class rcube_css
200  {
201  var $css_data = array();
202
203  var $css_groups = array();
204
205  var $include_files = array();
206
207  var $grouped_output = TRUE;
208
209  var $content_type = 'text/css';
210
211  var $base_path = '';
212
213  var $indent_chars = "\t";
214
215
216  // add or overwrite a css definition
217  // either pass porperty and value as separate arguments
218  // or provide an associative array as second argument
219  function set_style($selector, $property, $value='')
220    {
221    $a_elements = $this->_parse_selectors($selector);
222    foreach ($a_elements as $element)
223      {
224      if (!is_array($property))
225        $property = array($property => $value);
226
227      foreach ($property as $name => $value)
228        $this->css_data[$element][strtolower($name)] = $value;
229      }
230
231    // clear goups array
232    $this->css_groups = array();
233    }
234
235
236  // unset a style property
237  function remove_style($selector, $property)
238    {
239    if (!is_array($property))
240      $property = array($property);
241
242    foreach ($property as $key)
243      unset($this->css_data[$selector][strtolower($key)]);
244
245    // clear goups array
246    $this->css_groups = array();
247    }
248
249
250  // define base path for external css files
251  function set_basepath($path)
252    {
253    $this->base_path = preg_replace('/\/$/', '', $path);
254    }
255
256
257  // enable/disable grouped output
258  function set_grouped_output($grouped)
259    {
260    $this->grouped_output = $grouped;
261    }
262
263
264  // add a css file as external source
265  function include_file($filename, $media='')
266    {
267    // include multiple files
268    if (is_array($filename))
269      {
270      foreach ($filename as $file)
271        $this->include_file($file, $media);
272      }
273    // add single file
274    else if (!in_array($filename, $this->include_files))
275      $this->include_files[] = array('file' => $filename,
276                                     'media' => $media);
277    }
278
279
280  // parse css code
281  function import_string($str)
282    {
283    $ret = FALSE;
284    if (strlen($str))
285      $ret = $this->_parse($str);
286
287    return $ret;
288    }
289
290
291  // open and parse a css file
292  function import_file($file)
293    {
294    $ret = FALSE;
295
296    if (!is_file($file))
297      return $ret;
298
299    // for php version >= 4.3.0
300    if (function_exists('file_get_contents'))
301      $ret = $this->_parse(file_get_contents($file));
302
303    // for order php versions
304    else if ($fp = fopen($file, 'r'))
305      {
306      $ret = $this->_parse(fread($fp, filesize($file)));
307      fclose($fp);
308      }
309
310    return $ret;
311    }
312
313
314  // copy all properties inherited from superior styles to a specific selector
315  function copy_inherited_styles($selector)
316    {
317    // get inherited props from body and tag/class selectors
318    $css_props = $this->_get_inherited_styles($selector);
319
320    // write modified props back and clear goups array
321    if (sizeof($css_props))
322      {
323      $this->css_data[$selector] = $css_props;
324      $this->css_groups = array();
325      }
326    }
327
328
329  // return css definition for embedding in HTML
330  function show()
331    {
332    $out = '';
333
334    // include external css files
335    if (sizeof($this->include_files))
336      foreach ($this->include_files as $file_arr)
337      $out .= sprintf('<link rel="stylesheet" type="%s" href="%s"%s>'."\n",
338                        $this->content_type,
339                        $this->_get_file_path($file_arr['file']),
340                        $file_arr['media'] ? ' media="'.$file_arr['media'].'"' : '');
341
342
343    // compose css string
344    if (sizeof($this->css_data))
345      $out .= sprintf("<style type=\"%s\">\n<!--\n\n%s-->\n</style>",
346                      $this->content_type,
347                      $this->to_string());
348
349
350    return $out;
351    }
352
353
354  // return valid css code of the current styles grid
355  function to_string($selector=NULL)
356    {
357    // return code for a single selector
358    if ($selector)
359      {
360      $indent_str = $this->indent_chars;
361      $this->indent_chars = '';
362
363      $prop_arr = $this->to_array($selector);
364      $out = $this->_style2string($prop_arr, TRUE);
365
366      $this->indent_chars = $indent_str;
367      }
368
369    // compose css code for complete data grid
370    else
371      {
372      $out = '';
373      $css_data = $this->to_array();
374
375      foreach ($css_data as $key => $prop_arr)
376        $out .= sprintf("%s {\n%s}\n\n",
377                        $key,
378                        $this->_style2string($prop_arr, TRUE));
379      }
380
381    return $out;
382    }
383
384
385  // return a single-line string of a css definition
386  function to_inline($selector)
387    {
388    if ($this->css_data[$selector])
389      return str_replace('"', '\\"', $this->_style2string($this->css_data[$selector], FALSE));
390    }
391
392
393  // return an associative array with selector(s) as key and styles array as value
394  function to_array($selector=NULL)
395    {
396    if (!$selector && $this->grouped_output)
397      {
398      // build groups if desired
399      if (!sizeof($this->css_groups))
400        $this->_build_groups();
401
402      // modify group array to get an array(selector => properties)
403      $out_arr = array();
404      foreach ($this->css_groups as $group_arr)
405        {
406        $key = join(', ', $group_arr['selectors']);
407        $out_arr[$key] = $group_arr['properties'];
408        }
409      }
410    else
411      $out_arr = $this->css_data;
412
413    return $selector ? $out_arr[$selector] : $out_arr;
414    }
415
416
417  // create a css file
418  function to_file($filepath)
419    {
420    if ($fp = fopen($filepath, 'w'))
421      {
422      fwrite($fp, $this->to_string());
423      fclose($fp);
424      return TRUE;
425      }
426
427    return FALSE;
428    }
429
430
431  // alias method for import_string() [DEPRECATED]
432  function add($str)
433    {
434    $this->import_string($str);
435    }
436
437  // alias method for to_string() [DEPRECATED]
438  function get()
439    {
440    return $this->to_string();
441    }
442
443
444
445  // ******** private methods ********
446
447
448  // parse a string and add styles to internal data grid
449  function _parse($str)
450    {
451    // remove comments
452    $str = preg_replace("/\/\*(.*)?\*\//Usi", '', $str);
453
454    // parse style definitions
455    if (!preg_match_all ('/([a-z0-9\.#*:_][a-z0-9\.\-_#:*,\[\]\(\)\s\"\'\+\|>~=]+)\s*\{([^\}]*)\}/ims', $str, $matches, PREG_SET_ORDER))
456      return FALSE;
457
458
459    foreach ($matches as $match_arr)
460      {
461      // split selectors into array
462      $a_keys = $this->_parse_selectors(trim($match_arr[1]));
463
464      // parse each property of an element
465      $codes = explode(";", trim($match_arr[2]));
466      foreach ($codes as $code)
467        {
468        if (strlen(trim($code))>0)
469          {
470          // find the property and the value
471          if (!($sep = strpos($code, ':')))
472            continue;
473
474          $property = strtolower(trim(substr($code, 0, $sep)));
475          $value    = trim(substr($code, $sep+1));
476
477          // add the property to the object array
478          foreach ($a_keys as $key)
479            $this->css_data[$key][$property] = $value;
480          }
481        }
482      }
483
484    // clear goups array
485    if (sizeof($matches))
486      {
487      $this->css_groups = array();
488      return TRUE;
489      }
490
491    return FALSE;
492    }
493
494
495  // split selector group
496  function _parse_selectors($selector)
497    {
498    // trim selector and remove multiple spaces
499    $selector = preg_replace('/\s+/', ' ', trim($selector));
500
501    if (strpos($selector, ','))
502      return preg_split('/[\t\s\n\r]*,[\t\s\n\r]*/mi', $selector);
503    else
504      return array($selector);
505    }
506
507
508  // compare identical styles and make groups
509  function _build_groups()
510    {
511    // clear group array
512    $this->css_groups = array();
513    $string_group_map = array();
514
515    // bulild css string for each selector and check if the same is already defines
516    foreach ($this->css_data as $selector => $prop_arr)
517      {
518      // make shure to compare props in the same order
519      ksort($prop_arr);
520      $compare_str = preg_replace('/[\s\t]+/', '', $this->_style2string($prop_arr, FALSE));
521
522      // add selector to extisting group
523      if (isset($string_group_map[$compare_str]))
524        {
525        $group_index = $string_group_map[$compare_str];
526        $this->css_groups[$group_index]['selectors'][] = $selector;
527        }
528
529      // create new group
530      else
531        {
532        $i = sizeof($this->css_groups);
533        $string_group_map[$compare_str] = $i;
534        $this->css_groups[$i] = array('selectors' => array($selector),
535                                      'properties' => $this->css_data[$selector]);
536        }
537      }
538    }
539
540
541  // convert the prop array into a valid css definition
542  function _style2string($prop_arr, $multiline=TRUE)
543    {
544    $out = '';
545    $delm   = $multiline ? "\n" : '';
546    $spacer = $multiline ? ' ' : '';
547    $indent = $multiline ? $this->indent_chars : '';
548
549    if (is_array($prop_arr))
550      foreach ($prop_arr as $prop => $value)
551        if (strlen($value))
552          $out .= sprintf('%s%s:%s%s;%s',
553                          $indent,
554                          $prop,
555                          $spacer,
556                          $value,
557                          $delm);
558
559    return $out;
560    }
561
562
563  // copy all properties inherited from superior styles to a specific selector
564  function _get_inherited_styles($selector, $loop=FALSE)
565    {
566    $css_props = $this->css_data[$selector] ? $this->css_data[$selector] : array();
567
568    // get styles from tag selector
569    if (preg_match('/(([a-z0-9]*)(\.[^\s]+)?)$/i', $selector, $regs))
570      {
571      $sel = $regs[1];
572      $tagname = $regs[2];
573      $class = $regs[3];
574
575      if ($sel && is_array($this->css_data[$sel]))
576        $css_props = $this->_merge_styles($this->css_data[$sel], $css_props);
577
578      if ($class && is_array($this->css_data[$class]))
579        $css_props = $this->_merge_styles($this->css_data[$class], $css_props);
580
581      if ($tagname && is_array($this->css_data[$tagname]))
582        $css_props = $this->_merge_styles($this->css_data[$tagname], $css_props);
583      }
584
585    // analyse inheritance
586    if (strpos($selector, ' '))
587      {
588      $a_hier = split(' ', $selector);
589      if (sizeof($a_hier)>1)
590        {
591        array_pop($a_hier);
592        $base_selector = join(' ', $a_hier);
593
594        // call this method recursively
595        $new_props = $this->_get_inherited_styles($base_selector, TRUE);
596        $css_props = $this->_merge_styles($new_props, $css_props);
597        }
598      }
599
600    // get body style
601    if (!$loop && is_array($this->css_data['body']))
602      $css_props = $this->_merge_styles($this->css_data['body'], $css_props);
603
604    return $css_props;
605    }
606
607
608  // merge two arrays with style properties together like a browser would do
609  function _merge_styles($one, $two)
610    {
611    // these properties are additive
612    foreach (array('text-decoration') as $prop)
613      if ($one[$prop] && $two[$prop])
614        {
615        // if value contains 'none' it's ignored
616        if (strstr($one[$prop], 'none'))
617          continue;
618        else if (strstr($two[$prop], 'none'))
619          unset($two[$prop]);
620
621        $a_values_one = split(' ', $one[$prop]);
622        $a_values_two = split(' ', $two[$prop]);
623        $two[$prop] = join(' ', array_unique(array_merge($a_values_one, $a_values_two)));
624        }
625
626    return array_merge($one, $two);
627    }
628
629
630  // resolve file path
631  function _get_file_path($file)
632    {
633    if (!$this->base_path && $GLOBALS['CSS_PATH'])
634      $this->set_basepath($GLOBALS['CSS_PATH']);
635
636    $base = ($file{0}=='/' || $file{0}=='.' || substr($file, 0, 7)=='http://') ? '' :
637            ($this->base_path ? $this->base_path.'/' : '');
638    return $base.$file;
639    }
640
641  }
642
643
644
645class base_form_element
646  {
647  var $uppertags = FALSE;
648  var $upperattribs = FALSE;
649  var $upperprops = FALSE;
650  var $newline = FALSE;
651 
652  var $attrib = array();
653
654
655  // create string with attributes
656  function create_attrib_string($tagname='')
657    {
658    if (!sizeof($this->attrib))
659      return '';
660
661    if ($this->name!='')
662      $this->attrib['name'] = $this->name;
663
664    $attrib_arr = array();
665    foreach ($this->attrib as $key => $value)
666      {
667      // don't output some internally used attributes
668      if (in_array($key, array('form', 'quicksearch')))
669        continue;
670
671      // skip if size if not numeric
672      if (($key=='size' && !is_numeric($value)))
673        continue;
674       
675      // skip empty eventhandlers
676      if ((strpos($key,'on')===0 && $value==''))
677        continue;
678
679      // encode textarea content
680      if ($key=='value')
681        $value = rep_specialchars_output($value, 'html', 'replace', FALSE);
682
683      // attributes with no value
684      if (in_array($key, array('checked', 'multiple', 'disabled', 'selected')))
685        {
686        if ($value)
687          $attrib_arr[] = $key;
688        }
689      // don't convert size of value attribute
690      else if ($key=='value')
691        $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $value, 'value');
692       
693      // regular tag attributes
694      else
695        $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $this->_conv_case($value, 'value'));
696      }
697
698    return sizeof($attrib_arr) ? ' '.implode(' ', $attrib_arr) : '';
699    }
700   
701   
702  // convert tags and attributes to upper-/lowercase
703  // $type can either be "tag" or "attrib"
704  function _conv_case($str, $type='attrib')
705    {
706    if ($type == 'tag')
707      return $this->uppertags ? strtoupper($str) : strtolower($str);
708    else if ($type == 'attrib')
709      return $this->upperattribs ? strtoupper($str) : strtolower($str);
710    else if ($type == 'value')
711      return $this->upperprops ? strtoupper($str) : strtolower($str);
712    }   
713  }
714
715
716class input_field extends base_form_element
717  {
718  var $type = 'text';
719 
720  // PHP 5 constructor
721  function __construct($attrib=NULL)
722    {
723    if (is_array($attrib))
724      $this->attrib = $attrib;
725
726    if ($attrib['type'])
727      $this->type = $attrib['type'];   
728
729    if ($attrib['newline'])
730      $this->newline = TRUE;   
731    }
732
733  // PHP 4 compatibility
734  function input_field($attrib=array())
735    {
736    $this->__construct($attrib);
737    } 
738
739  // compose input tag
740  function show($value=NULL, $attrib=NULL)
741    {
742    // overwrite object attributes
743    if (is_array($attrib))
744      $this->attrib = array_merge($this->attrib, $attrib);
745
746    // set value attribute
747    if ($value!==NULL)
748      $this->attrib['value'] = $value;
749
750    $this->attrib['type'] = $this->type;
751
752    // return final tag
753    return sprintf('<%s%s />%s',
754                   $this->_conv_case('input', 'tag'),
755                   $this->create_attrib_string(),
756                   ($this->newline ? "\n" : ""));   
757    } 
758  }
759
760
761class textfield extends input_field
762  {
763  var $type = 'text';
764  }
765
766class passwordfield extends input_field
767  {
768  var $type = 'password';
769  }
770
771class radiobutton extends input_field
772  {
773  var $type = 'radio';
774  }
775
776class checkbox extends input_field
777  {
778  var $type = 'checkbox';
779
780
781  function show($value='', $attrib=NULL)
782    {
783    // overwrite object attributes
784    if (is_array($attrib))
785      $this->attrib = array_merge($this->attrib, $attrib);   
786
787    $this->attrib['type'] = $this->type;
788
789    if ($value && (string)$value==(string)$this->attrib['value'])
790      $this->attrib['checked'] = TRUE;
791    else
792      $this->attrib['checked'] = FALSE;
793
794    // return final tag
795    return sprintf('<%s%s />%s',
796                   $this->_conv_case('input', 'tag'),
797                   $this->create_attrib_string(),
798                   ($this->newline ? "\n" : ""));   
799    }
800  }
801
802
803class textarea extends base_form_element
804  {
805  // PHP 5 constructor
806  function __construct($attrib=array())
807    {
808    $this->attrib = $attrib;
809
810    if ($attrib['newline'])
811      $this->newline = TRUE;   
812    }
813
814  // PHP 4 compatibility
815  function textarea($attrib=array())
816    {
817    $this->__construct($attrib);
818    }
819   
820  function show($value='', $attrib=NULL)
821    {
822    // overwrite object attributes
823    if (is_array($attrib))
824      $this->attrib = array_merge($this->attrib, $attrib);
825   
826    // take value attribute as content
827    if ($value=='')
828      $value = $this->attrib['value'];
829   
830    // make shure we don't print the value attribute
831    if (isset($this->attrib['value']))
832      unset($this->attrib['value']);
833
834    if (strlen($value))
835      $value = rep_specialchars_output($value, 'html', 'replace', FALSE);
836   
837    // return final tag
838    return sprintf('<%s%s>%s</%s>%s',
839                   $this->_conv_case('textarea', 'tag'),
840                   $this->create_attrib_string(),
841                   $value,
842                   $this->_conv_case('textarea', 'tag'),
843                   ($this->newline ? "\n" : ""));       
844    }
845  }
846
847
848class hiddenfield extends base_form_element
849  {
850  var $fields_arr = array();
851  var $newline = TRUE;
852
853  // PHP 5 constructor
854  function __construct($attrib=NULL)
855    {
856    if (is_array($attrib))
857      $this->add($attrib);
858    }
859
860  // PHP 4 compatibility
861  function hiddenfield($attrib=NULL)
862    {
863    $this->__construct($attrib);
864    }
865
866  // add a hidden field to this instance
867  function add($attrib)
868    {
869    $this->fields_arr[] = $attrib;
870    }
871
872
873  function show()
874    {
875    $out = '';
876    foreach ($this->fields_arr as $attrib)
877      {
878      $this->attrib = $attrib;
879      $this->attrib['type'] = 'hidden';
880     
881      $out .= sprintf('<%s%s />%s',
882                   $this->_conv_case('input', 'tag'),
883                   $this->create_attrib_string(),
884                   ($this->newline ? "\n" : ""));   
885      }
886
887    return $out;
888    }
889  }
890
891
892class select extends base_form_element
893  {
894  var $options = array();
895
896  /*
897  syntax:
898  -------
899  // create instance. arguments are used to set attributes of select-tag
900  $select = new select(array('name' => 'fieldname'));
901
902  // add one option
903  $select->add('Switzerland', 'CH');
904
905  // add multiple options
906  $select->add(array('Switzerland', 'Germany'),
907               array('CH', 'DE'));
908
909  // add 10 blank options with 50 chars
910  // used to fill with javascript (necessary for 4.x browsers)
911  $select->add_blank(10, 50);
912
913  // generate pulldown with selection 'Switzerland'  and return html-code
914  // as second argument the same attributes available to instanciate can be used
915  print $select->show('CH');
916  */
917
918  // PHP 5 constructor
919  function __construct($attrib=NULL)
920    {
921    if (is_array($attrib))
922      $this->attrib = $attrib;
923
924    if ($attrib['newline'])
925      $this->newline = TRUE;
926    }
927
928  // PHP 4 compatibility
929  function select($attrib=NULL)
930    {
931    $this->__construct($attrib);
932    }
933
934
935  function add($names, $values=NULL)
936    {
937    if (is_array($names))
938      {
939      foreach ($names as $i => $text)
940        $this->options[] = array('text' => $text, 'value' => (string)$values[$i]);
941      }
942    else
943      {
944      $this->options[] = array('text' => $names, 'value' => (string)$values);
945      }
946    }
947
948   
949  function add_blank($nr, $width=0)
950    {
951    $text = $width ? str_repeat('&nbsp;', $width) : '';
952   
953    for ($i=0; $i < $nr; $i++)
954      $this->options[] = array('text' => $text);
955    }
956
957 
958  function show($select=array(), $attrib=NULL)
959    {
960    $options_str = "\n";
961    $value_str = $this->_conv_case(' value="%s"', 'attrib');
962   
963    if (!is_array($select))
964      $select = array((string)$select);
965   
966    foreach ($this->options as $option)
967      {
968      $selected = ((strlen($option['value']) && in_array($option['value'], $select, TRUE)) ||
969                   (in_array($option['text'], $select, TRUE))) ? $this->_conv_case(' selected', 'attrib') : '';
970                 
971      $options_str .= sprintf("<%s%s%s>%s</%s>\n",
972                             $this->_conv_case('option', 'tag'),
973                             strlen($option['value']) ? sprintf($value_str, $option['value']) : '',
974                             $selected,
975                             rep_specialchars_output($option['text'], 'html', 'replace', FALSE),
976                             $this->_conv_case('option', 'tag'));
977      }
978                             
979    // return final tag
980    return sprintf('<%s%s>%s</%s>%s',
981                   $this->_conv_case('select', 'tag'),
982                   $this->create_attrib_string(),
983                   $options_str,
984                   $this->_conv_case('select', 'tag'),
985                   ($this->newline ? "\n" : ""));   
986    }
987  }
988
989
990
991
992// ********* rcube schared functions *********
993
994
995// provide details about the client's browser
996function rcube_browser()
997  {
998  $HTTP_USER_AGENT = $_SERVER['HTTP_USER_AGENT'];
999
1000  $bw['ver'] = 0;
1001  $bw['win'] = stristr($HTTP_USER_AGENT, 'win');
1002  $bw['mac'] = stristr($HTTP_USER_AGENT, 'mac');
1003  $bw['linux'] = stristr($HTTP_USER_AGENT, 'linux');
1004  $bw['unix']  = stristr($HTTP_USER_AGENT, 'unix');
1005
1006  $bw['ns4'] = stristr($HTTP_USER_AGENT, 'mozilla/4') && !stristr($HTTP_USER_AGENT, 'msie');
1007  $bw['ns']  = ($bw['ns4'] || stristr($HTTP_USER_AGENT, 'netscape'));
1008  $bw['ie']  = stristr($HTTP_USER_AGENT, 'msie');
1009  $bw['mz']  = stristr($HTTP_USER_AGENT, 'mozilla/5');
1010  $bw['opera'] = stristr($HTTP_USER_AGENT, 'opera');
1011  $bw['safari'] = stristr($HTTP_USER_AGENT, 'safari');
1012
1013  if($bw['ns'])
1014    {
1015    $test = eregi("mozilla\/([0-9\.]+)", $HTTP_USER_AGENT, $regs);
1016    $bw['ver'] = $test ? (float)$regs[1] : 0;
1017    }
1018  if($bw['mz'])
1019    {
1020    $test = ereg("rv:([0-9\.]+)", $HTTP_USER_AGENT, $regs);
1021    $bw['ver'] = $test ? (float)$regs[1] : 0;
1022    }
1023  if($bw['ie'])
1024    {
1025    $test = eregi("msie ([0-9\.]+)", $HTTP_USER_AGENT, $regs);
1026    $bw['ver'] = $test ? (float)$regs[1] : 0;
1027    }
1028  if($bw['opera'])
1029    {
1030    $test = eregi("opera ([0-9\.]+)", $HTTP_USER_AGENT, $regs);
1031    $bw['ver'] = $test ? (float)$regs[1] : 0;
1032    }
1033
1034  if(eregi(" ([a-z]{2})-([a-z]{2})", $HTTP_USER_AGENT, $regs))
1035    $bw['lang'] =  $regs[1];
1036  else
1037    $bw['lang'] =  'en';
1038
1039  $bw['dom'] = ($bw['mz'] || $bw['safari'] || ($bw['ie'] && $bw['ver']>=5) || ($bw['opera'] && $bw['ver']>=7));
1040  $bw['pngalpha'] = $bw['mz'] || $bw['safari'] || ($bw['ie'] && $bw['ver']>=5.5) ||
1041                    ($bw['ie'] && $bw['ver']>=5 && $bw['mac']) || ($bw['opera'] && $bw['ver']>=7) ? TRUE : FALSE;
1042
1043  return $bw;
1044  }
1045
1046
1047// get text in the desired language from the language file
1048function rcube_label($attrib)
1049  {
1050  global $sess_user_lang, $INSTALL_PATH, $OUTPUT;
1051  static $sa_text_data, $s_language, $utf8_decode;
1052
1053  // extract attributes
1054  if (is_string($attrib))
1055    $attrib = array('name' => $attrib);
1056   
1057  $nr = is_numeric($attrib['nr']) ? $attrib['nr'] : 1;
1058  $vars = isset($attrib['vars']) ? $attrib['vars'] : '';
1059
1060  $command_name = strlen($attrib['command']) ? $attrib['command'] : NULL;
1061  $alias = $attrib['name'] ? $attrib['name'] : ($command_name && $command_label_map[$command_name] ? $command_label_map[$command_name] : '');
1062
1063
1064  // load localized texts
1065  if (!$sa_text_data || $s_language != $sess_user_lang)
1066    {
1067    $sa_text_data = array();
1068   
1069    // get english labels (these should be complete)
1070    @include($INSTALL_PATH.'program/localization/en_US/labels.inc');
1071    @include($INSTALL_PATH.'program/localization/en_US/messages.inc');
1072
1073    if (is_array($labels))
1074      $sa_text_data = $labels;
1075    if (is_array($messages))
1076      $sa_text_data = array_merge($sa_text_data, $messages);
1077   
1078    // include user language files
1079    if ($sess_user_lang!='en' && is_dir($INSTALL_PATH.'program/localization/'.$sess_user_lang))
1080      {
1081      include_once($INSTALL_PATH.'program/localization/'.$sess_user_lang.'/labels.inc');
1082      include_once($INSTALL_PATH.'program/localization/'.$sess_user_lang.'/messages.inc');
1083
1084      if (is_array($labels))
1085        $sa_text_data = array_merge($sa_text_data, $labels);
1086      if (is_array($messages))
1087        $sa_text_data = array_merge($sa_text_data, $messages);
1088      }
1089     
1090    $s_language = $sess_user_lang;
1091    }
1092
1093  // text does not exist
1094  if (!($text_item = $sa_text_data[$alias]))
1095    {
1096    /*
1097    raise_error(array('code' => 500,
1098                      'type' => 'php',
1099                      'line' => __LINE__,
1100                      'file' => __FILE__,
1101                      'message' => "Missing localized text for '$alias' in '$sess_user_lang'"), TRUE, FALSE);
1102    */
1103    return "[$alias]";
1104    }
1105
1106  // make text item array
1107  $a_text_item = is_array($text_item) ? $text_item : array('single' => $text_item);
1108
1109  // decide which text to use
1110  if ($nr==1)
1111    $text = $a_text_item['single'];
1112  else if ($nr>0)
1113    $text = $a_text_item['multiple'];
1114  else if ($nr==0)
1115    {
1116    if ($a_text_item['none'])
1117      $text = $a_text_item['none'];
1118    else if ($a_text_item['single'])
1119      $text = $a_text_item['single'];
1120    else if ($a_text_item['multiple'])
1121      $text = $a_text_item['multiple'];
1122    }
1123
1124  // default text is single
1125  if ($text=='')
1126    $text = $a_text_item['single'];
1127
1128  // replace vars in text
1129  if (is_array($attrib['vars']))
1130    {
1131    foreach ($attrib['vars'] as $var_key=>$var_value)
1132      $a_replace_vars[substr($var_key, 0, 1)=='$' ? substr($var_key, 1) : $var_key] = $var_value;
1133    }
1134
1135  if ($a_replace_vars)
1136    $text = preg_replace('/\${?([_a-z]{1}[_a-z0-9]*)}?/ei', '$a_replace_vars["\1"]', $text);
1137
1138  // remove variables in text which were not available in arg $vars and $nr
1139  eval("\$text = <<<EOF
1140$text
1141EOF;
1142");
1143
1144  // format output
1145  if (($attrib['uppercase'] && strtolower($attrib['uppercase']=='first')) || $attrib['ucfirst'])
1146    return ucfirst($text);
1147  else if ($attrib['uppercase'])
1148    return strtoupper($text);
1149  else if ($attrib['lowercase'])
1150    return strtolower($text);
1151  else
1152    return $text;
1153
1154  return $text;
1155  }
1156
1157
1158// send HTTP header for no-cacheing steps
1159function send_nocacheing_headers()
1160  {
1161  if (headers_sent())
1162    return;
1163
1164  header("Expires: ".gmdate("D, d M Y H:i:s")." GMT");
1165  header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
1166  header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
1167  header("Pragma: no-cache");
1168  }
1169
1170
1171// send header with expire date 30 days in future
1172function send_future_expire_header()
1173  {
1174  if (!headers_sent())
1175    header("Expires: ".gmdate("D, d M Y H:i:s", mktime()+2600000)." GMT");
1176  }
1177
1178
1179// function to convert an array to a javascript array
1180function array2js($arr, $type='')
1181  {
1182  if (!$type)
1183    $type = 'mixed';
1184
1185  if (is_array($arr))
1186    {
1187    // no items in array
1188    if (!sizeof($arr))
1189      return 'new Array()';
1190    else
1191      {
1192      $a_pairs = array();
1193      $keys_arr = array_keys($arr);
1194      $is_assoc = $have_numeric = 0;
1195
1196      for ($i=0; $i<sizeof($keys_arr); ++$i)
1197        {
1198        if(is_numeric($keys_arr[$i]))
1199          $have_numeric = 1;
1200        if (!is_numeric($keys_arr[$i]) || $keys_arr[$i]!=$i)
1201          $is_assoc = 1;
1202        if($is_assoc && $have_numeric)
1203          break;
1204        }
1205
1206      $previous_was_array = false;
1207      while (list($key, $value) = each($arr))
1208        {
1209        // enclose key with quotes if it is not variable-name conform
1210        if (!ereg("^[_a-zA-Z]{1}[_a-zA-Z0-9]*$", $key) /* || is_js_reserved_word($key) */)
1211          $key = "'$key'";
1212
1213        if (!is_array($value))
1214          {
1215          $value = str_replace("\r\n", '\n', $value);
1216          $value = str_replace("\n", '\n', $value);
1217          }
1218
1219        $is_string = false;
1220        if (!is_array($value))
1221          {
1222          if ($type=='string')
1223            $is_string = true;
1224          else if ((($type=='mixed' && is_numeric($value)) || $type=='int') && strlen($value)<16)   // js interprets numbers with digits >15 as ...e+...
1225            $is_string = FALSE;
1226          else
1227            $is_string = TRUE;
1228          }
1229
1230        if ($is_string)
1231          $value = "'".preg_replace("/(?<!\\\)'/", "\'", $value)."'";
1232
1233        $a_pairs[] = sprintf("%s%s",
1234                             $is_assoc ? "$key:" : '',
1235                             is_array($value) ? array2js($value, $type) : $value);
1236        }
1237
1238      if ($a_pairs)
1239        {
1240        if ($is_assoc)
1241          $return = '{'.implode(',', $a_pairs).'}';
1242        else
1243          $return = '['.implode(',', $a_pairs).']';
1244        }
1245
1246      return $return;
1247      }
1248    }
1249  else
1250    return $arr;
1251  }
1252
1253
1254// similar function as in_array() ut case-insensitive
1255function in_array_nocase($needle, $haystack)
1256  {
1257  foreach ($haystack as $value)
1258    {
1259    if (strtolower($needle)===strtolower($value))
1260      return TRUE;
1261    }
1262   
1263  return FALSE;
1264  }
1265
1266
1267
1268// find out if the string content means TRUE or FALSE
1269function get_boolean($str)
1270  {
1271  $str = strtolower($str);
1272  if(in_array($str, array('false', '0', 'no', 'nein', ''), TRUE))
1273    return FALSE;
1274  else
1275    return TRUE;
1276  }
1277
1278
1279function show_bytes($numbytes)
1280  {
1281  if ($numbytes > 1024)
1282    return sprintf('%d KB', round($numbytes/1024));
1283  else
1284    return sprintf('%d B', $numbytes);
1285  }
1286
1287
1288// convert paths like ../xxx to an absolute path using a base url
1289function make_absolute_url($path, $base_url)
1290    {
1291    $host_url = $base_url;
1292    $abs_path = $path;
1293
1294    // cut base_url to the last directory
1295    if (strpos($base_url, '/')>7)
1296      {
1297      $host_url = substr($base_url, 0, strpos($base_url, '/'));
1298      $base_url = substr($base_url, 0, strrpos($base_url, '/'));
1299      }
1300
1301    // $path is absolute
1302    if ($path{0}=='/')
1303      $abs_path = $host_url.$path;
1304    else
1305      {
1306      // strip './' because its the same as ''
1307      $path = preg_replace('/^\.\//', '', $path);
1308
1309      if(preg_match_all('/\.\.\//', $path, $matches, PREG_SET_ORDER))
1310        foreach($matches as $a_match)
1311          {
1312          if (strrpos($base_url, '/'))
1313            $base_url = substr($base_url, 0, strrpos($base_url, '/'));
1314         
1315          $path = substr($path, 3);
1316          }
1317
1318      $abs_path = $base_url.'/'.$path;
1319      }
1320     
1321    return $abs_path;
1322    }
1323
1324
1325
1326function abbrevate_string($str, $maxlength, $place_holder='...')
1327  {
1328  $length = strlen($str);
1329  $first_part_length = floor($maxlength/2) - strlen($place_holder);
1330 
1331  if ($length > $maxlength)
1332    {
1333    $second_starting_location = $length - $maxlength + $first_part_length + 1;
1334    $str = substr($str, 0, $first_part_length) . $place_holder . substr($str, $second_starting_location, $length);
1335    }
1336
1337  return $str;
1338  }
1339
1340
1341// delete all files within a folder
1342function clear_directory($dir_path)
1343  {
1344  $dir = @opendir($dir_path);
1345  if(!$dir) return FALSE;
1346
1347  while ($file = readdir($dir))
1348    if (strlen($file)>2)
1349      unlink("$dir_path/$file");
1350
1351  closedir($dir);
1352  return TRUE;
1353  }
1354
1355
1356?>
Note: See TracBrowser for help on using the repository browser.