From 6d969b4d9020560d3491d19a5b0487e325e9bce4 Mon Sep 17 00:00:00 2001
From: thomascube <thomas@roundcube.net>
Date: Tue, 07 Aug 2007 17:02:12 -0400
Subject: [PATCH] Documentation, code style and cleanup

---
 program/include/rcmail_template.inc |  308 ++++
 program/include/main.inc            |  515 ++++---
 bin/makedoc.sh                      |   18 
 program/include/bugs.inc            |   90 
 program/include/rcube_mdb2.inc      |    6 
 index.php                           |    1 
 /dev/null                           |  106 -
 program/include/rcube_db.inc        |    2 
 program/include/rcube_shared.inc    | 1523 ++++-------------------
 program/include/rcube_sqlite.inc    |   52 
 program/include/rcube_contacts.inc  |    9 
 program/include/rcube_html.inc      |  671 ++++++++++
 program/include/rcube_smtp.inc      |   11 
 .htaccess                           |    2 
 program/include/rcube_imap.inc      |  377 ++++-
 program/include/rcube_ldap.inc      |   41 
 16 files changed, 1,917 insertions(+), 1,815 deletions(-)

diff --git a/.htaccess b/.htaccess
index 9474105..b69de0c 100644
--- a/.htaccess
+++ b/.htaccess
@@ -4,7 +4,7 @@
 php_value	error_log	logs/errors
 php_value	upload_max_filesize	2M
 
-<FilesMatch "(\.inc|\~)$|^_">
+<FilesMatch "(\.inc|\~)$">
   Order allow,deny
   Deny from all
 </FilesMatch>
diff --git a/bin/makedoc.sh b/bin/makedoc.sh
new file mode 100755
index 0000000..5925d0a
--- /dev/null
+++ b/bin/makedoc.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+TITLE="RoundCube Classes"
+PACKAGES="Core"
+
+PATH_PROJECT=$PWD/program/include
+PATH_DOCS=$PWD/doc/phpdoc
+PATH_PHPDOC=/usr/local/php5/bin/phpdoc
+
+OUTPUTFORMAT=HTML
+CONVERTER=frames
+TEMPLATE=earthli
+PRIVATE=off
+
+# make documentation
+$PATH_PHPDOC -d $PATH_PROJECT -t $PATH_DOCS -ti "$TITLE" -dn $PACKAGES \
+-o $OUTPUTFORMAT:$CONVERTER:$TEMPLATE -pp $PRIVATE
+
diff --git a/index.php b/index.php
index 6047499..9908cf2 100644
--- a/index.php
+++ b/index.php
@@ -81,7 +81,6 @@
 require_once('include/rcube_imap.inc');
 require_once('include/bugs.inc');
 require_once('include/main.inc');
-require_once('include/cache.inc');
 require_once('PEAR.php');
 
 
diff --git a/program/include/bugs.inc b/program/include/bugs.inc
index 946a910..9d98ef4 100644
--- a/program/include/bugs.inc
+++ b/program/include/bugs.inc
@@ -4,8 +4,8 @@
  +-----------------------------------------------------------------------+
  | program/include/bugs.inc                                              |
  |                                                                       |
- | This file is part of the BQube Webmail client                         |
- | Copyright (C) 2005, BQube Dev - Switzerland                           |
+ | This file is part of the RoudCube Webmail client                      |
+ | Copyright (C) 2005-2007, RoudCube Dev - Switzerland                   |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
@@ -20,19 +20,29 @@
 */
 
 
-// throw system error and show error page
-function raise_error($arg=array(), $log=FALSE, $terminate=FALSE)
+/**
+ * Error handling and logging functions
+ *
+ * @package Core
+ */
+
+
+/**
+ * Throw system error and show error page
+ *
+ * @param array Named parameters
+ *  - code: Error code (required)
+ *  - type: Error type [php|db|imap|javascript] (required)
+ *  - message: Error message
+ *  - file: File where error occured
+ *  - line: Line where error occured
+ * @param boolean True to log the error
+ * @param boolean Terminate script execution
+ */
+function raise_error($arg=array(), $log=false, $terminate=false)
   {
   global $__page_content, $CONFIG, $OUTPUT, $ERROR_CODE, $ERROR_MESSAGE;
   
-  /* $arg keys:
-       int     code
-       string  type (php, xpath, db, imap, javascript)
-       string  message
-       sring   file
-       int     line
-  */
-
   // report bug (if not incompatible browser)
   if ($log && $arg['type'] && $arg['message'])
     log_bug($arg);
@@ -48,61 +58,53 @@
   }
 
 
-// report error
+/**
+ * Report error according to configured debug_level
+ *
+ * @param array Named parameters
+ * @see raise_error()
+ */
 function log_bug($arg_arr)
