source: github/program/include/main.inc @ 8c8b2a4

HEADcourier-fixdev-browser-capabilitiespdorelease-0.6release-0.7release-0.8
Last change on this file since 8c8b2a4 was 8c8b2a4, checked in by svncommit <devs@…>, 6 years ago

Allow 12 hour date to display for emails sent today (Doug Mandell).

  • Property mode set to 100644
File size: 55.4 KB
Line 
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, 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$
19
20*/
21
22require_once('lib/des.inc');
23require_once('lib/utf7.inc');
24require_once('lib/utf8.class.php');
25
26
27// define constannts for input reading
28define('RCUBE_INPUT_GET', 0x0101);
29define('RCUBE_INPUT_POST', 0x0102);
30define('RCUBE_INPUT_GPC', 0x0103);
31
32
33// register session and connect to server
34function rcmail_startup($task='mail')
35  {
36  global $sess_id, $sess_auth, $sess_user_lang;
37  global $CONFIG, $INSTALL_PATH, $BROWSER, $OUTPUT, $_SESSION, $IMAP, $DB, $JS_OBJECT_NAME;
38
39  // check client
40  $BROWSER = rcube_browser();
41
42  // load configuration
43  $CONFIG = rcmail_load_config();
44
45  // set session garbage collecting time according to session_lifetime
46  if (!empty($CONFIG['session_lifetime']))
47    ini_set('session.gc_maxlifetime', ($CONFIG['session_lifetime']) * 120);
48
49  // prepare DB connection
50  require_once('include/rcube_'.(empty($CONFIG['db_backend']) ? 'db' : $CONFIG['db_backend']).'.inc');
51 
52  $DB = new rcube_db($CONFIG['db_dsnw'], $CONFIG['db_dsnr'], $CONFIG['db_persistent']);
53  $DB->sqlite_initials = $INSTALL_PATH.'SQL/sqlite.initial.sql';
54  $DB->db_connect('w');
55
56  // we can use the database for storing session data
57  if (!$DB->is_error())
58    include_once('include/session.inc');
59
60  // init session
61  session_start();
62  $sess_id = session_id();
63
64  // create session and set session vars
65  if (!isset($_SESSION['auth_time']))
66    {
67    $_SESSION['user_lang'] = rcube_language_prop($CONFIG['locale_string']);
68    $_SESSION['auth_time'] = mktime();
69    setcookie('sessauth', rcmail_auth_hash($sess_id, $_SESSION['auth_time']));
70    }
71
72  // set session vars global
73  $sess_user_lang = rcube_language_prop($_SESSION['user_lang']);
74
75
76  // overwrite config with user preferences
77  if (is_array($_SESSION['user_prefs']))
78    $CONFIG = array_merge($CONFIG, $_SESSION['user_prefs']);
79
80
81  // reset some session parameters when changing task
82  if ($_SESSION['task'] != $task)
83    unset($_SESSION['page']);
84
85  // set current task to session
86  $_SESSION['task'] = $task;
87
88  // create IMAP object
89  if ($task=='mail')
90    rcmail_imap_init();
91
92
93  // set localization
94  if ($CONFIG['locale_string'])
95    setlocale(LC_ALL, $CONFIG['locale_string']);
96  else if ($sess_user_lang)
97    setlocale(LC_ALL, $sess_user_lang);
98
99
100  register_shutdown_function('rcmail_shutdown');
101  }
102
103
104// load roundcube configuration into global var
105function rcmail_load_config()
106  {
107        global $INSTALL_PATH;
108
109  // load config file
110        include_once('config/main.inc.php');
111        $conf = is_array($rcmail_config) ? $rcmail_config : array();
112
113  // load host-specific configuration
114  rcmail_load_host_config($conf);
115
116  $conf['skin_path'] = $conf['skin_path'] ? unslashify($conf['skin_path']) : 'skins/default';
117
118  // load db conf
119  include_once('config/db.inc.php');
120  $conf = array_merge($conf, $rcmail_config);
121
122  if (empty($conf['log_dir']))
123    $conf['log_dir'] = $INSTALL_PATH.'logs';
124  else
125    $conf['log_dir'] = unslashify($conf['log_dir']);
126
127  // set PHP error logging according to config
128  if ($conf['debug_level'] & 1)
129    {
130    ini_set('log_errors', 1);
131    ini_set('error_log', $conf['log_dir'].'/errors');
132    }
133  if ($conf['debug_level'] & 4)
134    ini_set('display_errors', 1);
135  else
136    ini_set('display_errors', 0);
137
138  return $conf;
139  }
140
141
142// load a host-specific config file if configured
143function rcmail_load_host_config(&$config)
144  {
145  $fname = NULL;
146 
147  if (is_array($config['include_host_config']))
148    $fname = $config['include_host_config'][$_SERVER['HTTP_HOST']];
149  else if (!empty($config['include_host_config']))
150    $fname = preg_replace('/[^a-z0-9\.\-_]/i', '', $_SERVER['HTTP_HOST']) . '.inc.php';
151
152   if ($fname && is_file('config/'.$fname))
153     {
154     include('config/'.$fname);
155     $config = array_merge($config, $rcmail_config);
156     }
157  }
158
159
160// create authorization hash
161function rcmail_auth_hash($sess_id, $ts)
162  {
163  global $CONFIG;
164 
165  $auth_string = sprintf('rcmail*sess%sR%s*Chk:%s;%s',
166                         $sess_id,
167                         $ts,
168                         $CONFIG['ip_check'] ? $_SERVER['REMOTE_ADDR'] : '***.***.***.***',
169                         $_SERVER['HTTP_USER_AGENT']);
170 
171  if (function_exists('sha1'))
172    return sha1($auth_string);
173  else
174    return md5($auth_string);
175  }
176
177
178// compare the auth hash sent by the client with the local session credentials
179function rcmail_authenticate_session()
180  {
181  $now = mktime();
182  $valid = ($_COOKIE['sessauth'] == rcmail_auth_hash(session_id(), $_SESSION['auth_time']) ||
183                                                $_COOKIE['sessauth'] == rcmail_auth_hash(session_id(), $_SESSION['last_auth']));
184
185  // renew auth cookie every 5 minutes (only for GET requests)
186  if (!$valid || ($_SERVER['REQUEST_METHOD']!='POST' && $now-$_SESSION['auth_time'] > 300))
187    {
188    $_SESSION['last_auth'] = $_SESSION['auth_time'];
189    $_SESSION['auth_time'] = $now;
190    setcookie('sessauth', rcmail_auth_hash(session_id(), $now));
191    }
192
193  if (!$valid)
194    write_log('timeouts',
195      "REQUEST: " . var_export($_REQUEST, true) .
196      "\nEXPECTED: " . rcmail_auth_hash(session_id(), $_SESSION['auth_time']) .
197      "\nOR LAST: " . rcmail_auth_hash(session_id(), $_SESSION['last_auth']) .
198      "\nSESSION: " . var_export($_SESSION, true));
199
200  return $valid;
201  }
202
203
204// create IMAP object and connect to server
205function rcmail_imap_init($connect=FALSE)
206  {
207  global $CONFIG, $DB, $IMAP;
208
209  $IMAP = new rcube_imap($DB);
210  $IMAP->debug_level = $CONFIG['debug_level'];
211  $IMAP->skip_deleted = $CONFIG['skip_deleted'];
212
213
214  // connect with stored session data
215  if ($connect)
216    {
217    if (!($conn = $IMAP->connect($_SESSION['imap_host'], $_SESSION['username'], decrypt_passwd($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl'])))
218      show_message('imaperror', 'error');
219     
220    rcmail_set_imap_prop();
221    }
222
223  // enable caching of imap data
224  if ($CONFIG['enable_caching']===TRUE)
225    $IMAP->set_caching(TRUE);
226
227  // set pagesize from config
228  if (isset($CONFIG['pagesize']))
229    $IMAP->set_pagesize($CONFIG['pagesize']);
230  }
231
232
233// set root dir and last stored mailbox
234// this must be done AFTER connecting to the server
235function rcmail_set_imap_prop()
236  {
237  global $CONFIG, $IMAP;
238
239  // set root dir from config
240  if (!empty($CONFIG['imap_root']))
241    $IMAP->set_rootdir($CONFIG['imap_root']);
242
243  if (is_array($CONFIG['default_imap_folders']))
244    $IMAP->set_default_mailboxes($CONFIG['default_imap_folders']);
245
246  if (!empty($_SESSION['mbox']))
247    $IMAP->set_mailbox($_SESSION['mbox']);
248  if (isset($_SESSION['page']))
249    $IMAP->set_page($_SESSION['page']);
250  }
251
252
253// do these things on script shutdown
254function rcmail_shutdown()
255  {
256  global $IMAP;
257 
258  if (is_object($IMAP))
259    {
260    $IMAP->close();
261    $IMAP->write_cache();
262    }
263   
264  // before closing the database connection, write session data
265  session_write_close();
266  }
267
268
269// destroy session data and remove cookie
270function rcmail_kill_session()
271  {
272  // save user preferences
273  $a_user_prefs = $_SESSION['user_prefs'];
274  if (!is_array($a_user_prefs))
275    $a_user_prefs = array();
276   
277  if ((isset($_SESSION['sort_col']) && $_SESSION['sort_col']!=$a_user_prefs['message_sort_col']) ||
278      (isset($_SESSION['sort_order']) && $_SESSION['sort_order']!=$a_user_prefs['message_sort_order']))
279    {
280    $a_user_prefs['message_sort_col'] = $_SESSION['sort_col'];
281    $a_user_prefs['message_sort_order'] = $_SESSION['sort_order'];
282    rcmail_save_user_prefs($a_user_prefs);
283    }
284
285  $_SESSION = array();
286  session_destroy();
287  }
288
289
290// return correct name for a specific database table
291function get_table_name($table)
292  {
293  global $CONFIG;
294 
295  // return table name if configured
296  $config_key = 'db_table_'.$table;
297
298  if (strlen($CONFIG[$config_key]))
299    return $CONFIG[$config_key];
300 
301  return $table;
302  }
303
304
305// return correct name for a specific database sequence
306// (used for Postres only)
307function get_sequence_name($sequence)
308  {
309  global $CONFIG;
310 
311  // return table name if configured
312  $config_key = 'db_sequence_'.$sequence;
313
314  if (strlen($CONFIG[$config_key]))
315    return $CONFIG[$config_key];
316 
317  return $table;
318  }
319
320
321// check the given string and returns language properties
322function rcube_language_prop($lang, $prop='lang')
323  {
324  global $INSTALL_PATH;
325  static $rcube_languages, $rcube_language_aliases, $rcube_charsets;
326
327  if (empty($rcube_languages))
328    @include($INSTALL_PATH.'program/localization/index.inc');
329   
330  // check if we have an alias for that language
331  if (!isset($rcube_languages[$lang]) && isset($rcube_language_aliases[$lang]))
332    $lang = $rcube_language_aliases[$lang];
333   
334  // try the first two chars
335  if (!isset($rcube_languages[$lang]) && strlen($lang)>2)
336    {
337    $lang = substr($lang, 0, 2);
338    $lang = rcube_language_prop($lang);
339    }
340
341  if (!isset($rcube_languages[$lang]))
342    $lang = 'en_US';
343
344  // language has special charset configured
345  if (isset($rcube_charsets[$lang]))
346    $charset = $rcube_charsets[$lang];
347  else
348    $charset = 'UTF-8';   
349
350
351  if ($prop=='charset')
352    return $charset;
353  else
354    return $lang;
355  }
356 
357
358// init output object for GUI and add common scripts
359function load_gui()
360  {
361  global $CONFIG, $OUTPUT, $COMM_PATH, $JS_OBJECT_NAME, $sess_user_lang;
362
363  // init output page
364  $OUTPUT = new rcube_html_page();
365 
366  // add common javascripts
367  $javascript = "var $JS_OBJECT_NAME = new rcube_webmail();\n";
368  $javascript .= sprintf("%s.set_env('comm_path', '%s');\n", $JS_OBJECT_NAME, str_replace('&amp;', '&', $COMM_PATH));
369
370  if (isset($CONFIG['javascript_config'] )){
371    foreach ($CONFIG['javascript_config'] as $js_config_var){
372      $javascript .= "$JS_OBJECT_NAME.set_env('$js_config_var', '" . $CONFIG[$js_config_var] . "');\n";
373    }
374  }
375
376  // don't wait for page onload. Call init at the bottom of the page (delayed)
377  $javascript_foot = "if (window.call_init)\n call_init('$JS_OBJECT_NAME');";
378
379  if (!empty($GLOBALS['_framed']))
380    $javascript .= "$JS_OBJECT_NAME.set_env('framed', true);\n";
381   
382  $OUTPUT->add_script($javascript, 'head');
383  $OUTPUT->add_script($javascript_foot, 'foot');
384  $OUTPUT->include_script('common.js');
385  $OUTPUT->include_script('app.js');
386  $OUTPUT->scripts_path = 'program/js/';
387
388  // set locale setting
389  rcmail_set_locale($sess_user_lang);
390
391  // set user-selected charset
392  if (!empty($CONFIG['charset']))
393    $OUTPUT->set_charset($CONFIG['charset']);
394
395  // add some basic label to client
396  rcube_add_label('loading','checkingmail');
397  }
398
399
400// set localization charset based on the given language
401function 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  $OUTPUT->set_charset(rcube_language_prop($lang, 'charset'));
413  }
414
415
416// auto-select IMAP host based on the posted login information
417function rcmail_autoselect_host()
418  {
419  global $CONFIG;
420 
421  $host = isset($_POST['_host']) ? get_input_value('_host', RCUBE_INPUT_POST) : $CONFIG['default_host'];
422  if (is_array($host))
423    {
424    list($user, $domain) = explode('@', get_input_value('_user', RCUBE_INPUT_POST));
425    if (!empty($domain))
426      {
427      foreach ($host as $imap_host => $mail_domains)
428        if (is_array($mail_domains) && in_array($domain, $mail_domains))
429          {
430          $host = $imap_host;
431          break;
432          }
433      }
434
435    // take the first entry if $host is still an array
436    if (is_array($host))
437      $host = array_shift($host);
438    }
439 
440  return $host;
441  }
442
443
444// perfom login to the IMAP server and to the webmail service
445function rcmail_login($user, $pass, $host=NULL)
446  {
447  global $CONFIG, $IMAP, $DB, $sess_user_lang;
448  $user_id = NULL;
449 
450  if (!$host)
451    $host = $CONFIG['default_host'];
452
453  // parse $host URL
454  $a_host = parse_url($host);
455  if ($a_host['host'])
456    {
457    $host = $a_host['host'];
458    $imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl','imaps','tls'))) ? TRUE : FALSE;
459    $imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : $CONFIG['default_port']);
460    }
461  else
462    $imap_port = $CONFIG['default_port'];
463
464
465  /* Modify username with domain if required 
466     Inspired by Marco <P0L0_notspam_binware.org>
467  */
468  // Check if we need to add domain
469  if (!empty($CONFIG['username_domain']) && !strstr($user, '@'))
470    {
471    if (is_array($CONFIG['username_domain']) && isset($CONFIG['username_domain'][$host]))
472      $user .= '@'.$CONFIG['username_domain'][$host];
473    else if (is_string($CONFIG['username_domain']))
474      $user .= '@'.$CONFIG['username_domain'];
475    }
476
477
478  // query if user already registered
479  $sql_result = $DB->query("SELECT user_id, username, language, preferences
480                            FROM ".get_table_name('users')."
481                            WHERE  mail_host=? AND (username=? OR alias=?)",
482                            $host,
483                            $user,
484                            $user);
485
486  // user already registered -> overwrite username
487  if ($sql_arr = $DB->fetch_assoc($sql_result))
488    {
489    $user_id = $sql_arr['user_id'];
490    $user = $sql_arr['username'];
491    }
492
493  // try to resolve email address from virtuser table   
494  if (!empty($CONFIG['virtuser_file']) && strstr($user, '@'))
495    $user = rcmail_email2user($user);
496
497
498  // exit if IMAP login failed
499  if (!($imap_login  = $IMAP->connect($host, $user, $pass, $imap_port, $imap_ssl)))
500    return FALSE;
501
502  // user already registered
503  if ($user_id && !empty($sql_arr))
504    {
505    // get user prefs
506    if (strlen($sql_arr['preferences']))
507      {
508      $user_prefs = unserialize($sql_arr['preferences']);
509      $_SESSION['user_prefs'] = $user_prefs;
510      array_merge($CONFIG, $user_prefs);
511      }
512
513
514    // set user specific language
515    if (strlen($sql_arr['language']))
516      $sess_user_lang = $_SESSION['user_lang'] = $sql_arr['language'];
517     
518    // update user's record
519    $DB->query("UPDATE ".get_table_name('users')."
520                SET    last_login=".$DB->now()."
521                WHERE  user_id=?",
522                $user_id);
523    }
524  // create new system user
525  else if ($CONFIG['auto_create_user'])
526    {
527    $user_id = rcmail_create_user($user, $host);
528    }
529
530  if ($user_id)
531    {
532    $_SESSION['user_id']   = $user_id;
533    $_SESSION['imap_host'] = $host;
534    $_SESSION['imap_port'] = $imap_port;
535    $_SESSION['imap_ssl']  = $imap_ssl;
536    $_SESSION['username']  = $user;
537    $_SESSION['user_lang'] = $sess_user_lang;
538    $_SESSION['password']  = encrypt_passwd($pass);
539
540    // force reloading complete list of subscribed mailboxes
541    rcmail_set_imap_prop();
542    $IMAP->clear_cache('mailboxes');
543    $IMAP->create_default_folders();
544
545    return TRUE;
546    }
547
548  return FALSE;
549  }
550
551
552// create new entry in users and identities table
553function rcmail_create_user($user, $host)
554  {
555  global $DB, $CONFIG, $IMAP;
556
557  $user_email = '';
558
559  // try to resolve user in virtusertable
560  if (!empty($CONFIG['virtuser_file']) && strstr($user, '@')==FALSE)
561    $user_email = rcmail_user2email($user);
562
563  $DB->query("INSERT INTO ".get_table_name('users')."
564              (created, last_login, username, mail_host, alias, language)
565              VALUES (".$DB->now().", ".$DB->now().", ?, ?, ?, ?)",
566              $user,
567              $host,
568              $user_email,
569                      $_SESSION['user_lang']);
570
571  if ($user_id = $DB->insert_id(get_sequence_name('users')))
572    {
573    $mail_domain = rcmail_mail_domain($host);
574   
575    if ($user_email=='')
576      $user_email = strstr($user, '@') ? $user : sprintf('%s@%s', $user, $mail_domain);
577
578    $user_name = $user!=$user_email ? $user : '';
579
580    // try to resolve the e-mail address from the virtuser table
581        if (!empty($CONFIG['virtuser_query']) &&
582        ($sql_result = $DB->query(preg_replace('/%u/', $user, $CONFIG['virtuser_query']))) &&
583        ($DB->num_rows()>0))
584      while ($sql_arr = $DB->fetch_array($sql_result))
585        {
586        $DB->query("INSERT INTO ".get_table_name('identities')."
587                   (user_id, del, standard, name, email)
588                   VALUES (?, 0, 1, ?, ?)",
589                   $user_id,
590                   $user_name,
591                   preg_replace('/^@/', $user . '@', $sql_arr[0]));
592        }
593    else
594      {
595      // also create new identity records
596      $DB->query("INSERT INTO ".get_table_name('identities')."
597                  (user_id, del, standard, name, email)
598                  VALUES (?, 0, 1, ?, ?)",
599                  $user_id,
600                  $user_name,
601                  $user_email);
602      }
603                       
604    // get existing mailboxes
605    $a_mailboxes = $IMAP->list_mailboxes();
606    }
607  else
608    {
609    raise_error(array('code' => 500,
610                      'type' => 'php',
611                      'line' => __LINE__,
612                      'file' => __FILE__,
613                      'message' => "Failed to create new user"), TRUE, FALSE);
614    }
615   
616  return $user_id;
617  }
618
619
620// load virtuser table in array
621function rcmail_getvirtualfile()
622  {
623  global $CONFIG;
624  if (empty($CONFIG['virtuser_file']) || !is_file($CONFIG['virtuser_file']))
625    return FALSE;
626 
627  // read file
628  $a_lines = file($CONFIG['virtuser_file']);
629  return $a_lines;
630  }
631
632
633// find matches of the given pattern in virtuser table
634function rcmail_findinvirtual($pattern)
635  {
636  $result = array();
637  $virtual = rcmail_getvirtualfile();
638  if ($virtual==FALSE)
639    return $result;
640
641  // check each line for matches
642  foreach ($virtual as $line)
643    {
644    $line = trim($line);
645    if (empty($line) || $line{0}=='#')
646      continue;
647     
648    if (eregi($pattern, $line))
649      $result[] = $line;
650    }
651
652  return $result;
653  }
654
655
656// resolve username with virtuser table
657function rcmail_email2user($email)
658  {
659  $user = $email;
660  $r = rcmail_findinvirtual("^$email");
661
662  for ($i=0; $i<count($r); $i++)
663    {
664    $data = $r[$i];
665    $arr = preg_split('/\s+/', $data);
666    if(count($arr)>0)
667      {
668      $user = trim($arr[count($arr)-1]);
669      break;
670      }
671    }
672
673  return $user;
674  }
675
676
677// resolve e-mail address with virtuser table
678function rcmail_user2email($user)
679  {
680  $email = "";
681  $r = rcmail_findinvirtual("$user$");
682
683  for ($i=0; $i<count($r); $i++)
684    {
685    $data=$r[$i];
686    $arr = preg_split('/\s+/', $data);
687    if (count($arr)>0)
688      {
689      $email = trim($arr[0]);
690      break;
691      }
692    }
693
694  return $email;
695  }
696
697
698function rcmail_save_user_prefs($a_user_prefs)
699  {
700  global $DB, $CONFIG, $sess_user_lang;
701 
702  $DB->query("UPDATE ".get_table_name('users')."
703              SET    preferences=?,
704                     language=?
705              WHERE  user_id=?",
706              serialize($a_user_prefs),
707              $sess_user_lang,
708              $_SESSION['user_id']);
709
710  if ($DB->affected_rows())
711    {
712    $_SESSION['user_prefs'] = $a_user_prefs; 
713    $CONFIG = array_merge($CONFIG, $a_user_prefs);
714    return TRUE;
715    }
716   
717  return FALSE;
718  }
719
720
721// overwrite action variable 
722function rcmail_overwrite_action($action)
723  {
724  global $OUTPUT, $JS_OBJECT_NAME;
725  $GLOBALS['_action'] = $action;
726
727  $OUTPUT->add_script(sprintf("\n%s.set_env('action', '%s');", $JS_OBJECT_NAME, $action)); 
728  }
729
730
731function show_message($message, $type='notice', $vars=NULL)
732  {
733  global $OUTPUT, $JS_OBJECT_NAME, $REMOTE_REQUEST;
734 
735  $framed = $GLOBALS['_framed'];
736  $command = sprintf("display_message('%s', '%s');",
737                     JQ(rcube_label(array('name' => $message, 'vars' => $vars))),
738                     $type);
739                     
740  if ($REMOTE_REQUEST)
741    return 'this.'.$command;
742 
743  else
744    $OUTPUT->add_script(sprintf("%s%s.%s\n",
745                                $framed ? sprintf('if(parent.%s)parent.', $JS_OBJECT_NAME) : '',
746                                $JS_OBJECT_NAME,
747                                $command));
748  }
749
750
751// encrypt IMAP password using DES encryption
752function encrypt_passwd($pass)
753  {
754  $cypher = des(get_des_key(), $pass, 1, 0, NULL);
755  return base64_encode($cypher);
756  }
757
758
759// decrypt IMAP password using DES encryption
760function decrypt_passwd($cypher)
761  {
762  $pass = des(get_des_key(), base64_decode($cypher), 0, 0, NULL);
763  return preg_replace('/\x00/', '', $pass);
764  }
765
766
767// return a 24 byte key for the DES encryption
768function get_des_key()
769  {
770  $key = !empty($GLOBALS['CONFIG']['des_key']) ? $GLOBALS['CONFIG']['des_key'] : 'rcmail?24BitPwDkeyF**ECB';
771  $len = strlen($key);
772 
773  // make sure the key is exactly 24 chars long
774  if ($len<24)
775    $key .= str_repeat('_', 24-$len);
776  else if ($len>24)
777    substr($key, 0, 24);
778 
779  return $key;
780  }
781
782
783// send correct response on a remote request
784function rcube_remote_response($js_code, $flush=FALSE)
785  {
786  global $OUTPUT, $CHARSET;
787  static $s_header_sent = FALSE;
788 
789  if (!$s_header_sent)
790    {
791    $s_header_sent = TRUE;
792    send_nocacheing_headers();
793    header('Content-Type: application/x-javascript; charset='.$CHARSET);
794    print '/** remote response ['.date('d/M/Y h:i:s O')."] **/\n";
795    }
796
797  // send response code
798  print rcube_charset_convert($js_code, $CHARSET, $OUTPUT->get_charset());
799
800  if ($flush)  // flush the output buffer
801    flush();
802  else         // terminate script
803    exit;
804  }
805
806
807// send correctly formatted response for a request posted to an iframe
808function rcube_iframe_response($js_code='')
809  {
810  global $OUTPUT, $JS_OBJECT_NAME;
811
812  if (!empty($js_code))
813    $OUTPUT->add_script("if(parent.$JS_OBJECT_NAME){\n" . $js_code . "\n}");
814
815  $OUTPUT->write();
816  exit;
817  }
818
819
820// read directory program/localization/ and return a list of available languages
821function rcube_list_languages()
822  {
823  global $CONFIG, $INSTALL_PATH;
824  static $sa_languages = array();
825
826  if (!sizeof($sa_languages))
827    {
828    @include($INSTALL_PATH.'program/localization/index.inc');
829
830    if ($dh = @opendir($INSTALL_PATH.'program/localization'))
831      {
832      while (($name = readdir($dh)) !== false)
833        {
834        if ($name{0}=='.' || !is_dir($INSTALL_PATH.'program/localization/'.$name))
835          continue;
836
837        if ($label = $rcube_languages[$name])
838          $sa_languages[$name] = $label ? $label : $name;
839        }
840      closedir($dh);
841      }
842    }
843  return $sa_languages;
844  }
845
846
847// add a localized label to the client environment
848function rcube_add_label()
849  {
850  global $OUTPUT, $JS_OBJECT_NAME;
851 
852  $arg_list = func_get_args();
853  foreach ($arg_list as $i => $name)
854    $OUTPUT->add_script(sprintf("%s.add_label('%s', '%s');",
855                                $JS_OBJECT_NAME,
856                                $name,
857                                JQ(rcube_label($name))));
858  }
859
860
861// remove temp files older than two day
862function rcmail_temp_gc()
863  {
864  $tmp = unslashify($CONFIG['temp_dir']);
865  $expire = mktime() - 172800;  // expire in 48 hours
866
867  if ($dir = opendir($tmp))
868    {
869    while (($fname = readdir($dir)) !== false)
870      {
871      if ($fname{0} == '.')
872        continue;
873
874      if (filemtime($tmp.'/'.$fname) < $expire)
875        @unlink($tmp.'/'.$fname);
876      }
877
878    closedir($dir);
879    }
880  }
881
882
883// remove all expired message cache records
884function rcmail_message_cache_gc()
885  {
886  global $DB, $CONFIG;
887 
888  // no cache lifetime configured
889  if (empty($CONFIG['message_cache_lifetime']))
890    return;
891 
892  // get target timestamp
893  $ts = get_offset_time($CONFIG['message_cache_lifetime'], -1);
894 
895  $DB->query("DELETE FROM ".get_table_name('messages')."
896             WHERE  created < ".$DB->fromunixtime($ts));
897  }
898
899
900/**
901 * Convert a string from one charset to another.
902 * Uses mbstring and iconv functions if possible
903 *
904 * @param  string Input string
905 * @param  string Suspected charset of the input string
906 * @param  string Target charset to convert to; defaults to $GLOBALS['CHARSET']
907 * @return Converted string
908 */
909function rcube_charset_convert($str, $from, $to=NULL)
910  {
911  global $MBSTRING;
912
913  $from = strtoupper($from);
914  $to = $to==NULL ? strtoupper($GLOBALS['CHARSET']) : strtoupper($to);
915
916  if ($from==$to || $str=='' || empty($from))
917    return $str;
918
919  // convert charset using mbstring module 
920  if ($MBSTRING)
921    {
922    $to = $to=="UTF-7" ? "UTF7-IMAP" : $to;
923    $from = $from=="UTF-7" ? "UTF7-IMAP": $from;
924
925    // return if convert succeeded
926    if (($out = mb_convert_encoding($str, $to, $from)) != '')
927      return $out;
928    }
929
930  // convert charset using iconv module 
931  if (function_exists('iconv') && $from!='UTF-7' && $to!='UTF-7')
932    return iconv($from, $to, $str);
933
934  $conv = new utf8();
935
936  // convert string to UTF-8
937  if ($from=='UTF-7')
938    $str = utf7_to_utf8($str);
939  else if (($from=='ISO-8859-1') && function_exists('utf8_encode'))
940    $str = utf8_encode($str);
941  else if ($from!='UTF-8')
942    {
943    $conv->loadCharset($from);
944    $str = $conv->strToUtf8($str);
945    }
946
947  // encode string for output
948  if ($to=='UTF-7')
949    return utf8_to_utf7($str);
950  else if ($to=='ISO-8859-1' && function_exists('utf8_decode'))
951    return utf8_decode($str);
952  else if ($to!='UTF-8')
953    {
954    $conv->loadCharset($to);
955    return $conv->utf8ToStr($str);
956    }
957
958  // return UTF-8 string
959  return $str;
960  }
961
962
963/**
964 * Replacing specials characters to a specific encoding type
965 *
966 * @param  string  Input string
967 * @param  string  Encoding type: text|html|xml|js|url
968 * @param  string  Replace mode for tags: show|replace|remove
969 * @param  boolean Convert newlines
970 * @return The quoted string
971 */
972function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE)
973  {
974  global $OUTPUT_TYPE, $OUTPUT;
975  static $html_encode_arr, $js_rep_table, $xml_rep_table;
976
977  if (!$enctype)
978    $enctype = $GLOBALS['OUTPUT_TYPE'];
979
980  // convert nbsps back to normal spaces if not html
981  if ($enctype!='html')
982    $str = str_replace(chr(160), ' ', $str);
983
984  // encode for plaintext
985  if ($enctype=='text')
986    return str_replace("\r\n", "\n", $mode=='remove' ? strip_tags($str) : $str);
987
988  // encode for HTML output
989  if ($enctype=='html')
990    {
991    if (!$html_encode_arr)
992      {
993      $html_encode_arr = get_html_translation_table(HTML_SPECIALCHARS);       
994      unset($html_encode_arr['?']);
995      }
996
997    $ltpos = strpos($str, '<');
998    $encode_arr = $html_encode_arr;
999
1000    // don't replace quotes and html tags
1001    if (($mode=='show' || $mode=='') && $ltpos!==false && strpos($str, '>', $ltpos)!==false)
1002      {
1003      unset($encode_arr['"']);
1004      unset($encode_arr['<']);
1005      unset($encode_arr['>']);
1006      unset($encode_arr['&']);
1007      }
1008    else if ($mode=='remove')
1009      $str = strip_tags($str);
1010   
1011    // avoid douple quotation of &
1012    $out = preg_replace('/&amp;([a-z]{2,5});/', '&\\1;', strtr($str, $encode_arr));
1013     
1014    return $newlines ? nl2br($out) : $out;
1015    }
1016
1017  if ($enctype=='url')
1018    return rawurlencode($str);
1019
1020  // if the replace tables for XML and JS are not yet defined
1021  if (!$js_rep_table)
1022    {
1023    $js_rep_table = $xml_rep_table = array();
1024    $xml_rep_table['&'] = '&amp;';
1025
1026    for ($c=160; $c<256; $c++)  // can be increased to support more charsets
1027      {
1028      $hex = dechex($c);
1029      $xml_rep_table[Chr($c)] = "&#$c;";
1030     
1031      if ($OUTPUT->get_charset()=='ISO-8859-1')
1032        $js_rep_table[Chr($c)] = sprintf("\u%s%s", str_repeat('0', 4-strlen($hex)), $hex);
1033      }
1034
1035    $xml_rep_table['"'] = '&quot;';
1036    }
1037
1038  // encode for XML
1039  if ($enctype=='xml')
1040    return strtr($str, $xml_rep_table);
1041
1042  // encode for javascript use
1043  if ($enctype=='js')
1044    {
1045    if ($OUTPUT->get_charset()!='UTF-8')
1046      $str = rcube_charset_convert($str, $GLOBALS['CHARSET'], $OUTPUT->get_charset());
1047     
1048    return addslashes(preg_replace(array("/\r\n/", "/\r/"), array('\n', '\n'), strtr($str, $js_rep_table)));
1049    }
1050
1051  // no encoding given -> return original string
1052  return $str;
1053  }
1054
1055/**
1056 * Quote a given string. Alias function for rep_specialchars_output
1057 * @see rep_specialchars_output
1058 */
1059function Q($str, $mode='strict', $newlines=TRUE)
1060  {
1061  return rep_specialchars_output($str, 'html', $mode, $newlines);
1062  }
1063
1064/**
1065 * Quote a given string. Alias function for rep_specialchars_output
1066 * @see rep_specialchars_output
1067 */
1068function JQ($str, $mode='strict', $newlines=TRUE)
1069  {
1070  return rep_specialchars_output($str, 'js', $mode, $newlines);
1071  }
1072
1073
1074/**
1075 * Read input value and convert it for internal use
1076 * Performs stripslashes() and charset conversion if necessary
1077 *
1078 * @param  string   Field name to read
1079 * @param  int      Source to get value from (GPC)
1080 * @param  boolean  Allow HTML tags in field value
1081 * @param  string   Charset to convert into
1082 * @return string   Field value or NULL if not available
1083 */
1084function get_input_value($fname, $source, $allow_html=FALSE, $charset=NULL)
1085  {
1086  global $OUTPUT;
1087  $value = NULL;
1088 
1089  if ($source==RCUBE_INPUT_GET && isset($_GET[$fname]))
1090    $value = $_GET[$fname];
1091  else if ($source==RCUBE_INPUT_POST && isset($_POST[$fname]))
1092    $value = $_POST[$fname];
1093  else if ($source==RCUBE_INPUT_GPC)
1094    {
1095    if (isset($_POST[$fname]))
1096      $value = $_POST[$fname];
1097    else if (isset($_GET[$fname]))
1098      $value = $_GET[$fname];
1099    else if (isset($_COOKIE[$fname]))
1100      $value = $_COOKIE[$fname];
1101    }
1102 
1103  // strip slashes if magic_quotes enabled
1104  if ((bool)get_magic_quotes_gpc())
1105    $value = stripslashes($value);
1106
1107  // remove HTML tags if not allowed   
1108  if (!$allow_html)
1109    $value = strip_tags($value);
1110 
1111  // convert to internal charset
1112  if (is_object($OUTPUT))
1113    return rcube_charset_convert($value, $OUTPUT->get_charset(), $charset);
1114  else
1115    return $value;
1116  }
1117
1118/**
1119 * Remove single and double quotes from given string
1120 */
1121function strip_quotes($str)
1122{
1123  return preg_replace('/[\'"]/', '', $str);
1124}
1125
1126
1127// ************** template parsing and gui functions **************
1128
1129
1130// return boolean if a specific template exists
1131function template_exists($name)
1132  {
1133  global $CONFIG, $OUTPUT;
1134  $skin_path = $CONFIG['skin_path'];
1135
1136  // check template file
1137  return is_file("$skin_path/templates/$name.html");
1138  }
1139
1140
1141// get page template an replace variable
1142// similar function as used in nexImage
1143function parse_template($name='main', $exit=TRUE)
1144  {
1145  global $CONFIG, $OUTPUT;
1146  $skin_path = $CONFIG['skin_path'];
1147
1148  // read template file
1149  $templ = '';
1150  $path = "$skin_path/templates/$name.html";
1151
1152  if($fp = @fopen($path, 'r'))
1153    {
1154    $templ = fread($fp, filesize($path));
1155    fclose($fp);
1156    }
1157  else
1158    {
1159    raise_error(array('code' => 500,
1160                      'type' => 'php',
1161                      'line' => __LINE__,
1162                      'file' => __FILE__,
1163                      'message' => "Error loading template for '$name'"), TRUE, TRUE);
1164    return FALSE;
1165    }
1166
1167
1168  // parse for specialtags
1169  $output = parse_rcube_xml(parse_rcube_conditions($templ));
1170 
1171  // add debug console
1172  if ($CONFIG['debug_level'] & 8)
1173    $OUTPUT->footer = '<div style="position:absolute;top:5px;left:5px;width:400px;opacity:0.8;z-index:9000;"><form name="debugform"><textarea name="console" rows="15" cols="40" style="width:400px;border:none;font-size:x-small"></textarea></form>';
1174
1175  $OUTPUT->write(trim(parse_with_globals($output)), $skin_path);
1176
1177  if ($exit)
1178    exit;
1179  }
1180
1181
1182
1183// replace all strings ($varname) with the content of the according global variable
1184function parse_with_globals($input)
1185  {
1186  $GLOBALS['__comm_path'] = $GLOBALS['COMM_PATH'];
1187  $output = preg_replace('/\$(__[a-z0-9_\-]+)/e', '$GLOBALS["\\1"]', $input);
1188  return $output;
1189  }
1190
1191
1192// parse conditional code
1193function parse_rcube_conditions($input)
1194  {
1195  if (($matches = preg_split('/<roundcube:(if|elseif|else|endif)\s+([^>]+)>/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE)) && count($matches)==4)
1196    {
1197    if (preg_match('/^(else|endif)$/i', $matches[1]))
1198      return $matches[0] . parse_rcube_conditions($matches[3]);
1199    else
1200      {
1201      $attrib = parse_attrib_string($matches[2]);
1202      if (isset($attrib['condition']))
1203        {
1204        $condmet = rcube_xml_condition($attrib['condition']);
1205        $submatches = preg_split('/<roundcube:(elseif|else|endif)\s+([^>]+)>/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE);
1206
1207                    if ($condmet)
1208                            $result = $submatches[0] . preg_replace('/.*<roundcube:endif\s+[^>]+>/is', '', $submatches[3]);
1209        else
1210          $result = "<roundcube:$submatches[1] $submatches[2]>" . $submatches[3];
1211         
1212        return $matches[0] . parse_rcube_conditions($result);
1213        }
1214      else
1215        {
1216        raise_error(array('code' => 500, 'type' => 'php', 'line' => __LINE__, 'file' => __FILE__,
1217                          'message' => "Unable to parse conditional tag " . $matches[2]), TRUE, FALSE);
1218        }
1219      }
1220    }
1221
1222  return $input;
1223  }
1224
1225 
1226/**
1227 * Determines if a given condition is met
1228 *
1229 * @return True if condition is valid, False is not
1230 */
1231function rcube_xml_condition($condition)
1232  {
1233  $condition = preg_replace(
1234      array('/session:([a-z0-9_]+)/i', '/config:([a-z0-9_]+)/i', '/request:([a-z0-9_]+)/ie'),
1235      array("\$_SESSION['\\1']", "\$GLOBALS['CONFIG']['\\1']", "get_input_value('\\1', RCUBE_INPUT_GPC)"),
1236      $condition);
1237
1238  return @eval("return (".$condition.");");
1239  }
1240
1241
1242function parse_rcube_xml($input)
1243  {
1244  $output = preg_replace('/<roundcube:([-_a-z]+)\s+([^>]+)>/Uie', "rcube_xml_command('\\1', '\\2')", $input);
1245  return $output;
1246  }
1247
1248
1249/**
1250 * Convert a xml command tag into real content
1251 */
1252function rcube_xml_command($command, $str_attrib, $add_attrib=array())
1253  {
1254  global $IMAP, $CONFIG, $OUTPUT;
1255 
1256  $command = strtolower($command);
1257  $attrib = parse_attrib_string($str_attrib) + $add_attrib;
1258 
1259  // empty output if required condition is not met
1260  if (!empty($attrib['condition']) && !rcube_xml_condition($attrib['condition']))
1261    return '';
1262
1263  // execute command
1264  switch ($command)
1265    {
1266    // return a button
1267    case 'button':
1268      if ($attrib['command'])
1269        return rcube_button($attrib);
1270      break;
1271
1272    // show a label
1273    case 'label':
1274      if ($attrib['name'] || $attrib['command'])
1275        return Q(rcube_label($attrib));
1276      break;
1277
1278    // create a menu item
1279    case 'menu':
1280      if ($attrib['command'] && $attrib['group'])
1281        rcube_menu($attrib);
1282      break;
1283
1284    // include a file
1285    case 'include':
1286      $path = realpath($CONFIG['skin_path'].$attrib['file']);
1287     
1288      if($fp = @fopen($path, 'r'))
1289        {
1290        $incl = fread($fp, filesize($path));
1291        fclose($fp);       
1292        return parse_rcube_xml($incl);
1293        }
1294      break;
1295
1296    // return code for a specific application object
1297    case 'object':
1298      $object = strtolower($attrib['name']);
1299
1300      $object_handlers = array(
1301        // GENERAL
1302        'loginform' => 'rcmail_login_form',
1303        'username'  => 'rcmail_current_username',
1304       
1305        // MAIL
1306        'mailboxlist' => 'rcmail_mailbox_list',
1307        'message' => 'rcmail_message_container',
1308        'messages' => 'rcmail_message_list',
1309        'messagecountdisplay' => 'rcmail_messagecount_display',
1310        'quotadisplay' => 'rcmail_quota_display',
1311        'messageheaders' => 'rcmail_message_headers',
1312        'messagebody' => 'rcmail_message_body',
1313        'messageattachments' => 'rcmail_message_attachments',
1314        'blockedobjects' => 'rcmail_remote_objects_msg',
1315        'messagecontentframe' => 'rcmail_messagecontent_frame',
1316        'messagepartframe' => 'rcmail_message_part_frame',
1317        'messagepartcontrols' => 'rcmail_message_part_controls',
1318        'composeheaders' => 'rcmail_compose_headers',
1319        'composesubject' => 'rcmail_compose_subject',
1320        'composebody' => 'rcmail_compose_body',
1321        'composeattachmentlist' => 'rcmail_compose_attachment_list',
1322        'composeattachmentform' => 'rcmail_compose_attachment_form',
1323        'composeattachment' => 'rcmail_compose_attachment_field',
1324        'priorityselector' => 'rcmail_priority_selector',
1325        'charsetselector' => 'rcmail_charset_selector',
1326        'editorselector' => 'rcmail_editor_selector',
1327        'searchform' => 'rcmail_search_form',
1328        'receiptcheckbox' => 'rcmail_receipt_checkbox',
1329       
1330        // ADDRESS BOOK
1331        'addresslist' => 'rcmail_contacts_list',
1332        'addressframe' => 'rcmail_contact_frame',
1333        'recordscountdisplay' => 'rcmail_rowcount_display',
1334        'contactdetails' => 'rcmail_contact_details',
1335        'contacteditform' => 'rcmail_contact_editform',
1336        'ldappublicsearch' => 'rcmail_ldap_public_search_form',
1337        'ldappublicaddresslist' => 'rcmail_ldap_public_list',
1338
1339        // USER SETTINGS
1340        'userprefs' => 'rcmail_user_prefs_form',
1341        'itentitieslist' => 'rcmail_identities_list',
1342        'identityframe' => 'rcmail_identity_frame',
1343        'identityform' => 'rcube_identity_form',
1344        'foldersubscription' => 'rcube_subscription_form',
1345        'createfolder' => 'rcube_create_folder_form',
1346        'renamefolder' => 'rcube_rename_folder_form',
1347        'composebody' => 'rcmail_compose_body'
1348      );
1349
1350     
1351      // execute object handler function
1352      if ($object_handlers[$object] && function_exists($object_handlers[$object]))
1353        return call_user_func($object_handlers[$object], $attrib);
1354       
1355      else if ($object=='productname')
1356        {
1357        $name = !empty($CONFIG['product_name']) ? $CONFIG['product_name'] : 'RoundCube Webmail';
1358        return Q($name);
1359        }
1360      else if ($object=='version')
1361        {
1362        return (string)RCMAIL_VERSION;
1363        }
1364      else if ($object=='pagetitle')
1365        {
1366        $task = $GLOBALS['_task'];
1367        $title = !empty($CONFIG['product_name']) ? $CONFIG['product_name'].' :: ' : '';
1368       
1369        if ($task=='login')
1370          $title = rcube_label(array('name' => 'welcome', 'vars' => array('product' => $CONFIG['product_name'])));
1371        else if ($task=='mail' && isset($GLOBALS['MESSAGE']['subject']))
1372          $title .= $GLOBALS['MESSAGE']['subject'];
1373        else if (isset($GLOBALS['PAGE_TITLE']))
1374          $title .= $GLOBALS['PAGE_TITLE'];
1375        else if ($task=='mail' && ($mbox_name = $IMAP->get_mailbox_name()))
1376          $title .= rcube_charset_convert($mbox_name, 'UTF-7', 'UTF-8');
1377        else
1378          $title .= ucfirst($task);
1379         
1380        return Q($title);
1381        }
1382
1383      break;
1384    }
1385
1386  return '';
1387  }
1388
1389
1390// create and register a button
1391function rcube_button($attrib)
1392  {
1393  global $CONFIG, $OUTPUT, $JS_OBJECT_NAME, $BROWSER, $COMM_PATH, $MAIN_TASKS;
1394  static $sa_buttons = array();
1395  static $s_button_count = 100;
1396 
1397  // these commands can be called directly via url
1398  $a_static_commands = array('compose', 'list');
1399 
1400  $skin_path = $CONFIG['skin_path'];
1401 
1402  if (!($attrib['command'] || $attrib['name']))
1403    return '';
1404
1405  // try to find out the button type
1406  if ($attrib['type'])
1407    $attrib['type'] = strtolower($attrib['type']);
1408  else
1409    $attrib['type'] = ($attrib['image'] || $attrib['imagepas'] || $attrib['imageact']) ? 'image' : 'link';
1410 
1411  $command = $attrib['command'];
1412 
1413  // take the button from the stack
1414  if($attrib['name'] && $sa_buttons[$attrib['name']])
1415    $attrib = $sa_buttons[$attrib['name']];
1416
1417  // add button to button stack
1418  else if($attrib['image'] || $attrib['imageact'] || $attrib['imagepas'] || $attrib['class'])
1419    {
1420    if(!$attrib['name'])
1421      $attrib['name'] = $command;
1422
1423    if (!$attrib['image'])
1424      $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact'];
1425
1426    $sa_buttons[$attrib['name']] = $attrib;
1427    }
1428
1429  // get saved button for this command/name
1430  else if ($command && $sa_buttons[$command])
1431    $attrib = $sa_buttons[$command];
1432
1433  //else
1434  //  return '';
1435
1436
1437  // set border to 0 because of the link arround the button
1438  if ($attrib['type']=='image' && !isset($attrib['border']))
1439    $attrib['border'] = 0;
1440   
1441  if (!$attrib['id'])
1442    $attrib['id'] =  sprintf('rcmbtn%d', $s_button_count++);
1443
1444  // get localized text for labels and titles
1445  if ($attrib['title'])
1446    $attrib['title'] = Q(rcube_label($attrib['title']));
1447  if ($attrib['label'])
1448    $attrib['label'] = Q(rcube_label($attrib['label']));
1449
1450  if ($attrib['alt'])
1451    $attrib['alt'] = Q(rcube_label($attrib['alt']));
1452
1453  // set title to alt attribute for IE browsers
1454  if ($BROWSER['ie'] && $attrib['title'] && !$attrib['alt'])
1455    {
1456    $attrib['alt'] = $attrib['title'];
1457    unset($attrib['title']);
1458    }
1459
1460  // add empty alt attribute for XHTML compatibility
1461  if (!isset($attrib['alt']))
1462    $attrib['alt'] = '';
1463
1464
1465  // register button in the system
1466  if ($attrib['command'])
1467    {
1468    $OUTPUT->add_script(sprintf("%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');",
1469                                $JS_OBJECT_NAME,
1470                                $command,
1471                                $attrib['id'],
1472                                $attrib['type'],
1473                                $attrib['imageact'] ? $skin_path.$attrib['imageact'] : $attrib['classact'],
1474                                $attrib['imagesel'] ? $skin_path.$attrib['imagesel'] : $attrib['classsel'],
1475                                $attrib['imageover'] ? $skin_path.$attrib['imageover'] : ''));
1476
1477    // make valid href to specific buttons
1478    if (in_array($attrib['command'], $MAIN_TASKS))
1479      $attrib['href'] = htmlentities(ereg_replace('_task=[a-z]+', '_task='.$attrib['command'], $COMM_PATH));
1480    else if (in_array($attrib['command'], $a_static_commands))
1481      $attrib['href'] = htmlentities($COMM_PATH.'&_action='.$attrib['command']);
1482    }
1483
1484  // overwrite attributes
1485  if (!$attrib['href'])
1486    $attrib['href'] = '#';
1487
1488  if ($command)
1489    $attrib['onclick'] = sprintf("return %s.command('%s','%s',this)", $JS_OBJECT_NAME, $command, $attrib['prop']);
1490   
1491  if ($command && $attrib['imageover'])
1492    {
1493    $attrib['onmouseover'] = sprintf("return %s.button_over('%s','%s')", $JS_OBJECT_NAME, $command, $attrib['id']);
1494    $attrib['onmouseout'] = sprintf("return %s.button_out('%s','%s')", $JS_OBJECT_NAME, $command, $attrib['id']);
1495    }
1496
1497  if ($command && $attrib['imagesel'])
1498    {
1499    $attrib['onmousedown'] = sprintf("return %s.button_sel('%s','%s')", $JS_OBJECT_NAME, $command, $attrib['id']);
1500    $attrib['onmouseup'] = sprintf("return %s.button_out('%s','%s')", $JS_OBJECT_NAME, $command, $attrib['id']);
1501    }
1502
1503  $out = '';
1504
1505  // generate image tag
1506  if ($attrib['type']=='image')
1507    {
1508    $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'width', 'height', 'border', 'hspace', 'vspace', 'align', 'alt'));
1509    $img_tag = sprintf('<img src="%%s"%s />', $attrib_str);
1510    $btn_content = sprintf($img_tag, $skin_path.$attrib['image']);
1511    if ($attrib['label'])
1512      $btn_content .= ' '.$attrib['label'];
1513   
1514    $link_attrib = array('href', 'onclick', 'onmouseover', 'onmouseout', 'onmousedown', 'onmouseup', 'title');
1515    }
1516  else if ($attrib['type']=='link')
1517    {
1518    $btn_content = $attrib['label'] ? $attrib['label'] : $attrib['command'];
1519    $link_attrib = array('href', 'onclick', 'title', 'id', 'class', 'style');
1520    }
1521  else if ($attrib['type']=='input')
1522    {
1523    $attrib['type'] = 'button';
1524   
1525    if ($attrib['label'])
1526      $attrib['value'] = $attrib['label'];
1527     
1528    $attrib_str = create_attrib_string($attrib, array('type', 'value', 'onclick', 'id', 'class', 'style'));
1529    $out = sprintf('<input%s disabled />', $attrib_str);
1530    }
1531
1532  // generate html code for button
1533  if ($btn_content)
1534    {
1535    $attrib_str = create_attrib_string($attrib, $link_attrib);
1536    $out = sprintf('<a%s>%s</a>', $attrib_str, $btn_content);
1537    }
1538
1539  return $out;
1540  }
1541
1542
1543function rcube_menu($attrib)
1544  {
1545 
1546  return '';
1547  }
1548
1549
1550
1551function rcube_table_output($attrib, $table_data, $a_show_cols, $id_col)
1552  {
1553  global $DB;
1554 
1555  // allow the following attributes to be added to the <table> tag
1556  $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
1557 
1558  $table = '<table' . $attrib_str . ">\n";
1559   
1560  // add table title
1561  $table .= "<thead><tr>\n";
1562
1563  foreach ($a_show_cols as $col)
1564    $table .= '<td class="'.$col.'">' . Q(rcube_label($col)) . "</td>\n";
1565
1566  $table .= "</tr></thead>\n<tbody>\n";
1567 
1568  $c = 0;
1569  if (!is_array($table_data))
1570    {
1571    while ($table_data && ($sql_arr = $DB->fetch_assoc($table_data)))
1572      {
1573      $zebra_class = $c%2 ? 'even' : 'odd';
1574
1575      $table .= sprintf('<tr id="rcmrow%d" class="contact '.$zebra_class.'">'."\n", $sql_arr[$id_col]);
1576
1577      // format each col
1578      foreach ($a_show_cols as $col)
1579        {
1580        $cont = Q($sql_arr[$col]);
1581        $table .= '<td class="'.$col.'">' . $cont . "</td>\n";
1582        }
1583
1584      $table .= "</tr>\n";
1585      $c++;
1586      }
1587    }
1588  else
1589    {
1590    foreach ($table_data as $row_data)
1591      {
1592      $zebra_class = $c%2 ? 'even' : 'odd';
1593
1594      $table .= sprintf('<tr id="rcmrow%d" class="contact '.$zebra_class.'">'."\n", $row_data[$id_col]);
1595
1596      // format each col
1597      foreach ($a_show_cols as $col)
1598        {
1599        $cont = Q($row_data[$col]);
1600        $table .= '<td class="'.$col.'">' . $cont . "</td>\n";
1601        }
1602
1603      $table .= "</tr>\n";
1604      $c++;
1605      }
1606    }
1607
1608  // complete message table
1609  $table .= "</tbody></table>\n";
1610 
1611  return $table;
1612  }
1613
1614
1615/**
1616 * Create an edit field for inclusion on a form
1617 *
1618 * @param string col field name
1619 * @param string value field value
1620 * @param array attrib HTML element attributes for field
1621 * @param string type HTML element type (default 'text')
1622 * @return string HTML field definition
1623 */
1624function rcmail_get_edit_field($col, $value, $attrib, $type='text')
1625  {
1626  $fname = '_'.$col;
1627  $attrib['name'] = $fname;
1628 
1629  if ($type=='checkbox')
1630    {
1631    $attrib['value'] = '1';
1632    $input = new checkbox($attrib);
1633    }
1634  else if ($type=='textarea')
1635    {
1636    $attrib['cols'] = $attrib['size'];
1637    $input = new textarea($attrib);
1638    }
1639  else
1640    $input = new textfield($attrib);
1641
1642  // use value from post
1643  if (!empty($_POST[$fname]))
1644    $value = $_POST[$fname];
1645
1646  $out = $input->show($value);
1647         
1648  return $out;
1649  }
1650
1651
1652// compose a valid attribute string for HTML tags
1653function create_attrib_string($attrib, $allowed_attribs=array('id', 'class', 'style'))
1654  {
1655  // allow the following attributes to be added to the <iframe> tag
1656  $attrib_str = '';
1657  foreach ($allowed_attribs as $a)
1658    if (isset($attrib[$a]))
1659      $attrib_str .= sprintf(' %s="%s"', $a, str_replace('"', '&quot;', $attrib[$a]));
1660
1661  return $attrib_str;
1662  }
1663
1664
1665// convert a HTML attribute string attributes to an associative array (name => value)
1666function parse_attrib_string($str)
1667  {
1668  $attrib = array();
1669  preg_match_all('/\s*([-_a-z]+)=["]([^"]+)["]?/i', stripslashes($str), $regs, PREG_SET_ORDER);
1670
1671  // convert attributes to an associative array (name => value)
1672  if ($regs)
1673    foreach ($regs as $attr)
1674      $attrib[strtolower($attr[1])] = $attr[2];
1675
1676  return $attrib;
1677  }
1678
1679
1680function format_date($date, $format=NULL)
1681  {
1682  global $CONFIG, $sess_user_lang;
1683 
1684  $ts = NULL;
1685 
1686  if (is_numeric($date))
1687    $ts = $date;
1688  else if (!empty($date))
1689    $ts = @strtotime($date);
1690   
1691  if (empty($ts))
1692    return '';
1693   
1694  // get user's timezone
1695  $tz = $CONFIG['timezone'];
1696  if ($CONFIG['dst_active'])
1697    $tz++;
1698
1699  // convert time to user's timezone
1700  $timestamp = $ts - date('Z', $ts) + ($tz * 3600);
1701 
1702  // get current timestamp in user's timezone
1703  $now = time();  // local time
1704  $now -= (int)date('Z'); // make GMT time
1705  $now += ($tz * 3600); // user's time
1706  $now_date = getdate($now);
1707
1708  $today_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday'], $now_date['year']);
1709  $week_limit = mktime(0, 0, 0, $now_date['mon'], $now_date['mday']-6, $now_date['year']);
1710
1711  // define date format depending on current time 
1712  if ($CONFIG['prettydate'] && !$format && $timestamp > $today_limit)
1713    return sprintf('%s %s', rcube_label('today'), date($CONFIG['date_today'] ? $CONFIG['date_today'] : 'H:i', $timestamp));
1714  else if ($CONFIG['prettydate'] && !$format && $timestamp > $week_limit)
1715    $format = $CONFIG['date_short'] ? $CONFIG['date_short'] : 'D H:i';
1716  else if (!$format)
1717    $format = $CONFIG['date_long'] ? $CONFIG['date_long'] : 'd.m.Y H:i';
1718
1719
1720  // parse format string manually in order to provide localized weekday and month names
1721  // an alternative would be to convert the date() format string to fit with strftime()
1722  $out = '';
1723  for($i=0; $i<strlen($format); $i++)
1724    {
1725    if ($format{$i}=='\\')  // skip escape chars
1726      continue;
1727   
1728    // write char "as-is"
1729    if ($format{$i}==' ' || $format{$i-1}=='\\')
1730      $out .= $format{$i};
1731    // weekday (short)
1732    else if ($format{$i}=='D')
1733      $out .= rcube_label(strtolower(date('D', $timestamp)));
1734    // weekday long
1735    else if ($format{$i}=='l')
1736      $out .= rcube_label(strtolower(date('l', $timestamp)));
1737    // month name (short)
1738    else if ($format{$i}=='M')
1739      $out .= rcube_label(strtolower(date('M', $timestamp)));
1740    // month name (long)
1741    else if ($format{$i}=='F')
1742      $out .= rcube_label(strtolower(date('F', $timestamp)));
1743    else
1744      $out .= date($format{$i}, $timestamp);
1745    }
1746 
1747  return $out;
1748  }
1749
1750
1751// ************** functions delivering gui objects **************
1752
1753
1754
1755function rcmail_message_container($attrib)
1756  {
1757  global $OUTPUT, $JS_OBJECT_NAME;
1758
1759  if (!$attrib['id'])
1760    $attrib['id'] = 'rcmMessageContainer';
1761
1762  // allow the following attributes to be added to the <table> tag
1763  $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id'));
1764  $out = '<div' . $attrib_str . "></div>";
1765 
1766  $OUTPUT->add_script("$JS_OBJECT_NAME.gui_object('message', '$attrib[id]');");
1767 
1768  return $out;
1769  }
1770
1771
1772// return the IMAP username of the current session
1773function rcmail_current_username($attrib)
1774  {
1775  global $DB;
1776  static $s_username;
1777
1778  // alread fetched 
1779  if (!empty($s_username))
1780    return $s_username;
1781
1782  // get e-mail address form default identity
1783  $sql_result = $DB->query("SELECT email AS mailto
1784                            FROM ".get_table_name('identities')."
1785                            WHERE  user_id=?
1786                            AND    standard=1
1787                            AND    del<>1",
1788                            $_SESSION['user_id']);
1789                                   
1790  if ($DB->num_rows($sql_result))
1791    {
1792    $sql_arr = $DB->fetch_assoc($sql_result);
1793    $s_username = $sql_arr['mailto'];
1794    }
1795  else if (strstr($_SESSION['username'], '@'))
1796    $s_username = $_SESSION['username'];
1797  else
1798    $s_username = $_SESSION['username'].'@'.$_SESSION['imap_host'];
1799
1800  return $s_username;
1801  }
1802
1803
1804// return the mail domain configured for the given host
1805function rcmail_mail_domain($host)
1806  {
1807  global $CONFIG;
1808
1809  $domain = $host;
1810  if (is_array($CONFIG['mail_domain']))
1811    {
1812    if (isset($CONFIG['mail_domain'][$host]))
1813      $domain = $CONFIG['mail_domain'][$host];
1814    }
1815  else if (!empty($CONFIG['mail_domain']))
1816    $domain = $CONFIG['mail_domain'];
1817
1818  return $domain;
1819  }
1820
1821
1822// return code for the webmail login form
1823function rcmail_login_form($attrib)
1824  {
1825  global $CONFIG, $OUTPUT, $JS_OBJECT_NAME, $SESS_HIDDEN_FIELD;
1826 
1827  $labels = array();
1828  $labels['user'] = rcube_label('username');
1829  $labels['pass'] = rcube_label('password');
1830  $labels['host'] = rcube_label('server');
1831 
1832  $input_user = new textfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30));
1833  $input_pass = new passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30));
1834  $input_action = new hiddenfield(array('name' => '_action', 'value' => 'login'));
1835   
1836  $fields = array();
1837  $fields['user'] = $input_user->show(get_input_value('_user', RCUBE_INPUT_POST));
1838  $fields['pass'] = $input_pass->show();
1839  $fields['action'] = $input_action->show();
1840 
1841  if (is_array($CONFIG['default_host']))
1842    {
1843    $select_host = new select(array('name' => '_host', 'id' => 'rcmloginhost'));
1844   
1845    foreach ($CONFIG['default_host'] as $key => $value)
1846    {
1847      if (!is_array($value))
1848        $select_host->add($value, (is_numeric($key) ? $value : $key));
1849      else
1850        {
1851        unset($select_host);
1852        break;
1853        }
1854    }
1855     
1856    $fields['host'] = isset($select_host) ? $select_host->show($_POST['_host']) : null;
1857    }
1858  else if (!strlen($CONFIG['default_host']))
1859    {
1860    $input_host = new textfield(array('name' => '_host', 'id' => 'rcmloginhost', 'size' => 30));
1861    $fields['host'] = $input_host->show($_POST['_host']);
1862    }
1863
1864  $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form';
1865  $form_start = !strlen($attrib['form']) ? '<form name="form" action="./" method="post">' : '';
1866  $form_end = !strlen($attrib['form']) ? '</form>' : '';
1867 
1868  if ($fields['host'])
1869    $form_host = <<<EOF
1870   
1871</tr><tr>
1872
1873<td class="title"><label for="rcmloginhost">$labels[host]</label></td>
1874<td>$fields[host]</td>
1875
1876EOF;
1877
1878  $OUTPUT->add_script("$JS_OBJECT_NAME.gui_object('loginform', '$form_name');");
1879 
1880  $out = <<<EOF
1881$form_start
1882$SESS_HIDDEN_FIELD
1883$fields[action]
1884<table><tr>
1885
1886<td class="title"><label for="rcmloginuser">$labels[user]</label></td>
1887<td>$fields[user]</td>
1888
1889</tr><tr>
1890
1891<td class="title"><label for="rcmloginpwd">$labels[pass]</label></td>
1892<td>$fields[pass]</td>
1893$form_host
1894</tr></table>
1895$form_end
1896EOF;
1897
1898  return $out;
1899  }
1900
1901
1902function rcmail_charset_selector($attrib)
1903  {
1904  global $OUTPUT;
1905 
1906  // pass the following attributes to the form class
1907  $field_attrib = array('name' => '_charset');
1908  foreach ($attrib as $attr => $value)
1909    if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex')))
1910      $field_attrib[$attr] = $value;
1911     
1912  $charsets = array(
1913    'US-ASCII'     => 'ASCII (English)',
1914    'EUC-JP'       => 'EUC-JP (Japanese)',
1915    'EUC-KR'       => 'EUC-KR (Korean)',
1916    'BIG5'         => 'BIG5 (Chinese)',
1917    'GB2312'       => 'GB2312 (Chinese)',
1918    'ISO-2022-JP'  => 'ISO-2022-JP (Japanese)',
1919    'ISO-8859-1'   => 'ISO-8859-1 (Latin-1)',
1920    'ISO-8859-2'   => 'ISO-8895-2 (Central European)',
1921    'ISO-8859-7'   => 'ISO-8859-7 (Greek)',
1922    'ISO-8859-9'   => 'ISO-8859-9 (Turkish)',
1923    'Windows-1251' => 'Windows-1251 (Cyrillic)',
1924    'Windows-1252' => 'Windows-1252 (Western)',
1925    'Windows-1255' => 'Windows-1255 (Hebrew)',
1926    'Windows-1256' => 'Windows-1256 (Arabic)',
1927    'Windows-1257' => 'Windows-1257 (Baltic)',
1928    'UTF-8'        => 'UTF-8'
1929    );
1930
1931  $select = new select($field_attrib);
1932  $select->add(array_values($charsets), array_keys($charsets));
1933 
1934  $set = $_POST['_charset'] ? $_POST['_charset'] : $OUTPUT->get_charset();
1935  return $select->show($set);
1936  }
1937
1938
1939/****** debugging functions ********/
1940
1941
1942/**
1943 * Print or write debug messages
1944 *
1945 * @param mixed Debug message or data
1946 */
1947function console($msg)
1948  {
1949  if (!is_string($msg))
1950    $msg = var_export($msg, true);
1951
1952  if (!($GLOBALS['CONFIG']['debug_level'] & 4))
1953    write_log('console', $msg);
1954  else if ($GLOBALS['REMOTE_REQUEST'])
1955    print "/*\n $msg \n*/\n";
1956  else
1957    {
1958    print '<div style="background:#eee; border:1px solid #ccc; margin-bottom:3px; padding:6px"><pre>';
1959    print $msg;
1960    print "</pre></div>\n";
1961    }
1962  }
1963
1964
1965/**
1966 * Append a line to a logfile in the logs directory.
1967 * Date will be added automatically to the line.
1968 *
1969 * @param $name Name of logfile
1970 * @param $line Line to append
1971 */
1972function write_log($name, $line)
1973  {
1974  global $CONFIG;
1975
1976  if (!is_string($line))
1977    $line = var_export($line, true);
1978 
1979  $log_entry = sprintf("[%s]: %s\n",
1980                 date("d-M-Y H:i:s O", mktime()),
1981                 $line);
1982                 
1983  if (empty($CONFIG['log_dir']))
1984    $CONFIG['log_dir'] = $INSTALL_PATH.'logs';
1985     
1986  // try to open specific log file for writing
1987  if ($fp = @fopen($CONFIG['log_dir'].'/'.$name, 'a'))   
1988    {
1989    fwrite($fp, $log_entry);
1990    fclose($fp);
1991    }
1992  }
1993
1994
1995function rcube_timer()
1996  {
1997  list($usec, $sec) = explode(" ", microtime());
1998  return ((float)$usec + (float)$sec);
1999  }
2000 
2001
2002function rcube_print_time($timer, $label='Timer')
2003  {
2004  static $print_count = 0;
2005 
2006  $print_count++;
2007  $now = rcube_timer();
2008  $diff = $now-$timer;
2009 
2010  if (empty($label))
2011    $label = 'Timer '.$print_count;
2012 
2013  console(sprintf("%s: %0.4f sec", $label, $diff));
2014  }
2015
2016?>
Note: See TracBrowser for help on using the repository browser.