]> git.donarmstrong.com Git - roundcube.git/blob - program/include/main.inc
Imported Upstream version 0.1~rc1
[roundcube.git] / program / include / main.inc
1 <?php
2
3 /*
4  +-----------------------------------------------------------------------+
5  | program/include/main.inc                                              |
6  |                                                                       |
7  | This file is part of the RoundCube Webmail client                     |
8  | Copyright (C) 2005-2007, RoundCube Dev, - Switzerland                 |
9  | Licensed under the GNU GPL                                            |
10  |                                                                       |
11  | PURPOSE:                                                              |
12  |   Provide basic functions for the webmail package                     |
13  |                                                                       |
14  +-----------------------------------------------------------------------+
15  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
16  +-----------------------------------------------------------------------+
17
18  $Id: main.inc 617 2007-06-13 06:57:22Z thomasb $
19
20 */
21
22 require_once('lib/utf7.inc');
23 require_once('include/rcmail_template.inc');
24
25
26 // define constannts for input reading
27 define('RCUBE_INPUT_GET', 0x0101);
28 define('RCUBE_INPUT_POST', 0x0102);
29 define('RCUBE_INPUT_GPC', 0x0103);
30
31
32 // register session and connect to server
33 function rcmail_startup($task='mail')
34   {
35   global $sess_id, $sess_user_lang;
36   global $CONFIG, $INSTALL_PATH, $BROWSER, $OUTPUT, $_SESSION, $IMAP, $DB;
37
38   // check client
39   $BROWSER = rcube_browser();
40
41   // load configuration
42   $CONFIG = rcmail_load_config();
43
44   // set session garbage collecting time according to session_lifetime
45   if (!empty($CONFIG['session_lifetime']))
46     ini_set('session.gc_maxlifetime', ($CONFIG['session_lifetime']) * 120);
47
48   // prepare DB connection
49   require_once('include/rcube_'.(empty($CONFIG['db_backend']) ? 'db' : $CONFIG['db_backend']).'.inc');
50   
51   $DB = new rcube_db($CONFIG['db_dsnw'], $CONFIG['db_dsnr'], $CONFIG['db_persistent']);
52   $DB->sqlite_initials = $INSTALL_PATH.'SQL/sqlite.initial.sql';
53   $DB->db_connect('w');
54
55   // use database for storing session data
56   include_once('include/session.inc');
57
58   // init session
59   session_start();
60   $sess_id = session_id();
61
62   // create session and set session vars
63   if (!isset($_SESSION['auth_time']))
64     {
65     $_SESSION['user_lang'] = rcube_language_prop($CONFIG['locale_string']);
66     $_SESSION['auth_time'] = time();
67     $_SESSION['temp'] = true;
68     }
69
70   // set session vars global
71   $sess_user_lang = rcube_language_prop($_SESSION['user_lang']);
72
73
74   // overwrite config with user preferences
75   if (is_array($_SESSION['user_prefs']))
76     $CONFIG = array_merge($CONFIG, $_SESSION['user_prefs']);
77
78
79   // reset some session parameters when changing task
80   if ($_SESSION['task'] != $task)
81     unset($_SESSION['page']);
82
83   // set current task to session
84   $_SESSION['task'] = $task;
85
86   // create IMAP object
87   if ($task=='mail')
88     rcmail_imap_init();
89
90
91   // set localization
92   if ($CONFIG['locale_string'])
93     setlocale(LC_ALL, $CONFIG['locale_string']);
94   else if ($sess_user_lang)
95     setlocale(LC_ALL, $sess_user_lang);
96
97
98   register_shutdown_function('rcmail_shutdown');
99   }
100
101
102 // load roundcube configuration into global var
103 function rcmail_load_config()
104   {
105   global $INSTALL_PATH;
106
107   // load config file
108   include_once('config/main.inc.php');
109   $conf = is_array($rcmail_config) ? $rcmail_config : array();
110
111   // load host-specific configuration
112   rcmail_load_host_config($conf);
113
114   $conf['skin_path'] = $conf['skin_path'] ? unslashify($conf['skin_path']) : 'skins/default';
115
116   // load db conf
117   include_once('config/db.inc.php');
118   $conf = array_merge($conf, $rcmail_config);
119
120   if (empty($conf['log_dir']))
121     $conf['log_dir'] = $INSTALL_PATH.'logs';
122   else
123     $conf['log_dir'] = unslashify($conf['log_dir']);
124
125   // set PHP error logging according to config
126   if ($conf['debug_level'] & 1)
127     {
128     ini_set('log_errors', 1);
129     ini_set('error_log', $conf['log_dir'].'/errors');
130     }
131   if ($conf['debug_level'] & 4)
132     ini_set('display_errors', 1);
133   else
134     ini_set('display_errors', 0);
135
136   return $conf;
137   }
138
139
140 // load a host-specific config file if configured
141 function rcmail_load_host_config(&$config)
142   {
143   $fname = NULL;
144   
145   if (is_array($config['include_host_config']))
146     $fname = $config['include_host_config'][$_SERVER['HTTP_HOST']];
147   else if (!empty($config['include_host_config']))
148     $fname = preg_replace('/[^a-z0-9\.\-_]/i', '', $_SERVER['HTTP_HOST']) . '.inc.php';
149
150    if ($fname && is_file('config/'.$fname))
151      {
152      include('config/'.$fname);
153      $config = array_merge($config, $rcmail_config);
154      }
155   }
156
157
158 // create authorization hash
159 function rcmail_auth_hash($sess_id, $ts)
160   {
161   global $CONFIG;
162   
163   $auth_string = sprintf('rcmail*sess%sR%s*Chk:%s;%s',
164                          $sess_id,
165                          $ts,
166                          $CONFIG['ip_check'] ? $_SERVER['REMOTE_ADDR'] : '***.***.***.***',
167                          $_SERVER['HTTP_USER_AGENT']);
168   
169   if (function_exists('sha1'))
170     return sha1($auth_string);
171   else
172     return md5($auth_string);
173   }
174
175
176 // compare the auth hash sent by the client with the local session credentials
177 function rcmail_authenticate_session()
178   {
179   global $CONFIG, $SESS_CLIENT_IP, $SESS_CHANGED;
180   
181   // advanced session authentication
182   if ($CONFIG['double_auth'])
183   {
184     $now = time();
185     $valid = ($_COOKIE['sessauth'] == rcmail_auth_hash(session_id(), $_SESSION['auth_time']) ||
186               $_COOKIE['sessauth'] == rcmail_auth_hash(session_id(), $_SESSION['last_auth']));
187
188     // renew auth cookie every 5 minutes (only for GET requests)
189     if (!$valid || ($_SERVER['REQUEST_METHOD']!='POST' && $now-$_SESSION['auth_time'] > 300))
190     {
191       $_SESSION['last_auth'] = $_SESSION['auth_time'];
192       $_SESSION['auth_time'] = $now;
193       setcookie('sessauth', rcmail_auth_hash(session_id(), $now));
194     }
195   }
196   else
197     $valid = $CONFIG['ip_check'] ? $_SERVER['REMOTE_ADDR'] == $SESS_CLIENT_IP : true;
198   
199   // check session filetime
200   if (!empty($CONFIG['session_lifetime']) && isset($SESS_CHANGED) && $SESS_CHANGED + $CONFIG['session_lifetime']*60 < time())
201     $valid = false;
202
203   return $valid;
204   }
205
206
207 // create IMAP object and connect to server
208 function rcmail_imap_init($connect=FALSE)
209   {
210   global $CONFIG, $DB, $IMAP, $OUTPUT;
211
212   $IMAP = new rcube_imap($DB);
213   $IMAP->debug_level = $CONFIG['debug_level'];
214   $IMAP->skip_deleted = $CONFIG['skip_deleted'];
215
216
217   // connect with stored session data
218   if ($connect)
219     {
220     if (!($conn = $IMAP->connect($_SESSION['imap_host'], $_SESSION['username'], decrypt_passwd($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl'])))
221       $OUTPUT->show_message('imaperror', 'error');
222       
223     rcmail_set_imap_prop();
224     }
225
226   // enable caching of imap data
227   if ($CONFIG['enable_caching']===TRUE)
228     $IMAP->set_caching(TRUE);
229
230   // set pagesize from config
231   if (isset($CONFIG['pagesize']))
232     $IMAP->set_pagesize($CONFIG['pagesize']);
233   }
234
235
236 // set root dir and last stored mailbox
237 // this must be done AFTER connecting to the server
238 function rcmail_set_imap_prop()
239   {
240   global $CONFIG, $IMAP;
241
242   // set root dir from config
243   if (!empty($CONFIG['imap_root']))
244     $IMAP->set_rootdir($CONFIG['imap_root']);
245
246   if (is_array($CONFIG['default_imap_folders']))
247     $IMAP->set_default_mailboxes($CONFIG['default_imap_folders']);
248
249   if (!empty($_SESSION['mbox']))
250     $IMAP->set_mailbox($_SESSION['mbox']);
251   if (isset($_SESSION['page']))
252     $IMAP->set_page($_SESSION['page']);
253   }
254
255
256 // do these things on script shutdown
257 function rcmail_shutdown()
258   {
259   global $IMAP;
260   
261   if (is_object($IMAP))
262     {
263     $IMAP->close();
264     $IMAP->write_cache();
265     }
266     
267   // before closing the database connection, write session data
268   session_write_close();
269   }
270
271
272 // destroy session data and remove cookie
273 function rcmail_kill_session()
274   {
275   // save user preferences
276   $a_user_prefs = $_SESSION['user_prefs'];
277   if (!is_array($a_user_prefs))
278     $a_user_prefs = array();
279     
280   if ((isset($_SESSION['sort_col']) && $_SESSION['sort_col']!=$a_user_prefs['message_sort_col']) ||
281       (isset($_SESSION['sort_order']) && $_SESSION['sort_order']!=$a_user_prefs['message_sort_order']))
282     {
283     $a_user_prefs['message_sort_col'] = $_SESSION['sort_col'];
284     $a_user_prefs['message_sort_order'] = $_SESSION['sort_order'];
285     rcmail_save_user_prefs($a_user_prefs);
286     }
287
288   $_SESSION = array('user_lang' => $GLOBALS['sess_user_lang'], 'auth_time' => time(), 'temp' => true);
289   setcookie('sessauth', '-del-', time()-60);
290   }
291
292
293 // return correct name for a specific database table
294 function get_table_name($table)
295   {
296   global $CONFIG;
297   
298   // return table name if configured
299   $config_key = 'db_table_'.$table;
300
301   if (strlen($CONFIG[$config_key]))
302     return $CONFIG[$config_key];
303   
304   return $table;
305   }
306
307
308 // return correct name for a specific database sequence
309 // (used for Postres only)
310 function get_sequence_name($sequence)
311   {
312   global $CONFIG;
313   
314   // return table name if configured
315   $config_key = 'db_sequence_'.$sequence;
316
317   if (strlen($CONFIG[$config_key]))
318     return $CONFIG[$config_key];
319   
320   return $table;
321   }
322
323
324 // check the given string and returns language properties
325 function rcube_language_prop($lang, $prop='lang')
326   {
327   global $INSTALL_PATH;
328   static $rcube_languages, $rcube_language_aliases, $rcube_charsets;
329
330   if (empty($rcube_languages))
331     @include($INSTALL_PATH.'program/localization/index.inc');
332     
333   // check if we have an alias for that language
334   if (!isset($rcube_languages[$lang]) && isset($rcube_language_aliases[$lang]))
335     $lang = $rcube_language_aliases[$lang];
336     
337   // try the first two chars
338   if (!isset($rcube_languages[$lang]) && strlen($lang)>2)
339     {
340     $lang = substr($lang, 0, 2);
341     $lang = rcube_language_prop($lang);
342     }
343
344   if (!isset($rcube_languages[$lang]))
345     $lang = 'en_US';
346
347   // language has special charset configured
348   if (isset($rcube_charsets[$lang]))
349     $charset = $rcube_charsets[$lang];
350   else
351     $charset = 'UTF-8';    
352
353
354   if ($prop=='charset')
355     return $charset;
356   else
357     return $lang;
358   }
359   
360
361 // init output object for GUI and add common scripts
362 function rcmail_load_gui()
363   {
364   global $CONFIG, $OUTPUT, $sess_user_lang;
365
366   // init output page
367   $OUTPUT = new rcmail_template($CONFIG, $GLOBALS['_task']);
368   $OUTPUT->set_env('comm_path', $GLOBALS['COMM_PATH']);
369
370   if (is_array($CONFIG['javascript_config']))
371   {
372     foreach ($CONFIG['javascript_config'] as $js_config_var)
373       $OUTPUT->set_env($js_config_var, $CONFIG[$js_config_var]);
374   }
375
376   if (!empty($GLOBALS['_framed']))
377     $OUTPUT->set_env('framed', true);
378
379   // set locale setting
380   rcmail_set_locale($sess_user_lang);
381
382   // set user-selected charset
383   if (!empty($CONFIG['charset']))
384     $OUTPUT->set_charset($CONFIG['charset']);
385     
386   // register common UI objects
387   $OUTPUT->add_handlers(array(
388     'loginform' => 'rcmail_login_form',
389     'username'  => 'rcmail_current_username',
390     'message' => 'rcmail_message_container',
391     'charsetselector' => 'rcmail_charset_selector',
392   ));
393
394   // add some basic label to client
395   if (!$OUTPUT->ajax_call)
396     rcube_add_label('loading');
397   }
398
399
400 // set localization charset based on the given language
401 function rcmail_set_locale($lang)
402   {
403   global $OUTPUT, $MBSTRING;
404   static $s_mbstring_loaded = NULL;
405   
406   // settings for mbstring module (by Tadashi Jokagi)
407   if (is_null($s_mbstring_loaded))
408     $MBSTRING = $s_mbstring_loaded = extension_loaded("mbstring");
409   else
410     $MBSTRING = $s_mbstring_loaded = FALSE;
411     
412   if ($MBSTRING)
413     mb_internal_encoding(RCMAIL_CHARSET);
414
415   $OUTPUT->set_charset(rcube_language_prop($lang, 'charset'));
416   }
417
418
419 // auto-select IMAP host based on the posted login information
420 function rcmail_autoselect_host()
421   {
422   global $CONFIG;
423   
424   $host = isset($_POST['_host']) ? get_input_value('_host', RCUBE_INPUT_POST) : $CONFIG['default_host'];
425   if (is_array($host))
426     {
427     list($user, $domain) = explode('@', get_input_value('_user', RCUBE_INPUT_POST));
428     if (!empty($domain))
429       {
430       foreach ($host as $imap_host => $mail_domains)
431         if (is_array($mail_domains) && in_array($domain, $mail_domains))
432           {
433           $host = $imap_host;
434           break;
435           }
436       }
437
438     // take the first entry if $host is still an array
439     if (is_array($host))
440       $host = array_shift($host);
441     }
442   
443   return $host;
444   }
445
446
447 // perfom login to the IMAP server and to the webmail service
448 function rcmail_login($user, $pass, $host=NULL)
449   {
450   global $CONFIG, $IMAP, $DB, $sess_user_lang;
451   $user_id = NULL;
452   
453   if (!$host)
454     $host = $CONFIG['default_host'];
455
456   // Validate that selected host is in the list of configured hosts
457   if (is_array($CONFIG['default_host']))
458     {
459     $allowed = FALSE;
460     foreach ($CONFIG['default_host'] as $key => $host_allowed)
461       {
462       if (!is_numeric($key))
463         $host_allowed = $key;
464       if ($host == $host_allowed)
465         {
466         $allowed = TRUE;
467         break;
468         }
469       }
470     if (!$allowed)
471       return FALSE;
472     }
473   else if (!empty($CONFIG['default_host']) && $host != $CONFIG['default_host'])
474     return FALSE;
475
476   // parse $host URL
477   $a_host = parse_url($host);
478   if ($a_host['host'])
479     {
480     $host = $a_host['host'];
481     $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? TRUE : FALSE;
482     $imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : $CONFIG['default_port']);
483     }
484   else
485     $imap_port = $CONFIG['default_port'];
486
487
488   /* Modify username with domain if required  
489      Inspired by Marco <P0L0_notspam_binware.org>
490   */
491   // Check if we need to add domain
492   if (!empty($CONFIG['username_domain']) && !strstr($user, '@'))
493     {
494     if (is_array($CONFIG['username_domain']) && isset($CONFIG['username_domain'][$host]))
495       $user .= '@'.$CONFIG['username_domain'][$host];
496     else if (is_string($CONFIG['username_domain']))
497       $user .= '@'.$CONFIG['username_domain'];
498     }
499
500
501   // query if user already registered
502   $sql_result = $DB->query("SELECT user_id, username, language, preferences
503                             FROM ".get_table_name('users')."
504                             WHERE  mail_host=? AND (username=? OR alias=?)",
505                             $host,
506                             $user,
507                             $user);
508
509   // user already registered -> overwrite username
510   if ($sql_arr = $DB->fetch_assoc($sql_result))
511     {
512     $user_id = $sql_arr['user_id'];
513     $user = $sql_arr['username'];
514     }
515
516   // try to resolve email address from virtuser table    
517   if (!empty($CONFIG['virtuser_file']) && strstr($user, '@'))
518     $user = rcmail_email2user($user);
519
520
521   // exit if IMAP login failed
522   if (!($imap_login  = $IMAP->connect($host, $user, $pass, $imap_port, $imap_ssl)))
523     return FALSE;
524
525   // user already registered
526   if ($user_id && !empty($sql_arr))
527     {
528     // get user prefs
529     if (strlen($sql_arr['preferences']))
530       {
531       $user_prefs = unserialize($sql_arr['preferences']);
532       $_SESSION['user_prefs'] = $user_prefs;
533       array_merge($CONFIG, $user_prefs);
534       }
535
536
537     // set user specific language
538     if (strlen($sql_arr['language']))
539       $sess_user_lang = $_SESSION['user_lang'] = $sql_arr['language'];
540       
541     // update user's record
542     $DB->query("UPDATE ".get_table_name('users')."
543                 SET    last_login=".$DB->now()."
544                 WHERE  user_id=?",
545                 $user_id);
546     }
547   // create new system user
548   else if ($CONFIG['auto_create_user'])
549     {
550     $user_id = rcmail_create_user($user, $host);
551     }
552
553   if ($user_id)
554     {
555     $_SESSION['user_id']   = $user_id;
556     $_SESSION['imap_host'] = $host;
557     $_SESSION['imap_port'] = $imap_port;
558     $_SESSION['imap_ssl']  = $imap_ssl;
559     $_SESSION['username']  = $user;
560     $_SESSION['user_lang'] = $sess_user_lang;
561     $_SESSION['password']  = encrypt_passwd($pass);
562     $_SESSION['login_time'] = mktime();
563
564     // force reloading complete list of subscribed mailboxes
565     rcmail_set_imap_prop();
566     $IMAP->clear_cache('mailboxes');
567     $IMAP->create_default_folders();
568
569     return TRUE;
570     }
571
572   return FALSE;
573   }
574
575
576 // create new entry in users and identities table
577 function rcmail_create_user($user, $host)
578   {
579   global $DB, $CONFIG, $IMAP;
580
581   $user_email = '';
582
583   // try to resolve user in virtusertable
584   if (!empty($CONFIG['virtuser_file']) && strstr($user, '@')==FALSE)
585     $user_email = rcmail_user2email($user);
586
587   $DB->query("INSERT INTO ".get_table_name('users')."
588               (created, last_login, username, mail_host, alias, language)
589               VALUES (".$DB->now().", ".$DB->now().", ?, ?, ?, ?)",
590               strip_newlines($user),
591               strip_newlines($host),
592               strip_newlines($user_email),
593               $_SESSION['user_lang']);
594
595   if ($user_id = $DB->insert_id(get_sequence_name('users')))
596     {
597     $mail_domain = rcmail_mail_domain($host);
598    
599     if ($user_email=='')
600       $user_email = strstr($user, '@') ? $user : sprintf('%s@%s', $user, $mail_domain);
601
602     $user_name = $user!=$user_email ? $user : '';
603
604     // try to resolve the e-mail address from the virtuser table
605     if (!empty($CONFIG['virtuser_query']) &&
606         ($sql_result = $DB->query(preg_replace('/%u/', $user, $CONFIG['virtuser_query']))) &&
607         ($DB->num_rows()>0))
608       while ($sql_arr = $DB->fetch_array($sql_result))
609         {
610         $DB->query("INSERT INTO ".get_table_name('identities')."
611                    (user_id, del, standard, name, email)
612                    VALUES (?, 0, 1, ?, ?)",
613                    $user_id,
614                    strip_newlines($user_name),
615                    preg_replace('/^@/', $user . '@', $sql_arr[0]));
616         }
617     else
618       {
619       // also create new identity records
620       $DB->query("INSERT INTO ".get_table_name('identities')."
621                   (user_id, del, standard, name, email)
622                   VALUES (?, 0, 1, ?, ?)",
623                   $user_id,
624                   strip_newlines($user_name),
625                   strip_newlines($user_email));
626       }
627                        
628     // get existing mailboxes
629     $a_mailboxes = $IMAP->list_mailboxes();
630     }
631   else
632     {
633     raise_error(array('code' => 500,
634                       'type' => 'php',
635                       'line' => __LINE__,
636                       'file' => __FILE__,
637                       'message' => "Failed to create new user"), TRUE, FALSE);
638     }
639     
640   return $user_id;
641   }
642
643
644 // load virtuser table in array
645 function rcmail_getvirtualfile()
646   {
647   global $CONFIG;
648   if (empty($CONFIG['virtuser_file']) || !is_file($CONFIG['virtuser_file']))
649     return FALSE;
650   
651   // read file 
652   $a_lines = file($CONFIG['virtuser_file']);
653   return $a_lines;
654   }
655
656
657 // find matches of the given pattern in virtuser table
658 function rcmail_findinvirtual($pattern)
659   {
660   $result = array();
661   $virtual = rcmail_getvirtualfile();
662   if ($virtual==FALSE)
663     return $result;
664
665   // check each line for matches
666   foreach ($virtual as $line)
667     {
668     $line = trim($line);
669     if (empty($line) || $line{0}=='#')
670       continue;
671       
672     if (eregi($pattern, $line))
673       $result[] = $line;
674     }
675
676   return $result;
677   }
678
679
680 // resolve username with virtuser table
681 function rcmail_email2user($email)
682   {
683   $user = $email;
684   $r = rcmail_findinvirtual("^$email");
685
686   for ($i=0; $i<count($r); $i++)
687     {
688     $data = $r[$i];
689     $arr = preg_split('/\s+/', $data);
690     if(count($arr)>0)
691       {
692       $user = trim($arr[count($arr)-1]);
693       break;
694       }
695     }
696
697   return $user;
698   }
699
700
701 // resolve e-mail address with virtuser table
702 function rcmail_user2email($user)
703   {
704   $email = "";
705   $r = rcmail_findinvirtual("$user$");
706
707   for ($i=0; $i<count($r); $i++)
708     {
709     $data=$r[$i];
710     $arr = preg_split('/\s+/', $data);
711     if (count($arr)>0)
712       {
713       $email = trim($arr[0]);
714       break;
715       }
716     }
717
718   return $email;
719   } 
720
721
722 function rcmail_save_user_prefs($a_user_prefs)
723   {
724   global $DB, $CONFIG, $sess_user_lang;
725   
726   $DB->query("UPDATE ".get_table_name('users')."
727               SET    preferences=?,
728                      language=?
729               WHERE  user_id=?",
730               serialize($a_user_prefs),
731               $sess_user_lang,
732               $_SESSION['user_id']);
733
734   if ($DB->affected_rows())
735     {
736     $_SESSION['user_prefs'] = $a_user_prefs;  
737     $CONFIG = array_merge($CONFIG, $a_user_prefs);
738     return TRUE;
739     }
740     
741   return FALSE;
742   }
743
744
745 // overwrite action variable  
746 function rcmail_overwrite_action($action)
747   {
748   global $OUTPUT;
749   $GLOBALS['_action'] = $action;
750   $OUTPUT->set_env('action', $action);
751   }
752
753
754 /**
755  * Compose an URL for a specific action
756  *
757  * @param string  Request action
758  * @param array   More URL parameters
759  * @param string  Request task (omit if the same)
760  * @return The application URL
761  */
762 function rcmail_url($action, $p=array(), $task=null)
763 {
764   global $MAIN_TASKS, $COMM_PATH;
765   $qstring = '';
766   $base = $COMM_PATH;
767   
768   if ($task && in_array($task, $MAIN_TASKS))
769     $base = ereg_replace('_task=[a-z]+', '_task='.$task, $COMM_PATH);
770   
771   if (is_array($p))
772     foreach ($p as $key => $val)
773       $qstring .= '&'.urlencode($key).'='.urlencode($val);
774   
775   return $base . ($action ? '&_action='.$action : '') . $qstring;
776 }
777
778
779 // @deprecated
780 function show_message($message, $type='notice', $vars=NULL)
781   {
782   global $OUTPUT;
783   $OUTPUT->show_message($message, $type, $vars);
784   }
785
786
787 // encrypt IMAP password using DES encryption
788 function encrypt_passwd($pass)
789   {
790   $td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_ECB, "");
791   $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
792   mcrypt_generic_init($td, get_des_key(), $iv);
793   $cypher = mcrypt_generic($td, $pass);
794   mcrypt_generic_deinit($td);
795   mcrypt_module_close($td);
796   return base64_encode($cypher);
797   }
798
799
800 // decrypt IMAP password using DES encryption
801 function decrypt_passwd($cypher)
802   {
803   $td = mcrypt_module_open(MCRYPT_TripleDES, "", MCRYPT_MODE_ECB, "");
804   $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
805   mcrypt_generic_init($td, get_des_key(), $iv);
806   $pass = mdecrypt_generic($td, base64_decode($cypher));
807   mcrypt_generic_deinit($td);
808   mcrypt_module_close($td);
809   return preg_replace('/\x00/', '', $pass);
810   }
811
812
813 // return a 24 byte key for the DES encryption
814 function get_des_key()
815   {
816   $key = !empty($GLOBALS['CONFIG']['des_key']) ? $GLOBALS['CONFIG']['des_key'] : 'rcmail?24BitPwDkeyF**ECB';
817   $len = strlen($key);
818   
819   // make sure the key is exactly 24 chars long
820   if ($len<24)
821     $key .= str_repeat('_', 24-$len);
822   else if ($len>24)
823     substr($key, 0, 24);
824   
825   return $key;
826   }
827
828
829 // read directory program/localization/ and return a list of available languages
830 function rcube_list_languages()
831   {
832   global $CONFIG, $INSTALL_PATH;
833   static $sa_languages = array();
834
835   if (!sizeof($sa_languages))
836     {
837     @include($INSTALL_PATH.'program/localization/index.inc');
838
839     if ($dh = @opendir($INSTALL_PATH.'program/localization'))
840       {
841       while (($name = readdir($dh)) !== false)
842         {
843         if ($name{0}=='.' || !is_dir($INSTALL_PATH.'program/localization/'.$name))
844           continue;
845
846         if ($label = $rcube_languages[$name])
847           $sa_languages[$name] = $label ? $label : $name;
848         }
849       closedir($dh);
850       }
851     }
852   return $sa_languages;
853   }
854
855
856 // add a localized label to the client environment
857 function rcube_add_label()
858   {
859   global $OUTPUT;
860   
861   $arg_list = func_get_args();
862   foreach ($arg_list as $i => $name)
863     $OUTPUT->command('add_label', $name, rcube_label($name));
864   }
865
866
867 // remove temp files older than two day
868 function rcmail_temp_gc()
869   {
870   $tmp = unslashify($CONFIG['temp_dir']);
871   $expire = mktime() - 172800;  // expire in 48 hours
872
873   if ($dir = opendir($tmp))
874     {
875     while (($fname = readdir($dir)) !== false)
876       {
877       if ($fname{0} == '.')
878         continue;
879
880       if (filemtime($tmp.'/'.$fname) < $expire)
881         @unlink($tmp.'/'.$fname);
882       }
883
884     closedir($dir);
885     }
886   }
887
888
889 // remove all expired message cache records
890 function rcmail_message_cache_gc()
891   {
892   global $DB, $CONFIG;
893   
894   // no cache lifetime configured
895   if (empty($CONFIG['message_cache_lifetime']))
896     return;
897   
898   // get target timestamp
899   $ts = get_offset_time($CONFIG['message_cache_lifetime'], -1);
900   
901   $DB->query("DELETE FROM ".get_table_name('messages')."
902              WHERE  created < ".$DB->fromunixtime($ts));
903   }
904
905
906 /**
907  * Convert a string from one charset to another.
908  * Uses mbstring and iconv functions if possible
909  *
910  * @param  string Input string
911  * @param  string Suspected charset of the input string
912  * @param  string Target charset to convert to; defaults to RCMAIL_CHARSET
913  * @return Converted string
914  */
915 function rcube_charset_convert($str, $from, $to=NULL)
916   {
917   global $MBSTRING;
918
919   $from = strtoupper($from);
920   $to = $to==NULL ? strtoupper(RCMAIL_CHARSET) : strtoupper($to);
921
922   if ($from==$to || $str=='' || empty($from))
923     return $str;
924
925   // convert charset using mbstring module  
926   if ($MBSTRING)
927     {
928     $to = $to=="UTF-7" ? "UTF7-IMAP" : $to;
929     $from = $from=="UTF-7" ? "UTF7-IMAP": $from;
930
931     // return if convert succeeded
932     if (($out = mb_convert_encoding($str, $to, $from)) != '')
933       return $out;
934     }
935
936   // convert charset using iconv module  
937   if (function_exists('iconv') && $from!='UTF-7' && $to!='UTF-7')
938     return iconv($from, $to, $str);
939
940   // convert string to UTF-8
941   if ($from=='UTF-7')
942     $str = utf7_to_utf8($str);
943   else if (($from=='ISO-8859-1') && function_exists('utf8_encode'))
944     $str = utf8_encode($str);
945
946   // encode string for output
947   if ($to=='UTF-7')
948     return utf8_to_utf7($str);
949   else if ($to=='ISO-8859-1' && function_exists('utf8_decode'))
950     return utf8_decode($str);
951
952   // return UTF-8 string
953   return $str;
954   }
955
956
957 /**
958  * Replacing specials characters to a specific encoding type
959  *
960  * @param  string  Input string
961  * @param  string  Encoding type: text|html|xml|js|url
962  * @param  string  Replace mode for tags: show|replace|remove
963  * @param  boolean Convert newlines
964  * @return The quoted string
965  */
966 function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE)
967   {
968   global $OUTPUT_TYPE, $OUTPUT;
969   static $html_encode_arr, $js_rep_table, $xml_rep_table;
970
971   if (!$enctype)
972     $enctype = $GLOBALS['OUTPUT_TYPE'];
973
974   // convert nbsps back to normal spaces if not html
975   if ($enctype!='html')
976     $str = str_replace(chr(160), ' ', $str);
977
978   // encode for plaintext
979   if ($enctype=='text')
980     return str_replace("\r\n", "\n", $mode=='remove' ? strip_tags($str) : $str);
981
982   // encode for HTML output
983   if ($enctype=='html')
984     {
985     if (!$html_encode_arr)
986       {
987       $html_encode_arr = get_html_translation_table(HTML_SPECIALCHARS);        
988       unset($html_encode_arr['?']);
989       }
990
991     $ltpos = strpos($str, '<');
992     $encode_arr = $html_encode_arr;
993
994     // don't replace quotes and html tags
995     if (($mode=='show' || $mode=='') && $ltpos!==false && strpos($str, '>', $ltpos)!==false)
996       {
997       unset($encode_arr['"']);
998       unset($encode_arr['<']);
999       unset($encode_arr['>']);
1000       unset($encode_arr['&']);
1001       }
1002     else if ($mode=='remove')
1003       $str = strip_tags($str);
1004     
1005     // avoid douple quotation of &
1006     $out = preg_replace('/&amp;([a-z]{2,5}|#[0-9]{2,4});/', '&\\1;', strtr($str, $encode_arr));
1007       
1008     return $newlines ? nl2br($out) : $out;
1009     }
1010
1011   if ($enctype=='url')
1012     return rawurlencode($str);
1013
1014   // if the replace tables for XML and JS are not yet defined
1015   if (!$js_rep_table)
1016     {
1017     $js_rep_table = $xml_rep_table = array();
1018     $xml_rep_table['&'] = '&amp;';
1019
1020     for ($c=160; $c<256; $c++)  // can be increased to support more charsets
1021       {
1022       $hex = dechex($c);
1023       $xml_rep_table[Chr($c)] = "&#$c;";
1024       
1025       if ($OUTPUT->get_charset()=='ISO-8859-1')
1026         $js_rep_table[Chr($c)] = sprintf("\u%s%s", str_repeat('0', 4-strlen($hex)), $hex);
1027       }
1028
1029     $xml_rep_table['"'] = '&quot;';
1030     }
1031
1032   // encode for XML
1033   if ($enctype=='xml')
1034     return strtr($str, $xml_rep_table);
1035
1036   // encode for javascript use
1037   if ($enctype=='js')
1038     {
1039     if ($OUTPUT->get_charset()!='UTF-8')
1040       $str = rcube_charset_convert($str, RCMAIL_CHARSET, $OUTPUT->get_charset());
1041       
1042     return preg_replace(array("/\r?\n/", "/\r/"), array('\n', '\n'), addslashes(strtr($str, $js_rep_table)));
1043     }
1044
1045   // no encoding given -> return original string
1046   return $str;
1047   }
1048   
1049 /**
1050  * Quote a given string. Alias function for rep_specialchars_output
1051  * @see rep_specialchars_output
1052  */
1053 function Q($str, $mode='strict', $newlines=TRUE)
1054   {
1055   return rep_specialchars_output($str, 'html', $mode, $newlines);
1056   }
1057
1058 /**
1059  * Quote a given string. Alias function for rep_specialchars_output
1060  * @see rep_specialchars_output
1061  */
1062 function JQ($str)
1063   {
1064   return rep_specialchars_output($str, 'js');
1065   }
1066
1067
1068 /**
1069  * Read input value and convert it for internal use
1070  * Performs stripslashes() and charset conversion if necessary
1071  * 
1072  * @param  string   Field name to read
1073  * @param  int      Source to get value from (GPC)
1074  * @param  boolean  Allow HTML tags in field value
1075  * @param  string   Charset to convert into
1076  * @return string   Field value or NULL if not available
1077  */
1078 function get_input_value($fname, $source, $allow_html=FALSE, $charset=NULL)
1079   {
1080   global $OUTPUT;
1081   $value = NULL;
1082   
1083   if ($source==RCUBE_INPUT_GET && isset($_GET[$fname]))
1084     $value = $_GET[$fname];
1085   else if ($source==RCUBE_INPUT_POST && isset($_POST[$fname]))
1086     $value = $_POST[$fname];
1087   else if ($source==RCUBE_INPUT_GPC)
1088     {
1089     if (isset($_POST[$fname]))
1090       $value = $_POST[$fname];
1091     else if (isset($_GET[$fname]))
1092       $value = $_GET[$fname];
1093     else if (isset($_COOKIE[$fname]))
1094       $value = $_COOKIE[$fname];
1095     }
1096   
1097   // strip slashes if magic_quotes enabled
1098   if ((bool)get_magic_quotes_gpc())
1099     $value = stripslashes($value);
1100
1101   // remove HTML tags if not allowed    
1102   if (!$allow_html)
1103     $value = strip_tags($value);
1104   
1105   // convert to internal charset
1106   if (is_object($OUTPUT))
1107     return rcube_charset_convert($value, $OUTPUT->get_charset(), $charset);
1108   else
1109     return $value;
1110   }
1111
1112 /**
1113  * Remove single and double quotes from given string
1114  */
1115 function strip_quotes($str)
1116 {
1117   return preg_replace('/[\'"]/', '', $str);
1118 }
1119
1120 /**
1121  * Remove new lines characters from given string
1122  */
1123 function strip_newlines($str)
1124 {
1125   return preg_replace('/[\r\n]/', '', $str);
1126 }
1127
1128
1129 // return boolean if a specific template exists
1130 function template_exists($name)
1131   {
1132   global $CONFIG;
1133   $skin_path = $CONFIG['skin_path'];
1134
1135   // check template file
1136   return is_file("$skin_path/templates/$name.html");
1137   }
1138
1139
1140 // Wrapper for rcmail_template::parse()
1141 // @deprecated
1142 function parse_template($name='main', $exit=true)
1143   {
1144   $GLOBALS['OUTPUT']->parse($name, $exit);
1145   }
1146
1147
1148
1149 function rcube_table_output($attrib, $table_data, $a_show_cols, $id_col)
1150   {
1151   global $DB;
1152   
1153   // allow the following attributes to be added to the <table> tag
1154   $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
1155   
1156   $table = '<table' . $attrib_str . ">\n";
1157     
1158   // add table title
1159   $table .= "<thead><tr>\n";
1160
1161   foreach ($a_show_cols as $col)
1162     $table .= '<td class="'.$col.'">' . Q(rcube_label($col)) . "</td>\n";
1163
1164   $table .= "</tr></thead>\n<tbody>\n";
1165   
1166   $c = 0;
1167   if (!is_array($table_data)) 
1168     {
1169     while ($table_data && ($sql_arr = $DB->fetch_assoc($table_data)))
1170       {
1171       $zebra_class = $c%2 ? 'even' : 'odd';
1172
1173       $table .= sprintf('<tr id="rcmrow%d" class="contact '.$zebra_class.'">'."\n", $sql_arr[$id_col]);
1174
1175       // format each col
1176       foreach ($a_show_cols as $col)
1177         {
1178         $cont = Q($sql_arr[$col]);
1179         $table .= '<td class="'.$col.'">' . $cont . "</td>\n";
1180         }
1181
1182       $table .= "</tr>\n";
1183       $c++;
1184       }
1185     }
1186   else 
1187     {
1188     foreach ($table_data as $row_data)
1189       {
1190       $zebra_class = $c%2 ? 'even' : 'odd';
1191
1192       $table .= sprintf('<tr id="rcmrow%d" class="contact '.$zebra_class.'">'."\n", $row_data[$id_col]);
1193
1194       // format each col
1195       foreach ($a_show_cols as $col)
1196         {
1197         $cont = Q($row_data[$col]);
1198         $table .= '<td class="'.$col.'">' . $cont . "</td>\n";
1199         }
1200
1201       $table .= "</tr>\n";
1202       $c++;
1203       }
1204     }
1205
1206   // complete message table
1207   $table .= "</tbody></table>\n";
1208   
1209   return $table;
1210   }
1211
1212
1213 /**
1214  * Create an edit field for inclusion on a form
1215  * 
1216  * @param string col field name
1217  * @param string value field value
1218  * @param array attrib HTML element attributes for field
1219  * @param string type HTML element type (default 'text')
1220  * @return string HTML field definition
1221  */
1222 function rcmail_get_edit_field($col, $value, $attrib, $type='text')
1223   {
1224   $fname = '_'.$col;
1225   $attrib['name'] = $fname;
1226   
1227   if ($type=='checkbox')
1228     {
1229     $attrib['value'] = '1';
1230     $input = new checkbox($attrib);
1231     }
1232   else if ($type=='textarea')
1233     {
1234     $attrib['cols'] = $attrib['size'];
1235     $input = new textarea($attrib);
1236     }
1237   else
1238     $input = new textfield($attrib);
1239
1240   // use value from post
1241   if (!empty($_POST[$fname]))
1242     $value = $_POST[$fname];
1243
1244   $out = $input->show($value);
1245          
1246   return $out;
1247   }
1248
1249
1250 // return the mail domain configured for the given host
1251 function rcmail_mail_domain($host)
1252   {
1253   global $CONFIG;
1254
1255   $domain = $host;
1256   if (is_array($CONFIG['mail_domain']))
1257     {
1258     if (isset($CONFIG['mail_domain'][$host]))
1259       $domain = $CONFIG['mail_domain'][$host];
1260     }
1261   else if (!empty($CONFIG['mail_domain']))
1262     $domain = $CONFIG['mail_domain'];
1263
1264   return $domain;
1265   }
1266
1267
1268 // compose a valid attribute string for HTML tags
1269 function create_attrib_string($attrib, $allowed_attribs=array('id', 'class', 'style'))
1270   {
1271   // allow the following attributes to be added to the <iframe> tag
1272   $attrib_str = '';
1273   foreach ($allowed_attribs as $a)
1274     if (isset($attrib[$a]))
1275       $attrib_str .= sprintf(' %s="%s"', $a, str_replace('"', '&quot;', $attrib[$a]));
1276
1277   return $attrib_str;
1278   }
1279
1280
1281 // convert a HTML attribute string attributes to an associative array (name => value)
1282 function parse_attrib_string($str)
1283   {
1284   $attrib = array();
1285   preg_match_all('/\s*([-_a-z]+)=(["\'])([^"]+)\2/Ui', stripslashes($str), $regs, PREG_SET_ORDER);
1286
1287   // convert attributes to an associative array (name => value)
1288   if ($regs)
1289     foreach ($regs as $attr)
1290       $attrib[strtolower($attr[1])] = $attr[3];
1291
1292   return $attrib;
1293   }
1294
1295
1296 function format_date($date, $format=NULL)
1297   {
1298   global $CONFIG, $sess_user_lang;
1299   
1300   $ts = NULL;
1301   
1302   if (is_numeric($date))
1303     $ts = $date;
1304   else if (!empty($date))
1305     $ts = @strtotime($date);
1306     
1307   if (empty($ts))
1308     return '';
1309    
1310   // get user's timezone
1311   $tz = $CONFIG['timezone'];
1312   if ($CONFIG['dst_active'])
1313     $tz++;
1314
1315   // convert time to user's timezone
1316   $timestamp = $ts - date('Z', $ts) + ($tz * 3600);
1317   
1318   // get current timestamp in user's timezone
1319   $now = time();  // local time
1320   $now -= (int)date('Z'); // make GMT time
1321   $now += ($tz * 3600); // user's time
1322   $now_date = getdate($now);
1323
1324   $today_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday'], $now_date['year']);
1325   $week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']);
1326
1327   // define date format depending on current time  
1328   if ($CONFIG['prettydate'] && !$format && $timestamp > $today_limit && $timestamp < $now)
1329     return sprintf('%s %s', rcube_label('today'), date($CONFIG['date_today'] ? $CONFIG['date_today'] : 'H:i', $timestamp));
1330   else if ($CONFIG['prettydate'] && !$format && $timestamp > $week_limit && $timestamp < $now)
1331     $format = $CONFIG['date_short'] ? $CONFIG['date_short'] : 'D H:i';
1332   else if (!$format)
1333     $format = $CONFIG['date_long'] ? $CONFIG['date_long'] : 'd.m.Y H:i';
1334
1335
1336   // parse format string manually in order to provide localized weekday and month names
1337   // an alternative would be to convert the date() format string to fit with strftime()
1338   $out = '';
1339   for($i=0; $i<strlen($format); $i++)
1340     {
1341     if ($format{$i}=='\\')  // skip escape chars
1342       continue;
1343     
1344     // write char "as-is"
1345     if ($format{$i}==' ' || $format{$i-1}=='\\')
1346       $out .= $format{$i};
1347     // weekday (short)
1348     else if ($format{$i}=='D')
1349       $out .= rcube_label(strtolower(date('D', $timestamp)));
1350     // weekday long
1351     else if ($format{$i}=='l')
1352       $out .= rcube_label(strtolower(date('l', $timestamp)));
1353     // month name (short)
1354     else if ($format{$i}=='M')
1355       $out .= rcube_label(strtolower(date('M', $timestamp)));
1356     // month name (long)
1357     else if ($format{$i}=='F')
1358       $out .= rcube_label(strtolower(date('F', $timestamp)));
1359     else
1360       $out .= date($format{$i}, $timestamp);
1361     }
1362   
1363   return $out;
1364   }
1365
1366
1367 function format_email_recipient($email, $name='')
1368   {
1369   if ($name && $name != $email)
1370     return sprintf('%s <%s>', strpos($name, ",") ? '"'.$name.'"' : $name, $email);
1371   else
1372     return $email;
1373   }
1374
1375
1376
1377 // ************** functions delivering gui objects **************
1378
1379
1380
1381 function rcmail_message_container($attrib)
1382   {
1383   global $OUTPUT;
1384
1385   if (!$attrib['id'])
1386     $attrib['id'] = 'rcmMessageContainer';
1387
1388   // allow the following attributes to be added to the <table> tag
1389   $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id'));
1390   $out = '<div' . $attrib_str . "></div>";
1391   
1392   $OUTPUT->add_gui_object('message', $attrib['id']);
1393   
1394   return $out;
1395   }
1396
1397
1398 // return the IMAP username of the current session
1399 function rcmail_current_username($attrib)
1400   {
1401   global $DB;
1402   static $s_username;
1403
1404   // alread fetched  
1405   if (!empty($s_username))
1406     return $s_username;
1407
1408   // get e-mail address form default identity
1409   $sql_result = $DB->query("SELECT email AS mailto
1410                             FROM ".get_table_name('identities')."
1411                             WHERE  user_id=?
1412                             AND    standard=1
1413                             AND    del<>1",
1414                             $_SESSION['user_id']);
1415                                    
1416   if ($DB->num_rows($sql_result))
1417     {
1418     $sql_arr = $DB->fetch_assoc($sql_result);
1419     $s_username = $sql_arr['mailto'];
1420     }
1421   else if (strstr($_SESSION['username'], '@'))
1422     $s_username = $_SESSION['username'];
1423   else
1424     $s_username = $_SESSION['username'].'@'.$_SESSION['imap_host'];
1425
1426   return $s_username;
1427   }
1428
1429
1430 // return code for the webmail login form
1431 function rcmail_login_form($attrib)
1432   {
1433   global $CONFIG, $OUTPUT, $SESS_HIDDEN_FIELD;
1434   
1435   $labels = array();
1436   $labels['user'] = rcube_label('username');
1437   $labels['pass'] = rcube_label('password');
1438   $labels['host'] = rcube_label('server');
1439   
1440   $input_user = new textfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30, 'autocomplete' => 'off'));
1441   $input_pass = new passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30));
1442   $input_action = new hiddenfield(array('name' => '_action', 'value' => 'login'));
1443     
1444   $fields = array();
1445   $fields['user'] = $input_user->show(get_input_value('_user', RCUBE_INPUT_POST));
1446   $fields['pass'] = $input_pass->show();
1447   $fields['action'] = $input_action->show();
1448   
1449   if (is_array($CONFIG['default_host']))
1450     {
1451     $select_host = new select(array('name' => '_host', 'id' => 'rcmloginhost'));
1452     
1453     foreach ($CONFIG['default_host'] as $key => $value)
1454     {
1455       if (!is_array($value))
1456         $select_host->add($value, (is_numeric($key) ? $value : $key));
1457       else
1458         {
1459         unset($select_host);
1460         break;
1461         }
1462     }
1463       
1464     $fields['host'] = isset($select_host) ? $select_host->show($_POST['_host']) : null;
1465     }
1466   else if (!strlen($CONFIG['default_host']))
1467     {
1468     $input_host = new textfield(array('name' => '_host', 'id' => 'rcmloginhost', 'size' => 30));
1469     $fields['host'] = $input_host->show($_POST['_host']);
1470     }
1471
1472   $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form';
1473   $form_start = !strlen($attrib['form']) ? '<form name="form" action="./" method="post">' : '';
1474   $form_end = !strlen($attrib['form']) ? '</form>' : '';
1475   
1476   if ($fields['host'])
1477     $form_host = <<<EOF
1478     
1479 </tr><tr>
1480
1481 <td class="title"><label for="rcmloginhost">$labels[host]</label></td>
1482 <td>$fields[host]</td>
1483
1484 EOF;
1485
1486   $OUTPUT->add_gui_object('loginform', $form_name);
1487   
1488   $out = <<<EOF
1489 $form_start
1490 $SESS_HIDDEN_FIELD
1491 $fields[action]
1492 <table><tr>
1493
1494 <td class="title"><label for="rcmloginuser">$labels[user]</label></td>
1495 <td>$fields[user]</td>
1496
1497 </tr><tr>
1498
1499 <td class="title"><label for="rcmloginpwd">$labels[pass]</label></td>
1500 <td>$fields[pass]</td>
1501 $form_host
1502 </tr></table>
1503 $form_end
1504 EOF;
1505
1506   return $out;
1507   }
1508
1509
1510 function rcmail_charset_selector($attrib)
1511   {
1512   global $OUTPUT;
1513   
1514   // pass the following attributes to the form class
1515   $field_attrib = array('name' => '_charset');
1516   foreach ($attrib as $attr => $value)
1517     if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex')))
1518       $field_attrib[$attr] = $value;
1519       
1520   $charsets = array(
1521     'US-ASCII'     => 'ASCII (English)',
1522     'EUC-JP'       => 'EUC-JP (Japanese)',
1523     'EUC-KR'       => 'EUC-KR (Korean)',
1524     'BIG5'         => 'BIG5 (Chinese)',
1525     'GB2312'       => 'GB2312 (Chinese)',
1526     'ISO-2022-JP'  => 'ISO-2022-JP (Japanese)',
1527     'ISO-8859-1'   => 'ISO-8859-1 (Latin-1)',
1528     'ISO-8859-2'   => 'ISO-8895-2 (Central European)',
1529     'ISO-8859-7'   => 'ISO-8859-7 (Greek)',
1530     'ISO-8859-9'   => 'ISO-8859-9 (Turkish)',
1531     'Windows-1251' => 'Windows-1251 (Cyrillic)',
1532     'Windows-1252' => 'Windows-1252 (Western)',
1533     'Windows-1255' => 'Windows-1255 (Hebrew)',
1534     'Windows-1256' => 'Windows-1256 (Arabic)',
1535     'Windows-1257' => 'Windows-1257 (Baltic)',
1536     'UTF-8'        => 'UTF-8'
1537     );
1538
1539   $select = new select($field_attrib);
1540   $select->add(array_values($charsets), array_keys($charsets));
1541   
1542   $set = $_POST['_charset'] ? $_POST['_charset'] : $OUTPUT->get_charset();
1543   return $select->show($set);
1544   }
1545
1546
1547 // return code for search function
1548 function rcmail_search_form($attrib)
1549   {
1550   global $OUTPUT;
1551
1552   // add some labels to client
1553   rcube_add_label('searching');
1554
1555   $attrib['name'] = '_q';
1556
1557   if (empty($attrib['id']))
1558     $attrib['id'] = 'rcmqsearchbox';
1559
1560   $input_q = new textfield($attrib);
1561   $out = $input_q->show();
1562
1563   $OUTPUT->add_gui_object('qsearchbox', $attrib['id']);
1564
1565   // add form tag around text field
1566   if (empty($attrib['form']))
1567     $out = sprintf(
1568       '<form name="rcmqsearchform" action="./" '.
1569       'onsubmit="%s.command(\'search\');return false" style="display:inline;">%s</form>',
1570       JS_OBJECT_NAME,
1571       $out);
1572
1573   return $out;
1574   } 
1575
1576
1577 /****** debugging functions ********/
1578
1579
1580 /**
1581  * Print or write debug messages
1582  *
1583  * @param mixed Debug message or data
1584  */
1585 function console($msg)
1586   {
1587   if (!is_string($msg))
1588     $msg = var_export($msg, true);
1589
1590   if (!($GLOBALS['CONFIG']['debug_level'] & 4))
1591     write_log('console', $msg);
1592   else if ($GLOBALS['REMOTE_REQUEST'])
1593     print "/*\n $msg \n*/\n";
1594   else
1595     {
1596     print '<div style="background:#eee; border:1px solid #ccc; margin-bottom:3px; padding:6px"><pre>';
1597     print $msg;
1598     print "</pre></div>\n";
1599     }
1600   }
1601
1602
1603 /**
1604  * Append a line to a logfile in the logs directory.
1605  * Date will be added automatically to the line.
1606  *
1607  * @param $name Name of logfile
1608  * @param $line Line to append
1609  */
1610 function write_log($name, $line)
1611   {
1612   global $CONFIG;
1613
1614   if (!is_string($line))
1615     $line = var_export($line, true);
1616   
1617   $log_entry = sprintf("[%s]: %s\n",
1618                  date("d-M-Y H:i:s O", mktime()),
1619                  $line);
1620                  
1621   if (empty($CONFIG['log_dir']))
1622     $CONFIG['log_dir'] = $INSTALL_PATH.'logs';
1623       
1624   // try to open specific log file for writing
1625   if ($fp = @fopen($CONFIG['log_dir'].'/'.$name, 'a'))    
1626     {
1627     fwrite($fp, $log_entry);
1628     fclose($fp);
1629     }
1630   }
1631
1632
1633 function rcube_timer()
1634   {
1635   list($usec, $sec) = explode(" ", microtime());
1636   return ((float)$usec + (float)$sec);
1637   }
1638   
1639
1640 function rcube_print_time($timer, $label='Timer')
1641   {
1642   static $print_count = 0;
1643   
1644   $print_count++;
1645   $now = rcube_timer();
1646   $diff = $now-$timer;
1647   
1648   if (empty($label))
1649     $label = 'Timer '.$print_count;
1650   
1651   console(sprintf("%s: %0.4f sec", $label, $diff));
1652   }
1653
1654 ?>