-  {
+{
   global $CONFIG, $INSTALL_PATH;
   $program = $arg_arr['type']=='xpath' ? 'XPath' : strtoupper($arg_arr['type']);
 
   // write error to local log file
   if ($CONFIG['debug_level'] & 1)
-    {
-    $log_entry = sprintf("[%s] %s Error: %s in %s on line %d\n",
-                 date("d-M-Y H:i:s O", mktime()),
-                 $program,
-                 $arg_arr['message'],
-                 $arg_arr['file'],
-                 $arg_arr['line']);
+  {
+    $log_entry = sprintf(
+      "[%s] %s Error: %s in %s on line %d\n",
+      date("d-M-Y H:i:s O", mktime()),
+      $program,
+      $arg_arr['message'],
+      $arg_arr['file'],
+      $arg_arr['line']);
                  
     if (empty($CONFIG['log_dir']))
       $CONFIG['log_dir'] = $INSTALL_PATH.'logs';
       
     // try to open specific log file for writing
     if ($fp = @fopen($CONFIG['log_dir'].'/errors', 'a'))
-    
-      {
+    {
       fwrite($fp, $log_entry);
       fclose($fp);
-      }
+    }
     else
-      {
+    {
       // send error to PHPs error handler
       trigger_error($arg_arr['message']);
-      }
     }
+  }
 
-/*
   // resport the bug to the global bug reporting system
   if ($CONFIG['debug_level'] & 2)
-    {
-    $delm = '%AC';
-    http_request(sprintf('http://roundcube.net/log/bug.php?_type=%s&_domain=%s&_server_ip=%s&_client_ip=%s&_useragent=%s&_url=%s%%3A//%s&_errors=%s%s%s%s%s',
-                 $arg_arr['type'],
-            	 $GLOBALS['HTTP_HOST'],
-                 $GLOBALS['SERVER_ADDR'],
-                 $GLOBALS['REMOTE_ADDR'],
-                 rawurlencode($GLOBALS['HTTP_USER_AGENT']),
-           		 $GLOBALS['SERVER_PORT']==43 ? 'https' : 'http',
-           		 $GLOBALS['HTTP_HOST'].$GLOBALS['REQUEST_URI'],
-           		 $arg_arr['file'], $delm,
-                 $arg_arr['line'], $delm,
-                 rawurlencode($arg_arr['message'])));
-    }
-*/
+  {
+    // TODO: Send error via HTTP
+  }
 
   // show error if debug_mode is on
   if ($CONFIG['debug_level'] & 4)
-    {
+  {
     print "<b>$program Error";
 
     if (!empty($arg_arr['file']) && !empty($arg_arr['line']))
@@ -112,7 +114,7 @@
     print nl2br($arg_arr['message']);
     print '<br />';
     flush();
-    }
   }
+}
 
 ?>
diff --git a/program/include/cache.inc b/program/include/cache.inc
deleted file mode 100644
index 06e0681..0000000
--- a/program/include/cache.inc
+++ /dev/null
@@ -1,106 +0,0 @@
-<?php
-
-/*
- +-----------------------------------------------------------------------+
- | program/include/cache.inc                                             |
- |                                                                       |
- | This file is part of the RoundCube Webmail client                     |
- | Copyright (C) 2005, RoundCube Dev, - Switzerland                      |
- | Licensed under the GNU GPL                                            |
- |                                                                       |
- | PURPOSE:                                                              |
- |   Provide access to the application cache                             |
- |                                                                       |
- +-----------------------------------------------------------------------+
- | Author: Thomas Bruederli <roundcube@gmail.com>                        |
- +-----------------------------------------------------------------------+
-
- $Id$
-
-*/
-
-
-function rcube_read_cache($key)
-  {
-  global $DB, $CACHE_KEYS;
-  
-  // query db
-  $sql_result = $DB->query("SELECT cache_id, data
-                            FROM ".get_table_name('cache')."
-                            WHERE  user_id=?
-                            AND    cache_key=?",
-                            $_SESSION['user_id'],
-                            $key);
-
-  // get cached data
-  if ($sql_arr = $DB->fetch_assoc($sql_result))
-    {
-    $data = $sql_arr['data'];
-    $CACHE_KEYS[$key] = $sql_arr['cache_id'];
-    }
-  else
-    $data = FALSE;
-
-  return $data;
-  }
-
-
-function rcube_write_cache($key, $data, $session_cache=FALSE)
-  {
-  global $DB, $CACHE_KEYS, $sess_id;
-  
-  // check if we already have a cache entry for this key
-  if (!isset($CACHE_KEYS[$key]))
-    {
-    $sql_result = $DB->query("SELECT cache_id
-                              FROM ".get_table_name('cache')."
-                              WHERE  user_id=?
-                              AND    cache_key=?",
-                              $_SESSION['user_id'],
-                              $key);
-                                     
-    if ($sql_arr = $DB->fetch_assoc($sql_result))
-      $CACHE_KEYS[$key] = $sql_arr['cache_id'];
-    else
-      $CACHE_KEYS[$key] = FALSE;
-    }
-
-  // update existing cache record
-  if ($CACHE_KEYS[$key])
-    {
-    $DB->query("UPDATE ".get_table_name('cache')."
-                SET    created=now(),
-                       data=?
-                WHERE  user_id=?
-                AND    cache_key=?",
-                $data,
-                $_SESSION['user_id'],
-                $key);
-    }
-  // add new cache record
-  else
-    {
-    $DB->query("INSERT INTO ".get_table_name('cache')."
-                (created, user_id, session_id, cache_key, data)
-                VALUES (now(), ?, ?, ?, ?)",
-                $_SESSION['user_id'],
-                $session_cache ? $sess_id : 'NULL',
-                $key,
-                $data);
-    }
-  }
-
-
-function rcube_clear_cache($key)
-  {
-  global $DB;
-
-  $DB->query("DELETE FROM ".get_table_name('cache')."
-              WHERE  user_id=?
-              AND    cache_key=?",
-              $_SESSION['user_id'],
-              $key);
-  }
-
-
-?>
\ No newline at end of file
diff --git a/program/include/main.inc b/program/include/main.inc
index e46cb53..aa1de97 100644
--- a/program/include/main.inc
+++ b/program/include/main.inc
@@ -19,6 +19,13 @@
 
 */
 
+/**
+ * RoundCube Webmail common functions
+ *
+ * @package Core
+ * @author Thomas Bruederli <roundcube@gmail.com>
+ */
+
 require_once('lib/des.inc');
 require_once('lib/utf7.inc');
 require_once('lib/utf8.class.php');
@@ -31,7 +38,12 @@
 define('RCUBE_INPUT_GPC', 0x0103);
 
 
-// register session and connect to server
+/**
+ * Initial startup function
+ * to register session, create database and imap connections
+ *
+ * @param string Current task
+ */
 function rcmail_startup($task='mail')
   {
   global $sess_id, $sess_user_lang;
@@ -48,9 +60,11 @@
     ini_set('session.gc_maxlifetime', ($CONFIG['session_lifetime']) * 120);
 
   // prepare DB connection
-  require_once('include/rcube_'.(empty($CONFIG['db_backend']) ? 'db' : $CONFIG['db_backend']).'.inc');
+  $dbwrapper = empty($CONFIG['db_backend']) ? 'db' : $CONFIG['db_backend'];
+  $dbclass = "rcube_" . $dbwrapper;
+  require_once("include/$dbclass.inc");
   
-  $DB = new rcube_db($CONFIG['db_dsnw'], $CONFIG['db_dsnr'], $CONFIG['db_persistent']);
+  $DB = new $dbclass($CONFIG['db_dsnw'], $CONFIG['db_dsnr'], $CONFIG['db_persistent']);
   $DB->sqlite_initials = $INSTALL_PATH.'SQL/sqlite.initial.sql';
   $DB->db_connect('w');
 
@@ -101,7 +115,11 @@
   }
 
 
-// load roundcube configuration into global var
+/**
+ * Load roundcube configuration array
+ *
+ * @return array Named configuration parameters
+ */
 function rcmail_load_config()
   {
   global $INSTALL_PATH;
@@ -139,7 +157,12 @@
   }
 
 
-// load a host-specific config file if configured
+/**
+ * Load a host-specific config file if configured
+ * This will merge the host specific configuration with the given one
+ *
+ * @param array Global configuration parameters
+ */
 function rcmail_load_host_config(&$config)
   {
   $fname = NULL;
@@ -157,7 +180,13 @@
   }
 
 
-// create authorization hash
+/**
+ * Create unique authorization hash
+ *
+ * @param string Session ID
+ * @param int Timestamp
+ * @return string The generated auth hash
+ */
 function rcmail_auth_hash($sess_id, $ts)
   {
   global $CONFIG;
@@ -175,7 +204,11 @@
   }
 
 
-// compare the auth hash sent by the client with the local session credentials
+/**
+ * Check the auth hash sent by the client against the local session credentials
+ *
+ * @return boolean True if valid, False if not
+ */
 function rcmail_authenticate_session()
   {
   global $CONFIG, $SESS_CLIENT_IP, $SESS_CHANGED;
@@ -206,7 +239,11 @@
   }
 
 
-// create IMAP object and connect to server
+/**
+ * Create global IMAP object and connect to server
+ *
+ * @param boolean True if connection should be established
+ */
 function rcmail_imap_init($connect=FALSE)
   {
   global $CONFIG, $DB, $IMAP, $OUTPUT;
@@ -235,8 +272,10 @@
   }
 
 
-// set root dir and last stored mailbox
-// this must be done AFTER connecting to the server
+/**
+ * Set root dir and last stored mailbox
+ * This must be done AFTER connecting to the server!
+ */
 function rcmail_set_imap_prop()
   {
   global $CONFIG, $IMAP;
@@ -255,7 +294,9 @@
   }
 
 
-// do these things on script shutdown
+/**
+ * Do these things on script shutdown
+ */
 function rcmail_shutdown()
   {
   global $IMAP;
@@ -271,7 +312,9 @@
   }
 
 
-// destroy session data and remove cookie
+/**
+ * Destroy session data and remove cookie
+ */
 function rcmail_kill_session()
   {
   // save user preferences
@@ -292,7 +335,12 @@
   }
 
 
-// return correct name for a specific database table
+/**
+ * Return correct name for a specific database table
+ *
+ * @param string Table name
+ * @return string Translated table name
+ */
 function get_table_name($table)
   {
   global $CONFIG;
@@ -307,8 +355,13 @@
   }
 
 
-// return correct name for a specific database sequence
-// (used for Postres only)
+/**
+ * Return correct name for a specific database sequence
+ * (used for Postres only)
+ *
+ * @param string Secuence name
+ * @return string Translated sequence name
+ */
 function get_sequence_name($sequence)
   {
   global $CONFIG;
@@ -323,7 +376,13 @@
   }
 
 
-// check the given string and returns language properties
+/**
+ * Check the given string and returns language properties
+ *
+ * @param string Language code
+ * @param string Peropert name
+ * @return string Property value
+ */
 function rcube_language_prop($lang, $prop='lang')
   {
   global $INSTALL_PATH;
@@ -360,7 +419,11 @@
   }
   
 
-// init output object for GUI and add common scripts
+/**
+ * Init output object for GUI and add common scripts.
+ * This will instantiate a rcmail_template object and set
+ * environment vars according to the current session and configuration
+ */
 function rcmail_load_gui()
   {
   global $CONFIG, $OUTPUT, $sess_user_lang;
@@ -399,7 +462,10 @@
   }
 
 
-// set localization charset based on the given language
+/**
+ * Set localization charset based on the given language.
+ * This also creates a global property for mbstring usage.
+ */
 function rcmail_set_locale($lang)
   {
   global $OUTPUT, $MBSTRING;
@@ -418,7 +484,11 @@
   }
 
 
-// auto-select IMAP host based on the posted login information
+/**
+ * Auto-select IMAP host based on the posted login information
+ *
+ * @return string Selected IMAP host
+ */
 function rcmail_autoselect_host()
   {
   global $CONFIG;
@@ -446,7 +516,15 @@
   }
 
 
-// perfom login to the IMAP server and to the webmail service
+/**
+ * Perfom login to the IMAP server and to the webmail service.
+ * This will also create a new user entry if auto_create_user is configured.
+ *
+ * @param string IMAP user name
+ * @param string IMAP password
+ * @param string IMAP host
+ * @return boolean True on success, False on failure
+ */
 function rcmail_login($user, $pass, $host=NULL)
   {
   global $CONFIG, $IMAP, $DB, $sess_user_lang;
@@ -575,7 +653,13 @@
   }
 
 
-// create new entry in users and identities table
+/**
+ * Create new entry in users and identities table
+ *
+ * @param string User name
+ * @param string IMAP host
+ * @return mixed New user ID or False on failure
+ */
 function rcmail_create_user($user, $host)
 {
   global $DB, $CONFIG, $IMAP;
@@ -646,7 +730,11 @@
 }
 
 
-// load virtuser table in array
+/**
+ * Load virtuser table in array
+ *
+ * @return array Virtuser table entries
+ */
 function rcmail_getvirtualfile()
   {
   global $CONFIG;
@@ -659,7 +747,12 @@
   }
 
 
-// find matches of the given pattern in virtuser table
+/**
+ * Find matches of the given pattern in virtuser table
+ * 
+ * @param string Regular expression to search for
+ * @return array Matching entries
+ */
 function rcmail_findinvirtual($pattern)
   {
   $result = array();
@@ -682,7 +775,12 @@
   }
 
 
-// resolve username with virtuser table
+/**
+ * Resolve username using a virtuser table
+ *
+ * @param string E-mail address to resolve
+ * @return string Resolved IMAP username
+ */
 function rcmail_email2user($email)
   {
   $user = $email;
@@ -703,7 +801,12 @@
   }
 
 
-// resolve e-mail address with virtuser table
+/**
+ * Resolve e-mail address from virtuser table
+ *
+ * @param string User name
+ * @return string Resolved e-mail address
+ */
 function rcmail_user2email($user)
   {
   $email = "";
@@ -724,6 +827,12 @@
   } 
 
 
+/**
+ * Write the given user prefs to the user's record
+ *
+ * @param mixed User prefs to save
+ * @return boolean True on success, False on failure
+ */
 function rcmail_save_user_prefs($a_user_prefs)
   {
   global $DB, $CONFIG, $sess_user_lang;
@@ -747,7 +856,11 @@
   }
 
 
-// overwrite action variable  
+/**
+ * Overwrite action variable
+ *
+ * @param string New action value
+ */
 function rcmail_overwrite_action($action)
   {
   global $OUTPUT;
@@ -789,7 +902,12 @@
   }
 
 
-// encrypt IMAP password using DES encryption
+/**
+ * Encrypt IMAP password using DES encryption
+ *
+ * @param string Password to encrypt
+ * @return string Encryprted string
+ */
 function encrypt_passwd($pass)
   {
   $cypher = des(get_des_key(), $pass, 1, 0, NULL);
@@ -797,7 +915,12 @@
   }
 
 
-// decrypt IMAP password using DES encryption
+/**
+ * Decrypt IMAP password using DES encryption
+ *
+ * @param string Encrypted password
+ * @return string Plain password
+ */
 function decrypt_passwd($cypher)
   {
   $pass = des(get_des_key(), base64_decode($cypher), 0, 0, NULL);
@@ -805,7 +928,11 @@
   }
 
 
-// return a 24 byte key for the DES encryption
+/**
+ * Return a 24 byte key for the DES encryption
+ *
+ * @return string DES encryption key
+ */
 function get_des_key()
   {
   $key = !empty($GLOBALS['CONFIG']['des_key']) ? $GLOBALS['CONFIG']['des_key'] : 'rcmail?24BitPwDkeyF**ECB';
@@ -821,7 +948,11 @@
   }
 
 
-// read directory program/localization/ and return a list of available languages
+/**
+ * Read directory program/localization and return a list of available languages
+ *
+ * @return array List of available localizations
+ */
 function rcube_list_languages()
   {
   global $CONFIG, $INSTALL_PATH;
@@ -848,7 +979,9 @@
   }
 
 
-// add a localized label to the client environment
+/**
+ * Add a localized label to the client environment
+ */
 function rcube_add_label()
   {
   global $OUTPUT;
@@ -859,7 +992,10 @@
   }
 
 
-// remove temp files older than two day
+/**
+ * Garbage collector function for temp files.
+ * Remove temp files older than two days
+ */
 function rcmail_temp_gc()
   {
   $tmp = unslashify($CONFIG['temp_dir']);
@@ -881,7 +1017,10 @@
   }
 
 
-// remove all expired message cache records
+/**
+ * Garbage collector for cache entries.
+ * Remove all expired message cache records
+ */
 function rcmail_message_cache_gc()
   {
   global $DB, $CONFIG;
@@ -1054,8 +1193,11 @@
   }
   
 /**
- * Quote a given string. Alias function for rep_specialchars_output
- * @see rep_specialchars_output
+ * Quote a given string.
+ * Shortcut function for rep_specialchars_output
+ *
+ * @return string HTML-quoted string
+ * @see rep_specialchars_output()
  */
 function Q($str, $mode='strict', $newlines=TRUE)
   {
@@ -1063,8 +1205,11 @@
   }
 
 /**
- * Quote a given string. Alias function for rep_specialchars_output
- * @see rep_specialchars_output
+ * Quote a given string for javascript output.
+ * Shortcut function for rep_specialchars_output
+ * 
+ * @return string JS-quoted string
+ * @see rep_specialchars_output()
  */
 function JQ($str)
   {
@@ -1116,16 +1261,24 @@
     return $value;
   }
 
+
 /**
  * Remove single and double quotes from given string
+ *
+ * @param string Input value
+ * @return string Dequoted string
  */
 function strip_quotes($str)
 {
   return preg_replace('/[\'"]/', '', $str);
 }
 
+
 /**
  * Remove new lines characters from given string
+ *
+ * @param string Input value
+ * @return string Stripped string
  */
 function strip_newlines($str)
 {
@@ -1133,7 +1286,12 @@
 }
 
 
-// return boolean if a specific template exists
+/**
+ * Check if a specific template exists
+ *
+ * @param string Template name
+ * @return boolean True if template exists
+ */
 function template_exists($name)
   {
   global $CONFIG;
@@ -1144,15 +1302,25 @@
   }
 
 
-// Wrapper for rcmail_template::parse()
-// @deprecated
+/**
+ * Wrapper for rcmail_template::parse()
+ * @deprecated
+ */
 function parse_template($name='main', $exit=true)
   {
   $GLOBALS['OUTPUT']->parse($name, $exit);
   }
 
 
-
+/**
+ * Create a HTML table based on the given data
+ *
+ * @param  array  Named table attributes
+ * @param  mixed  Table row data. Either a two-dimensional array or a valid SQL result set
+ * @param  array  List of cols to show
+ * @param  string Name of the identifier col
+ * @return string HTML table code
+ */
 function rcube_table_output($attrib, $table_data, $a_show_cols, $id_col)
   {
   global $DB;
@@ -1254,7 +1422,12 @@
   }
 
 
-// return the mail domain configured for the given host
+/**
+ * Return the mail domain configured for the given host
+ *
+ * @param string IMAP host
+ * @return string Resolved SMTP host
+ */
 function rcmail_mail_domain($host)
   {
   global $CONFIG;
@@ -1272,7 +1445,13 @@
   }
 
 
-// compose a valid attribute string for HTML tags
+/**
+ * Compose a valid attribute string for HTML tags
+ *
+ * @param array Named tag attributes
+ * @param array List of allowed attributes
+ * @return string HTML formatted attribute string
+ */
 function create_attrib_string($attrib, $allowed_attribs=array('id', 'class', 'style'))
   {
   // allow the following attributes to be added to the <iframe> tag
@@ -1285,7 +1464,12 @@
   }
 
 
-// convert a HTML attribute string attributes to an associative array (name => value)
+/**
+ * Convert a HTML attribute string attributes to an associative array (name => value)
+ *
+ * @param string Input string
+ * @return array Key-value pairs of parsed attributes
+ */
 function parse_attrib_string($str)
   {
   $attrib = array();
@@ -1300,6 +1484,14 @@
   }
 
 
+/**
+ * Convert the given date to a human readable form
+ * This uses the date formatting properties from config
+ *
+ * @param mixed Date representation (string or timestamp)
+ * @param string Date format to use
+ * @return string Formatted date string
+ */
 function format_date($date, $format=NULL)
   {
   global $CONFIG, $sess_user_lang;
@@ -1371,6 +1563,13 @@
   }
 
 
+/**
+ * Compose a valid representaion of name and e-mail address
+ *
+ * @param string E-mail address
+ * @param string Person name
+ * @return string Formatted string
+ */
 function format_email_recipient($email, $name='')
   {
   if ($name && $name != $email)
@@ -1379,206 +1578,6 @@
     return $email;
   }
 
-
-
-// ************** functions delivering gui objects **************
-
-
-
-function rcmail_message_container($attrib)
-  {
-  global $OUTPUT;
-
-  if (!$attrib['id'])
-    $attrib['id'] = 'rcmMessageContainer';
-
-  // allow the following attributes to be added to the <table> tag
-  $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id'));
-  $out = '<div' . $attrib_str . "></div>";
-  
-  $OUTPUT->add_gui_object('message', $attrib['id']);
-  
-  return $out;
-  }
-
-
-// return the IMAP username of the current session
-function rcmail_current_username($attrib)
-  {
-  global $DB;
-  static $s_username;
-
-  // alread fetched  
-  if (!empty($s_username))
-    return $s_username;
-
-  // get e-mail address form default identity
-  $sql_result = $DB->query("SELECT email AS mailto
-                            FROM ".get_table_name('identities')."
-                            WHERE  user_id=?
-                            AND    standard=1
-                            AND    del<>1",
-                            $_SESSION['user_id']);
-                                   
-  if ($DB->num_rows($sql_result))
-    {
-    $sql_arr = $DB->fetch_assoc($sql_result);
-    $s_username = $sql_arr['mailto'];
-    }
-  else if (strstr($_SESSION['username'], '@'))
-    $s_username = $_SESSION['username'];
-  else
-    $s_username = $_SESSION['username'].'@'.$_SESSION['imap_host'];
-
-  return $s_username;
-  }
-
-
-// return code for the webmail login form
-function rcmail_login_form($attrib)
-  {
-  global $CONFIG, $OUTPUT, $SESS_HIDDEN_FIELD;
-  
-  $labels = array();
-  $labels['user'] = rcube_label('username');
-  $labels['pass'] = rcube_label('password');
-  $labels['host'] = rcube_label('server');
-  
-  $input_user = new textfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30, 'autocomplete' => 'off'));
-  $input_pass = new passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30));
-  $input_action = new hiddenfield(array('name' => '_action', 'value' => 'login'));
-    
-  $fields = array();
-  $fields['user'] = $input_user->show(get_input_value('_user', RCUBE_INPUT_POST));
-  $fields['pass'] = $input_pass->show();
-  $fields['action'] = $input_action->show();
-  
-  if (is_array($CONFIG['default_host']))
-    {
-    $select_host = new select(array('name' => '_host', 'id' => 'rcmloginhost'));
-    
-    foreach ($CONFIG['default_host'] as $key => $value)
-    {
-      if (!is_array($value))
-        $select_host->add($value, (is_numeric($key) ? $value : $key));
-      else
-        {
-        unset($select_host);
-        break;
-        }
-    }
-      
-    $fields['host'] = isset($select_host) ? $select_host->show($_POST['_host']) : null;
-    }
-  else if (!strlen($CONFIG['default_host']))
-    {
-    $input_host = new textfield(array('name' => '_host', 'id' => 'rcmloginhost', 'size' => 30));
-    $fields['host'] = $input_host->show($_POST['_host']);
-    }
-
-  $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form';
-  $form_start = !strlen($attrib['form']) ? '<form name="form" action="./" method="post">' : '';
-  $form_end = !strlen($attrib['form']) ? '</form>' : '';
-  
-  if ($fields['host'])
-    $form_host = <<<EOF
-    
-</tr><tr>
-
-<td class="title"><label for="rcmloginhost">$labels[host]</label></td>
-<td>$fields[host]</td>
-
-EOF;
-
-  $OUTPUT->add_gui_object('loginform', $form_name);
-  
-  $out = <<<EOF
-$form_start
-$SESS_HIDDEN_FIELD
-$fields[action]
-<table><tr>
-
-<td class="title"><label for="rcmloginuser">$labels[user]</label></td>
-<td>$fields[user]</td>
-
-</tr><tr>
-
-<td class="title"><label for="rcmloginpwd">$labels[pass]</label></td>
-<td>$fields[pass]</td>
-$form_host
-</tr></table>
-$form_end
-EOF;
-
-  return $out;
-  }
-
-
-function rcmail_charset_selector($attrib)
-  {
-  global $OUTPUT;
-  
-  // pass the following attributes to the form class
-  $field_attrib = array('name' => '_charset');
-  foreach ($attrib as $attr => $value)
-    if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex')))
-      $field_attrib[$attr] = $value;
-      
-  $charsets = array(
-    'US-ASCII'     => 'ASCII (English)',
-    'EUC-JP'       => 'EUC-JP (Japanese)',
-    'EUC-KR'       => 'EUC-KR (Korean)',
-    'BIG5'         => 'BIG5 (Chinese)',
-    'GB2312'       => 'GB2312 (Chinese)',
-    'ISO-2022-JP'  => 'ISO-2022-JP (Japanese)',
-    'ISO-8859-1'   => 'ISO-8859-1 (Latin-1)',
-    'ISO-8859-2'   => 'ISO-8895-2 (Central European)',
-    'ISO-8859-7'   => 'ISO-8859-7 (Greek)',
-    'ISO-8859-9'   => 'ISO-8859-9 (Turkish)',
-    'Windows-1251' => 'Windows-1251 (Cyrillic)',
-    'Windows-1252' => 'Windows-1252 (Western)',
-    'Windows-1255' => 'Windows-1255 (Hebrew)',
-    'Windows-1256' => 'Windows-1256 (Arabic)',
-    'Windows-1257' => 'Windows-1257 (Baltic)',
-    'UTF-8'        => 'UTF-8'
-    );
-
-  $select = new select($field_attrib);
-  $select->add(array_values($charsets), array_keys($charsets));
-  
-  $set = $_POST['_charset'] ? $_POST['_charset'] : $OUTPUT->get_charset();
-  return $select->show($set);
-  }
-
-
-// return code for search function
-function rcmail_search_form($attrib)
-  {
-  global $OUTPUT;
-
-  // add some labels to client
-  rcube_add_label('searching');
-
-  $attrib['name'] = '_q';
-
-  if (empty($attrib['id']))
-    $attrib['id'] = 'rcmqsearchbox';
-
-  $input_q = new textfield($attrib);
-  $out = $input_q->show();
-
-  $OUTPUT->add_gui_object('qsearchbox', $attrib['id']);
-
-  // add form tag around text field
-  if (empty($attrib['form']))
-    $out = sprintf(
-      '<form name="rcmqsearchform" action="./" '.
-      'onsubmit="%s.command(\'search\');return false" style="display:inline;">%s</form>',
-      JS_OBJECT_NAME,
-      $out);
-
-  return $out;
-  } 
 
 
 /****** debugging functions ********/
@@ -1637,6 +1636,9 @@
   }
 
 
+/**
+ * @access private
+ */
 function rcube_timer()
   {
   list($usec, $sec) = explode(" ", microtime());
@@ -1644,6 +1646,9 @@
   }
   
 
+/**
+ * @access private
+ */
 function rcube_print_time($timer, $label='Timer')
   {
   static $print_count = 0;
@@ -1659,7 +1664,12 @@
   }
 
 
-// return the mailboxlist in HTML
+/**
+ * Return the mailboxlist in HTML
+ *
+ * @param array Named parameters
+ * @return string HTML code for the gui object
+ */
 function rcmail_mailbox_list($attrib)
   {
   global $IMAP, $CONFIG, $OUTPUT, $COMM_PATH;
@@ -1729,7 +1739,10 @@
 
 
 
-// create a hierarchical array of the mailbox list
+/**
+ * Create a hierarchical array of the mailbox list
+ * @access private
+ */
 function rcmail_build_folder_tree(&$arrFolders, $folder, $delm='/', $path='')
   {
   $pos = strpos($folder, $delm);
@@ -1758,7 +1771,10 @@
   }
   
 
-// return html for a structured list <ul> for the mailbox tree
+/**
+ * Return html for a structured list &lt;ul&gt; for the mailbox tree
+ * @access private
+ */
 function rcmail_render_folder_tree_html(&$arrFolders, &$special, &$mbox_name, $maxlength, $nestLevel=0)
   {
   global $COMM_PATH, $IMAP, $CONFIG, $OUTPUT;
@@ -1839,7 +1855,10 @@
   }
 
 
-// return html for a flat list <select> for the mailbox tree
+/**
+ * Return html for a flat list <select> for the mailbox tree
+ * @access private
+ */
 function rcmail_render_folder_tree_select(&$arrFolders, &$special, &$mbox_name, $maxlength, $nestLevel=0)
   {
   global $IMAP, $OUTPUT;
diff --git a/program/include/rcmail_template.inc b/program/include/rcmail_template.inc
index 3609bec..d158a01 100644
--- a/program/include/rcmail_template.inc
+++ b/program/include/rcmail_template.inc
@@ -10,7 +10,7 @@
  |                                                                       |
  | PURPOSE:                                                              |
  |   Class to handle HTML page output using a skin template.             |
- |   Extends rcube_html_page class from rcube_shared.inc                 |
+ |   Extends rcube_html_page class from rcube_html.inc                   |
  |                                                                       |
  +-----------------------------------------------------------------------+
  | Author: Thomas Bruederli <roundcube@gmail.com>                        |
@@ -20,9 +20,19 @@
 
 */
 
-require_once('include/rcube_shared.inc');
+
+/**
+ * Classes and functions for HTML output
+ *
+ * @package View
+ */
+
+require_once('include/rcube_html.inc');
 
 
+/**
+ * Class to create HTML page output using a skin template
+ */
 class rcmail_template extends rcube_html_page
 {
   var $config;
@@ -36,11 +46,14 @@
   var $object_handlers = array();
 
 
-  // PHP 5 constructor
+  /**
+   * Constructor
+   *
+   * @param array Configuration array
+   * @param string Current task
+   */
   function __construct(&$config, $task)
   {
-    parent::__construct();
-    
     $this->task = $task;
     $this->config = $config;
     $this->ajax_call = !empty($_GET['_remote']) || !empty($_POST['_remote']);
@@ -61,7 +74,10 @@
     }
   }
 
-  // PHP 4 compatibility
+  /**
+   * PHP 4 compatibility
+   * @see rcmail_template::__construct()
+   */
   function rcmail_template(&$config, $task)
   {
     $this->__construct($config, $task);
@@ -70,6 +86,10 @@
   
   /**
    * Set environment variable
+   *
+   * @param string Property name
+   * @param mixed Property value
+   * @param boolean True if this property should be added to client environment
    */
   function set_env($name, $value, $addtojs=true)
   {
@@ -135,6 +155,10 @@
 
   /**
    * Invoke display_message command
+   *
+   * @param string Message to display
+   * @param string Message type [notice|confirm|error]
+   * @param array Key-value pairs to be replaced in localized text
    */
   function show_message($message, $type='notice', $vars=NULL)
   {
@@ -211,7 +235,10 @@
   
   
   /**
-   * @override
+   * Process template and write to stdOut
+   *
+   * @param string HTML template
+   * @see rcube_html_page::write()
    */
   function write($template='')
   {
@@ -273,7 +300,7 @@
 
   /**
    * Return executable javascript code for all registered commands
-   * @private
+   * @access private
    */
   function get_js_commands()
   {
@@ -300,6 +327,7 @@
   
   /**
    * Make URLs starting with a slash point to skin directory
+   * @access private
    */
   function abs_url($str)
   {
@@ -311,8 +339,9 @@
   /*****  Template parsing methods  *****/
   
   /**
-   * Replace all strings ($varname) with the content
-   * of the according global variable.
+   * Replace all strings ($varname)
+   * with the content of the according global variable.
+   * @access private
    */
   function parse_with_globals($input)
   {
@@ -323,6 +352,7 @@
   
   /**
    * Parse for conditional tags
+   * @access private
    */
   function parse_conditions($input)
   {
@@ -361,6 +391,7 @@
    * Determines if a given condition is met
    *
    * @return True if condition is valid, False is not
+   * @access private
    */
   function check_condition($condition)
   {
@@ -379,6 +410,7 @@
    *
    * @param string Input string to parse
    * @return Altered input string
+   * @access private
    */
   function parse_xml($input)
   {
@@ -392,9 +424,10 @@
    * @param string Tag command: object,button,label, etc.
    * @param string Attribute string
    * @return Tag/Object content string
+   * @access private
    */
   function xml_command($command, $str_attrib, $add_attrib=array())
-    {
+  {
     $command = strtolower($command);
     $attrib = parse_attrib_string($str_attrib) + $add_attrib;
 
@@ -437,16 +470,16 @@
           return call_user_func($this->object_handlers[$object], $attrib);
 
         else if ($object=='productname')
-          {
+        {
           $name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'RoundCube Webmail';
           return Q($name);
-          }
+        }
         else if ($object=='version')
-          {
+        {
           return (string)RCMAIL_VERSION;
-          }
+        }
         else if ($object=='pagetitle')
-          {
+        {
           $task = $this->task;
           $title = !empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : '';
 
@@ -458,13 +491,13 @@
             $title .= ucfirst($task);
 
           return Q($title);
-          }
+        }
 
         break;
       }
 
     return '';
-    }
+  }
 
 
   /**
@@ -472,9 +505,10 @@
    *
    * @param array Button attributes
    * @return HTML button
+   * @access private
    */
   function button($attrib)
-    {
+  {
     global $CONFIG, $OUTPUT, $BROWSER, $MAIN_TASKS;
     static $sa_buttons = array();
     static $s_button_count = 100;
@@ -626,6 +660,238 @@
     return $out;
   }
 
-}
+}  // end class rcmail_template
 
-?>
\ No newline at end of file
+
+
+// ************** common functions delivering gui objects **************
+
+
+/**
+ * Builder for GUI object 'message'
+ *
+ * @param array Named tag parameters
+ * @return string HTML code for the gui object
+ */
+function rcmail_message_container($attrib)
+  {
+  global $OUTPUT;
+
+  if (!$attrib['id'])
+    $attrib['id'] = 'rcmMessageContainer';
+
+  // allow the following attributes to be added to the <table> tag
+  $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id'));
+  $out = '<div' . $attrib_str . "></div>";
+  
+  $OUTPUT->add_gui_object('message', $attrib['id']);
+  
+  return $out;
+  }
+
+
+/**
+ * GUI object 'username'
+ * Showing IMAP username of the current session
+ *
+ * @param array Named tag parameters (currently not used)
+ * @return string HTML code for the gui object
+ */
+function rcmail_current_username($attrib)
+  {
+  global $DB;
+  static $s_username;
+
+  // alread fetched  
+  if (!empty($s_username))
+    return $s_username;
+
+  // get e-mail address form default identity
+  $sql_result = $DB->query(
+    "SELECT email AS mailto
+     FROM ".get_table_name('identities')."
+     WHERE  user_id=?
+     AND    standard=1
+     AND    del<>1",
+    $_SESSION['user_id']);
+                                   
+  if ($DB->num_rows($sql_result))
+    {
+    $sql_arr = $DB->fetch_assoc($sql_result);
+    $s_username = $sql_arr['mailto'];
+    }
+  else if (strstr($_SESSION['username'], '@'))
+    $s_username = $_SESSION['username'];
+  else
+    $s_username = $_SESSION['username'].'@'.$_SESSION['imap_host'];
+
+  return $s_username;
+  }
+
+
+/**
+ * GUI object 'loginform'
+ * Returns code for the webmail login form
+ *
+ * @param array Named parameters
+ * @return string HTML code for the gui object
+ */
+function rcmail_login_form($attrib)
+  {
+  global $CONFIG, $OUTPUT, $SESS_HIDDEN_FIELD;
+  
+  $labels = array();
+  $labels['user'] = rcube_label('username');
+  $labels['pass'] = rcube_label('password');
+  $labels['host'] = rcube_label('server');
+  
+  $input_user = new textfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30, 'autocomplete' => 'off'));
+  $input_pass = new passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30));
+  $input_action = new hiddenfield(array('name' => '_action', 'value' => 'login'));
+    
+  $fields = array();
+  $fields['user'] = $input_user->show(get_input_value('_user', RCUBE_INPUT_POST));
+  $fields['pass'] = $input_pass->show();
+  $fields['action'] = $input_action->show();
+  
+  if (is_array($CONFIG['default_host']))
+    {
+    $select_host = new select(array('name' => '_host', 'id' => 'rcmloginhost'));
+    
+    foreach ($CONFIG['default_host'] as $key => $value)
+    {
+      if (!is_array($value))
+        $select_host->add($value, (is_numeric($key) ? $value : $key));
+      else
+        {
+        unset($select_host);
+        break;
+        }
+    }
+      
+    $fields['host'] = isset($select_host) ? $select_host->show($_POST['_host']) : null;
+    }
+  else if (!strlen($CONFIG['default_host']))
+    {
+    $input_host = new textfield(array('name' => '_host', 'id' => 'rcmloginhost', 'size' => 30));
+    $fields['host'] = $input_host->show($_POST['_host']);
+    }
+
+  $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form';
+  $form_start = !strlen($attrib['form']) ? '<form name="form" action="./" method="post">' : '';
+  $form_end = !strlen($attrib['form']) ? '</form>' : '';
+  
+  if ($fields['host'])
+    $form_host = <<<EOF
+    
+</tr><tr>
+
+<td class="title"><label for="rcmloginhost">$labels[host]</label></td>
+<td>$fields[host]</td>
+
+EOF;
+
+  $OUTPUT->add_gui_object('loginform', $form_name);
+  
+  $out = <<<EOF
+$form_start
+$SESS_HIDDEN_FIELD
+$fields[action]
+<table><tr>
+
+<td class="title"><label for="rcmloginuser">$labels[user]</label></td>
+<td>$fields[user]</td>
+
+</tr><tr>
+
+<td class="title"><label for="rcmloginpwd">$labels[pass]</label></td>
+<td>$fields[pass]</td>
+$form_host
+</tr></table>
+$form_end
+EOF;
+
+  return $out;
+  }
+
+
+/**
+ * GUI object 'charsetselector'
+ *
+ * @param array Named parameters for the select tag
+ * @return string HTML code for the gui object
+ */
+function rcmail_charset_selector($attrib)
+  {
+  global $OUTPUT;
+  
+  // pass the following attributes to the form class
+  $field_attrib = array('name' => '_charset');
+  foreach ($attrib as $attr => $value)
+    if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex')))
+      $field_attrib[$attr] = $value;
+      
+  $charsets = array(
+    'US-ASCII'     => 'ASCII (English)',
+    'EUC-JP'       => 'EUC-JP (Japanese)',
+    'EUC-KR'       => 'EUC-KR (Korean)',
+    'BIG5'         => 'BIG5 (Chinese)',
+    'GB2312'       => 'GB2312 (Chinese)',
+    'ISO-2022-JP'  => 'ISO-2022-JP (Japanese)',
+    'ISO-8859-1'   => 'ISO-8859-1 (Latin-1)',
+    'ISO-8859-2'   => 'ISO-8895-2 (Central European)',
+    'ISO-8859-7'   => 'ISO-8859-7 (Greek)',
+    'ISO-8859-9'   => 'ISO-8859-9 (Turkish)',
+    'Windows-1251' => 'Windows-1251 (Cyrillic)',
+    'Windows-1252' => 'Windows-1252 (Western)',
+    'Windows-1255' => 'Windows-1255 (Hebrew)',
+    'Windows-1256' => 'Windows-1256 (Arabic)',
+    'Windows-1257' => 'Windows-1257 (Baltic)',
+    'UTF-8'        => 'UTF-8'
+    );
+
+  $select = new select($field_attrib);
+  $select->add(array_values($charsets), array_keys($charsets));
+  
+  $set = $_POST['_charset'] ? $_POST['_charset'] : $OUTPUT->get_charset();
+  return $select->show($set);
+  }
+
+
+/**
+ * GUI object 'searchform'
+ * Returns code for search function
+ *
+ * @param array Named parameters
+ * @return string HTML code for the gui object
+ */
+function rcmail_search_form($attrib)
+  {
+  global $OUTPUT;
+
+  // add some labels to client
+  rcube_add_label('searching');
+
+  $attrib['name'] = '_q';
+
+  if (empty($attrib['id']))
+    $attrib['id'] = 'rcmqsearchbox';
+
+  $input_q = new textfield($attrib);
+  $out = $input_q->show();
+
+  $OUTPUT->add_gui_object('qsearchbox', $attrib['id']);
+
+  // add form tag around text field
+  if (empty($attrib['form']))
+    $out = sprintf(
+      '<form name="rcmqsearchform" action="./" '.
+      'onsubmit="%s.command(\'search\');return false" style="display:inline;">%s</form>',
+      JS_OBJECT_NAME,
+      $out);
+
+  return $out;
+  } 
+
+
+?>
diff --git a/program/include/rcube_contacts.inc b/program/include/rcube_contacts.inc
index c6dc40d..9ba965e 100644
--- a/program/include/rcube_contacts.inc
+++ b/program/include/rcube_contacts.inc
@@ -19,6 +19,12 @@
 
 */
 
+
+/**
+ * Model class for the local address book database
+ *
+ * @package Addressbook
+ */
 class rcube_contacts
 {
   var $db = null;
@@ -55,7 +61,7 @@
   /**
    * PHP 4 object constructor
    *
-   * @see  rcube_contacts::__construct
+   * @see rcube_contacts::__construct()
    */
   function rcube_contacts($dbconn, $user)
   {
@@ -125,6 +131,7 @@
    * List the current set of contact records
    *
    * @param  array  List of cols to show
+   * @param  int    Only return this number of records, use negative values for tail
    * @return array  Indexed list of contact records, each a hash array
    */
   function list_records($cols=null, $subset=0)
diff --git a/program/include/rcube_db.inc b/program/include/rcube_db.inc
index 626cb64..ed2dcc5 100644
--- a/program/include/rcube_db.inc
+++ b/program/include/rcube_db.inc
@@ -33,7 +33,7 @@
  *
  * This is a wrapper for the PEAR::DB class
  *
- * @package    RoundCube Webmail
+ * @package    Database
  * @author     David Saez Padros <david@ols.es>
  * @author     Thomas Bruederli <roundcube@gmail.com>
  * @version    1.17
diff --git a/program/include/rcube_html.inc b/program/include/rcube_html.inc
new file mode 100644
index 0000000..5ebfa32
--- /dev/null
+++ b/program/include/rcube_html.inc
@@ -0,0 +1,671 @@
+<?php
+
+/*
+ +-----------------------------------------------------------------------+
+ | rcube_html.inc                                                        |
+ |                                                                       |
+ | This file is part of the RoundCube PHP suite                          |
+ | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland                 |
+ | Licensed under the GNU GPL                                            |
+ |                                                                       |
+ | CONTENTS:                                                             |
+ |   Common Classes to create HTML output                                |
+ |                                                                       |
+ +-----------------------------------------------------------------------+
+ | Author: Thomas Bruederli <roundcube@gmail.com>                        |
+ +-----------------------------------------------------------------------+
+
+ $Id:  $
+
+*/
+
+
+/**
+ * HTML page builder class
+ *
+ * @package HTML
+ */
+class rcube_html_page
+{
+  var $scripts_path = '';
+  var $script_files = array();
+  var $scripts = array();
+  var $charset = 'UTF-8';
+  
+  var $script_tag_file = "<script type=\"text/javascript\" src=\"%s%s\"></script>\n";
+  var $script_tag      = "<script type=\"text/javascript\">\n<!--\n%s\n\n//-->\n</script>\n";
+  var $default_template = "<html>\n<head><title></title></head>\n<body></body>\n</html>";
+
+  var $title = 'RoundCube Mail';
+  var $header = '';
+  var $footer = '';
+  var $body = '';
+  var $body_attrib = array();
+  var $meta_tags = array();
+  
+  
+  /**
+   * Link an external script file
+   *
+   * @param string File URL
+   * @param string Target position [head|foot]
+   */
+  function include_script($file, $position='head')
+  {
+    static $sa_files = array();
+    
+    if (in_array($file, $sa_files))
+      return;
+      
+    if (!is_array($this->script_files[$position]))
+      $this->script_files[$position] = array();
+      
+    $this->script_files[$position][] = $file;
+  }
+  
+  /**
+   * Add inline javascript code
+   *
+   * @param string JS code snippet
+   * @param string Target position [head|head_top|foot]
+   */
+  function add_script($script, $position='head')
+  {
+    if (!isset($this->scripts[$position]))
+      $this->scripts[$position] = "\n".rtrim($script);
+    else
+      $this->scripts[$position] .= "\n".rtrim($script);
+  }
+
+  /**
+   * Add HTML code to the page header
+   */
+  function add_header($str)
+  {
+    $this->header .= "\n".$str;
+  }
+
+  /**
+   * Add HTML code to the page footer
+   * To be added right befor </body>
+   */
+  function add_footer($str)
+  {
+    $this->footer .= "\n".$str;
+  }
+
+  /**
+   * Setter for page title
+   */
+  function set_title($t)
+  {
+    $this->title = $t;
+  }
+
+
+  /**
+   * Setter for output charset.
+   * To be specified in a meta tag and sent as http-header
+   */
+  function set_charset($charset)
+  {
+    global $MBSTRING;
+    
+    $this->charset = $charset;
+    
+    if ($MBSTRING && function_exists("mb_internal_encoding"))
+      {
+      if(!@mb_internal_encoding($charset))
+        $MBSTRING = FALSE;
+      }
+  }
+
+  /**
+   * Getter for output charset
+   */
+  function get_charset()
+  {
+    return $this->charset;
+  }
+
+
+  /**
+   * Reset all saved properties
+   */
+  function reset()
+  {
+    $this->script_files = array();
+    $this->scripts = array();
+    $this->title = '';
+    $this->header = '';
+    $this->footer = '';
+  }
+
+
+  /**
+   * Process template and write to stdOut
+   *
+   * @param string HTML template
+   * @param string Base for absolute paths
+   */
+  function write($templ='', $base_path='')
+  {
+    $output = empty($templ) ? $this->default_template : trim($templ);
+    
+    // replace specialchars in content
+    $__page_title = Q($this->title, 'show', FALSE);
+    $__page_header = $__page_body = $__page_footer = '';
+    
+    
+    // include meta tag with charset
+    if (!empty($this->charset))
+    {
+      header('Content-Type: text/html; charset='.$this->charset, true);
+      $__page_header = '<meta http-equiv="content-type" content="text/html; charset='.$this->charset.'" />'."\n";
+    }
+  
+  
+    // definition of the code to be placed in the document header and footer
+    if (is_array($this->script_files['head']))
+      foreach ($this->script_files['head'] as $file)
+        $__page_header .= sprintf($this->script_tag_file, $this->scripts_path, $file);
+
+    $head_script = $this->scripts['head_top'] . $this->scripts['head'];
+    if (!empty($head_script))
+      $__page_header .= sprintf($this->script_tag, $head_script);
+
+    if (!empty($this->header))
+      $__page_header .= $this->header;
+
+    if (is_array($this->script_files['foot']))
+      foreach ($this->script_files['foot'] as $file)
+        $__page_footer .= sprintf($this->script_tag_file, $this->scripts_path, $file);
+
+    if (!empty($this->scripts['foot']))
+      $__page_footer .= sprintf($this->script_tag, $this->scripts['foot']);
+      
+    if (!empty($this->footer))
+      $__page_footer .= $this->footer;
+
+    // find page header
+    if ($hpos = strpos(strtolower($output), '</head>'))
+      $__page_header .= "\n";
+    else 
+    {
+      if (!is_numeric($hpos))
+        $hpos = strpos(strtolower($output), '<body');
+      if (!is_numeric($hpos) && ($hpos = strpos(strtolower($output), '<html')))
+      {
+        while($output[$hpos]!='>')
+          $hpos++;
+        $hpos++;
+      }
+  
+      $__page_header = "<head>\n<title>$__page_title</title>\n$__page_header\n</head>\n";
+    }
+  
+    // add page hader
+    if ($hpos)
+      $output = substr($output,0,$hpos) . $__page_header . substr($output,$hpos,strlen($output));
+    else
+      $output = $__page_header . $output;
+  
+  
+    // find page body
+    if($bpos = strpos(strtolower($output), '<body'))
+    {
+      while($output[$bpos]!='>') $bpos++;
+      $bpos++;
+    }
+    else
+      $bpos = strpos(strtolower($output), '</head>')+7;
+  
+    // add page body
+    if($bpos && $__page_body)
+      $output = substr($output,0,$bpos) . "\n$__page_body\n" . substr($output,$bpos,strlen($output));
+  
+  
+    // find and add page footer
+    $output_lc = strtolower($output);
+    if(($fpos = strrstr($output_lc, '</body>')) ||
+       ($fpos = strrstr($output_lc, '</html>')))
+      $output = substr($output, 0, $fpos) . "$__page_footer\n" . substr($output, $fpos);
+    else
+      $output .= "\n$__page_footer";
+  
+  
+    // reset those global vars
+    $__page_header = $__page_footer = '';
+  
+  
+    // correct absolute paths in images and other tags
+    $output = preg_replace('/(src|href|background)=(["\']?)(\/[a-z0-9_\-]+)/Ui', "\\1=\\2$base_path\\3", $output);
+    $output = str_replace('$__skin_path', $base_path, $output);
+  
+    print rcube_charset_convert($output, 'UTF-8', $this->charset);
+  }
+    
+}  // end class rcube_html_page
+
+
+
+/**
+ * Base class to build a HTML for element
+ *
+ * @package HTML
+ */
+class rcube_form_element
+  {
+  var $uppertags = FALSE;
+  var $upperattribs = FALSE;
+  var $upperprops = FALSE;
+  var $newline = FALSE;
+  
+  var $attrib = array();
+
+
+  /**
+   * Create string with saved attributes
+   *
+   * @return string HTML formatted tag attributes
+   */
+  function create_attrib_string()
+  {
+    if (!sizeof($this->attrib))
+      return '';
+
+    if ($this->name!='')
+      $this->attrib['name'] = $this->name;
+
+    $attrib_arr = array();
+    foreach ($this->attrib as $key => $value)
+    {
+      // don't output some internally used attributes
+      if (in_array($key, array('form', 'quicksearch')))
+        continue;
+
+      // skip if size if not numeric
+      if (($key=='size' && !is_numeric($value)))
+        continue;
+        
+      // skip empty eventhandlers
+      if ((strpos($key,'on')===0 && $value==''))
+        continue;
+
+      // encode textarea content
+      if ($key=='value')
+        $value = Q($value, 'strict', FALSE);
+
+      // attributes with no value
+      if (in_array($key, array('checked', 'multiple', 'disabled', 'selected')))
+      {
+        if ($value)
+          $attrib_arr[] = $key;
+      }
+      // don't convert size of value attribute
+      else if ($key=='value')
+        $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $value, 'value');
+        
+      // regular tag attributes
+      else
+        $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $this->_conv_case($value, 'value'));
+    }
+
+    return sizeof($attrib_arr) ? ' '.implode(' ', $attrib_arr) : '';
+  }
+    
+    
+  /**
+   * Convert tags and attributes to upper-/lowercase
+   *
+   * @param string Input string
+   * @param string Value type (can either be "tag" or "attrib")
+   * @return string Converted output string
+   * @access private
+   */
+  function _conv_case($str, $type='attrib')
+    {
+    if ($type == 'tag')
+      return $this->uppertags ? strtoupper($str) : strtolower($str);
+    else if ($type == 'attrib')
+      return $this->upperattribs ? strtoupper($str) : strtolower($str);
+    else if ($type == 'value')
+      return $this->upperprops ? strtoupper($str) : strtolower($str);
+    }    
+  }
+
+
+/**
+ * Builder for an <input> field
+ *
+ * @package HTML
+ */
+class input_field extends rcube_form_element
+{
+  var $type = 'text';
+  
+  /**
+   * Constructor
+   * @param array Named tag attributes
+   */
+  function input_field($attrib=array())
+  {
+    if (is_array($attrib))
+      $this->attrib = $attrib;
+
+    if ($attrib['type'])
+      $this->type = $attrib['type'];    
+
+    if ($attrib['newline'])
+      $this->newline = TRUE;    
+  }  
+
+  /**
+   * Compose input tag
+   *
+   * @param string Field value
+   * @param array  Additional tag attributes
+   * @return string Final HTML code
+   */
+  function show($value=NULL, $attrib=NULL)
+  {
+    // overwrite object attributes
+    if (is_array($attrib))
+      $this->attrib = array_merge($this->attrib, $attrib);
+
+    // set value attribute
+    if ($value!==NULL)
+      $this->attrib['value'] = $value;
+
+    $this->attrib['type'] = $this->type;
+
+    // return final tag
+    return sprintf(
+      '<%s%s />%s',
+      $this->_conv_case('input', 'tag'),
+      $this->create_attrib_string(),
+      ($this->newline ? "\n" : ""));
+  }  
+}
+
+
+/**
+ * Builder for a <input type="text"> field
+ *
+ * @package HTML
+ */
+class textfield extends input_field
+{
+  var $type = 'text';
+}
+
+/**
+ * Builder for a <input type="password"> field
+ *
+ * @package HTML
+ */
+class passwordfield extends input_field
+{
+  var $type = 'password';
+}
+
+/**
+ * Builder for <input type="radio"> fields
+ *
+ * @package HTML
+ */
+class radiobutton extends input_field
+{
+  var $type = 'radio';
+}
+
+/**
+ * Builder for <input type="checkbox"> fields
+ *
+ * @package HTML
+ */
+class checkbox extends input_field
+{
+  var $type = 'checkbox';
+
+
+  /**
+   * Compose input tag
+   *
+   * @param string Field value
+   * @param array  Additional tag attributes
+   * @return string Final HTML code
+   */
+  function show($value='', $attrib=NULL)
+  {
+    // overwrite object attributes
+    if (is_array($attrib))
+      $this->attrib = array_merge($this->attrib, $attrib);    
+
+    $this->attrib['type'] = $this->type;
+
+    if ($value && (string)$value==(string)$this->attrib['value'])
+      $this->attrib['checked'] = TRUE;
+    else
+      $this->attrib['checked'] = FALSE;
+
+    // return final tag
+    return sprintf(
+      '<%s%s />%s',
+      $this->_conv_case('input', 'tag'),
+      $this->create_attrib_string(),
+      ($this->newline ? "\n" : ""));
+  }
+}
+
+
+/**
+ * Builder for a <textarea> field
+ *
+ * @package HTML
+ */
+class textarea extends rcube_form_element
+  {
+
+  /**
+   * Constructor
+   * @param array Named tag attributes
+   */
+  function textarea($attrib=array())
+  {
+    $this->attrib = $attrib;
+
+    if ($attrib['newline'])
+      $this->newline = TRUE;
+  }
+  
+  /**
+   * Create HTML representation for this field
+   *
+   * @param string Field value
+   * @param array  Additional tag attributes
+   * @return string Final HTML code
+   */
+  function show($value='', $attrib=NULL)
+  {
+    // overwrite object attributes
+    if (is_array($attrib))
+      $this->attrib = array_merge($this->attrib, $attrib);
+    
+    // take value attribute as content
+    if ($value=='')
+      $value = $this->attrib['value'];
+    
+    // make shure we don't print the value attribute
+    if (isset($this->attrib['value']))
+      unset($this->attrib['value']);
+
+    if (!empty($value) && !isset($this->attrib['mce_editable']))
+      $value = Q($value, 'strict', FALSE);
+
+    // return final tag
+    return sprintf(
+      '<%s%s>%s</%s>%s',
+      $this->_conv_case('textarea', 'tag'),
+      $this->create_attrib_string(),
+      $value,
+      $this->_conv_case('textarea', 'tag'),
+      ($this->newline ? "\n" : ""));       
+  }
+}
+
+
+/**
+ * Builder for group of hidden form fields
+ *
+ * @package HTML
+ */
+class hiddenfield extends rcube_form_element
+{
+  var $fields_arr = array();
+  var $newline = TRUE;
+
+  /**
+   * Constructor
+   *
+   * @param array Named tag attributes
+   */
+  function hiddenfield($attrib=NULL)
+  {
+    if (is_array($attrib))
+      $this->add($attrib);
+  }
+
+  /**
+   * Add a hidden field to this instance
+   * @param array Named tag attributes
+   */
+  function add($attrib)
+  {
+    $this->fields_arr[] = $attrib;
+  }
+
+
+  /**
+   * Create HTML code for the hidden fields
+   *
+   * @return string Final HTML code
+   */
+  function show()
+  {
+    $out = '';
+    foreach ($this->fields_arr as $attrib)
+    {
+      $this->attrib = $attrib;
+      $this->attrib['type'] = 'hidden';
+      
+      $out .= sprintf(
+        '<%s%s />%s',
+        $this->_conv_case('input', 'tag'),
+        $this->create_attrib_string(),
+        ($this->newline ? "\n" : ""));
+    }
+
+    return $out;
+  }
+}
+
+
+/**
+ * Builder for HTML drop-down menus
+ * Syntax:<pre>
+ * // create instance. arguments are used to set attributes of select-tag
+ * $select = new select(array('name' => 'fieldname'));
+ *
+ * // add one option
+ * $select->add('Switzerland', 'CH');
+ *
+ * // add multiple options
+ * $select->add(array('Switzerland','Germany'), array('CH','DE'));
+ *
+ * // generate pulldown with selection 'Switzerland'  and return html-code
+ * // as second argument the same attributes available to instanciate can be used
+ * print $select->show('CH');
+ * </pre>
+ *
+ * @package HTML
+ */
+class select extends rcube_form_element
+{
+  var $options = array();
+
+  /**
+   * Constructor
+   *
+   * @param array Named tag attributes
+   */
+  function select($attrib=NULL)
+  {
+    if (is_array($attrib))
+      $this->attrib = $attrib;
+
+    if ($attrib['newline'])
+      $this->newline = TRUE;
+  }
+
+
+  /**
+   * Add one ore more menu options
+   *
+   * @param mixed Array with names or single option name
+   * @param mixed Array with values or single option value
+   */
+  function add($names, $values=NULL)
+  {
+    if (is_array($names))
+    {
+      foreach ($names as $i => $text)
+        $this->options[] = array('text' => $text, 'value' => (string)$values[$i]);
+    }
+    else
+      $this->options[] = array('text' => $names, 'value' => (string)$values);
+  }
+
+
+  /**
+   * Generate HTML code for this drop-down menu
+   *
+   * @param string Value of the selected option
+   * @param array Additional tag attributes
+   * @return string Final HTML code
+   */
+  function show($select=array(), $attrib=NULL)
+  {
+    $options_str = "\n";
+    $value_str = $this->_conv_case(' value="%s"', 'attrib');
+    
+    if (!is_array($select))
+      $select = array((string)$select);
+
+    foreach ($this->options as $option)
+    {
+      $selected = ((isset($option['value']) &&
+                    in_array($option['value'], $select, TRUE)) ||
+                   (in_array($option['text'], $select, TRUE))) ?
+        $this->_conv_case(' selected', 'attrib') : '';
+                   
+      $options_str .= sprintf("<%s%s%s>%s</%s>\n",
+                             $this->_conv_case('option', 'tag'),
+                             !empty($option['value']) ? sprintf($value_str, Q($option['value'])) : '',
+                             $selected, 
+                             Q($option['text'], 'strict', FALSE),
+                             $this->_conv_case('option', 'tag'));
+    }
+
+    // return final tag
+    return sprintf('<%s%s>%s</%s>%s',
+                   $this->_conv_case('select', 'tag'),
+                   $this->create_attrib_string(),
+                   $options_str,
+                   $this->_conv_case('select', 'tag'),
+                   ($this->newline ? "\n" : ""));    
+  }
+}
+
+
+?>
diff --git a/program/include/rcube_imap.inc b/program/include/rcube_imap.inc
index 9ca6cf5..0cfda15 100644
--- a/program/include/rcube_imap.inc
+++ b/program/include/rcube_imap.inc
@@ -21,7 +21,7 @@
 */
 
 
-/**
+/*
  * Obtain classes from the Iloha IMAP library
  */
 require_once('lib/imap.inc');
@@ -33,13 +33,13 @@
  *
  * This is a wrapper that implements the Iloha IMAP Library (IIL)
  *
- * @package    RoundCube Webmail
+ * @package    Mail
  * @author     Thomas Bruederli <roundcube@gmail.com>
  * @version    1.36
  * @link       http://ilohamail.org
  */
 class rcube_imap
-  {
+{
   var $db;
   var $conn;
   var $root_ns = '';
@@ -70,7 +70,7 @@
   /**
    * Object constructor
    *
-   * @param  object  Database connection
+   * @param object DB Database connection
    */
   function __construct($db_conn)
     {
@@ -294,6 +294,7 @@
 
   /**
    * Return the saved search set as hash array
+   * @return array Search set
    */
   function get_search_set()
     {
@@ -382,8 +383,8 @@
    * Private method for mailbox listing
    *
    * @return  array   List of mailboxes/folders
+   * @see     rcube_imap::list_mailboxes()
    * @access  private
-   * @see     rcube_imap::list_mailboxes
    */
   function _list_mailboxes($root='', $filter='*')
     {
@@ -413,8 +414,8 @@
    * @param   string   Mailbox/folder name
    * @param   string   Mode for count [ALL|UNSEEN|RECENT]
    * @param   boolean  Force reading from server and update cache
-   * @return  number   Number of messages
-   * @access  public   
+   * @return  int      Number of messages
+   * @access  public
    */
   function messagecount($mbox_name='', $mode='ALL', $force=FALSE)
     {
@@ -427,7 +428,7 @@
    * Private method for getting nr of messages
    *
    * @access  private
-   * @see     rcube_imap::messagecount
+   * @see     rcube_imap::messagecount()
    */
   function _messagecount($mailbox='', $mode='ALL', $force=FALSE)
     {
@@ -496,7 +497,7 @@
    * convert mailbox name with root dir first
    *
    * @param   string   Mailbox/folder name
-   * @param   number   Current page to list
+   * @param   int      Current page to list
    * @param   string   Header field to sort by
    * @param   string   Sort order [ASC|DESC]
    * @return  array    Indexed array with message header objects
@@ -616,7 +617,7 @@
    *
    * @param   string   Mailbox/folder name
    * @param   array    List of message ids to list
-   * @param   number   Current page to list
+   * @param   int      Current page to list
    * @param   string   Header field to sort by
    * @param   string   Sort order [ASC|DESC]
    * @return  array    Indexed array with message header objects
@@ -633,7 +634,7 @@
    * Private method for listing a set of message headers
    *
    * @access  private
-   * @see     rcube_imap::list_header_set
+   * @see     rcube_imap::list_header_set()
    */
   function _list_header_set($mailbox, $msgs, $page=NULL, $sort_field=NULL, $sort_order=NULL)
     {
@@ -671,7 +672,7 @@
   /**
    * Helper function to get first and last index of the requested set
    *
-   * @param  number  message count
+   * @param  int     message count
    * @param  mixed   page number to show, or string 'all'
    * @return array   array with two values: first index, last index
    * @access private
@@ -713,7 +714,7 @@
    * @param  string  Message index to fetch
    * @param  array   Reference to message headers array
    * @param  array   Array with cache index
-   * @return number  Number of deleted messages
+   * @return int     Number of deleted messages
    * @access private
    */
   function _fetch_headers($mailbox, $msgs, &$a_msg_headers, $cache_key)
@@ -815,6 +816,9 @@
     }
 
 
+  /**
+   * @access private
+   */
   function sync_header_index($mailbox)
     {
     $cache_key = $mailbox.'.msg';
@@ -927,6 +931,8 @@
   
   /**
    * Refresh saved search set
+   *
+   * @return array Current search set
    */
   function refresh_search()
     {
@@ -973,8 +979,8 @@
    * Fetch body structure from the IMAP server and build
    * an object structure similar to the one generated by PEAR::Mail_mimeDecode
    *
-   * @param Int Message UID to fetch
-   * @return object Standard object tree or False on failure
+   * @param int Message UID to fetch
+   * @return object stdClass Message part tree or False on failure
    */
   function &get_structure($uid)
     {
@@ -1136,7 +1142,7 @@
   /**
    * Return a flat array with references to all parts, indexed by part numbers
    *
-   * @param object Message body structure
+   * @param object rcube_message_part Message body structure
    * @return Array with part number -> object pairs
    */
   function get_mime_numbers(&$structure)
@@ -1150,7 +1156,7 @@
   /**
    * Helper method for recursive calls
    *
-   * @access 
+   * @access private
    */
   function _get_part_numbers(&$part, &$a_parts)
     {
@@ -1168,9 +1174,9 @@
    *
    * @param  int    Message UID
    * @param  string Part number
-   * @param  object Part object created by get_structure()
+   * @param  object rcube_message_part Part object created by get_structure()
    * @param  mixed  True to print part, ressource to write part contents in
-   * @return Message/part body if not printed
+   * @return string Message/part body if not printed
    */
   function &get_message_part($uid, $part=1, $o_part=NULL, $print=NULL)
     {
@@ -1223,8 +1229,8 @@
    * Fetch message body of a specific message from the server
    *
    * @param  int    Message UID
-   * @return Message/part body
-   * @see    ::get_message_part()
+   * @return string Message/part body
+   * @see    rcube_imap::get_message_part()
    */
   function &get_body($uid, $part=1)
     {
@@ -1236,15 +1242,15 @@
    * Returns the whole message source as string
    *
    * @param int  Message UID
-   * @return Message source string
+   * @return string Message source string
    */
   function &get_raw_body($uid)
     {
     if (!($msg_id = $this->_uid2id($uid)))
       return FALSE;
 
-	$body = iil_C_FetchPartHeader($this->conn, $this->mailbox, $msg_id, NULL);
-	$body .= iil_C_HandlePartBody($this->conn, $this->mailbox, $msg_id, NULL, 1);
+    $body = iil_C_FetchPartHeader($this->conn, $this->mailbox, $msg_id, NULL);
+    $body .= iil_C_HandlePartBody($this->conn, $this->mailbox, $msg_id, NULL, 1);
 
     return $body;    
     }
@@ -1260,9 +1266,9 @@
     if (!($msg_id = $this->_uid2id($uid)))
       return FALSE;
 
-	print iil_C_FetchPartHeader($this->conn, $this->mailbox, $msg_id, NULL);
-	flush();
-	iil_C_HandlePartBody($this->conn, $this->mailbox, $msg_id, NULL, 2);
+    print iil_C_FetchPartHeader($this->conn, $this->mailbox, $msg_id, NULL);
+    flush();
+    iil_C_HandlePartBody($this->conn, $this->mailbox, $msg_id, NULL, 2);
     }
 
 
@@ -1271,7 +1277,7 @@
    *
    * @param mixed  Message UIDs as array or as comma-separated string
    * @param string Flag to set: SEEN, UNDELETED, DELETED, RECENT, ANSWERED, DRAFT
-   * @return True on success, False on failure
+   * @return boolean True on success, False on failure
    */
   function set_flag($uids, $flag)
     {
@@ -1324,7 +1330,13 @@
     }
 
 
-  // append a mail message (source) to a specific mailbox
+  /**
+   * Append a mail message (source) to a specific mailbox
+   *
+   * @param string Target mailbox
+   * @param string Message source
+   * @return boolean True on success, False on error
+   */
   function save_message($mbox_name, &$message)
     {
     $mbox_name = stripslashes($mbox_name);
@@ -1344,7 +1356,14 @@
     }
 
 
-  // move a message from one mailbox to another
+  /**
+   * Move a message from one mailbox to another
+   *
+   * @param string List of UIDs to move, separated by comma
+   * @param string Target mailbox
+   * @param string Source mailbox
+   * @return boolean True on success, False on error
+   */
   function move_message($uids, $to_mbox, $from_mbox='')
     {
     $to_mbox = stripslashes($to_mbox);
@@ -1408,7 +1427,13 @@
     }
 
 
-  // mark messages as deleted and expunge mailbox
+  /**
+   * Mark messages as deleted and expunge mailbox
+   *
+   * @param string List of UIDs to move, separated by comma
+   * @param string Source mailbox
+   * @return boolean True on success, False on error
+   */
   function delete_message($uids, $mbox_name='')
     {
     $mbox_name = stripslashes($mbox_name);
@@ -1460,7 +1485,12 @@
     }
 
 
-  // clear all messages in a specific mailbox
+  /**
+   * Clear all messages in a specific mailbox
+   *
+   * @param string Mailbox name
+   * @return int Above 0 on success
+   */
   function clear_mailbox($mbox_name=NULL)
     {
     $mbox_name = stripslashes($mbox_name);
@@ -1487,7 +1517,13 @@
     }
 
 
-  // send IMAP expunge command and clear cache
+  /**
+   * Send IMAP expunge command and clear cache
+   *
+   * @param string Mailbox name
+   * @param boolean False if cache should not be cleared
+   * @return boolean True on success
+   */
   function expunge($mbox_name='', $clear_cache=TRUE)
     {
     $mbox_name = stripslashes($mbox_name);
@@ -1496,7 +1532,12 @@
     }
 
 
-  // send IMAP expunge command and clear cache
+  /**
+   * Send IMAP expunge command and clear cache
+   *
+   * @see rcube_imap::expunge()
+   * @access private
+   */
   function _expunge($mailbox, $clear_cache=TRUE)
     {
     $result = iil_C_Expunge($this->conn, $mailbox);
@@ -1520,7 +1561,7 @@
    * Get a list of all folders available on the IMAP server
    * 
    * @param string IMAP root dir
-   * @return array Inbdexed array with folder names 
+   * @return array Indexed array with folder names
    */
   function list_unsubscribed($root='')
     {
@@ -1547,8 +1588,10 @@
 
 
   /**
-   * Get quota
+   * Get mailbox quota information
    * added by Nuny
+   * 
+   * @return mixed Quota info or False if not supported
    */
   function get_quota()
     {
@@ -1560,9 +1603,12 @@
 
 
   /**
-   * subscribe to a specific mailbox(es)
+   * Subscribe to a specific mailbox(es)
+   *
+   * @param string Mailbox name(s)
+   * @return boolean True on success
    */ 
-  function subscribe($mbox_name, $mode='subscribe')
+  function subscribe($mbox_name)
     {
     if (is_array($mbox_name))
       $a_mboxes = $mbox_name;
@@ -1575,7 +1621,10 @@
 
 
   /**
-   * unsubscribe mailboxes
+   * Unsubscribe mailboxes
+   *
+   * @param string Mailbox name(s)
+   * @return boolean True on success
    */
   function unsubscribe($mbox_name)
     {
@@ -1625,7 +1674,7 @@
    *
    * @param string Mailbox to rename (as utf-7 string)
    * @param string New mailbox name (as utf-7 string)
-   * @param string Name of the renames mailbox, false on error
+   * @return string Name of the renames mailbox, False on error
    */
   function rename_mailbox($mbox_name, $new_name)
     {
@@ -1668,7 +1717,10 @@
 
 
   /**
-   * remove mailboxes from server
+   * Remove mailboxes from server
+   *
+   * @param string Mailbox name
+   * @return boolean True on success
    */
   function delete_mailbox($mbox_name)
     {
@@ -1736,7 +1788,9 @@
    *   internal caching methods
    * --------------------------------*/
 
-
+  /**
+   * @access private
+   */
   function set_caching($set)
     {
     if ($set && is_object($this->db))
@@ -1745,7 +1799,9 @@
       $this->caching_enabled = FALSE;
     }
 
-
+  /**
+   * @access private
+   */
   function get_cache($key)
     {
     // read cache
@@ -1758,7 +1814,9 @@
     return $this->cache[$key];
     }
 
-
+  /**
+   * @access private
+   */
   function update_cache($key, $data)
     {
     $this->cache[$key] = $data;
@@ -1766,7 +1824,9 @@
     $this->cache_changes[$key] = TRUE;
     }
 
-
+  /**
+   * @access private
+   */
   function write_cache()
     {
     if ($this->caching_enabled && $this->cache_changed)
@@ -1779,7 +1839,9 @@
       }    
     }
 
-
+  /**
+   * @access private
+   */
   function clear_cache($key=NULL)
     {
     if ($key===NULL)
@@ -1799,8 +1861,9 @@
       }
     }
 
-
-
+  /**
+   * @access private
+   */
   function _read_cache_record($key)
     {
     $cache_data = FALSE;
@@ -1823,10 +1886,12 @@
         }
       }
 
-    return $cache_data;    
+    return $cache_data;
     }
-    
 
+  /**
+   * @access private
+   */
   function _write_cache_record($key, $data)
     {
     if (!$this->db)
@@ -1875,7 +1940,9 @@
       }
     }
 
-
+  /**
+   * @access private
+   */
   function _clear_cache_record($key)
     {
     $this->db->query(
@@ -1893,8 +1960,13 @@
    * --------------------------------*/
    
 
-  // checks if the cache is up-to-date
-  // return: -3 = off, -2 = incomplete, -1 = dirty
+  /**
+   * Checks if the cache is up-to-date
+   *
+   * @param string Mailbox name
+   * @param string Internal cache key
+   * @return int -3 = off, -2 = incomplete, -1 = dirty
+   */
   function check_cache_status($mailbox, $cache_key)
     {
     if (!$this->caching_enabled)
@@ -1926,8 +1998,9 @@
       return -2;
     }
 
-
-
+  /**
+   * @access private
+   */
   function get_message_cache($key, $from, $to, $sort_field, $sort_order)
     {
     $cache_key = "$key:$from:$to:$sort_field:$sort_order";
@@ -1961,7 +2034,9 @@
     return $this->cache[$cache_key];
     }
 
-
+  /**
+   * @access private
+   */
   function &get_cached_message($key, $uid, $struct=false)
     {
     if (!$this->caching_enabled)
@@ -1993,7 +2068,9 @@
     return $this->cache[$internal_key][$uid];
     }
 
-   
+  /**
+   * @access private
+   */  
   function get_message_cache_index($key, $force=FALSE, $sort_col='idx', $sort_order='ASC')
     {
     static $sa_message_index = array();
@@ -2021,7 +2098,9 @@
     return $sa_message_index[$key];
     }
 
-
+  /**
+   * @access private
+   */
   function add_message_cache($key, $index, $headers, $struct=null)
     {
     if (!$this->caching_enabled || empty($key) || !is_object($headers) || empty($headers->uid))
@@ -2073,7 +2152,9 @@
       }
     }
     
-    
+  /**
+   * @access private
+   */
   function remove_message_cache($key, $index)
     {
     $this->db->query(
@@ -2086,7 +2167,9 @@
       $index);
     }
 
-
+  /**
+   * @access private
+   */
   function clear_message_cache($key, $start_index=1)
     {
     $this->db->query(
@@ -2106,7 +2189,14 @@
    *   encoding/decoding methods
    * --------------------------------*/
 
-  
+  /**
+   * Split an address list into a structured array list
+   *
+   * @param string  Input string
+   * @param int     List only this number of addresses
+   * @param boolean Decode address strings
+   * @return array  Indexed list of addresses
+   */
   function decode_address_list($input, $max=null, $decode=true)
     {
     $a = $this->_parse_address_list($input, $decode);
@@ -2142,6 +2232,13 @@
     }
 
 
+  /**
+   * Decode a message header value
+   *
+   * @param string  Header value
+   * @param boolean Remove quotes if necessary
+   * @return string Decoded string
+   */
   function decode_header($input, $remove_quotes=FALSE)
     {
     $str = $this->decode_mime_string((string)$input);
@@ -2155,7 +2252,10 @@
   /**
    * Decode a mime-encoded string to internal charset
    *
-   * @access static
+   * @param string  Header value
+   * @param string  Fallback charset if none specified
+   * @return string Decoded string
+   * @static
    */
   function decode_mime_string($input, $fallback=null)
     {
@@ -2187,7 +2287,7 @@
   /**
    * Decode a part of a mime-encoded string
    *
-   * @access static
+   * @access private
    */
   function _decode_mime_string_part($str)
     {
@@ -2215,6 +2315,14 @@
     }
 
 
+  /**
+   * Decode a mime part
+   *
+   * @param string Input string
+   * @param string Part encoding
+   * @return string Decoded string
+   * @access private
+   */
   function mime_decode($input, $encoding='7bit')
     {
     switch (strtolower($encoding))
@@ -2237,25 +2345,13 @@
     }
 
 
-  function mime_encode($input, $encoding='7bit')
-    {
-    switch ($encoding)
-      {
-      case 'quoted-printable':
-        return quoted_printable_encode($input);
-        break;
-
-      case 'base64':
-        return base64_encode($input);
-        break;
-
-      default:
-        return $input;
-      }
-    }
-
-
-  // convert body chars according to the ctype_parameters
+  /**
+   * Convert body charset to UTF-8 according to the ctype_parameters
+   *
+   * @param string Part body to decode
+   * @param string Charset to convert from
+   * @return string Content converted to internal charset
+   */
   function charset_decode($body, $ctype_param)
     {
     if (is_array($ctype_param) && !empty($ctype_param['charset']))
@@ -2266,6 +2362,33 @@
     }
 
 
+  /**
+   * Translate UID to message ID
+   *
+   * @param int    Message UID
+   * @param string Mailbox name
+   * @return int   Message ID
+   */
+  function get_id($uid, $mbox_name=NULL) 
+    {
+      $mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
+      return $this->_uid2id($uid, $mailbox);
+    }
+
+
+  /**
+   * Translate message number to UID
+   *
+   * @param int    Message ID
+   * @param string Mailbox name
+   * @return int   Message UID
+   */
+  function get_uid($id,$mbox_name=NULL)
+    {
+      $mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
+      return $this->_id2uid($id, $mailbox);
+    }
+
 
 
   /* --------------------------------
@@ -2273,6 +2396,9 @@
    * --------------------------------*/
 
 
+  /**
+   * @access private
+   */
   function _mod_mailbox($mbox_name, $mode='in')
     {
     if ((!empty($this->root_ns) && $this->root_ns == $mbox_name) || $mbox_name == 'INBOX')
@@ -2287,7 +2413,10 @@
     }
 
 
-  // sort mailboxes first by default folders and then in alphabethical order
+  /**
+   * Sort mailboxes first by default folders and then in alphabethical order
+   * @access private
+   */
   function _sort_mailbox_list($a_folders)
     {
     $a_out = $a_defaults = array();
@@ -2296,10 +2425,10 @@
     foreach($a_folders as $i => $folder)
       {
       if ($folder{0}=='.')
-      	continue;
+        continue;
 
       if (($p = array_search(strtolower($folder), $this->default_folders_lc))!==FALSE)
-      	$a_defaults[$p] = $folder;
+        $a_defaults[$p] = $folder;
       else
         $a_out[] = $folder;
       }
@@ -2310,18 +2439,9 @@
     return array_merge($a_defaults, $a_out);
     }
 
-  function get_id($uid, $mbox_name=NULL) 
-    {
-      $mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
-      return $this->_uid2id($uid, $mailbox);
-    }
-  
-  function get_uid($id,$mbox_name=NULL)
-    {
-      $mailbox = $mbox_name ? $this->_mod_mailbox($mbox_name) : $this->mailbox;
-      return $this->_id2uid($id, $mailbox);
-    }
-
+  /**
+   * @access private
+   */
   function _uid2id($uid, $mbox_name=NULL)
     {
     if (!$mbox_name)
@@ -2333,6 +2453,9 @@
     return $this->uid_id_map[$mbox_name][$uid];
     }
 
+  /**
+   * @access private
+   */
   function _id2uid($id, $mbox_name=NULL)
     {
     if (!$mbox_name)
@@ -2342,7 +2465,10 @@
     }
 
 
-  // parse string or array of server capabilities and put them in internal array
+  /**
+   * Parse string or array of server capabilities and put them in internal array
+   * @access private
+   */
   function _parse_capability($caps)
     {
     if (!is_array($caps))
@@ -2369,7 +2495,10 @@
     }
 
 
-  // subscribe/unsubscribe a list of mailboxes and update local cache
+  /**
+   * Subscribe/unsubscribe a list of mailboxes and update local cache
+   * @access private
+   */
   function _change_subscription($a_mboxes, $mode)
     {
     $updated = FALSE;
@@ -2410,7 +2539,10 @@
     }
 
 
-  // increde/decrese messagecount for a specific mailbox
+  /**
+   * Increde/decrese messagecount for a specific mailbox
+   * @access private
+   */
   function _set_messagecount($mbox_name, $mode, $increment)
     {
     $a_mailbox_cache = FALSE;
@@ -2436,7 +2568,10 @@
     }
 
 
-  // remove messagecount of a specific mailbox from cache
+  /**
+   * Remove messagecount of a specific mailbox from cache
+   * @access private
+   */
   function _clear_messagecount($mbox_name='')
     {
     $a_mailbox_cache = FALSE;
@@ -2452,7 +2587,10 @@
     }
 
 
-  // split RFC822 header string into an associative array
+  /**
+   * Split RFC822 header string into an associative array
+   * @access private
+   */
   function _parse_headers($headers)
     {
     $a_headers = array();
@@ -2473,6 +2611,9 @@
     }
 
 
+  /**
+   * @access private
+   */
   function _parse_address_list($str, $decode=true)
     {
     // remove any newlines and carriage returns before
@@ -2501,6 +2642,9 @@
     }
 
 
+  /**
+   * @access private
+   */
   function _explode_quoted_string($delimiter, $string)
     {
     $result = array();
@@ -2519,11 +2663,14 @@
     $result[] = substr($string, $p);
     return $result;
     }
-  }
+
+}  // end class rcube_imap
 
 
 /**
  * Class representing a message part
+ *
+ * @package Mail
  */
 class rcube_message_part
 {
@@ -2544,10 +2691,9 @@
 
 
 /**
- * rcube_header_sorter
- * 
  * Class for sorting an array of iilBasicHeader objects in a predetermined order.
  *
+ * @package Mail
  * @author Eric Stadtherr
  */
 class rcube_header_sorter
@@ -2555,9 +2701,9 @@
    var $sequence_numbers = array();
    
    /**
-    * set the predetermined sort order.
+    * Set the predetermined sort order.
     *
-    * @param array $seqnums numerically indexed array of IMAP message sequence numbers
+    * @param array Numerically indexed array of IMAP message sequence numbers
     */
    function set_sequence_numbers($seqnums)
    {
@@ -2565,9 +2711,9 @@
    }
  
    /**
-    * sort the array of header objects
+    * Sort the array of header objects
     *
-    * @param array $headers array of iilBasicHeader objects indexed by UID
+    * @param array Array of iilBasicHeader objects indexed by UID
     */
    function sort_headers(&$headers)
    {
@@ -2582,9 +2728,10 @@
    }
  
    /**
-    * get the position of a message sequence number in my sequence_numbers array
+    * Get the position of a message sequence number in my sequence_numbers array
     *
-    * @param integer $seqnum message sequence number contained in sequence_numbers  
+    * @param int Message sequence number contained in sequence_numbers
+    * @return int Position, -1 if not found
     */
    function position_of($seqnum)
    {
@@ -2620,10 +2767,10 @@
 /**
  * Add quoted-printable encoding to a given string
  * 
- * @param string  $input      string to encode
- * @param int     $line_max   add new line after this number of characters
- * @param boolena $space_conf true if spaces should be converted into =20
- * @return encoded string
+ * @param string   String to encode
+ * @param int      Add new line after this number of characters
+ * @param boolean  True if spaces should be converted into =20
+ * @return string Encoded string
  */
 function quoted_printable_encode($input, $line_max=76, $space_conv=false)
   {
diff --git a/program/include/rcube_ldap.inc b/program/include/rcube_ldap.inc
index 1aa88f1..976b73d 100644
--- a/program/include/rcube_ldap.inc
+++ b/program/include/rcube_ldap.inc
@@ -19,6 +19,12 @@
 
 */
 
+
+/**
+ * Model class to access an LDAP address directory
+ *
+ * @package Addressbook
+ */
 class rcube_ldap
 {
   var $conn;
@@ -59,7 +65,7 @@
   /**
    * PHP 4 object constructor
    *
-   * @see  rcube_ldap::__construct
+   * @see  rcube_ldap::__construct()
    */
   function rcube_ldap($p)
   {
@@ -105,6 +111,10 @@
 
   /**
    * Bind connection with DN and password
+   *
+   * @param string Bind DN
+   * @param string Bind password
+   * @return boolean True on success, False on error
    */
   function bind($dn, $pass)
   {
@@ -163,7 +173,7 @@
   /**
    * Save a search string for future listings
    *
-   * @param string ??
+   * @param string Filter string
    */
   function set_search_set($filter)
   {
@@ -197,6 +207,7 @@
    * List the current set of contact records
    *
    * @param  array  List of cols to show
+   * @param  int    Only return this number of records (not implemented)
    * @return array  Indexed list of contact records, each a hash array
    */
   function list_records($cols=null, $subset=0)
@@ -229,7 +240,7 @@
    * @param array   List of fields to search in
    * @param string  Search value
    * @param boolean True if results are requested, False if count only
-   * @return Indexed list of contact records and 'count' value
+   * @return array  Indexed list of contact records and 'count' value
    */
   function search($fields, $value, $strict=false, $select=true)
   {
@@ -283,7 +294,7 @@
   /**
    * Count number of available contacts in database
    *
-   * @return Result array with values for 'count' and 'first'
+   * @return object rcube_result_set Resultset with values for 'count' and 'first'
    */
   function count()
   {
@@ -298,7 +309,7 @@
   /**
    * Return the last result set
    *
-   * @return Result array or NULL if nothing selected yet
+   * @return object rcube_result_set Current resultset or NULL if nothing selected yet
    */
   function get_result()
   {
@@ -309,8 +320,9 @@
   /**
    * Get a specific contact record
    *
-   * @param mixed record identifier
-   * @return Hash array with all record fields or False if not found
+   * @param mixed   Record identifier
+   * @param boolean Return as associative array
+   * @return mixed  Hash array or rcube_result_set with all record fields
    */
   function get_record($dn, $assoc=false)
   {
@@ -335,8 +347,8 @@
   /**
    * Create a new contact record
    *
-   * @param array Assoziative array with save data
-   * @return The create record ID on success, False on error
+   * @param array    Hash array with save data
+   * @return boolean The create record ID on success, False on error
    */
   function insert($save_cols)
   {
@@ -349,8 +361,8 @@
    * Update a specific contact record
    *
    * @param mixed Record identifier
-   * @param array Assoziative array with save data
-   * @return True on success, False on error
+   * @param array Hash array with save data
+   * @return boolean True on success, False on error
    */
   function update($id, $save_cols)
   {
@@ -363,6 +375,7 @@
    * Mark one or more contact records as deleted
    *
    * @param array  Record identifiers
+   * @return boolean True on success, False on error
    */
   function delete($ids)
   {
@@ -374,7 +387,7 @@
   /**
    * Execute the LDAP search based on the stored credentials
    *
-   * @private
+   * @access private
    */
   function _exec_search()
   {
@@ -390,7 +403,7 @@
   
   
   /**
-   * @private
+   * @access private
    */
   function _ldap2result($rec)
   {
@@ -410,7 +423,7 @@
   
   
   /**
-   * @private
+   * @access private
    */
   function _map_field($field)
   {
diff --git a/program/include/rcube_mdb2.inc b/program/include/rcube_mdb2.inc
index 47def03..b88a773 100644
--- a/program/include/rcube_mdb2.inc
+++ b/program/include/rcube_mdb2.inc
@@ -32,14 +32,14 @@
  *
  * This is a wrapper for the PEAR::MDB2 class
  *
- * @package    RoundCube Webmail
+ * @package    Database
  * @author     David Saez Padros <david@ols.es>
  * @author     Thomas Bruederli <roundcube@gmail.com>
  * @author     Lukas Kahwe Smith <smith@pooteeweet.org>
  * @version    1.16
  * @link       http://pear.php.net/package/MDB2
  */
-class rcube_db
+class rcube_mdb2
   {
   var $db_dsnw;               // DSN for write operations
   var $db_dsnr;               // DSN for read operations
@@ -76,7 +76,7 @@
   /**
    * PHP 4 object constructor
    *
-   * @see  rcube_MDB2::__construct
+   * @see  rcube_mdb2::__construct
    */
   function rcube_db($db_dsnw,$db_dsnr='')
     {
diff --git a/program/include/rcube_shared.inc b/program/include/rcube_shared.inc
index 0f8be06..acf98c9 100644
--- a/program/include/rcube_shared.inc
+++ b/program/include/rcube_shared.inc
@@ -20,1039 +20,20 @@
 */
 
 
-// ********* round cube schared classes *********
+/**
+ * RoundCube shared functions
+ * 
+ * @package Core
+ */
 
-class rcube_html_page
-  {
-  var $css;
-  
-  var $scripts_path = '';
-  var $script_files = array();
-  var $external_scripts = array();
-  var $scripts = array();
-  var $charset = 'ISO-8859-1';
-  
-  var $script_tag_file = "<script type=\"text/javascript\" src=\"%s%s\"></script>\n";
-  var $script_tag      = "<script type=\"text/javascript\">\n<!--\n%s\n\n//-->\n</script>\n";
-  var $default_template = "<html>\n<head><title></title></head>\n<body></body>\n</html>";
-  var $tag_format_external_script = "<script type=\"text/javascript\" src=\"%s\"></script>\n";
 
-  var $title = '';
-  var $header = '';
-  var $footer = '';
-  var $body = '';
-  var $body_attrib = array();
-  var $meta_tags = array();
-
-
-  // PHP 5 constructor
-  function __construct()
-    {
-    $this->css = new rcube_css();
-    }
-
-  // PHP 4 compatibility
-  function rcube_html_page()
-    {
-    $this->__construct();
-    }
-
-
-  function include_script($file, $position='head')
-    {
-    static $sa_files = array();
-    
-    if (in_array($file, $sa_files))
-      return;
-      
-    if (!is_array($this->script_files[$position]))
-      $this->script_files[$position] = array();
-      
-    $this->script_files[$position][] = $file;
-    }
-    
-  function include_external_script($script_location, $position='head')
-  {
-     if (!is_array($this->external_scripts[$position]))
-     {
-        $this->external_scripts[$position] = array();
-     }
-     
-     $this->external_scripts[$position][] = $script_location;
-  }
-
-  function add_script($script, $position='head')
-    {
-    if (!isset($this->scripts[$position]))
-      $this->scripts[$position] = "\n".rtrim($script);
-    else
-      $this->scripts[$position] .= "\n".rtrim($script);
-    }
-
-  function add_header($str)
-    {
-    $this->header .= "\n".$str;
-    }
-
-  function add_footer($str)
-    {
-    $this->footer .= "\n".$str;
-    }
-
-  function set_title($t)
-    {
-    $this->title = $t;
-    }
-
-
-  function set_charset($charset)
-    {
-    global $MBSTRING;
-    
-    $this->charset = $charset;
-    
-    if ($MBSTRING && function_exists("mb_internal_encoding"))
-      {
-      if(!@mb_internal_encoding($charset))
-        $MBSTRING = FALSE;
-      }
-    }
-
-  function get_charset()
-    {
-    return $this->charset;
-    }
-
-
-  function reset()
-    {
-    $this->css = new rcube_css();
-    $this->script_files = array();
-    $this->scripts = array();
-    $this->title = '';
-    $this->header = '';
-    $this->footer = '';
-    }
-
-
-  function write($templ='', $base_path='')
-    {
-    $output = empty($templ) ? $this->default_template : trim($templ);
-    
-    // set default page title
-    if (empty($this->title))
-      $this->title = 'RoundCube Mail';
-  
-    // replace specialchars in content
-    $__page_title = Q($this->title, 'show', FALSE);
-    $__page_header = $__page_body = $__page_footer = '';
-    
-    
-    // include meta tag with charset
-    if (!empty($this->charset))
-      {
-      header('Content-Type: text/html; charset='.$this->charset);
-      $__page_header = '<meta http-equiv="content-type" content="text/html; charset='.$this->charset.'" />'."\n";
-      }
-  
-  
-    // definition of the code to be placed in the document header and footer
-    if (is_array($this->script_files['head']))
-      foreach ($this->script_files['head'] as $file)
-        $__page_header .= sprintf($this->script_tag_file, $this->scripts_path, $file);
-
-    if (is_array($this->external_scripts['head']))
-      foreach ($this->external_scripts['head'] as $xscript)
-        $__page_header .= sprintf($this->tag_format_external_script, $xscript);
-
-    $head_script = $this->scripts['head_top'] . $this->scripts['head'];
-    if (!empty($head_script))
-      $__page_header .= sprintf($this->script_tag, $head_script);
-
-    if (!empty($this->header))
-      $__page_header .= $this->header;
-
-    if (is_array($this->script_files['foot']))
-      foreach ($this->script_files['foot'] as $file)
-        $__page_footer .= sprintf($this->script_tag_file, $this->scripts_path, $file);
-
-    if (!empty($this->scripts['foot']))
-      $__page_footer .= sprintf($this->script_tag, $this->scripts['foot']);
-      
-    if (!empty($this->footer))
-      $__page_footer .= $this->footer;
-
-    $__page_header .= $this->css->show();
-  
-    // find page header
-    if($hpos = strpos(strtolower($output), '</head>'))
-      $__page_header .= "\n";
-    else 
-      {
-      if (!is_numeric($hpos))
-        $hpos = strpos(strtolower($output), '<body');
-      if (!is_numeric($hpos) && ($hpos = strpos(strtolower($output), '<html')))
-        {
-        while($output[$hpos]!='>')
-        $hpos++;
-        $hpos++;
-        }
-  
-      $__page_header = "<head>\n<title>$__page_title</title>\n$__page_header\n</head>\n";
-      }
-  
-    // add page hader
-    if($hpos)
-      $output = substr($output,0,$hpos) . $__page_header . substr($output,$hpos,strlen($output));
-    else
-      $output = $__page_header . $output;
-  
-  
-    // find page body
-    if($bpos = strpos(strtolower($output), '<body'))
-      {
-      while($output[$bpos]!='>') $bpos++;
-      $bpos++;
-      }
-    else
-      $bpos = strpos(strtolower($output), '</head>')+7;
-  
-    // add page body
-    if($bpos && $__page_body)
-      $output = substr($output,0,$bpos) . "\n$__page_body\n" . substr($output,$bpos,strlen($output));
-  
-  
-    // find and add page footer
-    $output_lc = strtolower($output);
-    if(($fpos = strrstr($output_lc, '</body>')) ||
-       ($fpos = strrstr($output_lc, '</html>')))
-      $output = substr($output, 0, $fpos) . "$__page_footer\n" . substr($output, $fpos);
-    else
-      $output .= "\n$__page_footer";
-  
-  
-    // reset those global vars
-    $__page_header = $__page_footer = '';
-  
-  
-    // correct absolute paths in images and other tags
-    $output = preg_replace('/(src|href|background)=(["\']?)(\/[a-z0-9_\-]+)/Ui', "\\1=\\2$base_path\\3", $output);
-    $output = str_replace('$__skin_path', $base_path, $output);
-  
-    print rcube_charset_convert($output, 'UTF-8', $this->charset);
-    }
-    
-    
-  function _parse($templ)
-    {
-    
-    }
-  }
-
-
-
-
-class rcube_css
-  {
-  var $css_data = array();
-
-  var $css_groups = array();
-
-  var $include_files = array();
-
-  var $grouped_output = TRUE;
-
-  var $content_type = 'text/css';
-
-  var $base_path = '';
-
-  var $indent_chars = "\t";
-
-
-  // add or overwrite a css definition
-  // either pass porperty and value as separate arguments
-  // or provide an associative array as second argument
-  function set_style($selector, $property, $value='')
-    {
-    $a_elements = $this->_parse_selectors($selector);
-    foreach ($a_elements as $element)
-      {
-      if (!is_array($property))
-        $property = array($property => $value);
-
-      foreach ($property as $name => $value)
-        $this->css_data[$element][strtolower($name)] = $value;
-      }
-
-    // clear goups array
-    $this->css_groups = array();
-    }
-
-
-  // unset a style property
-  function remove_style($selector, $property)
-    {
-    if (!is_array($property))
-      $property = array($property);
-
-    foreach ($property as $key)
-      unset($this->css_data[$selector][strtolower($key)]);
-
-    // clear goups array
-    $this->css_groups = array();
-    }
-
-
-  // define base path for external css files
-  function set_basepath($path)
-    {
-    $this->base_path = preg_replace('/\/$/', '', $path);
-    }
-
-
-  // enable/disable grouped output
-  function set_grouped_output($grouped)
-    {
-    $this->grouped_output = $grouped;
-    }
-
-
-  // add a css file as external source
-  function include_file($filename, $media='')
-    {
-    // include multiple files
-    if (is_array($filename))
-      {
-      foreach ($filename as $file)
-        $this->include_file($file, $media);
-      }
-    // add single file
-    else if (!in_array($filename, $this->include_files))
-      $this->include_files[] = array('file' => $filename,
-                                     'media' => $media);
-    }
-
-
-  // parse css code
-  function import_string($str)
-    {
-    $ret = FALSE;
-    if (strlen($str))
-      $ret = $this->_parse($str);
-
-    return $ret;
-    }
-
-
-  // open and parse a css file
-  function import_file($file)
-    {
-    $ret = FALSE;
-
-    if (!is_file($file))
-      return $ret;
-
-    // for php version >= 4.3.0
-    if (function_exists('file_get_contents'))
-      $ret = $this->_parse(file_get_contents($file));
-
-    // for order php versions
-    else if ($fp = fopen($file, 'r'))
-      {
-      $ret = $this->_parse(fread($fp, filesize($file)));
-      fclose($fp);
-      }
-
-    return $ret;
-    }
-
-
-  // copy all properties inherited from superior styles to a specific selector
-  function copy_inherited_styles($selector)
-    {
-    // get inherited props from body and tag/class selectors
-    $css_props = $this->_get_inherited_styles($selector);
-
-    // write modified props back and clear goups array
-    if (sizeof($css_props))
-      {
-      $this->css_data[$selector] = $css_props;
-      $this->css_groups = array();
-      }
-    }
-
-
-  // return css definition for embedding in HTML
-  function show()
-    {
-    $out = '';
-
-    // include external css files
-    if (sizeof($this->include_files))
-      foreach ($this->include_files as $file_arr)
-      $out .= sprintf('<link rel="stylesheet" type="%s" href="%s"%s>'."\n",
-                        $this->content_type,
-                        $this->_get_file_path($file_arr['file']),
-                        $file_arr['media'] ? ' media="'.$file_arr['media'].'"' : '');
-
-
-    // compose css string
-    if (sizeof($this->css_data))
-      $out .= sprintf("<style type=\"%s\">\n<!--\n\n%s-->\n</style>",
-                      $this->content_type,
-                      $this->to_string());
-
-
-    return $out;
-    }
-
-
-  // return valid css code of the current styles grid
-  function to_string($selector=NULL)
-    {
-    // return code for a single selector
-    if ($selector)
-      {
-      $indent_str = $this->indent_chars;
-      $this->indent_chars = '';
-
-      $prop_arr = $this->to_array($selector);
-      $out = $this->_style2string($prop_arr, TRUE);
-
-      $this->indent_chars = $indent_str;
-      }
-
-    // compose css code for complete data grid
-    else
-      {
-      $out = '';
-      $css_data = $this->to_array();
-
-      foreach ($css_data as $key => $prop_arr)
-        $out .= sprintf("%s {\n%s}\n\n",
-                        $key,
-                        $this->_style2string($prop_arr, TRUE));
-      }
-
-    return $out;
-    }
-
-
-  // return a single-line string of a css definition
-  function to_inline($selector)
-    {
-    if ($this->css_data[$selector])
-      return str_replace('"', '\\"', $this->_style2string($this->css_data[$selector], FALSE));
-    }
-
-
-  // return an associative array with selector(s) as key and styles array as value
-  function to_array($selector=NULL)
-    {
-    if (!$selector && $this->grouped_output)
-      {
-      // build groups if desired
-      if (!sizeof($this->css_groups))
-        $this->_build_groups();
-
-      // modify group array to get an array(selector => properties)
-      $out_arr = array();
-      foreach ($this->css_groups as $group_arr)
-        {
-        $key = join(', ', $group_arr['selectors']);
-        $out_arr[$key] = $group_arr['properties'];
-        }
-      }
-    else
-      $out_arr = $this->css_data;
-
-    return $selector ? $out_arr[$selector] : $out_arr;
-    }
-
-
-  // create a css file
-  function to_file($filepath)
-    {
-    if ($fp = fopen($filepath, 'w'))
-      {
-      fwrite($fp, $this->to_string());
-      fclose($fp);
-      return TRUE;
-      }
-
-    return FALSE;
-    }
-
-
-  // alias method for import_string() [DEPRECATED]
-  function add($str)
-    {
-    $this->import_string($str);
-    }
-
-  // alias method for to_string() [DEPRECATED]
-  function get()
-    {
-    return $this->to_string();
-    }
-
-
-
-  // ******** private methods ********
-
-
-  // parse a string and add styles to internal data grid
-  function _parse($str)
-    {
-    // remove comments
-    $str = preg_replace("/\/\*(.*)?\*\//Usi", '', $str);
-
-    // parse style definitions
-    if (!preg_match_all ('/([a-z0-9\.#*:_][a-z0-9\.\-_#:*,\[\]\(\)\s\"\'\+\|>~=]+)\s*\{([^\}]*)\}/ims', $str, $matches, PREG_SET_ORDER))
-      return FALSE;
-
-
-    foreach ($matches as $match_arr)
-      {
-      // split selectors into array
-      $a_keys = $this->_parse_selectors(trim($match_arr[1]));
-
-      // parse each property of an element
-      $codes = explode(";", trim($match_arr[2]));
-      foreach ($codes as $code)
-        {
-        if (strlen(trim($code))>0)
-          {
-          // find the property and the value
-          if (!($sep = strpos($code, ':')))
-            continue;
-
-          $property = strtolower(trim(substr($code, 0, $sep)));
-          $value    = trim(substr($code, $sep+1));
-
-          // add the property to the object array
-          foreach ($a_keys as $key)
-            $this->css_data[$key][$property] = $value;
-          }
-        }
-      }
-
-    // clear goups array
-    if (sizeof($matches))
-      {
-      $this->css_groups = array();
-      return TRUE;
-      }
-
-    return FALSE;
-    }
-
-
-  // split selector group
-  function _parse_selectors($selector)
-    {
-    // trim selector and remove multiple spaces
-    $selector = preg_replace('/\s+/', ' ', trim($selector));
-
-    if (strpos($selector, ','))
-      return preg_split('/[\t\s\n\r]*,[\t\s\n\r]*/mi', $selector);
-    else
-      return array($selector);
-    }
-
-
-  // compare identical styles and make groups
-  function _build_groups()
-    {
-    // clear group array
-    $this->css_groups = array();
-    $string_group_map = array();
-
-    // bulild css string for each selector and check if the same is already defines
-    foreach ($this->css_data as $selector => $prop_arr)
-      {
-      // make shure to compare props in the same order
-      ksort($prop_arr);
-      $compare_str = preg_replace('/[\s\t]+/', '', $this->_style2string($prop_arr, FALSE));
-
-      // add selector to extisting group
-      if (isset($string_group_map[$compare_str]))
-        {
-        $group_index = $string_group_map[$compare_str];
-        $this->css_groups[$group_index]['selectors'][] = $selector;
-        }
-
-      // create new group
-      else
-        {
-        $i = sizeof($this->css_groups);
-        $string_group_map[$compare_str] = $i;
-        $this->css_groups[$i] = array('selectors' => array($selector),
-                                      'properties' => $this->css_data[$selector]);
-        }
-      }
-    }
-
-
-  // convert the prop array into a valid css definition
-  function _style2string($prop_arr, $multiline=TRUE)
-    {
-    $out = '';
-    $delm   = $multiline ? "\n" : '';
-    $spacer = $multiline ? ' ' : '';
-    $indent = $multiline ? $this->indent_chars : '';
-
-    if (is_array($prop_arr))
-      foreach ($prop_arr as $prop => $value)
-        if (strlen($value))
-          $out .= sprintf('%s%s:%s%s;%s',
-                          $indent,
-                          $prop,
-                          $spacer,
-                          $value,
-                          $delm);
-
-    return $out;
-    }
-
-
-  // copy all properties inherited from superior styles to a specific selector
-  function _get_inherited_styles($selector, $loop=FALSE)
-    {
-    $css_props = $this->css_data[$selector] ? $this->css_data[$selector] : array();
-
-    // get styles from tag selector
-    if (preg_match('/(([a-z0-9]*)(\.[^\s]+)?)$/i', $selector, $regs))
-      {
-      $sel = $regs[1];
-      $tagname = $regs[2];
-      $class = $regs[3];
-
-      if ($sel && is_array($this->css_data[$sel]))
-        $css_props = $this->_merge_styles($this->css_data[$sel], $css_props);
-
-      if ($class && is_array($this->css_data[$class]))
-        $css_props = $this->_merge_styles($this->css_data[$class], $css_props);
-
-      if ($tagname && is_array($this->css_data[$tagname]))
-        $css_props = $this->_merge_styles($this->css_data[$tagname], $css_props);
-      }
-
-    // analyse inheritance
-    if (strpos($selector, ' '))
-      {
-      $a_hier = split(' ', $selector);
-      if (sizeof($a_hier)>1)
-        {
-        array_pop($a_hier);
-        $base_selector = join(' ', $a_hier);
-
-        // call this method recursively
-        $new_props = $this->_get_inherited_styles($base_selector, TRUE);
-        $css_props = $this->_merge_styles($new_props, $css_props);
-        }
-      }
-
-    // get body style
-    if (!$loop && is_array($this->css_data['body']))
-      $css_props = $this->_merge_styles($this->css_data['body'], $css_props);
-
-    return $css_props;
-    }
-
-
-  // merge two arrays with style properties together like a browser would do
-  function _merge_styles($one, $two)
-    {
-    // these properties are additive
-    foreach (array('text-decoration') as $prop)
-      if ($one[$prop] && $two[$prop])
-        {
-        // if value contains 'none' it's ignored
-        if (strstr($one[$prop], 'none'))
-          continue;
-        else if (strstr($two[$prop], 'none'))
-          unset($two[$prop]);
-
-        $a_values_one = split(' ', $one[$prop]);
-        $a_values_two = split(' ', $two[$prop]);
-        $two[$prop] = join(' ', array_unique(array_merge($a_values_one, $a_values_two)));
-        }
-
-    return array_merge($one, $two);
-    }
-
-
-  // resolve file path
-  function _get_file_path($file)
-    {
-    if (!$this->base_path && $GLOBALS['CSS_PATH'])
-      $this->set_basepath($GLOBALS['CSS_PATH']);
-
-    $base = ($file{0}=='/' || $file{0}=='.' || substr($file, 0, 7)=='http://') ? '' :
-            ($this->base_path ? $this->base_path.'/' : '');
-    return $base.$file;
-    }
-
-  }
-
-
-
-class base_form_element
-  {
-  var $uppertags = FALSE;
-  var $upperattribs = FALSE;
-  var $upperprops = FALSE;
-  var $newline = FALSE;
-  
-  var $attrib = array();
-
-
-  // create string with attributes
-  function create_attrib_string($tagname='')
-    {
-    if (!sizeof($this->attrib))
-      return '';
-
-    if ($this->name!='')
-      $this->attrib['name'] = $this->name;
-
-    $attrib_arr = array();
-    foreach ($this->attrib as $key => $value)
-      {
-      // don't output some internally used attributes
-      if (in_array($key, array('form', 'quicksearch')))
-        continue;
-
-      // skip if size if not numeric
-      if (($key=='size' && !is_numeric($value)))
-        continue;
-        
-      // skip empty eventhandlers
-      if ((strpos($key,'on')===0 && $value==''))
-        continue;
-
-      // encode textarea content
-      if ($key=='value')
-        $value = Q($value, 'strict', FALSE);
-
-      // attributes with no value
-      if (in_array($key, array('checked', 'multiple', 'disabled', 'selected')))
-        {
-        if ($value)
-          $attrib_arr[] = $key;
-        }
-      // don't convert size of value attribute
-      else if ($key=='value')
-        $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $value, 'value');
-        
-      // regular tag attributes
-      else
-        $attrib_arr[] = sprintf('%s="%s"', $this->_conv_case($key, 'attrib'), $this->_conv_case($value, 'value'));
-      }
-
-    return sizeof($attrib_arr) ? ' '.implode(' ', $attrib_arr) : '';
-    }
-    
-    
-  // convert tags and attributes to upper-/lowercase
-  // $type can either be "tag" or "attrib"
-  function _conv_case($str, $type='attrib')
-    {
-    if ($type == 'tag')
-      return $this->uppertags ? strtoupper($str) : strtolower($str);
-    else if ($type == 'attrib')
-      return $this->upperattribs ? strtoupper($str) : strtolower($str);
-    else if ($type == 'value')
-      return $this->upperprops ? strtoupper($str) : strtolower($str);
-    }    
-  }
-
-
-class input_field extends base_form_element
-  {
-  var $type = 'text';
-  
-  // PHP 5 constructor
-  function __construct($attrib=NULL)
-    {
-    if (is_array($attrib))
-      $this->attrib = $attrib;
-
-    if ($attrib['type'])
-      $this->type = $attrib['type'];    
-
-    if ($attrib['newline'])
-      $this->newline = TRUE;    
-    }
-
-  // PHP 4 compatibility
-  function input_field($attrib=array())
-    {
-    $this->__construct($attrib);
-    }  
-
-  // compose input tag
-  function show($value=NULL, $attrib=NULL)
-    {
-    // overwrite object attributes
-    if (is_array($attrib))
-      $this->attrib = array_merge($this->attrib, $attrib);
-
-    // set value attribute
-    if ($value!==NULL)
-      $this->attrib['value'] = $value;
-
-    $this->attrib['type'] = $this->type;
-
-    // return final tag
-    return sprintf('<%s%s />%s',
-                   $this->_conv_case('input', 'tag'),
-                   $this->create_attrib_string(),
-                   ($this->newline ? "\n" : ""));    
-    }  
-  }
-
-
-class textfield extends input_field
-  {
-  var $type = 'text';
-  }
-
-class passwordfield extends input_field
-  {
-  var $type = 'password';
-  }
-
-class radiobutton extends input_field
-  {
-  var $type = 'radio';
-  }
-
-class checkbox extends input_field
-  {
-  var $type = 'checkbox';
-
-
-  function show($value='', $attrib=NULL)
-    {
-    // overwrite object attributes
-    if (is_array($attrib))
-      $this->attrib = array_merge($this->attrib, $attrib);    
-
-    $this->attrib['type'] = $this->type;
-
-    if ($value && (string)$value==(string)$this->attrib['value'])
-      $this->attrib['checked'] = TRUE;
-    else
-      $this->attrib['checked'] = FALSE;
-
-    // return final tag
-    return sprintf('<%s%s />%s',
-                   $this->_conv_case('input', 'tag'),
-                   $this->create_attrib_string(),
-                   ($this->newline ? "\n" : ""));    
-    }
-  }
-
-
-class textarea extends base_form_element
-  {
-  // PHP 5 constructor
-  function __construct($attrib=array())
-    {
-    $this->attrib = $attrib;
-
-    if ($attrib['newline'])
-      $this->newline = TRUE;    
-    }
-
-  // PHP 4 compatibility
-  function textarea($attrib=array())
-    {
-    $this->__construct($attrib);
-    }
-    
-  function show($value='', $attrib=NULL)
-    {
-    // overwrite object attributes
-    if (is_array($attrib))
-      $this->attrib = array_merge($this->attrib, $attrib);
-    
-    // take value attribute as content
-    if ($value=='')
-      $value = $this->attrib['value'];
-    
-    // make shure we don't print the value attribute
-    if (isset($this->attrib['value']))
-      unset($this->attrib['value']);
-
-    if (!empty($value) && !isset($this->attrib['mce_editable']))
-      $value = Q($value, 'strict', FALSE);
-
-    // return final tag
-    return sprintf('<%s%s>%s</%s>%s',
-                   $this->_conv_case('textarea', 'tag'),
-                   $this->create_attrib_string(),
-                   $value,
-                   $this->_conv_case('textarea', 'tag'),
-                   ($this->newline ? "\n" : ""));       
-    }
-  }
-
-
-class hiddenfield extends base_form_element
-  {
-  var $fields_arr = array();
-  var $newline = TRUE;
-
-  // PHP 5 constructor
-  function __construct($attrib=NULL)
-    {
-    if (is_array($attrib))
-      $this->add($attrib);
-    }
-
-  // PHP 4 compatibility
-  function hiddenfield($attrib=NULL)
-    {
-    $this->__construct($attrib);
-    }
-
-  // add a hidden field to this instance
-  function add($attrib)
-    {
-    $this->fields_arr[] = $attrib;
-    }
-
-
-  function show()
-    {
-    $out = '';
-    foreach ($this->fields_arr as $attrib)
-      {
-      $this->attrib = $attrib;
-      $this->attrib['type'] = 'hidden';
-      
-      $out .= sprintf('<%s%s />%s',
-                   $this->_conv_case('input', 'tag'),
-                   $this->create_attrib_string(),
-                   ($this->newline ? "\n" : ""));   
-      }
-
-    return $out;
-    }
-  }
-
-
-class select extends base_form_element
-  {
-  var $options = array();
-
-  /*
-  syntax:
-  -------
-  // create instance. arguments are used to set attributes of select-tag
-  $select = new select(array('name' => 'fieldname'));
-
-  // add one option
-  $select->add('Switzerland', 'CH');
-
-  // add multiple options
-  $select->add(array('Switzerland', 'Germany'),
-               array('CH', 'DE'));
-
-  // add 10 blank options with 50 chars
-  // used to fill with javascript (necessary for 4.x browsers)
-  $select->add_blank(10, 50);
-
-  // generate pulldown with selection 'Switzerland'  and return html-code
-  // as second argument the same attributes available to instanciate can be used
-  print $select->show('CH');
-  */
-
-  // PHP 5 constructor
-  function __construct($attrib=NULL)
-    {
-    if (is_array($attrib))
-      $this->attrib = $attrib;
-
-    if ($attrib['newline'])
-      $this->newline = TRUE;
-    }
-
-  // PHP 4 compatibility
-  function select($attrib=NULL)
-    {
-    $this->__construct($attrib);
-    }
-
-
-  function add($names, $values=NULL)
-    {
-    if (is_array($names))
-      {
-      foreach ($names as $i => $text)
-        $this->options[] = array('text' => $text, 'value' => (string)$values[$i]);
-      }
-    else
-      {
-      $this->options[] = array('text' => $names, 'value' => (string)$values);
-      }
-    }
-
-    
-  function add_blank($nr, $width=0)
-    {
-    $text = $width ? str_repeat('&nbsp;', $width) : '';
-    
-    for ($i=0; $i < $nr; $i++)
-      $this->options[] = array('text' => $text);
-    }
-
-  
-  function show($select=array(), $attrib=NULL)
-    {
-    $options_str = "\n";
-    $value_str = $this->_conv_case(' value="%s"', 'attrib');
-    
-    if (!is_array($select))
-      $select = array((string)$select);
-
-    foreach ($this->options as $option)
-      {
-      $selected = ((isset($option['value']) &&
-                    in_array($option['value'], $select, TRUE)) ||
-                   (in_array($option['text'], $select, TRUE))) ?
-        $this->_conv_case(' selected', 'attrib') : '';
-                   
-      $options_str .= sprintf("<%s%s%s>%s</%s>\n",
-                             $this->_conv_case('option', 'tag'),
-                             !empty($option['value']) ? sprintf($value_str, Q($option['value'])) : '',
-                             $selected, 
-                             Q($option['text'], 'strict', FALSE),
-                             $this->_conv_case('option', 'tag'));
-      }
-
-    // return final tag
-    return sprintf('<%s%s>%s</%s>%s',
-                   $this->_conv_case('select', 'tag'),
-                   $this->create_attrib_string(),
-                   $options_str,
-                   $this->_conv_case('select', 'tag'),
-                   ($this->newline ? "\n" : ""));    
-    }
-  }
-
-
-
-
-// ********* rcube schared functions *********
-
-
-// provide details about the client's browser
+/**
+ * Provide details about the client's browser
+ *
+ * @return array Key-value pairs of browser properties
+ */
 function rcube_browser()
-  {
+{
   $HTTP_USER_AGENT = $_SERVER['HTTP_USER_AGENT'];
 
   $bw['ver'] = 0;
@@ -1069,25 +50,25 @@
   $bw['safari'] = stristr($HTTP_USER_AGENT, 'safari');
 
   if($bw['ns'])
-    {
+  {
     $test = eregi("mozilla\/([0-9\.]+)", $HTTP_USER_AGENT, $regs);
     $bw['ver'] = $test ? (float)$regs[1] : 0;
-    }
+  }
   if($bw['mz'])
-    {
+  {
     $test = ereg("rv:([0-9\.]+)", $HTTP_USER_AGENT, $regs);
     $bw['ver'] = $test ? (float)$regs[1] : 0;
-    }
+  }
   if($bw['ie'])
-    {
+  {
     $test = eregi("msie ([0-9\.]+)", $HTTP_USER_AGENT, $regs);
     $bw['ver'] = $test ? (float)$regs[1] : 0;
-    }
+  }
   if($bw['opera'])
-    {
+  {
     $test = eregi("opera ([0-9\.]+)", $HTTP_USER_AGENT, $regs);
     $bw['ver'] = $test ? (float)$regs[1] : 0;
-    }
+  }
 
   if(eregi(" ([a-z]{2})-([a-z]{2})", $HTTP_USER_AGENT, $regs))
     $bw['lang'] =  $regs[1];
@@ -1099,12 +80,17 @@
                     ($bw['ie'] && $bw['ver']>=5 && $bw['mac']) || ($bw['opera'] && $bw['ver']>=7) ? TRUE : FALSE;
 
   return $bw;
-  }
+}
 
 
-// get text in the desired language from the language file
+/**
+ * Get localized text in the desired language
+ *
+ * @param mixed Named parameters array or label name
+ * @return string Localized text
+ */
 function rcube_label($attrib)
-  {
+{
   global $sess_user_lang, $INSTALL_PATH, $OUTPUT;
   static $sa_text_data, $s_language, $utf8_decode;
 
@@ -1135,7 +121,7 @@
     
     // include user language files
     if ($sess_user_lang!='en' && is_dir($INSTALL_PATH.'program/localization/'.$sess_user_lang))
-      {
+    {
       include_once($INSTALL_PATH.'program/localization/'.$sess_user_lang.'/labels.inc');
       include_once($INSTALL_PATH.'program/localization/'.$sess_user_lang.'/messages.inc');
 
@@ -1143,23 +129,24 @@
         $sa_text_data = array_merge($sa_text_data, $labels);
       if (is_array($messages))
         $sa_text_data = array_merge($sa_text_data, $messages);
-      }
+    }
       
     $s_language = $sess_user_lang;
-    }
+  }
 
   // text does not exist
   if (!($text_item = $sa_text_data[$alias]))
-    {
+  {
     /*
-    raise_error(array('code' => 500,
-                      'type' => 'php',
-                      'line' => __LINE__,
-                      'file' => __FILE__,
-                      'message' => "Missing localized text for '$alias' in '$sess_user_lang'"), TRUE, FALSE);
+    raise_error(array(
+      'code' => 500,
+      'type' => 'php',
+      'line' => __LINE__,
+      'file' => __FILE__,
+      'message' => "Missing localized text for '$alias' in '$sess_user_lang'"), TRUE, FALSE);
     */
     return "[$alias]";
-    }
+  }
 
   // make text item array 
   $a_text_item = is_array($text_item) ? $text_item : array('single' => $text_item);
@@ -1170,14 +157,14 @@
   else if ($nr>0)
     $text = $a_text_item['multiple'];
   else if ($nr==0)
-    {
+  {
     if ($a_text_item['none'])
       $text = $a_text_item['none'];
     else if ($a_text_item['single'])
       $text = $a_text_item['single'];
     else if ($a_text_item['multiple'])
       $text = $a_text_item['multiple'];
-    }
+  }
 
   // default text is single
   if ($text=='')
@@ -1185,10 +172,10 @@
 
   // replace vars in text
   if (is_array($attrib['vars']))
-    {
+  {
     foreach ($attrib['vars'] as $var_key=>$var_value)
       $a_replace_vars[substr($var_key, 0, 1)=='$' ? substr($var_key, 1) : $var_key] = $var_value;
-    }
+  }
 
   if ($a_replace_vars)
     $text = preg_replace('/\${?([_a-z]{1}[_a-z0-9]*)}?/ei', '$a_replace_vars["\1"]', $text);
@@ -1208,12 +195,14 @@
     return strtolower($text);
 
   return $text;
-  }
+}
 
 
-// send HTTP header for no-cacheing steps
+/**
+ * Send HTTP headers to prevent caching this page
+ */
 function send_nocacheing_headers()
-  {
+{
   if (headers_sent())
     return;
 
@@ -1221,22 +210,32 @@
   header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
   header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
   header("Pragma: no-cache");
-  }
+}
 
 
-// send header with expire date 30 days in future
+/**
+ * Send header with expire date 30 days in future
+ *
+ * @param int Expiration time in seconds
+ */
 function send_future_expire_header($offset=2600000)
-  {
+{
   if (headers_sent())
     return;
 
   header("Expires: ".gmdate("D, d M Y H:i:s", mktime()+$offset)." GMT");
   header("Cache-Control: max-age=$offset");
   header("Pragma: ");
-  }
+}
 
 
-// check request for If-Modified-Since and send an according response
+/**
+ * Check request for If-Modified-Since and send an according response.
+ * This will terminate the current script if headers match the given values
+ *
+ * @param int Modified date as unix timestamp
+ * @param string Etag value for caching
+ */
 function send_modified_header($mdate, $etag=null)
 {
   if (headers_sent())
@@ -1268,260 +267,311 @@
 
 
 /**
- * Convert a variable into a javascript notation string
+ * Convert a variable into a javascript object notation
+ *
+ * @param mixed Input value
+ * @return string Serialized JSON string
  */
 function json_serialize($var)
+{
+  if (is_object($var))
+    $var = get_object_vars($var);
+
+  if (is_array($var))
   {
-    if (is_object($var))
-      $var = get_object_vars($var);
-
-    if (is_array($var))
-    {
-      // empty array
-      if (!sizeof($var))
-        return '[]';
-      else
-      {
-        $keys_arr = array_keys($var);
-        $is_assoc = $have_numeric = 0;
-
-        for ($i=0; $i<sizeof($keys_arr); ++$i)
-        {
-          if (is_numeric($keys_arr[$i]))
-            $have_numeric = 1;
-          if (!is_numeric($keys_arr[$i]) || $keys_arr[$i] != $i)
-            $is_assoc = 1;
-          if ($is_assoc && $have_numeric)
-            break;
-        }
-        
-        $brackets = $is_assoc ? '{}' : '[]';
-        $pairs = array();
-
-        foreach ($var as $key => $value)
-        {
-          // enclose key with quotes if it is not variable-name conform
-          if (!ereg("^[_a-zA-Z]{1}[_a-zA-Z0-9]*$", $key) /* || is_js_reserved_word($key) */)
-            $key = "'$key'";
-
-          $pairs[] = sprintf("%s%s", $is_assoc ? "$key:" : '', json_serialize($value));
-        }
-
-        return $brackets{0} . implode(',', $pairs) . $brackets{1};
-      }
-    }
-    else if (is_numeric($var) && strval(intval($var)) === strval($var))
-      return $var;
-    else if (is_bool($var))
-      return $var ? '1' : '0';
+    // empty array
+    if (!sizeof($var))
+      return '[]';
     else
-      return "'".JQ($var)."'";
-  
+    {
+      $keys_arr = array_keys($var);
+      $is_assoc = $have_numeric = 0;
+
+      for ($i=0; $i<sizeof($keys_arr); ++$i)
+      {
+        if (is_numeric($keys_arr[$i]))
+          $have_numeric = 1;
+        if (!is_numeric($keys_arr[$i]) || $keys_arr[$i] != $i)
+          $is_assoc = 1;
+        if ($is_assoc && $have_numeric)
+          break;
+      }
+      
+      $brackets = $is_assoc ? '{}' : '[]';
+      $pairs = array();
+
+      foreach ($var as $key => $value)
+      {
+        // enclose key with quotes if it is not variable-name conform
+        if (!ereg("^[_a-zA-Z]{1}[_a-zA-Z0-9]*$", $key) /* || is_js_reserved_word($key) */)
+          $key = "'$key'";
+
+        $pairs[] = sprintf("%s%s", $is_assoc ? "$key:" : '', json_serialize($value));
+      }
+
+      return $brackets{0} . implode(',', $pairs) . $brackets{1};
+    }
   }
+  else if (is_numeric($var) && strval(intval($var)) === strval($var))
+    return $var;
+  else if (is_bool($var))
+    return $var ? '1' : '0';
+  else
+    return "'".JQ($var)."'";
+
+}
 
 /**
- * function to convert an array to a javascript array
+ * Function to convert an array to a javascript array
+ * Actually an alias function for json_serialize()
  * @deprecated
  */
 function array2js($arr, $type='')
-  {
+{
   return json_serialize($arr);
-  }
+}
 
 
 /**
  * Similar function as in_array() but case-insensitive
+ *
+ * @param mixed Needle value
+ * @param array Array to search in
+ * @return boolean True if found, False if not
  */
 function in_array_nocase($needle, $haystack)
-  {
+{
   foreach ($haystack as $value)
-    {
     if (strtolower($needle)===strtolower($value))
-      return TRUE;
-    }
-    
-  return FALSE;
-  }
+      return true;
+  
+  return false;
+}
 
 
 /**
  * Find out if the string content means TRUE or FALSE
+ *
+ * @param string Input value
+ * @return boolean Imagine what!
  */
 function get_boolean($str)
-  {
+{
   $str = strtolower($str);
   if(in_array($str, array('false', '0', 'no', 'nein', ''), TRUE))
     return FALSE;
   else
     return TRUE;
-  }
+}
 
 
-// parse a human readable string for a number of bytes
+/**
+ * Parse a human readable string for a number of bytes
+ *
+ * @param string Input string
+ * @return int Number of bytes
+ */
 function parse_bytes($str)
-  {
+{
   if (is_numeric($str))
     return intval($str);
     
   if (preg_match('/([0-9]+)([a-z])/i', $str, $regs))
+  {
+    $bytes = floatval($regs[1]);
+    switch (strtolower($regs[2]))
     {
-      $bytes = floatval($regs[1]);
-      switch (strtolower($regs[2]))
-      {
-        case 'g':
-          $bytes *= 1073741824;
-          break;
-        case 'm':
-          $bytes *= 1048576;
-          break;
-        case 'k':
-          $bytes *= 1024;
-          break;
-      }
+      case 'g':
+        $bytes *= 1073741824;
+        break;
+      case 'm':
+        $bytes *= 1048576;
+        break;
+      case 'k':
+        $bytes *= 1024;
+        break;
     }
+  }
 
   return intval($bytes);
-  }
+}
     
-// create a human readable string for a number of bytes
+/**
+ * Create a human readable string for a number of bytes
+ *
+ * @param int Number of bytes
+ * @return string Byte string
+ */
 function show_bytes($bytes)
-  {
+{
   if ($bytes > 1073741824)
-    {
+  {
     $gb = $bytes/1073741824;
     $str = sprintf($gb>=10 ? "%d GB" : "%.1f GB", $gb);
-    }
+  }
   else if ($bytes > 1048576)
-    {
+  {
     $mb = $bytes/1048576;
     $str = sprintf($mb>=10 ? "%d MB" : "%.1f MB", $mb);
-    }
+  }
   else if ($bytes > 1024)
     $str = sprintf("%d KB",  round($bytes/1024));
   else
     $str = sprintf('%d B', $bytes);
 
   return $str;
-  }
+}
 
 
-// convert paths like ../xxx to an absolute path using a base url
+/**
+ * Convert paths like ../xxx to an absolute path using a base url
+ *
+ * @param string Relative path
+ * @param string Base URL
+ * @return string Absolute URL
+ */
 function make_absolute_url($path, $base_url)
-    {
-    $host_url = $base_url;
-    $abs_path = $path;
+{
+  $host_url = $base_url;
+  $abs_path = $path;
 
-    // cut base_url to the last directory
-    if (strpos($base_url, '/')>7)
+  // cut base_url to the last directory
+  if (strpos($base_url, '/')>7)
+  {
+    $host_url = substr($base_url, 0, strpos($base_url, '/'));
+    $base_url = substr($base_url, 0, strrpos($base_url, '/'));
+  }
+
+  // $path is absolute
+  if ($path{0}=='/')
+    $abs_path = $host_url.$path;
+  else
+  {
+    // strip './' because its the same as ''
+    $path = preg_replace('/^\.\//', '', $path);
+
+    if (preg_match_all('/\.\.\//', $path, $matches, PREG_SET_ORDER))
+      foreach ($matches as $a_match)
       {
-      $host_url = substr($base_url, 0, strpos($base_url, '/'));
-      $base_url = substr($base_url, 0, strrpos($base_url, '/'));
+        if (strrpos($base_url, '/'))
+          $base_url = substr($base_url, 0, strrpos($base_url, '/'));
+        
+        $path = substr($path, 3);
       }
 
-    // $path is absolute
-    if ($path{0}=='/')
-      $abs_path = $host_url.$path;
-    else
-      {
-      // strip './' because its the same as ''
-      $path = preg_replace('/^\.\//', '', $path);
-
-      if(preg_match_all('/\.\.\//', $path, $matches, PREG_SET_ORDER))
-        foreach($matches as $a_match)
-          {
-          if (strrpos($base_url, '/'))
-            $base_url = substr($base_url, 0, strrpos($base_url, '/'));
-          
-          $path = substr($path, 3);
-          }
-
-      $abs_path = $base_url.'/'.$path;
-      }
-      
-    return $abs_path;
-    }
+    $abs_path = $base_url.'/'.$path;
+  }
+    
+  return $abs_path;
+}
 
 
-// wrapper function for strlen
+/**
+ * Wrapper function for strlen
+ */
 function rc_strlen($str)
-  {
-    if (function_exists('mb_strlen'))
-      return mb_strlen($str);
-    else
-      return strlen($str);
-  }
+{
+  if (function_exists('mb_strlen'))
+    return mb_strlen($str);
+  else
+    return strlen($str);
+}
   
-// wrapper function for strtolower
+/**
+ * Wrapper function for strtolower
+ */
 function rc_strtolower($str)
-  {
-    if (function_exists('mb_strtolower'))
-      return mb_strtolower($str);
-    else
-      return strtolower($str);
-  }
+{
+  if (function_exists('mb_strtolower'))
+    return mb_strtolower($str);
+  else
+    return strtolower($str);
+}
 
-// wrapper function for substr
+/**
+ * Wrapper function for substr
+ */
 function rc_substr($str, $start, $len=null)
-  {
+{
   if (function_exists('mb_substr'))
     return mb_substr($str, $start, $len);
   else
     return substr($str, $start, $len);
-  }
+}
 
-// wrapper function for strpos
+/**
+ * Wrapper function for strpos
+ */
 function rc_strpos($haystack, $needle, $offset=0)
-  {
+{
   if (function_exists('mb_strpos'))
     return mb_strpos($haystack, $needle, $offset);
   else
     return strpos($haystack, $needle, $offset);
-  }
+}
 
-// wrapper function for strrpos
+/**
+ * Wrapper function for strrpos
+ */
 function rc_strrpos($haystack, $needle, $offset=0)
-  {
+{
   if (function_exists('mb_strrpos'))
     return mb_strrpos($haystack, $needle, $offset);
   else
     return strrpos($haystack, $needle, $offset);
-  }
+}
 
 
-// replace the middle part of a string with ...
-// if it is longer than the allowed length
+/**
+ * Replace the middle part of a string with ...
+ * if it is longer than the allowed length
+ *
+ * @param string Input string
+ * @param int    Max. length
+ * @param string Replace removed chars with this
+ * @return string Abbrevated string
+ */
 function abbrevate_string($str, $maxlength, $place_holder='...')
-  {
+{
   $length = rc_strlen($str);
   $first_part_length = floor($maxlength/2) - rc_strlen($place_holder);
   
   if ($length > $maxlength)
-    {
+  {
     $second_starting_location = $length - $maxlength + $first_part_length + 1;
     $str = rc_substr($str, 0, $first_part_length) . $place_holder . rc_substr($str, $second_starting_location, $length);
-    }
+  }
 
   return $str;
-  }
+}
 
 
-// make sure the string ends with a slash
+/**
+ * Make sure the string ends with a slash
+ */
 function slashify($str)
-  {
+{
   return unslashify($str).'/';
-  }
+}
 
 
-// remove slash at the end of the string
+/**
+ * Remove slash at the end of the string
+ */
 function unslashify($str)
-  {
+{
   return preg_replace('/\/$/', '', $str);
-  }
+}
   
 
-// delete all files within a folder
+/**
+ * Delete all files within a folder
+ *
+ * @param string Path to directory
+ * @return boolean True on success, False if directory was not found
+ */
 function clear_directory($dir_path)
-  {
+{
   $dir = @opendir($dir_path);
   if(!$dir) return FALSE;
 
@@ -1531,26 +581,32 @@
 
   closedir($dir);
   return TRUE;
-  }
+}
 
 
-// create a unix timestamp with a specified offset from now
+/**
+ * Create a unix timestamp with a specified offset from now
+ *
+ * @param string String representation of the offset (e.g. 20min, 5h, 2days)
+ * @param int Factor to multiply with the offset
+ * @return int Unix timestamp
+ */
 function get_offset_time($offset_str, $factor=1)
   {
   if (preg_match('/^([0-9]+)\s*([smhdw])/i', $offset_str, $regs))
-    {
+  {
     $amount = (int)$regs[1];
     $unit = strtolower($regs[2]);
-    }
+  }
   else
-    {
+  {
     $amount = (int)$offset_str;
     $unit = 's';
-    }
+  }
     
   $ts = mktime();
   switch ($unit)
-    {
+  {
     case 'w':
       $amount *= 7;
     case 'd':
@@ -1561,37 +617,34 @@
       $amount *= 60;
     case 's':
       $ts += $amount * $factor;
-    }
+  }
 
   return $ts;
-  }
+}
 
 
 /**
- * strrstr
+ * Return the last occurence of a string in another string
  *
- * return the last occurence of a string in another string
  * @param haystack string string in which to search
  * @param needle string string for which to search
  * @return index of needle within haystack, or false if not found
  */
 function strrstr($haystack, $needle)
+{
+  $pver = phpversion();
+  if ($pver[0] >= 5)
+      return strrpos($haystack, $needle);
+  else
   {
-    $pver = phpversion();
-    if ($pver[0] >= 5)
-      {
-        return strrpos($haystack, $needle);
-      }
-    else
-      {
-        $index = strpos(strrev($haystack), strrev($needle));
-        if($index === false) {
-            return false;
-        }
-        $index = strlen($haystack) - strlen($needle) - $index;
-        return $index;
-      }
+    $index = strpos(strrev($haystack), strrev($needle));
+    if($index === false)
+        return false;
+    
+    $index = strlen($haystack) - strlen($needle) - $index;
+    return $index;
   }
+}
 
 
 ?>
diff --git a/program/include/rcube_smtp.inc b/program/include/rcube_smtp.inc
index 2ddb5cf..7b83987 100644
--- a/program/include/rcube_smtp.inc
+++ b/program/include/rcube_smtp.inc
@@ -5,7 +5,7 @@
  | program/include/rcube_smtp.inc                                        |
  |                                                                       |
  | This file is part of the RoundCube Webmail client                     |
- | Copyright (C) 2005, RoundCube Dev. - Switzerland                      |
+ | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland                 |
  | Licensed under the GNU GPL                                            |
  |                                                                       |
  | PURPOSE:                                                              |
@@ -19,6 +19,11 @@
 
 */
 
+/**
+ * SMTP delivery functions
+ *
+ * @package Mail
+ */
 
 // include required PEAR classes
 require_once('Net/SMTP.php');
@@ -47,7 +52,6 @@
  * @param string The full text of the message body, including any Mime parts, etc.
  *
  * @return bool  Returns TRUE on success, or FALSE on error
- * @access public
  */
 function smtp_mail($from, $recipients, &$headers, &$body, &$response)
   {
@@ -342,6 +346,9 @@
   }
 
 
+/**
+ * @access private
+ */
 function smtp_explode_quoted_str($delimiter, $string)
   {
   $quotes=explode("\"", $string);
diff --git a/program/include/rcube_sqlite.inc b/program/include/rcube_sqlite.inc
index 78c671d..2b0d044 100644
--- a/program/include/rcube_sqlite.inc
+++ b/program/include/rcube_sqlite.inc
@@ -20,52 +20,58 @@
 
 */
 
+/**
+ * Callback functions for sqlite database interface
+ *
+ * @package Database
+ */
+
 
 function rcube_sqlite_from_unixtime($timestamp)
   {
-	$timestamp = trim($timestamp);
-	if (!preg_match("/^[0-9]+$/is", $timestamp))
-	  $ret = strtotime($timestamp);
-	else
-	  $ret = $timestamp;
-	  
-	$ret = date("Y-m-d H:i:s", $ret);
-	rcube_sqlite_debug("FROM_UNIXTIME ($timestamp) = $ret");
-	return $ret;
+  $timestamp = trim($timestamp);
+  if (!preg_match("/^[0-9]+$/is", $timestamp))
+    $ret = strtotime($timestamp);
+  else
+    $ret = $timestamp;
+    
+  $ret = date("Y-m-d H:i:s", $ret);
+  rcube_sqlite_debug("FROM_UNIXTIME ($timestamp) = $ret");
+  return $ret;
   }
 
 
 function rcube_sqlite_unix_timestamp($timestamp="")
   {
-	$timestamp = trim($timestamp);
-	if (!$timestamp)
-	  $ret = time();
-	else if (!preg_match("/^[0-9]+$/is", $timestamp))
-	  $ret = strtotime($timestamp);
-	else
-	  $ret = $timestamp;
+  $timestamp = trim($timestamp);
+  if (!$timestamp)
+    $ret = time();
+  else if (!preg_match("/^[0-9]+$/is", $timestamp))
+    $ret = strtotime($timestamp);
+  else
+    $ret = $timestamp;
 
-	rcube_sqlite_debug("UNIX_TIMESTAMP ($timestamp) = $ret");
-	return $ret;
+  rcube_sqlite_debug("UNIX_TIMESTAMP ($timestamp) = $ret");
+  return $ret;
   }
 
 
 function rcube_sqlite_now()
   {
-	rcube_sqlite_debug("NOW() = ".date("Y-m-d H:i:s"));
-	return date("Y-m-d H:i:s");
+  rcube_sqlite_debug("NOW() = ".date("Y-m-d H:i:s"));
+  return date("Y-m-d H:i:s");
   }
 
 
 function rcube_sqlite_md5($str)
   {
-	return md5($str);
+  return md5($str);
   }
 
 
 function rcube_sqlite_debug($str)
   {
-	//console($str);
+  //console($str);
   }
-	
+  
 ?>
\ No newline at end of file

--
Gitblit v1.9.1