thomascube
2008-04-12 47124c2279382714afd8dbe4a867a867ea179199
Changed codebase to PHP5 with autoloader + added some new classes from the devel-vnext branch

7 files added
9 files renamed
31 files modified
2 files deleted
4799 ■■■■■ changed files
CHANGELOG 19 ●●●●● patch | view | raw | blame | history
INSTALL 2 ●●● patch | view | raw | blame | history
README 4 ●●●● patch | view | raw | blame | history
bin/html2text.php 18 ●●●● patch | view | raw | blame | history
bin/modcss.php 6 ●●●●● patch | view | raw | blame | history
bin/msgexport.sh 8 ●●●● patch | view | raw | blame | history
bin/msgimport.sh 8 ●●●● patch | view | raw | blame | history
config/main.inc.php.dist 3 ●●●●● patch | view | raw | blame | history
index.php 157 ●●●●● patch | view | raw | blame | history
installer/check.php 2 ●●● patch | view | raw | blame | history
installer/config.php 77 ●●●● patch | view | raw | blame | history
installer/index.php 23 ●●●● patch | view | raw | blame | history
installer/test.php 36 ●●●●● patch | view | raw | blame | history
installer/welcome.html 2 ●●● patch | view | raw | blame | history
program/include/bugs.inc 4 ●●●● patch | view | raw | blame | history
program/include/html.php 642 ●●●●● patch | view | raw | blame | history
program/include/iniset.php 98 ●●●●● patch | view | raw | blame | history
program/include/main.inc 89 ●●●●● patch | view | raw | blame | history
program/include/rcmail_template.inc 948 ●●●●● patch | view | raw | blame | history
program/include/rcube_browser.php 75 ●●●●● patch | view | raw | blame | history
program/include/rcube_contacts.php 57 ●●●●● patch | view | raw | blame | history
program/include/rcube_db.php 11 ●●●● patch | view | raw | blame | history
program/include/rcube_html.inc 667 ●●●●● patch | view | raw | blame | history
program/include/rcube_html_page.php 256 ●●●●● patch | view | raw | blame | history
program/include/rcube_imap.php 5 ●●●●● patch | view | raw | blame | history
program/include/rcube_json_output.php 237 ●●●●● patch | view | raw | blame | history
program/include/rcube_ldap.php 6 ●●●● patch | view | raw | blame | history
program/include/rcube_mail_mime.php 63 ●●●● patch | view | raw | blame | history
program/include/rcube_mdb2.php 11 ●●●● patch | view | raw | blame | history
program/include/rcube_result_set.php 74 ●●●●● patch | view | raw | blame | history
program/include/rcube_shared.inc 12 ●●●● patch | view | raw | blame | history
program/include/rcube_template.php 1004 ●●●●● patch | view | raw | blame | history
program/include/rcube_user.php patch | view | raw | blame | history
program/js/app.js 35 ●●●● patch | view | raw | blame | history
program/lib/html2text.php patch | view | raw | blame | history
program/steps/addressbook/edit.inc 6 ●●●● patch | view | raw | blame | history
program/steps/addressbook/func.inc 7 ●●●● patch | view | raw | blame | history
program/steps/error.inc 2 ●●● patch | view | raw | blame | history
program/steps/mail/addcontact.inc 2 ●●●●● patch | view | raw | blame | history
program/steps/mail/compose.inc 38 ●●●●● patch | view | raw | blame | history
program/steps/mail/func.inc 3 ●●●● patch | view | raw | blame | history
program/steps/mail/get.inc 2 ●●● patch | view | raw | blame | history
program/steps/mail/sendmail.inc 13 ●●●●● patch | view | raw | blame | history
program/steps/mail/sendmdn.inc 2 ●●●●● patch | view | raw | blame | history
program/steps/mail/show.inc 23 ●●●●● patch | view | raw | blame | history
program/steps/settings/edit_identity.inc 4 ●●●● patch | view | raw | blame | history
program/steps/settings/func.inc 24 ●●●● patch | view | raw | blame | history
program/steps/settings/identities.inc 2 ●●● patch | view | raw | blame | history
program/steps/settings/manage_folders.inc 12 ●●●● patch | view | raw | blame | history
CHANGELOG
@@ -1,14 +1,19 @@
CHANGELOG RoundCube Webmail
---------------------------
2008/04/11 (alec)
2008/04/12 (thomasb)
----------
- Changed codebase to PHP5 with autoloader
- Added some new classes from devel-vnext branch
2008/04/11 (alec)
----------
- Mark as read in one action with message preview (#1484972)
- Delete redundant quota reads (#1484972)
- Add options for empty trash and expunge inbox on logout (#1483863)
2008/04/10 (alec)
----------
- Add rows highlighting in onmousemove on ksearch list
- Remove lines wrapping when displaying message
- Fix month localization
@@ -16,7 +21,7 @@
- Fix debug (ajax) console 
2008/04/02 (alec)
----------
- Updated timezones list (#1484908)
- Fix design in Settings (#1484799)
- Fix deleting messages after clicking on "All" (#1484838)
@@ -24,21 +29,21 @@
- Fix creating a new folder w/a comma in its name (#1484681)
2008/04/01 (thomasb)
----------
- Fix Enter problem on login (#1484839)
- Make the http-received header in outgoing mails configurable
2008/03/30 (till)
----------
- Fix Firefox problem with ob_gzhandler (#1484932)
- Improve message previewpane - less loading (#1484316)
2008/03/28 (thomasb)
----------
- Disable installer by default; add config option to enable it again 
2008/03/24 (till)
----------
- Don't send mark requests for already marked messages (#1484906)
- Fix "quote inside a quote" (#1484783)
INSTALL
@@ -11,7 +11,7 @@
* The Apache or Lighttpd Webserver
* .htaccess support allowing overrides for DirectoryIndex
* PHP Version 4.3.1 or greater including
* PHP Version 5.2 or greater including
   - PCRE (perl compatible regular expression)
   - libiconv (recommended)
   - mbstring (optional)
README
@@ -4,8 +4,8 @@
ATTENTION
---------
This is just a snapshot of the current SVN repository and is NOT A STABLE
version of RoundCube. There have been major changes since the latest release
so please read the update instructions carefully. It's not recommended to
version of RoundCube. Unlike the latest release this version requires PHP 5
and does not work on a webserver with PHP 4. It's not recommended to
replace an existing installation of RoundCube with this version. Also using
a separate database or this installation is highly recommended.
bin/html2text.php
@@ -1,21 +1,11 @@
<?php
require_once('../program/lib/html2text.inc');
define('INSTALL_PATH', realpath('./../') . '/');
require INSTALL_PATH.'program/include/iniset.php';
$htmlText = $HTTP_RAW_POST_DATA;
$converter = new html2text($htmlText);
$converter = new html2text($HTTP_RAW_POST_DATA);
header('Content-Type: text/plain; charset=UTF-8');
$plaintext = $converter->get_text();
$phpver = explode('.', phpversion());
$vernum = $phpver[0] . $phpver[1] . $phpver[2];
# html_entity_decode doesn't handle UTF character sets in PHP 4.x
if (($vernum >= 500) && function_exists('html_entity_decode'))
    print html_entity_decode($plaintext, ENT_COMPAT, 'UTF-8');
else
    print $plaintext;
print html_entity_decode($converter->get_text(), ENT_COMPAT, 'UTF-8');
?>
bin/modcss.php
@@ -19,10 +19,8 @@
*/
$INSTALL_PATH = realpath("./../") . "/";
ini_set('include_path', $INSTALL_PATH.PATH_SEPARATOR.$INSTALL_PATH.'program'.PATH_SEPARATOR.ini_get('include_path'));
require 'include/main.inc';
define('INSTALL_PATH', realpath('./../') . '/');
require INSTALL_PATH.'program/include/iniset.php';
$source = "";
if ($url = preg_replace('/[^a-z0-9.-_\?\$&=%]/i', '', $_GET['u']))
bin/msgexport.sh
@@ -1,14 +1,10 @@
#!/usr/bin/php -qC 
<?php
$CWD = $INSTALL_PATH = preg_replace('/bin\/$/', '', getcwd() . '/');
ini_set('include_path',  ini_get('include_path') . PATH_SEPARATOR . $CWD.'program/');
define('INSTALL_PATH', preg_replace('/bin\/$/', '', getcwd()) . '/');
ini_set('memory_limit', -1);
require_once('include/rcube_shared.inc');
require_once('include/rcube_imap.inc');
require_once('include/main.inc');
require_once('include/bugs.inc');
require_once INSTALL_PATH.'program/include/iniset.php';
/**
 * Parse commandline arguments into a hash array
bin/msgimport.sh
File was renamed from bin/msgimport
@@ -1,14 +1,10 @@
#!/usr/bin/php -qC 
<?php
$CWD = $INSTALL_PATH = preg_replace('/bin\/$/', '', getcwd() . '/');
ini_set('include_path',  ini_get('include_path') . PATH_SEPARATOR . $CWD.'program/');
define('INSTALL_PATH', preg_replace('/bin\/$/', '', getcwd()) . '/');
ini_set('memory_limit', -1);
require_once('include/rcube_shared.inc');
require_once('include/rcube_imap.inc');
require_once('include/main.inc');
require_once('include/bugs.inc');
require_once INSTALL_PATH.'program/include/iniset.php';
/**
 * Parse commandline arguments into a hash array
config/main.inc.php.dist
@@ -240,9 +240,6 @@
// don't allow these settings to be overriden by the user
$rcmail_config['dont_override'] = array();
// list of configuration option names that need to be available in Javascript.
$rcmail_config['javascript_config'] = array('read_when_deleted', 'flag_for_deletion');
// try to load host-specific configuration
$rcmail_config['include_host_config'] = false;
index.php
@@ -40,54 +40,12 @@
*/
// application constants
define('RCMAIL_VERSION', '0.1-trunk');
define('RCMAIL_CHARSET', 'UTF-8');
define('JS_OBJECT_NAME', 'rcmail');
// include environment
require_once 'program/include/iniset.php';
// define global vars
$OUTPUT_TYPE = 'html';
$INSTALL_PATH = dirname(__FILE__);
$MAIN_TASKS = array('mail','settings','addressbook','logout');
if (empty($INSTALL_PATH))
  $INSTALL_PATH = './';
else
  $INSTALL_PATH .= '/';
// make sure path_separator is defined
if (!defined('PATH_SEPARATOR'))
  define('PATH_SEPARATOR', (eregi('win', PHP_OS) ? ';' : ':'));
// RC include folders MUST be included FIRST to avoid other
// possible not compatible libraries (i.e PEAR) to be included
// instead the ones provided by RC
ini_set('include_path', $INSTALL_PATH.PATH_SEPARATOR.$INSTALL_PATH.'program'.PATH_SEPARATOR.$INSTALL_PATH.'program/lib'.PATH_SEPARATOR.ini_get('include_path'));
ini_set('session.name', 'roundcube_sessid');
ini_set('session.use_cookies', 1);
ini_set('session.gc_maxlifetime', 21600);
ini_set('session.gc_divisor', 500);
ini_set('error_reporting', E_ALL&~E_NOTICE);
set_magic_quotes_runtime(0);
// increase maximum execution time for php scripts
// (does not work in safe mode)
if (!ini_get('safe_mode')) @set_time_limit(120);
// include base files
require_once('include/rcube_shared.inc');
require_once('include/rcube_imap.inc');
require_once('include/bugs.inc');
require_once('include/main.inc');
require_once('PEAR.php');
// set PEAR error handling
// PEAR::setErrorHandling(PEAR_ERROR_TRIGGER, E_USER_NOTICE);
// catch some url/post parameters
$_task = strip_quotes(get_input_value('_task', RCUBE_INPUT_GPC));
@@ -100,17 +58,16 @@
// set output buffering
if ($_action != 'get' && $_action != 'viewsource')
{
if ($_action != 'get' && $_action != 'viewsource') {
  // use gzip compression if supported
  if (function_exists('ob_gzhandler')
    && !ini_get('zlib.output_compression')
    && ini_get('output_handler') != 'ob_gzhandler')
  {
      && !ini_get('zlib.output_compression')
      && ini_get('output_handler') != 'ob_gzhandler') {
    ob_start('ob_gzhandler');
  }
  else
  else {
    ob_start();
  }
}
@@ -123,20 +80,23 @@
// add framed parameter
if ($_framed)
{
if ($_framed) {
  $COMM_PATH .= '&_framed=1';
  $SESS_HIDDEN_FIELD .= "\n".'<input type="hidden" name="_framed" value="1" />';
}
// init necessary objects for GUI
rcmail_load_gui();
// init output class
if (!empty($_GET['_remote']) || !empty($_POST['_remote'])) {
  rcmail_init_json();
}
else {
  rcmail_load_gui();
}
// check DB connections and exit on failure
if ($err_str = $DB->is_error())
{
if ($err_str = $DB->is_error()) {
  raise_error(array(
    'code' => 603,
    'type' => 'db',
@@ -145,24 +105,21 @@
// error steps
if ($_action=='error' && !empty($_GET['_code']))
if ($_action=='error' && !empty($_GET['_code'])) {
  raise_error(array('code' => hexdec($_GET['_code'])), FALSE, TRUE);
}
// try to log in
if ($_action=='login' && $_task=='mail')
{
if ($_action=='login' && $_task=='mail') {
  $host = rcmail_autoselect_host();
  
  // check if client supports cookies
  if (empty($_COOKIE))
  {
  if (empty($_COOKIE)) {
    $OUTPUT->show_message("cookiesdisabled", 'warning');
  }
  else if ($_SESSION['temp'] && !empty($_POST['_user']) && isset($_POST['_pass']) &&
           rcmail_login(trim(get_input_value('_user', RCUBE_INPUT_POST), ' '),
              get_input_value('_pass', RCUBE_INPUT_POST, true, 'ISO-8859-1'), $host))
  {
              get_input_value('_pass', RCUBE_INPUT_POST, true, 'ISO-8859-1'), $host)) {
    // create new session ID
    unset($_SESSION['temp']);
    sess_regenerate_id();
@@ -174,26 +131,22 @@
    header("Location: $COMM_PATH");
    exit;
  }
  else
  {
  else {
    $OUTPUT->show_message($IMAP->error_code == -1 ? 'imaperror' : 'loginfailed', 'warning');
    rcmail_kill_session();
  }
}
// end session
else if (($_task=='logout' || $_action=='logout') && isset($_SESSION['user_id']))
{
else if (($_task=='logout' || $_action=='logout') && isset($_SESSION['user_id'])) {
  $OUTPUT->show_message('loggedout');
  rcmail_logout_actions();
  rcmail_kill_session();
}
// check session and auth cookie
else if ($_action != 'login' && $_SESSION['user_id'] && $_action != 'send')
{
  if (!rcmail_authenticate_session())
  {
else if ($_action != 'login' && $_SESSION['user_id'] && $_action != 'send') {
  if (!rcmail_authenticate_session()) {
    $OUTPUT->show_message('sessionerror', 'error');
    rcmail_kill_session();
  }
@@ -201,22 +154,20 @@
// log in to imap server
if (!empty($USER->ID) && $_task=='mail')
{
if (!empty($USER->ID) && $_task=='mail') {
  $conn = $IMAP->connect($_SESSION['imap_host'], $_SESSION['username'], decrypt_passwd($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl']);
  if (!$conn)
  {
  if (!$conn) {
    $OUTPUT->show_message($IMAP->error_code == -1 ? 'imaperror' : 'sessionerror', 'error');
    rcmail_kill_session();
  }
  else
  else {
    rcmail_set_imap_prop();
  }
}
// not logged in -> set task to 'login
if (empty($USER->ID))
{
if (empty($USER->ID)) {
  if ($OUTPUT->ajax_call)
    $OUTPUT->remote_response("setTimeout(\"location.href='\"+this.env.comm_path+\"'\", 2000);");
  
@@ -225,10 +176,8 @@
// check client X-header to verify request origin
if ($OUTPUT->ajax_call)
{
  if (empty($CONFIG['devel_mode']) && !rc_request_header('X-RoundCube-Referer'))
  {
if ($OUTPUT->ajax_call) {
  if (empty($CONFIG['devel_mode']) && !rc_request_header('X-RoundCube-Referer')) {
    header('HTTP/1.1 404 Not Found');
    die("Invalid Request");
  }
@@ -237,24 +186,25 @@
// set task and action to client
$OUTPUT->set_env('task', $_task);
if (!empty($_action))
if (!empty($_action)) {
  $OUTPUT->set_env('action', $_action);
}
// not logged in -> show login page
if (empty($USER->ID))
{
if (empty($USER->ID)) {
  // check if installer is still active
  if ($CONFIG['enable_installer'] && is_readable('./installer/index.php'))
    $OUTPUT->add_footer('
  <div style="background:#ef9398; border:2px solid #dc5757; padding:0.5em; margin:2em auto; width:50em">
  <h2 style="margin-top:0.2em">Installer script is still accessible</h2>
  <p>The install script of your RoundCube installation is still stored in its default location!</p>
  <p>Please <b>remove</b> the whole <tt>installer</tt> folder from the RoundCube directory because
  these files may expose sensitive configuration data like server passwords and encryption keys
  to the public. Make sure you cannot access the <a href="./installer/">installer script</a> from your browser.</p>
  </div>');
  if ($CONFIG['enable_installer'] && is_readable('./installer/index.php')) {
    $OUTPUT->add_footer(html::div(array('style' => "background:#ef9398; border:2px solid #dc5757; padding:0.5em; margin:2em auto; width:50em"),
      html::tag('h2', array('style' => "margin-top:0.2em"), "Installer script is still accessible") .
      html::p(null, "The install script of your RoundCube installation is still stored in its default location!") .
      html::p(null, "Please <b>remove</b> the whole <tt>installer</tt> folder from the RoundCube directory because .
        these files may expose sensitive configuration data like server passwords and encryption keys
        to the public. Make sure you cannot access the <a href=\"./installer/\">installer script</a> from your browser.")
      )
    );
  }
  
  $OUTPUT->task = 'login';
  $OUTPUT->send('login');
@@ -263,16 +213,14 @@
// handle keep-alive signal
if ($_action=='keep-alive')
{
if ($_action=='keep-alive') {
  $OUTPUT->reset();
  $OUTPUT->send('');
  exit;
}
// include task specific files
if ($_task=='mail')
{
if ($_task=='mail') {
  include_once('program/steps/mail/func.inc');
  
  if ($_action=='show' || $_action=='preview' || $_action=='print')
@@ -327,13 +275,12 @@
    include('program/steps/mail/rss.inc');
    
  // make sure the message count is refreshed
  $IMAP->messagecount($_SESSION['mbox'], 'ALL', TRUE);
  $IMAP->messagecount($_SESSION['mbox'], 'ALL', true);
}
// include task specific files
if ($_task=='addressbook')
{
if ($_task=='addressbook') {
  include_once('program/steps/addressbook/func.inc');
  if ($_action=='save')
@@ -363,8 +310,7 @@
// include task specific files
if ($_task=='settings')
{
if ($_task=='settings') {
  include_once('program/steps/settings/func.inc');
  if ($_action=='save-identity')
@@ -385,7 +331,6 @@
  if ($_action=='folders' || $_action=='subscribe' || $_action=='unsubscribe' ||
      $_action=='create-folder' || $_action=='rename-folder' || $_action=='delete-folder')
    include('program/steps/settings/manage_folders.inc');
}
@@ -399,6 +344,6 @@
  'type' => 'php',
  'line' => __LINE__,
  'file' => __FILE__,
  'message' => "Invalid request"), TRUE, TRUE);
  'message' => "Invalid request"), true, true);
                      
?>
installer/check.php
@@ -37,7 +37,7 @@
<h3>Checking PHP version</h3>
<?php
define('MIN_PHP_VERSION', '4.3.1');
define('MIN_PHP_VERSION', '5.2.0');
if (version_compare(PHP_VERSION, MIN_PHP_VERSION, '>=')) {
    $RCI->pass('Version', 'PHP ' . PHP_VERSION . ' detected');
} else {
installer/config.php
@@ -2,9 +2,6 @@
<input type="hidden" name="_step" value="2" />
<?php
ini_set('display_errors', 1);
require_once 'include/rcube_html.inc';
// also load the default config to fill in the fields
$RCI->load_defaults();
@@ -29,7 +26,7 @@
  echo ' within the <tt>config/</tt> directory of your RoundCube installation.<br/>';
  echo ' Make sure that there are no characters outside the <tt>&lt;?php ?&gt;</tt> brackets when saving the files.</p>';
  
  $textbox = new textarea(array('rows' => 16, 'cols' => 60, 'class' => "configfile"));
  $textbox = new html_textarea(array('rows' => 16, 'cols' => 60, 'class' => "configfile"));
  
  echo '<div><em>main.inc.php</em></div>';
  echo $textbox->show($RCI->create_config('main'));
@@ -56,7 +53,7 @@
<?php
/*
$value = $RCI->getprop('debug_level');
$check_debug = new checkbox(array('name' => '_debug_level[]'));
$check_debug = new html_checkbox(array('name' => '_debug_level[]'));
echo $check_debug->show(($value & 1) ? 1 : 0 , array('value' => 1, 'id' => 'cfgdebug1'));
echo '<label for="cfgdebug1">Log errors</label><br />';
@@ -74,7 +71,7 @@
<dd>
<?php
$input_prodname = new textfield(array('name' => '_product_name', 'size' => 30, 'id' => "cfgprodname"));
$input_prodname = new html_inputfield(array('name' => '_product_name', 'size' => 30, 'id' => "cfgprodname"));
echo $input_prodname->show($RCI->getprop('product_name'));
?>
@@ -85,7 +82,7 @@
<dd>
<?php
$input_skinpath = new textfield(array('name' => '_skin_path', 'size' => 30, 'id' => "cfgskinpath"));
$input_skinpath = new html_inputfield(array('name' => '_skin_path', 'size' => 30, 'id' => "cfgskinpath"));
echo $input_skinpath->show($RCI->getprop('skin_path'));
?>
@@ -96,7 +93,7 @@
<dd>
<?php
$input_tempdir = new textfield(array('name' => '_temp_dir', 'size' => 30, 'id' => "cfgtempdir"));
$input_tempdir = new html_inputfield(array('name' => '_temp_dir', 'size' => 30, 'id' => "cfgtempdir"));
echo $input_tempdir->show($RCI->getprop('temp_dir'));
?>
@@ -107,7 +104,7 @@
<dd>
<?php
$input_logdir = new textfield(array('name' => '_log_dir', 'size' => 30, 'id' => "cfglogdir"));
$input_logdir = new html_inputfield(array('name' => '_log_dir', 'size' => 30, 'id' => "cfglogdir"));
echo $input_logdir->show($RCI->getprop('log_dir'));
?>
@@ -118,7 +115,7 @@
<dd>
<?php
$check_ipcheck = new checkbox(array('name' => '_ip_check', 'id' => "cfgipcheck"));
$check_ipcheck = new html_checkbox(array('name' => '_ip_check', 'id' => "cfgipcheck"));
echo $check_ipcheck->show(intval($RCI->getprop('ip_check')), array('value' => 1));
?>
@@ -131,7 +128,7 @@
<dd>
<?php
$input_deskey = new textfield(array('name' => '_des_key', 'size' => 30, 'id' => "cfgdeskey"));
$input_deskey = new html_inputfield(array('name' => '_des_key', 'size' => 30, 'id' => "cfgdeskey"));
echo $input_deskey->show($RCI->getprop('des_key'));
?>
@@ -144,7 +141,7 @@
<dd>
<?php
$check_caching = new checkbox(array('name' => '_enable_caching', 'id' => "cfgcache"));
$check_caching = new html_checkbox(array('name' => '_enable_caching', 'id' => "cfgcache"));
echo $check_caching->show(intval($RCI->getprop('enable_caching')), array('value' => 1));
?>
@@ -155,7 +152,7 @@
<dd>
<?php
$check_caching = new checkbox(array('name' => '_enable_spellcheck', 'id' => "cfgspellcheck"));
$check_caching = new html_checkbox(array('name' => '_enable_spellcheck', 'id' => "cfgspellcheck"));
echo $check_caching->show(intval($RCI->getprop('enable_spellcheck')), array('value' => 1));
?>
@@ -168,7 +165,7 @@
<dd>
<?php
$select_mdnreq = new select(array('name' => '_mdn_requests', 'id' => "cfgmdnreq"));
$select_mdnreq = new html_select(array('name' => '_mdn_requests', 'id' => "cfgmdnreq"));
$select_mdnreq->add(array('ask the user', 'send automatically', 'ignore'), array(0, 1, 2));
echo $select_mdnreq->show(intval($RCI->getprop('mdn_requests')));
@@ -192,17 +189,17 @@
$supported_dbs = array('MySQL' => 'mysql', 'MySQLi' => 'mysqli',
    'PgSQL' => 'pgsql', 'SQLite' => 'sqlite');
$select_dbtype = new select(array('name' => '_dbtype', 'id' => "cfgdbtype"));
$select_dbtype = new html_select(array('name' => '_dbtype', 'id' => "cfgdbtype"));
foreach ($supported_dbs AS $database => $ext) {
    if (extension_loaded($ext)) {
        $select_dbtype->add($database, $ext);
    }
}
$input_dbhost = new textfield(array('name' => '_dbhost', 'size' => 20, 'id' => "cfgdbhost"));
$input_dbname = new textfield(array('name' => '_dbname', 'size' => 20, 'id' => "cfgdbname"));
$input_dbuser = new textfield(array('name' => '_dbuser', 'size' => 20, 'id' => "cfgdbuser"));
$input_dbpass = new textfield(array('name' => '_dbpass', 'size' => 20, 'id' => "cfgdbpass"));
$input_dbhost = new html_inputfield(array('name' => '_dbhost', 'size' => 20, 'id' => "cfgdbhost"));
$input_dbname = new html_inputfield(array('name' => '_dbname', 'size' => 20, 'id' => "cfgdbname"));
$input_dbuser = new html_inputfield(array('name' => '_dbuser', 'size' => 20, 'id' => "cfgdbuser"));
$input_dbpass = new html_inputfield(array('name' => '_dbpass', 'size' => 20, 'id' => "cfgdbpass"));
$dsnw = DB::parseDSN($RCI->getprop('db_dsnw'));
@@ -228,7 +225,7 @@
@include_once 'DB.php';
@include_once 'MDB2.php';
$select_dbba = new select(array('name' => '_db_backend', 'id' => "cfgdbba"));
$select_dbba = new html_select(array('name' => '_db_backend', 'id' => "cfgdbba"));
if (class_exists('DB'))
  $select_dbba->add('DB', 'db');
@@ -254,7 +251,7 @@
<div id="defaulthostlist">
<?php
$text_imaphost = new textfield(array('name' => '_default_host[]', 'size' => 30));
$text_imaphost = new html_inputfield(array('name' => '_default_host[]', 'size' => 30));
$default_hosts = $RCI->get_hostlist();
if (empty($default_hosts))
@@ -279,7 +276,7 @@
<dd>
<?php
$text_imapport = new textfield(array('name' => '_default_port', 'size' => 6, 'id' => "cfgimapport"));
$text_imapport = new html_inputfield(array('name' => '_default_port', 'size' => 6, 'id' => "cfgimapport"));
echo $text_imapport->show($RCI->getprop('default_port'));
?>
@@ -290,7 +287,7 @@
<dd>
<?php
$text_userdomain = new textfield(array('name' => '_username_domain', 'size' => 30, 'id' => "cfguserdomain"));
$text_userdomain = new html_inputfield(array('name' => '_username_domain', 'size' => 30, 'id' => "cfguserdomain"));
echo $text_userdomain->show($RCI->getprop('username_domain'));
?>
@@ -303,7 +300,7 @@
<dd>
<?php
$check_autocreate = new checkbox(array('name' => '_auto_create_user', 'id' => "cfgautocreate"));
$check_autocreate = new html_checkbox(array('name' => '_auto_create_user', 'id' => "cfgautocreate"));
echo $check_autocreate->show(intval($RCI->getprop('auto_create_user')), array('value' => 1));
?>
@@ -320,7 +317,7 @@
<dd>
<?php
$text_sentmbox = new textfield(array('name' => '_sent_mbox', 'size' => 20, 'id' => "cfgsentmbox"));
$text_sentmbox = new html_inputfield(array('name' => '_sent_mbox', 'size' => 20, 'id' => "cfgsentmbox"));
echo $text_sentmbox->show($RCI->getprop('sent_mbox'));
?>
@@ -333,7 +330,7 @@
<dd>
<?php
$text_trashmbox = new textfield(array('name' => '_trash_mbox', 'size' => 20, 'id' => "cfgtrashmbox"));
$text_trashmbox = new html_inputfield(array('name' => '_trash_mbox', 'size' => 20, 'id' => "cfgtrashmbox"));
echo $text_trashmbox->show($RCI->getprop('trash_mbox'));
?>
@@ -346,7 +343,7 @@
<dd>
<?php
$text_draftsmbox = new textfield(array('name' => '_drafts_mbox', 'size' => 20, 'id' => "cfgdraftsmbox"));
$text_draftsmbox = new html_inputfield(array('name' => '_drafts_mbox', 'size' => 20, 'id' => "cfgdraftsmbox"));
echo $text_draftsmbox->show($RCI->getprop('drafts_mbox'));
?>
@@ -364,7 +361,7 @@
<dd>
<?php
$text_smtphost = new textfield(array('name' => '_smtp_server', 'size' => 30, 'id' => "cfgsmtphost"));
$text_smtphost = new html_inputfield(array('name' => '_smtp_server', 'size' => 30, 'id' => "cfgsmtphost"));
echo $text_smtphost->show($RCI->getprop('smtp_server'));
?>
@@ -377,7 +374,7 @@
<dd>
<?php
$text_smtpport = new textfield(array('name' => '_smtp_port', 'size' => 6, 'id' => "cfgsmtpport"));
$text_smtpport = new html_inputfield(array('name' => '_smtp_port', 'size' => 6, 'id' => "cfgsmtpport"));
echo $text_smtpport->show($RCI->getprop('smtp_port'));
?>
@@ -388,8 +385,8 @@
<dd>
<?php
$text_smtpuser = new textfield(array('name' => '_smtp_user', 'size' => 20, 'id' => "cfgsmtpuser"));
$text_smtppass = new textfield(array('name' => '_smtp_pass', 'size' => 20, 'id' => "cfgsmtppass"));
$text_smtpuser = new html_inputfield(array('name' => '_smtp_user', 'size' => 20, 'id' => "cfgsmtpuser"));
$text_smtppass = new html_inputfield(array('name' => '_smtp_pass', 'size' => 20, 'id' => "cfgsmtppass"));
echo $text_smtpuser->show($RCI->getprop('smtp_user'));
echo $text_smtppass->show($RCI->getprop('smtp_pass'));
@@ -398,7 +395,7 @@
<p>
<?php
$check_smtpuser = new checkbox(array('name' => '_smtp_user_u', 'id' => "cfgsmtpuseru"));
$check_smtpuser = new html_checkbox(array('name' => '_smtp_user_u', 'id' => "cfgsmtpuseru"));
echo $check_smtpuser->show($RCI->getprop('smtp_user') == '%u' || $_POST['_smtp_user_u'] ? 1 : 0, array('value' => 1));
?>
@@ -410,7 +407,7 @@
<dd>
<?php
/*
$select_smtpauth = new select(array('name' => '_smtp_auth_type', 'id' => "cfgsmtpauth"));
$select_smtpauth = new html_select(array('name' => '_smtp_auth_type', 'id' => "cfgsmtpauth"));
$select_smtpauth->add(array('(auto)', 'PLAIN', 'DIGEST-MD5', 'CRAM-MD5', 'LOGIN'), array('0', 'PLAIN', 'DIGEST-MD5', 'CRAM-MD5', 'LOGIN'));
echo $select_smtpauth->show(intval($RCI->getprop('smtp_auth_type')));
*/
@@ -422,7 +419,7 @@
<dd>
<?php
$check_smtplog = new checkbox(array('name' => '_smtp_log', 'id' => "cfgsmtplog"));
$check_smtplog = new html_checkbox(array('name' => '_smtp_log', 'id' => "cfgsmtplog"));
echo $check_smtplog->show(intval($RCI->getprop('smtp_log')), array('value' => 1));
?>
@@ -441,7 +438,7 @@
<dd>
<?php
$input_locale = new textfield(array('name' => '_locale_string', 'size' => 6, 'id' => "cfglocale"));
$input_locale = new html_inputfield(array('name' => '_locale_string', 'size' => 6, 'id' => "cfglocale"));
echo $input_locale->show($RCI->getprop('locale_string'));
?>
@@ -453,7 +450,7 @@
<dd>
<?php
$input_pagesize = new textfield(array('name' => '_pagesize', 'size' => 6, 'id' => "cfgpagesize"));
$input_pagesize = new html_inputfield(array('name' => '_pagesize', 'size' => 6, 'id' => "cfgpagesize"));
echo $input_pagesize->show($RCI->getprop('pagesize'));
?>
@@ -464,7 +461,7 @@
<dd>
<?php
$check_htmlview = new checkbox(array('name' => '_prefer_html', 'id' => "cfghtmlview", 'value' => 1));
$check_htmlview = new html_checkbox(array('name' => '_prefer_html', 'id' => "cfghtmlview", 'value' => 1));
echo $check_htmlview->show(intval($RCI->getprop('prefer_html')));
?>
@@ -475,7 +472,7 @@
<dd>
<?php
$check_prevpane = new checkbox(array('name' => '_preview_pane', 'id' => "cfgprevpane", 'value' => 1));
$check_prevpane = new html_checkbox(array('name' => '_preview_pane', 'id' => "cfgprevpane", 'value' => 1));
echo $check_prevpane->show(intval($RCI->getprop('preview_pane')));
?>
@@ -486,7 +483,7 @@
<dd>
<?php
$check_htmlcomp = new checkbox(array('name' => '_htmleditor', 'id' => "cfghtmlcompose", 'value' => 1));
$check_htmlcomp = new html_checkbox(array('name' => '_htmleditor', 'id' => "cfghtmlcompose", 'value' => 1));
echo $check_htmlcomp->show(intval($RCI->getprop('htmleditor')));
?>
@@ -498,7 +495,7 @@
<label for="cfgautosave">Save compose message every</label>
<?php
$select_autosave = new select(array('name' => '_draft_autosave', 'id' => 'cfgautosave'));
$select_autosave = new html_select(array('name' => '_draft_autosave', 'id' => 'cfgautosave'));
$select_autosave->add('never', 0);
foreach (array(3, 5, 10) as $i => $min)
  $select_autosave->add("$min min", $min*60);
installer/index.php
@@ -3,7 +3,25 @@
ini_set('error_reporting', E_ALL&~E_NOTICE);
ini_set('display_errors', 1);
define('INSTALL_PATH', realpath(dirname(__FILE__) . '/../').'/');
$include_path  = INSTALL_PATH . 'program/lib' . PATH_SEPARATOR . INSTALL_PATH . 'program' . PATH_SEPARATOR . INSTALL_PATH . 'program/include' . PATH_SEPARATOR . ini_get('include_path');
set_include_path($include_path);
session_start();
/**
 * Use PHP5 autoload for dynamic class loading
 * (copy from program/incllude/iniset.php)
 */
function __autoload($classname)
{
  $filename = preg_replace(
      array('/MDB2_(.+)/', '/Mail_(.+)/', '/^html_.+/', '/^utf8$/'),
      array('MDB2/\\1', 'Mail/\\1', 'html', 'utf8.class'),
      $classname
  );
  include_once $filename. '.php';
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
@@ -32,11 +50,6 @@
<?php
  $docroot = realpath(dirname(__FILE__) . '/../');
  $include_path  = $docroot . '/program/lib' . PATH_SEPARATOR . $docroot . '/program' . PATH_SEPARATOR . ini_get('include_path');
  set_include_path($include_path);
  require_once 'rcube_install.php';
  $RCI = rcube_install::get_instance();
  $RCI->load_config();
installer/test.php
@@ -3,10 +3,8 @@
<h3>Check config files</h3>
<?php
require_once 'include/rcube_html.inc';
$read_main = is_readable('../config/main.inc.php');
$read_db = is_readable('../config/db.inc.php');
$read_main = is_readable(INSTALL_PATH.'config/main.inc.php');
$read_db = is_readable(INSTALL_PATH.'config/db.inc.php');
if ($read_main && !empty($RCI->config)) {
  $RCI->pass('main.inc.php');
@@ -38,7 +36,7 @@
if ($RCI->configured) {
    $pass = false;
    foreach (array($RCI->config['temp_dir'],$RCI->config['log_dir']) as $dir) {
        $dirpath = $dir{0} == '/' ? $dir : $docroot . '/' . $dir;
        $dirpath = $dir{0} == '/' ? $dir : INSTALL_PATH . $dir;
        if (is_writable(realpath($dirpath))) {
            $RCI->pass($dir);
            $pass = true;
@@ -68,10 +66,9 @@
        echo 'Backend: ';
        echo 'PEAR::' . strtoupper($RCI->config['db_backend']) . '<br />';
        $_class = 'rcube_' . strtolower($RCI->config['db_backend']);
        require_once 'include/' . $_class . '.inc';
        $dbclass = 'rcube_' . strtolower($RCI->config['db_backend']);
        $DB = new $_class($RCI->config['db_dsnw'], '', false);
        $DB = new $dbclass($RCI->config['db_dsnw'], '', false);
        $DB->db_connect('w');
        if (!($db_error_msg = $DB->is_error())) {
            $RCI->pass('DSN (write)');
@@ -164,11 +161,11 @@
  $pass = $RCI->getprop('smtp_pass', '(none)');
  
  if ($user == '%u') {
    $user_field = new textfield(array('name' => '_smtp_user'));
    $user_field = new html_inputfield(array('name' => '_smtp_user'));
    $user = $user_field->show($_POST['_smtp_user']);
  }
  if ($pass == '%p') {
    $pass_field = new passwordfield(array('name' => '_smtp_pass'));
    $pass_field = new html_passwordfield(array('name' => '_smtp_pass'));
    $pass = $pass_field->show();
  }
  
@@ -176,8 +173,8 @@
  echo "Password: $pass<br />";
}
$from_field = new textfield(array('name' => '_from', 'id' => 'sendmailfrom'));
$to_field = new textfield(array('name' => '_to', 'id' => 'sendmailto'));
$from_field = new html_inputfield(array('name' => '_from', 'id' => 'sendmailfrom'));
$to_field = new html_inputfield(array('name' => '_to', 'id' => 'sendmailto'));
?>
</p>
@@ -186,8 +183,7 @@
if (isset($_POST['sendmail']) && !empty($_POST['_from']) && !empty($_POST['_to'])) {
  
  require_once 'lib/rc_mail_mime.inc';
  require_once 'include/rcube_smtp.inc';
  require_once 'rcube_smtp.inc';
  
  echo '<p>Trying to send email...<br />';
  
@@ -214,7 +210,7 @@
        $CONFIG['smtp_pass'] = $_POST['_smtp_pass'];
      }
      $mail_object  = new rc_mail_mime();
      $mail_object  = new rcube_mail_mime();
      $send_headers = $mail_object->headers($headers);
      
      $status = smtp_mail($headers['From'], $headers['To'],
@@ -271,15 +267,15 @@
$default_hosts = $RCI->get_hostlist();
if (!empty($default_hosts)) {
  $host_field = new select(array('name' => '_host', 'id' => 'imaphost'));
  $host_field = new html_select(array('name' => '_host', 'id' => 'imaphost'));
  $host_field->add($default_hosts);
}
else {
  $host_field = new textfield(array('name' => '_host', 'id' => 'imaphost'));
  $host_field = new html_inputfield(array('name' => '_host', 'id' => 'imaphost'));
}
$user_field = new textfield(array('name' => '_user', 'id' => 'imapuser'));
$pass_field = new passwordfield(array('name' => '_pass', 'id' => 'imappass'));
$user_field = new html_inputfield(array('name' => '_user', 'id' => 'imapuser'));
$pass_field = new html_passwordfield(array('name' => '_pass', 'id' => 'imappass'));
?>
@@ -307,8 +303,6 @@
<?php
if (isset($_POST['imaptest']) && !empty($_POST['_host']) && !empty($_POST['_user'])) {
  require_once 'include/rcube_imap.inc';
  
  echo '<p>Connecting to ' . Q($_POST['_host']) . '...<br />';
  
installer/welcome.html
@@ -6,7 +6,7 @@
<p>The basic requirements are:</p>
<ul>
  <li>PHP Version 4.3.1 or greater including
  <li>PHP Version 5.2.0 or greater including
    <ul>
      <li>PCRE (perl compatible regular expression)</li>
      <li>Session support</li>
program/include/bugs.inc
@@ -66,7 +66,7 @@
 */
function log_bug($arg_arr)
{
  global $CONFIG, $INSTALL_PATH;
  global $CONFIG;
  $program = $arg_arr['type']=='xpath' ? 'XPath' : strtoupper($arg_arr['type']);
  // write error to local log file
@@ -81,7 +81,7 @@
      $arg_arr['line']);
                 
    if (empty($CONFIG['log_dir']))
      $CONFIG['log_dir'] = $INSTALL_PATH.'logs';
      $CONFIG['log_dir'] = INSTALL_PATH.'logs';
      
    // try to open specific log file for writing
    if ($fp = @fopen($CONFIG['log_dir'].'/errors', 'a'))
program/include/html.php
New file
@@ -0,0 +1,642 @@
<?php
/*
 +-----------------------------------------------------------------------+
 | program/include/html.php                                              |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2005-2008, RoundCube Dev, - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
 |   Helper class to create valid XHTML code                             |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 +-----------------------------------------------------------------------+
 $Id: $
 */
/**
 * Class for HTML code creation
 *
 * @package HTML
 */
class html
{
    protected $tagname;
    protected $attrib = array();
    protected $allowed;
    protected $content;
    protected static $common_attrib = array('id','class','style','title','align');
    public static $containers = array('div','span','p','h1','h2','h3','form','textarea');
    public static $lc_tags = true;
    /**
     * Constructor
     *
     * @param array Hash array with tag attributes
     */
    public function __construct($attrib = array())
    {
        if (is_array($attrib)) {
            $this->attrib = $attrib;
        }
    }
    /**
     * Return the tag code
     *
     * @return string The finally composed HTML tag
     */
    public function show()
    {
        return self::tag($this->tagname, $this->attrib, $this->content, $this->allowed);
    }
    /****** STATIC METHODS *******/
    /**
     * Generic method to create a HTML tag
     *
     * @param string Tag name
     * @param array  Tag attributes as key/value pairs
     * @param string Optinal Tag content (creates a container tag)
     * @param array  List with allowed attributes, omit to allow all
     * @return string The XHTML tag
     */
    public static function tag($tagname, $attrib = array(), $content = null, $allowed_attrib = null)
    {
        $inline_tags = array('a','span','img');
        $suffix = $attrib['nl'] || ($content && $attrib['nl'] !== false && !in_array($tagname, $inline_tags)) ? "\n" : '';
        $tagname = self::$lc_tags ? strtolower($tagname) : $tagname;
        if ($content || in_array($tagname, self::$containers)) {
            $templ = $attrib['noclose'] ? "<%s%s>%s" : "<%s%s>%s</%s>%s";
            unset($attrib['noclose']);
            return sprintf($templ, $tagname, self::attrib_string($attrib, $allowed_attrib), $content, $tagname, $suffix);
        }
        else {
            return sprintf("<%s%s />%s", $tagname, self::attrib_string($attrib, $allowed_attrib), $suffix);
        }
    }
    /**
     * Derrived method for <div> containers
     *
     * @param mixed  Hash array with tag attributes or string with class name
     * @param string Div content
     * @return string HTML code
     * @see html::tag()
     */
    public static function div($attr = null, $cont = null)
    {
        if (is_string($attr)) {
            $attr = array('class' => $attr);
        }
        return self::tag('div', $attr, $cont, self::$common_attrib);
    }
    /**
     * Derrived method for <p> blocks
     *
     * @param mixed  Hash array with tag attributes or string with class name
     * @param string Paragraph content
     * @return string HTML code
     * @see html::tag()
     */
    public static function p($attr = null, $cont = null)
    {
        if (is_string($attr)) {
            $attr = array('class' => $attr);
        }
        return self::tag('p', $attr, $cont, self::$common_attrib);
    }
    /**
     * Derrived method to create <img />
     *
     * @param mixed Hash array with tag attributes or string with image source (src)
     * @return string HTML code
     * @see html::tag()
     */
    public static function img($attr = null)
    {
        if (is_string($attr)) {
            $attr = array('src' => $attr);
        }
        return self::tag('img', $attr + array('alt' => ''), null, array_merge(self::$common_attrib, array('src','alt','width','height','border','usemap')));
    }
    /**
     * Derrived method for link tags
     *
     * @param mixed  Hash array with tag attributes or string with link location (href)
     * @param string Link content
     * @return string HTML code
     * @see html::tag()
     */
    public static function a($attr, $cont)
    {
        if (is_string($attr)) {
            $attr = array('href' => $attr);
        }
        return self::tag('a', $attr, $cont, array_merge(self::$common_attrib, array('href','target','name','onclick','onmouseover','onmouseout')));
    }
    /**
     * Derrived method for inline span tags
     *
     * @param mixed  Hash array with tag attributes or string with class name
     * @param string Tag content
     * @return string HTML code
     * @see html::tag()
     */
    public static function span($attr, $cont)
    {
        if (is_string($attr)) {
            $attr = array('class' => $attr);
        }
        return self::tag('span', $attr, $cont, self::$common_attrib);
    }
    /**
     * Derrived method for form element labels
     *
     * @param mixed  Hash array with tag attributes or string with 'for' attrib
     * @param string Tag content
     * @return string HTML code
     * @see html::tag()
     */
    public static function label($attr, $cont)
    {
        if (is_string($attr)) {
            $attr = array('for' => $attr);
        }
        return self::tag('label', $attr, $cont, array_merge(self::$common_attrib, array('for')));
    }
    /**
     * Derrived method for line breaks
     *
     * @return string HTML code
     * @see html::tag()
     */
    public static function br()
    {
        return self::tag('br');
    }
    /**
     * Create string with attributes
     *
     * @param array Associative arry with tag attributes
     * @param array List of allowed attributes
     * @return string Valid attribute string
     */
    public static function attrib_string($attrib = array(), $allowed = null)
    {
        if (empty($attrib)) {
            return '';
        }
        $allowed_f = array_flip((array)$allowed);
        $attrib_arr = array();
        foreach ($attrib as $key => $value) {
            // skip size if not numeric
            if (($key=='size' && !is_numeric($value))) {
                continue;
            }
            // ignore "internal" or not allowed attributes
            if ($key == 'nl' || ($allowed && !isset($allowed_f[$key])) || $value === null) {
                continue;
            }
            // skip empty eventhandlers
            if (preg_match('/^on[a-z]+/', $key) && !$value) {
                continue;
            }
            // attributes with no value
            if (in_array($key, array('checked', 'multiple', 'disabled', 'selected'))) {
                if ($value) {
                    $attrib_arr[] = sprintf('%s="%s"', $key, $key);
                }
            }
            else if ($key=='value') {
                $attrib_arr[] = sprintf('%s="%s"', $key, Q($value, 'strict', false));
            }
            else {
                $attrib_arr[] = sprintf('%s="%s"', $key, Q($value));
            }
        }
        return count($attrib_arr) ? ' '.implode(' ', $attrib_arr) : '';
    }
}
/**
 * Class to create an HTML input field
 *
 * @package HTML
 */
class html_inputfield extends html
{
    protected $tagname = 'input';
    protected $type = 'text';
    public function __construct($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 attributes to override
     * @return string HTML output
     */
    public 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;
        }
        // set type
        $this->attrib['type'] = $this->type;
        return parent::show();
    }
}
/**
 * Class to create an HTML password field
 *
 * @package HTML
 */
class html_passwordfield extends html_inputfield
{
    protected $type = 'password';
}
/**
 * Class to create an hidden HTML input field
 *
 * @package HTML
 */
class html_hiddenfield extends html_inputfield
{
    protected $type = 'hidden';
    protected $fields_arr = array();
    protected $newline = true;
    /**
     * Constructor
     *
     * @param array Named tag attributes
     */
    public function __construct($attrib = null)
    {
        if (is_array($attrib)) {
            $this->add($attrib);
        }
    }
    /**
     * Add a hidden field to this instance
     *
     * @param array Named tag attributes
     */
    public function add($attrib)
    {
        $this->fields_arr[] = $attrib;
    }
    /**
     * Create HTML code for the hidden fields
     *
     * @return string Final HTML code
     */
    public function show()
    {
        $out = '';
        foreach ($this->fields_arr as $attrib) {
            $out .= self::tag($this->tagname, array('type' => $this->type) + $attrib);
        }
        return $out;
    }
}
/**
 * Class to create HTML radio buttons
 *
 * @package HTML
 */
class html_radiobutton extends html_inputfield
{
    protected $type = 'radio';
    /**
     * Get HTML code for this object
     *
     * @param string Value of the checked field
     * @param array Additional attributes to override
     * @return string HTML output
     */
    public function show($value = '', $attrib = null)
    {
        // overwrite object attributes
        if (is_array($attrib)) {
            $this->attrib = array_merge($this->attrib, $attrib);
        }
        // set value attribute
        $this->attrib['checked'] = ($value && (string)$value == (string)$this->attrib['value']);
        return parent::show();
    }
}
/**
 * Class to create HTML checkboxes
 *
 * @package HTML
 */
class html_checkbox extends html_inputfield
{
    protected $type = 'checkbox';
    /**
     * Get HTML code for this object
     *
     * @param string Value of the checked field
     * @param array Additional attributes to override
     * @return string HTML output
     */
    public function show($value = '', $attrib = null)
    {
        // overwrite object attributes
        if (is_array($attrib)) {
            $this->attrib = array_merge($this->attrib, $attrib);
        }
        // set value attribute
        $this->attrib['checked'] = ($value && (string)$value == (string)$this->attrib['value']);
        return parent::show();
    }
}
/**
 * Class to create an HTML textarea
 *
 * @package HTML
 */
class html_textarea extends html
{
    protected $tagname = 'textarea';
    protected $allowed_attrib = array('name','rows','cols','wrap');
    /**
     * Get HTML code for this object
     *
     * @param string Textbox value
     * @param array Additional attributes to override
     * @return string HTML output
     */
    public 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 self::tag($this->tagname, $this->attrib, Q($value), array_merge(self::$common_attrib, $this->allowed_attrib));
    }
}
/**
 * Builder for HTML drop-down menus
 * Syntax:<pre>
 * // create instance. arguments are used to set attributes of select-tag
 * $select = new html_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 html_select extends html
{
    protected $tagname = 'select';
    protected $options = array();
    /**
     * Add a new option to this drop-down
     *
     * @param mixed Option name or array with option names
     * @param mixed Option value or array with option values
     */
    public function add($names, $values = null)
    {
        if (is_array($names)) {
            foreach ($names as $i => $text) {
                $this->options[] = array('text' => $text, 'value' => $values[$i]);
            }
        }
        else {
            $this->options[] = array('text' => $names, 'value' => $values);
        }
    }
    /**
     * Get HTML code for this object
     *
     * @param string Value of the selection option
     * @param array Additional attributes to override
     * @return string HTML output
     */
    public function show($select = array(), $attrib = null)
    {
        // overwrite object attributes
        if (is_array($attrib)) {
            $this->attrib = array_merge($this->attrib, $attrib);
        }
        $this->content = "\n";
        $select = (array)$select;
        foreach ($this->options as $option) {
            $attr = array(
                'value' => $option['value'],
                'selected' => ((!empty($option['value']) && in_array($option['value'], $select, true)) ||
            (in_array($option['text'], $select, TRUE))) ? 1 : null);
            $this->content .= self::tag('option', $attr, Q($option['text']));
        }
        return parent::show();
    }
}
/**
 * Class to build an HTML table
 *
 * @package HTML
 */
class html_table extends html
{
    protected $tagname = 'table';
    protected $allowed = array('id','class','style','width','summary','cellpadding','cellspacing','border');
    private $header = array();
    private $rows = array();
    private $rowindex = 0;
    private $colindex = 0;
    public function __construct($attrib = array())
    {
        $this->attrib = array_merge($attrib, array('summary' => '', 'border' => 0));
    }
    /**
     * Add a table cell
     *
     * @param array Cell attributes
     * @param string Cell content
     */
    public function add($attr, $cont)
    {
        if (is_string($attr)) {
            $attr = array('class' => $attr);
        }
        $cell = new stdClass;
        $cell->attrib = $attr;
        $cell->content = $cont;
        $this->rows[$this->rowindex]->cells[$this->colindex] = $cell;
        $this->colindex++;
        if ($this->attrib['cols'] && $this->colindex == $this->attrib['cols']) {
            $this->add_row();
        }
    }
    /**
     * Add a table header cell
     *
     * @param array Cell attributes
     * @param string Cell content
     */
    private function add_header($attr, $cont)
    {
        if (is_string($attr))
        $attr = array('class' => $attr);
        $cell = new stdClass;
        $cell->attrib = $attr;
        $cell->content = $cont;
        $this->header[] = $cell;
    }
    /**
     * Jump to next row
     *
     * @param array Row attributes
     */
    private function add_row($attr = array())
    {
        $this->rowindex++;
        $this->colindex = 0;
        $this->rows[$this->rowindex] = new stdClass;
        $this->rows[$this->rowindex]->attrib = $attr;
        $this->rows[$this->rowindex]->cells = array();
    }
    /**
     * Build HTML output of the table data
     *
     * @param array Table attributes
     * @return string The final table HTML code
     */
    public function show($attr = array())
    {
        $this->attrib = array_merge($this->attrib, $attr);
        $thead = $tbody = "";
        // include <thead>
        if (!empty($this->header)) {
            $rowcontent = '';
            foreach ($this->header as $c => $col) {
                $rowcontent .= self::tag('th', $col->attrib, $col->content);
            }
            $thead = self::tag('thead', null, self::tag('tr', null, $rowcontent));
        }
        foreach ($this->rows as $r => $row) {
            $rowcontent = '';
            foreach ($row->cells as $c => $col) {
                $rowcontent .= self::tag('td', $col->attrib, $col->content);
            }
            if ($r < $this->rowindex || count($row->cells)) {
                $tbody .= self::tag('tr', $rows->attrib, $rowcontent);
            }
        }
        if ($this->attrib['rowsonly']) {
            return $tbody;
        }
        // add <tbody>
        $this->content = $thead . self::tag('tbody', null, $tbody);
        unset($this->attrib['cols'], $this->attrib['rowsonly']);
        return parent::show();
    }
}
?>
program/include/iniset.php
New file
@@ -0,0 +1,98 @@
<?php
/*
 +-----------------------------------------------------------------------+
 | program/include/iniset.inc                                            |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2008, RoundCube Dev, - Switzerland                      |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
 |   Setup the application envoronment required to process               |
 |   any request.                                                        |
 +-----------------------------------------------------------------------+
 | Author: Till Klampaeckel <till@php.net>                               |
 |         Thomas Bruederli <roundcube@gmail.com>                        |
 +-----------------------------------------------------------------------+
 $Id: cache.inc 88 2005-12-03 16:54:12Z roundcube $
*/
// application constants
define('RCMAIL_VERSION', '0.1-trunk');
define('RCMAIL_CHARSET', 'UTF-8');
define('JS_OBJECT_NAME', 'rcmail');
if (!defined('INSTALL_PATH')) {
  define('INSTALL_PATH', dirname($_SERVER['SCRIPT_FILENAME']).'/');
}
// make sure path_separator is defined
if (!defined('PATH_SEPARATOR')) {
  define('PATH_SEPARATOR', (eregi('win', PHP_OS) ? ';' : ':'));
}
// RC include folders MUST be included FIRST to avoid other
// possible not compatible libraries (i.e PEAR) to be included
// instead the ones provided by RC
$include_path = INSTALL_PATH . PATH_SEPARATOR;
$include_path.= INSTALL_PATH . 'program' . PATH_SEPARATOR;
$include_path.= INSTALL_PATH . 'program/lib' . PATH_SEPARATOR;
$include_path.= INSTALL_PATH . 'program/include' . PATH_SEPARATOR;
$include_path.= ini_get('include_path');
if (set_include_path($include_path) === false) {
  die('Fatal error: ini_set/set_include_path does not work.');
}
ini_set('session.name', 'roundcube_sessid');
ini_set('session.use_cookies', 1);
ini_set('session.gc_maxlifetime', 21600);
ini_set('session.gc_divisor', 500);
ini_set('error_reporting', E_ALL&~E_NOTICE);
set_magic_quotes_runtime(0);
// increase maximum execution time for php scripts
// (does not work in safe mode)
if (!ini_get('safe_mode')) {
  set_time_limit(120);
}
/**
 * Use PHP5 autoload for dynamic class loading
 *
 * @todo Make Zend, PEAR etc play with this
 */
function __autoload($classname)
{
  $filename = preg_replace(
      array('/MDB2_(.+)/', '/Mail_(.+)/', '/^html_.+/', '/^utf8$/'),
      array('MDB2/\\1', 'Mail/\\1', 'html', 'utf8.class'),
      $classname
  );
  include_once $filename. '.php';
}
/**
 * Local callback function for PEAR errors
 */
function rcube_pear_error($err)
{
  error_log(sprintf("%s (%s): %s",
    $err->getMessage(),
    $err->getCode(),
    $err->getUserinfo()), 0);
}
// include global functions
require_once 'include/bugs.inc';
require_once 'include/main.inc';
require_once 'include/rcube_shared.inc';
// set PEAR error handling (will also load the PEAR main class)
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'rcube_pear_error');
program/include/main.inc
@@ -27,9 +27,7 @@
 */
require_once('lib/utf7.inc');
require_once('include/rcube_user.inc');
require_once('include/rcube_shared.inc');
require_once('include/rcmail_template.inc');
// fallback if not PHP modules are available
@include_once('lib/des.inc');
@@ -50,14 +48,11 @@
function rcmail_startup($task='mail')
  {
  global $sess_id, $sess_user_lang;
  global $CONFIG, $INSTALL_PATH, $BROWSER, $OUTPUT, $_SESSION, $IMAP, $DB, $USER;
  global $CONFIG, $OUTPUT, $IMAP, $DB, $USER;
  // start output buffering, we don't need any output yet, 
  // it'll be cleared after reading of config files, etc.
  ob_start();
  // check client
  $BROWSER = rcube_browser();
  // load configuration
  $CONFIG = rcmail_load_config();
@@ -74,10 +69,9 @@
  // prepare DB connection
  $dbwrapper = empty($CONFIG['db_backend']) ? 'db' : $CONFIG['db_backend'];
  $dbclass = "rcube_" . $dbwrapper;
  require_once("include/$dbclass.inc");
  
  $DB = new $dbclass($CONFIG['db_dsnw'], $CONFIG['db_dsnr'], $CONFIG['db_persistent']);
  $DB->sqlite_initials = $INSTALL_PATH.'SQL/sqlite.initial.sql';
  $DB->sqlite_initials = INSTALL_PATH.'SQL/sqlite.initial.sql';
  $DB->set_debug((bool)$CONFIG['sql_debug']);
  $DB->db_connect('w');
@@ -136,8 +130,6 @@
 */
function rcmail_load_config()
  {
  global $INSTALL_PATH;
  // load config file
  include_once('config/main.inc.php');
  $conf = is_array($rcmail_config) ? $rcmail_config : array();
@@ -152,7 +144,7 @@
  $conf = array_merge($conf, $rcmail_config);
  if (empty($conf['log_dir']))
    $conf['log_dir'] = $INSTALL_PATH.'logs';
    $conf['log_dir'] = INSTALL_PATH.'logs';
  else
    $conf['log_dir'] = unslashify($conf['log_dir']);
@@ -427,11 +419,10 @@
 */
function rcube_language_prop($lang, $prop='lang')
  {
  global $INSTALL_PATH;
  static $rcube_languages, $rcube_language_aliases, $rcube_charsets;
  if (empty($rcube_languages))
    @include($INSTALL_PATH.'program/localization/index.inc');
    @include(INSTALL_PATH.'program/localization/index.inc');
    
  // check if we have an alias for that language
  if (!isset($rcube_languages[$lang]) && isset($rcube_language_aliases[$lang]))
@@ -451,7 +442,7 @@
  if (isset($rcube_charsets[$lang]))
    $charset = $rcube_charsets[$lang];
  else
    $charset = 'UTF-8';
    $charset = 'UTF-8';
  if ($prop=='charset')
@@ -467,18 +458,15 @@
 * environment vars according to the current session and configuration
 */
function rcmail_load_gui()
  {
{
  global $CONFIG, $OUTPUT, $sess_user_lang;
  // init output page
  $OUTPUT = new rcmail_template($CONFIG, $GLOBALS['_task']);
  $OUTPUT = new rcube_template($CONFIG, $GLOBALS['_task']);
  $OUTPUT->set_env('comm_path', $GLOBALS['COMM_PATH']);
  if (is_array($CONFIG['javascript_config']))
  {
    foreach ($CONFIG['javascript_config'] as $js_config_var)
      $OUTPUT->set_env($js_config_var, $CONFIG[$js_config_var]);
  }
  foreach (array('read_when_deleted', 'flag_for_deletion') as $js_config_var)
    $OUTPUT->set_env($js_config_var, $CONFIG[$js_config_var]);
  if (!empty($GLOBALS['_framed']))
    $OUTPUT->set_env('framed', true);
@@ -490,19 +478,23 @@
  if (!empty($CONFIG['charset']))
    $OUTPUT->set_charset($CONFIG['charset']);
    
  // register common UI objects
  $OUTPUT->add_handlers(array(
    'loginform' => 'rcmail_login_form',
    'username'  => 'rcmail_current_username',
    'message' => 'rcmail_message_container',
    'charsetselector' => 'rcmail_charset_selector',
  ));
  // add some basic label to client
  if (!$OUTPUT->ajax_call)
    rcube_add_label('loading', 'movingmessage');
  }
  $OUTPUT->add_label('loading', 'movingmessage');
}
/**
 * Create an output object for JSON responses
 */
function rcmail_init_json()
{
  global $CONFIG, $OUTPUT;
  // init output object
  $OUTPUT = new rcube_json_output($CONFIG, $GLOBALS['_task']);
  // set locale setting
  rcmail_set_locale($sess_user_lang);
}
/**
 * Set localization charset based on the given language.
@@ -878,18 +870,18 @@
 */
function rcube_list_languages()
  {
  global $CONFIG, $INSTALL_PATH;
  global $CONFIG;
  static $sa_languages = array();
  if (!sizeof($sa_languages))
    {
    @include($INSTALL_PATH.'program/localization/index.inc');
    @include(INSTALL_PATH.'program/localization/index.inc');
    if ($dh = @opendir($INSTALL_PATH.'program/localization'))
    if ($dh = @opendir(INSTALL_PATH.'program/localization'))
      {
      while (($name = readdir($dh)) !== false)
        {
        if ($name{0}=='.' || !is_dir($INSTALL_PATH.'program/localization/'.$name))
        if ($name{0}=='.' || !is_dir(INSTALL_PATH.'program/localization/'.$name))
          continue;
        if ($label = $rcube_languages[$name])
@@ -904,6 +896,7 @@
/**
 * Add a localized label to the client environment
 * @deprecated
 */
function rcube_add_label()
  {
@@ -911,7 +904,7 @@
  
  $arg_list = func_get_args();
  foreach ($arg_list as $i => $name)
    $OUTPUT->command('add_label', $name, rcube_label($name));
    $OUTPUT->add_label($name);
  }
@@ -1135,7 +1128,7 @@
    if ($OUTPUT->get_charset()!='UTF-8')
      $str = rcube_charset_convert($str, RCMAIL_CHARSET, $OUTPUT->get_charset());
      
    return preg_replace(array("/\r?\n/", "/\r/"), array('\n', '\n'), addslashes(strtr($str, $js_rep_table)));
    return preg_replace(array("/\r?\n/", "/\r/", '/<\\//'), array('\n', '\n', '<\\/'), addslashes(strtr($str, $js_rep_table)));
    }
  // no encoding given -> return original string
@@ -1261,16 +1254,6 @@
/**
 * 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
@@ -1360,15 +1343,15 @@
  if ($type=='checkbox')
    {
    $attrib['value'] = '1';
    $input = new checkbox($attrib);
    $input = new html_checkbox($attrib);
    }
  else if ($type=='textarea')
    {
    $attrib['cols'] = $attrib['size'];
    $input = new textarea($attrib);
    $input = new html_textarea($attrib);
    }
  else
    $input = new textfield($attrib);
    $input = new html_inputfield($attrib);
  // use value from post
  if (!empty($_POST[$fname]))
@@ -1645,7 +1628,7 @@
 */
function write_log($name, $line)
  {
  global $CONFIG, $INSTALL_PATH;
  global $CONFIG;
  if (!is_string($line))
    $line = var_export($line, true);
@@ -1655,7 +1638,7 @@
                 $line);
                 
  if (empty($CONFIG['log_dir']))
    $CONFIG['log_dir'] = $INSTALL_PATH.'logs';
    $CONFIG['log_dir'] = INSTALL_PATH.'logs';
      
  // try to open specific log file for writing
  if ($fp = @fopen($CONFIG['log_dir'].'/'.$name, 'a'))    
program/include/rcmail_template.inc
File was deleted
program/include/rcube_browser.php
New file
@@ -0,0 +1,75 @@
<?php
/*
 +-----------------------------------------------------------------------+
 | program/include/rcube_browser.php                                     |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2007-2008, RoundCube Dev. - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
 |   Class representing the client browser's properties                  |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 +-----------------------------------------------------------------------+
 $Id: rcube_browser.php 328 2006-08-30 17:41:21Z thomasb $
*/
/**
 * rcube_browser
 *
 * Provide details about the client's browser based on the User-Agent header
 *
 * @package Core
 */
class rcube_browser
{
    function __construct()
    {
        $HTTP_USER_AGENT = $_SERVER['HTTP_USER_AGENT'];
        $this->ver = 0;
        $this->win = stristr($HTTP_USER_AGENT, 'win');
        $this->mac = stristr($HTTP_USER_AGENT, 'mac');
        $this->linux = stristr($HTTP_USER_AGENT, 'linux');
        $this->unix  = stristr($HTTP_USER_AGENT, 'unix');
        $this->ns4 = stristr($HTTP_USER_AGENT, 'mozilla/4') && !stristr($HTTP_USER_AGENT, 'msie');
        $this->ns  = ($this->ns4 || stristr($HTTP_USER_AGENT, 'netscape'));
        $this->ie  = stristr($HTTP_USER_AGENT, 'msie');
        $this->mz  = stristr($HTTP_USER_AGENT, 'mozilla/5');
        $this->opera = stristr($HTTP_USER_AGENT, 'opera');
        $this->safari = stristr($HTTP_USER_AGENT, 'safari');
        if ($this->ns) {
            $test = eregi("mozilla\/([0-9\.]+)", $HTTP_USER_AGENT, $regs);
            $this->ver = $test ? (float)$regs[1] : 0;
        }
        if ($this->mz) {
            $test = ereg("rv:([0-9\.]+)", $HTTP_USER_AGENT, $regs);
            $this->ver = $test ? (float)$regs[1] : 0;
        }
        if($this->ie) {
            $test = eregi("msie ([0-9\.]+)", $HTTP_USER_AGENT, $regs);
            $this->ver = $test ? (float)$regs[1] : 0;
        }
        if ($this->opera) {
            $test = eregi("opera ([0-9\.]+)", $HTTP_USER_AGENT, $regs);
            $this->ver = $test ? (float)$regs[1] : 0;
        }
        if (eregi(" ([a-z]{2})-([a-z]{2})", $HTTP_USER_AGENT, $regs))
            $this->lang =  $regs[1];
        else
            $this->lang =  'en';
        $this->dom = ($this->mz || $this->safari || ($this->ie && $this->ver>=5) || ($this->opera && $this->ver>=7));
        $this->pngalpha = $this->mz || $this->safari || ($this->ie && $this->ver>=5.5) ||
            ($this->ie && $this->ver>=5 && $this->mac) || ($this->opera && $this->ver>=7) ? true : false;
    }
  }
program/include/rcube_contacts.php
File was renamed from program/include/rcube_contacts.inc
@@ -2,10 +2,10 @@
/*
 +-----------------------------------------------------------------------+
 | program/include/rcube_contacts.inc                                    |
 | program/include/rcube_contacts.php                                    |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2006-2007, RoundCube Dev. - Switzerland                 |
 | Copyright (C) 2006-2008, RoundCube Dev. - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
@@ -403,56 +403,3 @@
}
/**
 * RoundCube result set class.
 * Representing an address directory result set.
 */
class rcube_result_set
{
  var $count = 0;
  var $first = 0;
  var $current = 0;
  var $records = array();
  function __construct($c=0, $f=0)
  {
    $this->count = (int)$c;
    $this->first = (int)$f;
  }
  function rcube_result_set($c=0, $f=0)
  {
    $this->__construct($c, $f);
  }
  function add($rec)
  {
    $this->records[] = $rec;
  }
  function iterate()
  {
    return $this->records[$this->current++];
  }
  function first()
  {
    $this->current = 0;
    return $this->records[$this->current++];
  }
  // alias
  function next()
  {
    return $this->iterate();
  }
  function seek($i)
  {
    $this->current = $i;
  }
}
?>
program/include/rcube_db.php
File was renamed from program/include/rcube_db.inc
@@ -2,10 +2,10 @@
/*
 +-----------------------------------------------------------------------+
 | program/include/rcube_db.inc                                          |
 | program/include/rcube_db.php                                          |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland                 |
 | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
@@ -21,11 +21,6 @@
*/
/**
 * Obtain the PEAR::DB class that is used for abstraction
 */
require_once 'DB.php';
/**
 * Database independent query interface
@@ -605,4 +600,4 @@
  }  // end class rcube_db
?>
program/include/rcube_html.inc
File was deleted
program/include/rcube_html_page.php
New file
@@ -0,0 +1,256 @@
<?php
/*
 +-----------------------------------------------------------------------+
 | program/include/rcube_html_page.php                                   |
 |                                                                       |
 | This file is part of the RoundCube PHP suite                          |
 | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | CONTENTS:                                                             |
 |   Class to build XHTML page output                                    |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 +-----------------------------------------------------------------------+
 $Id:  $
*/
/**
 * Class for HTML page creation
 *
 * @package HTML
 */
class rcube_html_page
{
    protected $scripts_path = '';
    protected $script_files = array();
    protected $external_scripts = array();
    protected $scripts = array();
    protected $charset = 'UTF-8';
    protected $script_tag_file = "<script type=\"text/javascript\" src=\"%s%s\"></script>\n";
    protected $script_tag      = "<script type=\"text/javascript\">\n<!--\n%s\n\n//-->\n</script>\n";
    protected $default_template = "<html>\n<head><title></title></head>\n<body></body>\n</html>";
    protected $tag_format_external_script = "<script type=\"text/javascript\" src=\"%s\"></script>\n";
    protected $title = '';
    protected $header = '';
    protected $footer = '';
    protected $body = '';
    /** Constructor */
    public function __construct() {}
    /**
     * Link an external script file
     *
     * @param string File URL
     * @param string Target position [head|foot]
     */
    public 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]
     */
    public 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
     */
    public function add_header($str)
    {
        $this->header .= "\n".$str;
    }
    /**
     * Add HTML code to the page footer
     * To be added right befor </body>
     */
    public function add_footer($str)
    {
        $this->footer .= "\n".$str;
    }
    /**
     * Setter for page title
     */
    public function set_title($t)
    {
        $this->title = $t;
    }
    /**
     * Setter for output charset.
     * To be specified in a meta tag and sent as http-header
     */
    public function set_charset($charset)
    {
        $this->charset = $charset;
    }
    /**
     * Getter for output charset
     */
    public function get_charset()
    {
        return $this->charset;
    }
    /**
     * Reset all saved properties
     */
    public 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
     */
    public 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)) {
            if (!headers_sent()) {
                header('Content-Type: text/html; charset=' . $this->charset);
            }
            $__page_header = '<meta http-equiv="content-type"';
            $__page_header.= ' content="text/html; charset=';
            $__page_header.= $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 = strrpos($output_lc, '</body>')) || ($fpos = strrpos($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);
    }
}
program/include/rcube_imap.php
File was renamed from program/include/rcube_imap.inc
@@ -2,10 +2,10 @@
/*
 +-----------------------------------------------------------------------+
 | program/include/rcube_imap.inc                                        |
 | program/include/rcube_imap.php                                        |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland                 |
 | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
@@ -2929,4 +2929,3 @@
  }
?>
program/include/rcube_json_output.php
New file
@@ -0,0 +1,237 @@
<?php
/*
 +-----------------------------------------------------------------------+
 | program/include/rcube_json_output.php                                 |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2008, RoundCube Dev. - Switzerland                      |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
 |   Class to handle HTML page output using a skin template.             |
 |   Extends rcube_html_page class from rcube_shared.inc                 |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 +-----------------------------------------------------------------------+
 $Id:  $
*/
/**
 * View class to produce JSON responses
 *
 * @package View
 */
class rcube_json_output
{
    private $config;
    private $charset = 'UTF-8';
    private $env = array();
    private $texts = array();
    private $commands = array();
    public $task = '';
    public $ajax_call = true;
    /**
     * Constructor
     */
    public function __construct(&$config, $task)
    {
        $this->task   = $task;
        $this->config = $config;
    }
    /**
     * Set environment variable
     *
     * @param string Property name
     * @param mixed Property value
     */
    public function set_env($name, $value)
    {
        $this->env[$name] = $value;
    }
    /**
     * @ignore
     */
    public function set_pagetitle($title)
    {
        // ignore
    }
    /**
     * @ignore
     */
    function set_charset($charset)
    {
        // ignore: $this->charset = $charset;
    }
    /**
     * Get charset for output
     *
     * @return string Output charset
     */
    function get_charset()
    {
        return $this->charset;
    }
    /**
     * Register a template object handler
     *
     * @param  string Object name
     * @param  string Function name to call
     * @return void
     */
    public function add_handler($obj, $func)
    {
        // ignore
    }
    /**
     * Register a list of template object handlers
     *
     * @param  array Hash array with object=>handler pairs
     * @return void
     */
    public function add_handlers($arr)
    {
        // ignore
    }
    /**
     * Call a client method
     *
     * @param string Method to call
     * @param ... Additional arguments
     */
    public function command()
    {
        $this->commands[] = func_get_args();
    }
    /**
     * Add a localized label to the client environment
     */
    public function add_label()
    {
        $arg_list = func_get_args();
        foreach ($arg_list as $i => $name) {
            $this->texts[$name] = rcube::gettext($name);
        }
    }
    /**
     * 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
     * @uses self::command()
     */
    public function show_message($message, $type='notice', $vars=null)
    {
        $this->command(
            'display_message',
            rcube::gettext(array('name' => $message, 'vars' => $vars)),
            $type
        );
    }
    /**
     * Delete all stored env variables and commands
     */
    public public function reset()
    {
        $this->env = array();
        $this->texts = array();
        $this->commands = array();
    }
    /**
     * Send an AJAX response to the client.
     */
    public function send()
    {
        $this->remote_response();
        exit;
    }
    /**
     * Send an AJAX response with executable JS code
     *
     * @param  string  Additional JS code
     * @param  boolean True if output buffer should be flushed
     * @return void
     * @deprecated
     */
    public function remote_response($add='', $flush=false)
    {
        static $s_header_sent = false;
        if (!$s_header_sent) {
            $s_header_sent = true;
            send_nocacheing_headers();
            header('Content-Type: application/x-javascript; charset=' . $this->get_charset());
            print '/** ajax response ['.date('d/M/Y h:i:s O')."] **/\n";
        }
        // unset default env vars
        unset($this->env['task'], $this->env['action'], $this->env['comm_path']);
        // send response code
        echo $this->get_js_commands() . $add;
        // flush the output buffer
        if ($flush)
            flush();
    }
    /**
     * Return executable javascript code for all registered commands
     *
     * @return string $out
     */
    private function get_js_commands()
    {
        $out = 'this.set_env('.json_serialize($this->env).");\n";
        foreach($this->texts as $name => $text) {
            $out .= sprintf("this.add_label('%s', '%s');\n", $name, JQ($text));
        }
        foreach ($this->commands as $i => $args) {
            $method = array_shift($args);
            foreach ($args as $i => $arg) {
                $args[$i] = json_serialize($arg);
            }
            $out .= sprintf(
                "this.%s(%s);\n",
                preg_replace('/^parent\./', '', $method),
                implode(',', $args)
            );
        }
        return $out;
    }
}
program/include/rcube_ldap.php
File was renamed from program/include/rcube_ldap.inc
@@ -1,10 +1,10 @@
<?php
/*
 +-----------------------------------------------------------------------+
 | program/include/rcube_ldap.inc                                        |
 | program/include/rcube_ldap.php                                        |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2006-2007, RoundCube Dev. - Switzerland                 |
 | Copyright (C) 2006-2008, RoundCube Dev. - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
@@ -456,4 +456,4 @@
}
?>
program/include/rcube_mail_mime.php
File was renamed from program/lib/rc_mail_mime.inc
@@ -2,10 +2,10 @@
/*
 +-----------------------------------------------------------------------+
 | program/lib/rc_mime.inc                                               |
 | program/include/rcube_mail_mime.php                                   |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2007, RoundCube Dev. - Switzerland                      |
 | Copyright (C) 2007-2008, RoundCube Dev. - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
@@ -19,19 +19,22 @@
*/
// require Mail_mime class 1.4.0
require_once('Mail/mime.php');
class rc_mail_mime extends Mail_mime
/**
 * Replacement PEAR:Mail_mime with some additional or overloaded methods
 *
 * @package Mail
 */
class rcube_mail_mime extends Mail_mime
{
  /**
   * Set build parameters
   */
  function setParam($param)
  {
    if (is_array($param))
    if (is_array($param)) {
      $this->_build_params = array_merge($this->_build_params, $param);
    }
  }
  
  /**
@@ -51,16 +54,20 @@
  function addHTMLImage($file, $c_type='application/octet-stream', $name = '', $isfilename = true, $contentid = '')
  {
    $filedata = ($isfilename === true) ? $this->_file2str($file) : $file;
    if ($isfilename === true)
    if ($isfilename === true) {
      $filename = ($name == '' ? $file : $name);
    else
    }
    else {
      $filename = $name;
    }
    if (PEAR::isError($filedata))
    if (PEAR::isError($filedata)) {
        return $filedata;
    }
    if ($contentid == '')
    if ($contentid == '') {
       $contentid = md5(uniqid(time()));
    }
    $this->_html_images[] = array(
      'body'   => $filedata,
@@ -117,31 +124,29 @@
    foreach ($input as $hdr_name => $hdr_value)
    {
      // if header contains e-mail addresses
      if (preg_match('/\s<.+@[a-z0-9\-\.]+\.[a-z]+>/U', $hdr_value))
      if (preg_match('/\s<.+@[a-z0-9\-\.]+\.[a-z]+>/U', $hdr_value)) {
        $chunks = $this->_explode_quoted_string(',', $hdr_value);
      else
      }
      else {
        $chunks = array($hdr_value);
      }
      $hdr_value = '';
      $line_len = 0;
      foreach ($chunks as $i => $value)
      {
      foreach ($chunks as $i => $value) {
        $value = trim($value);
        //This header contains non ASCII chars and should be encoded.
        if (preg_match('#[\x80-\xFF]{1}#', $value))
        {
        if (preg_match('#[\x80-\xFF]{1}#', $value)) {
          $suffix = '';
          // Don't encode e-mail address
          if (preg_match('/(.+)\s(<.+@[a-z0-9\-\.]+>)$/Ui', $value, $matches))
          {
          if (preg_match('/(.+)\s(<.+@[a-z0-9\-\.]+>)$/Ui', $value, $matches)) {
            $value = $matches[1];
            $suffix = ' '.$matches[2];
          }
          switch ($params['head_encoding'])
          {
          switch ($params['head_encoding']) {
            case 'base64':
            // Base64 encoding has been selected.
            $mode = 'B';
@@ -162,13 +167,11 @@
        // add chunk to output string by regarding the header maxlen
        $len = strlen($value);
        if ($i == 0 || $line_len + $len < $maxlen)
        {
        if ($i == 0 || $line_len + $len < $maxlen) {
          $hdr_value .= ($i>0?', ':'') . $value;
          $line_len += $len + ($i>0?2:0);
        }
        else
        {
        else {
          $hdr_value .= ($i>0?', ':'') . "\n " . $value;
          $line_len = $len;
        }
@@ -185,12 +188,11 @@
  {
    $result = array();
    $strlen = strlen($string);
    for ($q=$p=$i=0; $i < $strlen; $i++)
    {
      if ($string{$i} == "\"" && $string{$i-1} != "\\")
    for ($q=$p=$i=0; $i < $strlen; $i++) {
      if ($string{$i} == "\"" && $string{$i-1} != "\\") {
        $q = $q ? false : true;
      else if (!$q && $string{$i} == $delimiter)
      {
      }
      else if (!$q && $string{$i} == $delimiter) {
        $result[] = substr($string, $p, $i - $p);
        $p = $i + 1;
      }
@@ -202,4 +204,3 @@
}
?>
program/include/rcube_mdb2.php
File was renamed from program/include/rcube_mdb2.inc
@@ -2,10 +2,10 @@
/*
 +-----------------------------------------------------------------------+
 | program/include/rcube_mdb2.inc                                        |
 | program/include/rcube_mdb2.php                                        |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland                 |
 | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
@@ -19,12 +19,6 @@
 $Id$
*/
/**
 * Obtain the PEAR::DB class that is used for abstraction
 */
require_once('MDB2.php');
/**
@@ -617,4 +611,3 @@
}
?>
program/include/rcube_result_set.php
New file
@@ -0,0 +1,74 @@
<?php
/*
 +-----------------------------------------------------------------------+
 | program/include/rcube_result_set.php                                  |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2006-2008, RoundCube Dev. - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
 |   Class representing an address directory result set                  |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 +-----------------------------------------------------------------------+
 $Id: rcube_result_set.php 328 2006-08-30 17:41:21Z thomasb $
*/
/**
 * RoundCube result set class.
 * Representing an address directory result set.
 *
 * @package Addressbook
 */
class rcube_result_set
{
  var $count = 0;
  var $first = 0;
  var $current = 0;
  var $records = array();
  function __construct($c=0, $f=0)
  {
    $this->count = (int)$c;
    $this->first = (int)$f;
  }
  function rcube_result_set($c=0, $f=0)
  {
    $this->__construct($c, $f);
  }
  function add($rec)
  {
    $this->records[] = $rec;
  }
  function iterate()
  {
    return $this->records[$this->current++];
  }
  function first()
  {
    $this->current = 0;
    return $this->records[$this->current++];
  }
  // alias
  function next()
  {
    return $this->iterate();
  }
  function seek($i)
  {
    $this->current = $i;
  }
}
program/include/rcube_shared.inc
@@ -91,7 +91,7 @@
 */
function rcube_label($attrib)
{
  global $sess_user_lang, $INSTALL_PATH, $OUTPUT;
  global $sess_user_lang, $OUTPUT;
  static $sa_text_data, $s_language, $utf8_decode;
  // extract attributes
@@ -111,8 +111,8 @@
    $sa_text_data = array();
    
    // get english labels (these should be complete)
    @include($INSTALL_PATH.'program/localization/en_US/labels.inc');
    @include($INSTALL_PATH.'program/localization/en_US/messages.inc');
    @include(INSTALL_PATH.'program/localization/en_US/labels.inc');
    @include(INSTALL_PATH.'program/localization/en_US/messages.inc');
    if (is_array($labels))
      $sa_text_data = $labels;
@@ -120,10 +120,10 @@
      $sa_text_data = array_merge($sa_text_data, $messages);
    
    // include user language files
    if ($sess_user_lang!='en' && is_dir($INSTALL_PATH.'program/localization/'.$sess_user_lang))
    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');
      include_once(INSTALL_PATH.'program/localization/'.$sess_user_lang.'/labels.inc');
      include_once(INSTALL_PATH.'program/localization/'.$sess_user_lang.'/messages.inc');
      if (is_array($labels))
        $sa_text_data = array_merge($sa_text_data, $labels);
program/include/rcube_template.php
New file
@@ -0,0 +1,1004 @@
<?php
/*
 +-----------------------------------------------------------------------+
 | program/include/rcube_template.php                                    |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2006-2008, RoundCube Dev. - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
 |   Class to handle HTML page output using a skin template.             |
 |   Extends rcube_html_page class from rcube_shared.inc                 |
 |                                                                       |
 +-----------------------------------------------------------------------+
 | Author: Thomas Bruederli <roundcube@gmail.com>                        |
 +-----------------------------------------------------------------------+
 $Id$
 */
/**
 * Class to create HTML page output using a skin template
 *
 * @package View
 * @todo Documentation
 * @uses rcube_html_page
 */
class rcube_template extends rcube_html_page
{
    var $config;
    var $task = '';
    var $framed = false;
    var $pagetitle = '';
    var $env = array();
    var $js_env = array();
    var $js_commands = array();
    var $object_handlers = array();
    public $ajax_call = false;
    /**
     * Constructor
     *
     * @todo   Use jQuery's $(document).ready() here.
     */
    public function __construct(&$config, $task)
    {
        parent::__construct();
        $this->task = $task;
        $this->config = $config;
        // add common javascripts
        $javascript = 'var '.JS_OBJECT_NAME.' = new rcube_webmail();';
        // don't wait for page onload. Call init at the bottom of the page (delayed)
        $javascript_foot = "if (window.call_init)\n call_init('".JS_OBJECT_NAME."');";
        $this->add_script($javascript, 'head_top');
        $this->add_script($javascript_foot, 'foot');
        $this->scripts_path = 'program/js/';
        $this->include_script('common.js');
        $this->include_script('app.js');
        // register common UI objects
        $this->add_handlers(array(
            'loginform'       => array($this, 'login_form'),
            'username'        => array($this, 'current_username'),
            'message'         => array($this, 'message_container'),
            'charsetselector' => array($this, 'charset_selector'),
        ));
    }
    /**
     * Set environment variable
     *
     * @param string Property name
     * @param mixed Property value
     * @param boolean True if this property should be added to client environment
     */
    public function set_env($name, $value, $addtojs = true)
    {
        $this->env[$name] = $value;
        if ($addtojs || isset($this->js_env[$name])) {
            $this->js_env[$name] = $value;
        }
    }
    /**
     * Set page title variable
     */
    public function set_pagetitle($title)
    {
        $this->pagetitle = $title;
    }
    /**
     * Register a template object handler
     *
     * @param  string Object name
     * @param  string Function name to call
     * @return void
     */
    public function add_handler($obj, $func)
    {
        $this->object_handlers[$obj] = $func;
    }
    /**
     * Register a list of template object handlers
     *
     * @param  array Hash array with object=>handler pairs
     * @return void
     */
    public function add_handlers($arr)
    {
        $this->object_handlers = array_merge($this->object_handlers, $arr);
    }
    /**
     * Register a GUI object to the client script
     *
     * @param  string Object name
     * @param  string Object ID
     * @return void
     */
    public function add_gui_object($obj, $id)
    {
        $this->add_script(JS_OBJECT_NAME.".gui_object('$obj', '$id');");
    }
    /**
     * Call a client method
     *
     * @param string Method to call
     * @param ... Additional arguments
     */
    public function command()
    {
        $this->js_commands[] = func_get_args();
    }
    /**
     * Add a localized label to the client environment
     */
    public function add_label()
    {
        $arg_list = func_get_args();
        foreach ($arg_list as $i => $name) {
            $this->command('add_label', $name, rcube_label($name));
        }
    }
    /**
     * 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
     * @uses self::command()
     */
    public function show_message($message, $type='notice', $vars=NULL)
    {
        $this->command(
            'display_message',
            rcube_label(array('name' => $message, 'vars' => $vars)),
            $type);
    }
    /**
     * Delete all stored env variables and commands
     *
     * @return void
     * @uses   rcube_html::reset()
     * @uses   self::$env
     * @uses   self::$js_env
     * @uses   self::$js_commands
     * @uses   self::$object_handlers
     */
    public public function reset()
    {
        $this->env = array();
        $this->js_env = array();
        $this->js_commands = array();
        $this->object_handlers = array();
        parent::reset();
    }
    /**
     * Send the request output to the client.
     * This will either parse a skin tempalte or send an AJAX response
     *
     * @param string  Template name
     * @param boolean True if script should terminate (default)
     */
    public function send($templ = null, $exit = true)
    {
        if ($templ != 'iframe') {
            $this->parse($templ, false);
        }
        else {
            $this->framed = $templ == 'iframe' ? true : $this->framed;
            $this->write();
        }
        if ($exit) {
            exit;
        }
    }
    /**
     * Process template and write to stdOut
     *
     * @param string HTML template
     * @see rcube_html_page::write()
     * @override
     */
    public function write($template = '')
    {
        // unlock interface after iframe load
        if ($this->framed) {
            array_unshift($this->js_commands, array('set_busy', false));
        }
        // write all env variables to client
        $js = $this->framed ? "if(window.parent) {\n" : '';
        $js .= $this->get_js_commands() . ($this->framed ? ' }' : '');
        $this->add_script($js, 'head_top');
        // call super method
        parent::write($template, $this->config['skin_path']);
    }
    /**
     * Parse a specific skin template and deliver to stdout
     *
     * Either returns nothing, or exists hard (exit();)
     *
     * @param  string  Template name
     * @param  boolean Exit script
     * @return void
     * @link   http://php.net/manual/en/function.exit.php
     */
    private function parse($name = 'main', $exit = true)
    {
        $skin_path = $this->config['skin_path'];
        // read template file
        $templ = '';
        $path = "$skin_path/templates/$name.html";
        if (($fp = fopen($path, 'r')) === false) {
            $message = '';
            ob_start();
            fopen($path, 'r');
            $message.= ob_get_contents();
            ob_end_clean();
            rcube_error::raise(array(
                'code' => 501,
                'type' => 'php',
                'line' => __LINE__,
                'file' => __FILE__,
                'message' => 'Error loading template for '.$name.': '.$message
                ), true, true);
            return false;
        }
        $templ = fread($fp, filesize($path));
        fclose($fp);
        // parse for specialtags
        $output = $this->parse_conditions($templ);
        $output = $this->parse_xml($output);
        // add debug console
        if ($this->config['debug_level'] & 8) {
            $this->add_footer('<div style="position:absolute;top:5px;left:5px;width:400px;padding:0.2em;background:white;opacity:0.8;z-index:9000">
                <a href="#toggle" onclick="con=document.getElementById(\'dbgconsole\');con.style.display=(con.style.display==\'none\'?\'block\':\'none\');return false">console</a>
                <form action="/" name="debugform"><textarea name="console" id="dbgconsole" rows="20" cols="40" wrap="off" style="display:none;width:400px;border:none;font-size:x-small"></textarea></form></div>'
            );
        }
        $output = $this->parse_with_globals($output);
        $this->write(trim($output), $skin_path);
        if ($exit) {
            exit;
        }
    }
    /**
     * Return executable javascript code for all registered commands
     *
     * @return string $out
     */
    private function get_js_commands()
    {
        $out = '';
        if (!$this->framed && !empty($this->js_env)) {
            $out .= JS_OBJECT_NAME . '.set_env('.json_serialize($this->js_env).");\n";
        }
        foreach ($this->js_commands as $i => $args) {
            $method = array_shift($args);
            foreach ($args as $i => $arg) {
                $args[$i] = json_serialize($arg);
            }
            $parent = $this->framed || preg_match('/^parent\./', $method);
            $out .= sprintf(
                "%s.%s(%s);\n",
            ($parent ? 'parent.' : '') . JS_OBJECT_NAME,
            preg_replace('/^parent\./', '', $method),
            implode(',', $args)
            );
        }
        // add command to set page title
        if ($this->ajax_call && !empty($this->pagetitle)) {
            $out .= sprintf(
                "this.set_pagetitle('%s');\n",
                JQ((!empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : '') . $this->pagetitle)
            );
        }
        return $out;
    }
    /**
     * Make URLs starting with a slash point to skin directory
     *
     * @param  string Input string
     * @return string
     */
    public function abs_url($str)
    {
        return preg_replace('/^\//', $this->config['skin_path'].'/', $str);
    }
    /*****  Template parsing methods  *****/
    /**
     * Replace all strings ($varname)
     * with the content of the according global variable.
     */
    private function parse_with_globals($input)
    {
        $GLOBALS['__comm_path'] = Q($GLOBALS['COMM_PATH']);
        return preg_replace('/\$(__[a-z0-9_\-]+)/e', '$GLOBALS["\\1"]', $input);
    }
    /**
     * Public wrapper to dipp into template parsing.
     *
     * @param  string $input
     * @return string
     * @uses   rcube_template::parse_xml()
     * @since  0.1-rc1
     */
    public function just_parse($input)
    {
        return $this->parse_xml($input);
    }
    /**
     * Parse for conditional tags
     *
     * @param  string $input
     * @return string
     */
    private function parse_conditions($input)
    {
        $matches = preg_split('/<roundcube:(if|elseif|else|endif)\s+([^>]+)>/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE);
        if ($matches && count($matches) == 4) {
            if (preg_match('/^(else|endif)$/i', $matches[1])) {
                return $matches[0] . $this->parse_conditions($matches[3]);
            }
            $attrib = parse_attrib_string($matches[2]);
            if (isset($attrib['condition'])) {
                $condmet = $this->check_condition($attrib['condition']);
                $submatches = preg_split('/<roundcube:(elseif|else|endif)\s+([^>]+)>/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE);
                if ($condmet) {
                    $result = $submatches[0];
                    $result.= ($submatches[1] != 'endif' ? preg_replace('/.*<roundcube:endif\s+[^>]+>/Uis', '', $submatches[3], 1) : $submatches[3]);
                }
                else {
                    $result = "<roundcube:$submatches[1] $submatches[2]>" . $submatches[3];
                }
                return $matches[0] . $this->parse_conditions($result);
            }
            rcube_error::raise(array(
                'code' => 500,
                'type' => 'php',
                'line' => __LINE__,
                'file' => __FILE__,
                'message' => "Unable to parse conditional tag " . $matches[2]
            ), true, false);
        }
        return $input;
    }
    /**
     * Determines if a given condition is met
     *
     * @todo   Get rid off eval() once I understand what this does.
     * @todo   Extend this to allow real conditions, not just "set"
     * @param  string Condition statement
     * @return boolean True if condition is met, False is not
     */
    private function check_condition($condition)
    {
        $condition = preg_replace(
            array(
                '/session:([a-z0-9_]+)/i',
                '/config:([a-z0-9_]+)/i',
                '/env:([a-z0-9_]+)/i',
                '/request:([a-z0-9_]+)/ie'
            ),
            array(
                "\$_SESSION['\\1']",
                "\$this->config['\\1']",
                "\$this->env['\\1']",
                "get_input_value('\\1', RCUVE_INPUT_GPC)"
            ),
            $condition);
            return eval("return (".$condition.");");
    }
    /**
     * Search for special tags in input and replace them
     * with the appropriate content
     *
     * @param  string Input string to parse
     * @return string Altered input string
     * @todo   Maybe a cache.
     */
    private function parse_xml($input)
    {
        return preg_replace('/<roundcube:([-_a-z]+)\s+([^>]+)>/Uie', "\$this->xml_command('\\1', '\\2')", $input);
    }
    /**
     * Convert a xml command tag into real content
     *
     * @param  string Tag command: object,button,label, etc.
     * @param  string Attribute string
     * @return string Tag/Object content
     */
    private function xml_command($command, $str_attrib, $add_attrib = array())
    {
        $command = strtolower($command);
        $attrib  = parse_attrib_string($str_attrib) + $add_attrib;
        // empty output if required condition is not met
        if (!empty($attrib['condition']) && !$this->check_condition($attrib['condition'])) {
            return '';
        }
        // execute command
        switch ($command) {
            // return a button
            case 'button':
                if ($attrib['command']) {
                    return $this->button($attrib);
                }
                break;
            // show a label
            case 'label':
                if ($attrib['name'] || $attrib['command']) {
                    return Q(rcube_label($attrib + array('vars' => array('product' => $this->config['product_name']))));
                }
                break;
            // include a file
            case 'include':
                $path = realpath($this->config['skin_path'].$attrib['file']);
                if ($fsize = filesize($path)) {
                    if ($this->config['skin_include_php']) {
                        $incl = $this->include_php($path);
                    }
                    else if ($fp = fopen($path, 'r')) {
                        $incl = fread($fp, $fsize);
                        fclose($fp);
                    }
                    return $this->parse_xml($incl);
                }
                break;
            case 'plugin.include':
                //rcube::tfk_debug(var_export($this->config['skin_path'], true));
                $path = realpath($this->config['skin_path'].$attrib['file']);
                if (!$path) {
                    //rcube::tfk_debug("Does not exist:");
                    //rcube::tfk_debug($this->config['skin_path']);
                    //rcube::tfk_debug($attrib['file']);
                    //rcube::tfk_debug($path);
                }
                $incl = file_get_contents($path);
                if ($incl) {
                    return $this->parse_xml($incl);
                }
                break;
            // return code for a specific application object
            case 'object':
                $object = strtolower($attrib['name']);
                // we are calling a class/method
                if (($handler = $this->object_handlers[$object]) && is_array($handler)) {
                    if ((is_object($handler[0]) && method_exists($handler[0], $handler[1])) ||
                    (is_string($handler[0]) && class_exists($handler[0])))
                    return call_user_func($handler, $attrib);
                }
                else if (function_exists($handler)) {
                    // execute object handler function
                    return call_user_func($handler, $attrib);
                }
                if ($object=='productname') {
                    $name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'RoundCube Webmail';
                    return Q($name);
                }
                if ($object=='version') {
                    return (string)RCMAIL_VERSION;
                }
                if ($object=='pagetitle') {
                    $task  = $this->task;
                    $title = !empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : '';
                    if (!empty($this->pagetitle)) {
                        $title .= $this->pagetitle;
                    }
                    else if ($task == 'login') {
                        $title = rcube_label(array('name' => 'welcome', 'vars' => array('product' => $this->config['product_name'])));
                    }
                    else {
                        $title .= ucfirst($task);
                    }
                    return Q($title);
                }
                break;
            // return variable
            case 'var':
                $var = explode(':', $attrib['name']);
                $name = $var[1];
                $value = '';
                switch ($var[0]) {
                    case 'env':
                        $value = $this->env[$name];
                        break;
                    case 'config':
                        $value = $this->config[$name];
                        if (is_array($value) && $value[$_SESSION['imap_host']]) {
                            $value = $value[$_SESSION['imap_host']];
                        }
                        break;
                    case 'request':
                        $value = get_input_value($name, RCUBE_INPUT_GPC);
                        break;
                    case 'session':
                        $value = $_SESSION[$name];
                        break;
                }
                if (is_array($value)) {
                    $value = implode(', ', $value);
                }
                return Q($value);
                break;
        }
        return '';
    }
    /**
     * Include a specific file and return it's contents
     *
     * @param string File path
     * @return string Contents of the processed file
     */
    private function include_php($file)
    {
        ob_start();
        include $file;
        $out = ob_get_contents();
        ob_end_clean();
        return $out;
    }
    /**
     * Create and register a button
     *
     * @param  array Named button attributes
     * @return string HTML button
     * @todo   Remove all inline JS calls and use jQuery instead.
     * @todo   Remove all sprintf()'s - they are pretty, but also slow.
     */
    private function button($attrib)
    {
        global $CONFIG, $OUTPUT, $MAIN_TASKS;
        static $sa_buttons = array();
        static $s_button_count = 100;
        // these commands can be called directly via url
        $a_static_commands = array('compose', 'list');
        $browser   = new rcube_browser();
        $skin_path = $this->config['skin_path'];
        if (!($attrib['command'] || $attrib['name'])) {
            return '';
        }
        // try to find out the button type
        if ($attrib['type']) {
            $attrib['type'] = strtolower($attrib['type']);
        }
        else {
            $attrib['type'] = ($attrib['image'] || $attrib['imagepas'] || $attrib['imageact']) ? 'image' : 'link';
        }
        $command = $attrib['command'];
        // take the button from the stack
        if ($attrib['name'] && $sa_buttons[$attrib['name']]) {
            $attrib = $sa_buttons[$attrib['name']];
        }
        else if($attrib['image'] || $attrib['imageact'] || $attrib['imagepas'] || $attrib['class']) {
            // add button to button stack
            if (!$attrib['name']) {
                $attrib['name'] = $command;
            }
            if (!$attrib['image']) {
                $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact'];
            }
            $sa_buttons[$attrib['name']] = $attrib;
        }
        else if ($command && $sa_buttons[$command]) {
            // get saved button for this command/name
            $attrib = $sa_buttons[$command];
        }
        // set border to 0 because of the link arround the button
        if ($attrib['type']=='image' && !isset($attrib['border'])) {
            $attrib['border'] = 0;
        }
        if (!$attrib['id']) {
            $attrib['id'] =  sprintf('rcmbtn%d', $s_button_count++);
        }
        // get localized text for labels and titles
        if ($attrib['title']) {
            $attrib['title'] = Q(rcube_label($attrib['title']));
        }
        if ($attrib['label']) {
            $attrib['label'] = Q(rcube_label($attrib['label']));
        }
        if ($attrib['alt']) {
            $attrib['alt'] = Q(rcube_label($attrib['alt']));
        }
        // set title to alt attribute for IE browsers
        if ($browser->ie && $attrib['title'] && !$attrib['alt']) {
            $attrib['alt'] = $attrib['title'];
            unset($attrib['title']);
        }
        // add empty alt attribute for XHTML compatibility
        if (!isset($attrib['alt'])) {
            $attrib['alt'] = '';
        }
        // register button in the system
        if ($attrib['command']) {
            $this->add_script(sprintf(
                "%s.register_button('%s', '%s', '%s', '%s', '%s', '%s');",
                JS_OBJECT_NAME,
                $command,
                $attrib['id'],
                $attrib['type'],
                $attrib['imageact'] ? $skin_path.$attrib['imageact'] : $attrib['classact'],
                $attrib['imagesel'] ? $skin_path.$attrib['imagesel'] : $attrib['classsel'],
                $attrib['imageover'] ? $skin_path.$attrib['imageover'] : ''
            ));
            // make valid href to specific buttons
            if (in_array($attrib['command'], $MAIN_TASKS)) {
                $attrib['href'] = Q(rcmail_url(null, null, $attrib['command']));
            }
            else if (in_array($attrib['command'], $a_static_commands)) {
                $attrib['href'] = Q(rcmail_url($attrib['command']));
            }
        }
        // overwrite attributes
        if (!$attrib['href']) {
            $attrib['href'] = '#';
        }
        if ($command) {
            $attrib['onclick'] = sprintf(
                "return %s.command('%s','%s',this)",
                JS_OBJECT_NAME,
                $command,
                $attrib['prop']
            );
        }
        if ($command && $attrib['imageover']) {
            $attrib['onmouseover'] = sprintf(
                "return %s.button_over('%s','%s')",
                JS_OBJECT_NAME,
                $command,
                $attrib['id']
            );
            $attrib['onmouseout'] = sprintf(
                "return %s.button_out('%s','%s')",
                JS_OBJECT_NAME,
                $command,
                $attrib['id']
            );
        }
        if ($command && $attrib['imagesel']) {
            $attrib['onmousedown'] = sprintf(
                "return %s.button_sel('%s','%s')",
                JS_OBJECT_NAME,
                $command,
                $attrib['id']
            );
            $attrib['onmouseup'] = sprintf(
                "return %s.button_out('%s','%s')",
                JS_OBJECT_NAME,
                $command,
                $attrib['id']
            );
        }
        $out = '';
        // generate image tag
        if ($attrib['type']=='image') {
            $attrib_str = html::attrib_string(
                $attrib,
                array(
                    'style', 'class', 'id', 'width',
                    'height', 'border', 'hspace',
                    'vspace', 'align', 'alt',
                )
            );
            $img_tag = sprintf('<img src="%%s"%s />', $attrib_str);
            $btn_content = sprintf($img_tag, $skin_path.$attrib['image']);
            if ($attrib['label']) {
                $btn_content .= ' '.$attrib['label'];
            }
            $link_attrib = array('href', 'onclick', 'onmouseover', 'onmouseout', 'onmousedown', 'onmouseup', 'title');
        }
        else if ($attrib['type']=='link') {
            $btn_content = $attrib['label'] ? $attrib['label'] : $attrib['command'];
            $link_attrib = array('href', 'onclick', 'title', 'id', 'class', 'style');
        }
        else if ($attrib['type']=='input') {
            $attrib['type'] = 'button';
            if ($attrib['label']) {
                $attrib['value'] = $attrib['label'];
            }
            $attrib_str = html::attrib_string(
                $attrib,
                array(
                    'type', 'value', 'onclick',
                    'id', 'class', 'style'
                )
            );
            $out = sprintf('<input%s disabled="disabled" />', $attrib_str);
        }
        // generate html code for button
        if ($btn_content) {
            $attrib_str = html::attrib_string($attrib, $link_attrib);
            $out = sprintf('<a%s>%s</a>', $attrib_str, $btn_content);
        }
        return $out;
    }
    /*  ************* common functions delivering gui objects **************  */
    /**
     * 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
     */
    static function current_username($attrib)
    {
        global $USER;
        static $username;
        // alread fetched
        if (!empty($username)) {
            return $username;
        }
        // get e-mail address form default identity
        if ($sql_arr = $USER->get_identity()) {
          $s_username = $sql_arr['email'];
        }
        else if (strstr($_SESSION['username'], '@')) {
            $username = $_SESSION['username'];
        }
        else {
            $username = $_SESSION['username'].'@'.$_SESSION['imap_host'];
        }
        return $username;
    }
    /**
     * GUI object 'loginform'
     * Returns code for the webmail login form
     *
     * @param array Named parameters
     * @return string HTML code for the gui object
     */
    private function login_form($attrib)
    {
        global $CONFIG, $SESS_HIDDEN_FIELD;
        $default_host = $CONFIG['default_host'];
        $_SESSION['temp'] = true;
        $input_user   = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30, 'autocomplete' => 'off'));
        $input_pass   = new html_passwordfield(array('name' => '_pass', 'id' => 'rcmloginpwd', 'size' => 30));
        $input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login'));
        $input_host   = null;
        if (is_array($default_host)) {
            $input_host = new html_select(array('name' => '_host', 'id' => 'rcmloginhost'));
            foreach ($default_host as $key => $value) {
                if (!is_array($value)) {
                    $input_host->add($value, (is_numeric($key) ? $value : $key));
                }
                else {
                    $input_host = null;
                    break;
                }
            }
        }
        else if (!strlen($default_host)) {
            $input_host = new html_inputfield(array('name' => '_host', 'id' => 'rcmloginhost', 'size' => 30));
        }
        $form_name  = !empty($attrib['form']) ? $attrib['form'] : 'form';
        $this->add_gui_object('loginform', $form_name);
        // create HTML table with two cols
        $table = new html_table(array('cols' => 2));
        $table->add('title', html::label('rcmloginuser', Q(rcube_label('username'))));
        $table->add(null, $input_user->show(get_input_value('_user', RCUVE_INPUT_POST)));
        $table->add('title', html::label('rcmloginpwd', Q(rcube_label('password'))));
        $table->add(null, $input_pass->show());
        // add host selection row
        if (is_object($input_host)) {
            $table->add('title', html::label('rcmloginhost', Q(rcube_label('server'))));
            $table->add(null, $input_host->show(get_input_value('_host', RCUVE_INPUT_POST)));
        }
        $out = $SESS_HIDDEN_FIELD;
        $out .= $input_action->show();
        $out .= $table->show();
        // surround html output with a form tag
        if (empty($attrib['form'])) {
            $out = html::tag(
                'form',
                array(
                    'name' => $form_name,
                    'action' => "./",
                    'method' => "post"
                ),
            $out);
        }
        return $out;
    }
    /**
     * GUI object 'searchform'
     * Returns code for search function
     *
     * @param array Named parameters
     * @return string HTML code for the gui object
     */
    private function search_form($attrib)
    {
        // add some labels to client
        $this->add_label('searching');
        $attrib['name'] = '_q';
        if (empty($attrib['id'])) {
            $attrib['id'] = 'rcmqsearchbox';
        }
        $input_q = new html_inputfield($attrib);
        $out = $input_q->show();
        $this->add_gui_object('qsearchbox', $attrib['id']);
        // add form tag around text field
        if (empty($attrib['form'])) {
            $out = html::tag(
                'form',
                array(
                    'name' => "rcmqsearchform",
                    'action' => "./",
                    'onsubmit' => JS_OBJECT_NAME . ".command('search');return false;",
                    'style' => "display:inline",
                ),
            $out);
        }
        return $out;
    }
    /**
     * Builder for GUI object 'message'
     *
     * @param array Named tag parameters
     * @return string HTML code for the gui object
     */
    private function message_container($attrib)
    {
        if (isset($attrib['id']) === false) {
            $attrib['id'] = 'rcmMessageContainer';
        }
        $this->add_gui_object('message', $attrib['id']);
        return html::div($attrib, "");
    }
    /**
     * GUI object 'charsetselector'
     *
     * @param array Named parameters for the select tag
     * @return string HTML code for the gui object
     */
    static function charset_selector($attrib)
    {
        // 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 html_select($field_attrib);
            $select->add(array_values($charsets), array_keys($charsets));
            $set = $_POST['_charset'] ? $_POST['_charset'] : $this->get_charset();
            return $select->show($set);
    }
}  // end class rcube_template
program/include/rcube_user.php
program/js/app.js
@@ -1581,11 +1581,11 @@
        parent.rcmail.set_classname(rows[uid].obj, 'unread', false);
        if (rows[uid].replied && parent.rcmail.env.repliedicon)
          icn_src = parent.rcmail.env.repliedicon;
          icn_src = parent.rcmail.env.repliedicon;
        else if (parent.rcmail.env.messageicon)
          icn_src = parent.rcmail.env.messageicon;
      
    if (rows[uid].icon && icn_src)
        if (rows[uid].icon && icn_src)
          rows[uid].icon.src = icn_src;
      }
  }
@@ -3502,28 +3502,27 @@
          this.message_list.init();
      case 'purge':
      case 'expunge':
    if (!this.env.messagecount)
          {
        // clear preview pane content
        if (this.env.contentframe)
          this.show_contentframe(false);
        // disable commands useless when mailbox is empty
        this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'mark', 'viewsource',
          'print', 'load-attachment', 'purge', 'expunge', 'select-all', 'select-none', 'sort', false);
      }
      case 'expunge':
        if (!this.env.messagecount)
        {
          // clear preview pane content
          if (this.env.contentframe)
            this.show_contentframe(false);
          // disable commands useless when mailbox is empty
          this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'mark', 'viewsource',
          'print', 'load-attachment', 'purge', 'expunge', 'select-all', 'select-none', 'sort', false);
        }
    break;
      break;
      case 'list':
    this.msglist_select(this.message_list);
        this.msglist_select(this.message_list);
      case 'check-recent':
      case 'getunread':
    this.enable_command('show', 'expunge', 'select-all', 'select-none', 'sort', (this.env.messagecount > 0));
    this.enable_command('purge', (this.env.messagecount && (this.env.mailbox==this.env.trash_mailbox || this.env.mailbox==this.env.junk_mailbox)));
    break;
        this.enable_command('show', 'expunge', 'select-all', 'select-none', 'sort', (this.env.messagecount > 0));
        this.enable_command('purge', (this.env.messagecount && (this.env.mailbox==this.env.trash_mailbox || this.env.mailbox==this.env.junk_mailbox)));
        break;
      }
program/lib/html2text.php
program/steps/addressbook/edit.inc
@@ -89,7 +89,7 @@
  $form_start = '';
  if (!strlen($EDIT_FORM))
    {
    $hiddenfields = new hiddenfield(array('name' => '_task', 'value' => $GLOBALS['_task']));
    $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $GLOBALS['_task']));
    $hiddenfields->add(array('name' => '_action', 'value' => 'save', 'source' => get_input_value('_source', RCUBE_INPUT_GPC)));
    
    if (($result = $CONTACTS->get_result()) && ($record = $result->first()))
@@ -114,8 +114,8 @@
if (!$CONTACTS->get_result() && template_exists('addcontact'))
  parse_template('addcontact');
  $OUTPUT->send('addcontact');
// this will be executed if no template for addcontact exists
parse_template('editcontact');
$OUTPUT->send('editcontact');
?>
program/steps/addressbook/func.inc
@@ -19,9 +19,6 @@
*/
require_once('include/rcube_contacts.inc');
require_once('include/rcube_ldap.inc');
// instantiate a contacts object according to the given source
if (($source = get_input_value('_source', RCUBE_INPUT_GPC)) && isset($CONFIG['ldap_public'][$source]))
  $CONTACTS = new rcube_ldap($CONFIG['ldap_public'][$source]);
@@ -157,7 +154,7 @@
    
    // format each col
    foreach ($a_show_cols as $col)
      $a_row_cols[$col] = $row[$col];
      $a_row_cols[$col] = Q($row[$col]);
    
    $OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols);
    }
@@ -231,7 +228,7 @@
  'addresslist' => 'rcmail_contacts_list',
  'addressframe' => 'rcmail_contact_frame',
  'recordscountdisplay' => 'rcmail_rowcount_display',
  'searchform' => 'rcmail_search_form'
  'searchform' => array($OUTPUT, 'search_form')
));
?>
program/steps/error.inc
@@ -101,7 +101,7 @@
  {
  $OUTPUT->scripts = array();
  $OUTPUT->script_files = array();
  parse_template('error');
  $OUTPUT->send('error');
  }
program/steps/mail/addcontact.inc
@@ -19,8 +19,6 @@
*/
require_once('include/rcube_contacts.inc');
$done = false;
if (!empty($_POST['_address']))
program/steps/mail/compose.inc
@@ -19,9 +19,6 @@
*/
require_once('Mail/mimeDecode.php');
require_once('lib/html2text.inc');
// define constants for message compose mode
define('RCUBE_COMPOSE_REPLY', 0x0106);
define('RCUBE_COMPOSE_FORWARD', 0x0107);
@@ -159,14 +156,14 @@
      }
        
      $allow_attrib = array('id', 'class', 'style', 'cols', 'rows', 'tabindex');
      $field_type = 'textarea';
      $field_type = 'html_textarea';
      break;
    case 'replyto':
    case 'reply-to':
      $fname = '_replyto';
      $allow_attrib = array('id', 'class', 'style', 'size', 'tabindex');
      $field_type = 'textfield';
      $field_type = 'html_inputfield';
      break;    
  }
 
@@ -231,7 +228,7 @@
    // create teaxtarea object
    $input = new $field_type($field_attrib);
    $out = $input->show($fvalue);
    $out = $input->show($fvalue);
  }
  
  if ($form_start)
@@ -285,7 +282,7 @@
    $a_signatures = array();
    $field_attrib['onchange'] = JS_OBJECT_NAME.".change_identity(this)";
    $select_from = new select($field_attrib);
    $select_from = new html_select($field_attrib);
    while ($sql_arr = $DB->fetch_assoc($sql_result))
    {
@@ -327,7 +324,7 @@
  }
  else
  {
    $input_from = new textfield($field_attrib);
    $input_from = new html_inputfield($field_attrib);
    $out = $input_from->show($_POST['_from']);
  }
  
@@ -419,19 +416,19 @@
  $out = $form_start ? "$form_start\n" : '';
  $saveid = new hiddenfield(array('name' => '_draft_saveid', 'value' => $compose_mode==RCUBE_COMPOSE_DRAFT ? str_replace(array('<','>'), "", $MESSAGE['headers']->messageID) : ''));
  $saveid = new html_hiddenfield(array('name' => '_draft_saveid', 'value' => $compose_mode==RCUBE_COMPOSE_DRAFT ? str_replace(array('<','>'), "", $MESSAGE['headers']->messageID) : ''));
  $out .= $saveid->show();
  $drafttoggle = new hiddenfield(array('name' => '_draft', 'value' => 'yes'));
  $drafttoggle = new html_hiddenfield(array('name' => '_draft', 'value' => 'yes'));
  $out .= $drafttoggle->show();
  $msgtype = new hiddenfield(array('name' => '_is_html', 'value' => ($isHtml?"1":"0")));
  $msgtype = new html_hiddenfield(array('name' => '_is_html', 'value' => ($isHtml?"1":"0")));
  $out .= $msgtype->show();
  // If desired, set this text area to be editable by TinyMCE
  if ($isHtml)
    $attrib['mce_editable'] = "true";
  $textarea = new textarea($attrib);
  $textarea = new html_textarea($attrib);
  $out .= $textarea->show($body);
  $out .= $form_end ? "\n$form_end" : '';
@@ -622,7 +619,7 @@
  unset($attrib['form']);
  
  $attrib['name'] = '_subject';
  $textfield = new textfield($attrib);
  $textfield = new html_inputfield($attrib);
  $subject = '';
@@ -750,7 +747,7 @@
  unset($attrib['form']);
  
  $attrib['name'] = '_priority';
  $selector = new select($attrib);
  $selector = new html_select($attrib);
  $selector->add(array(rcube_label('lowest'),
                       rcube_label('low'),
@@ -781,7 +778,7 @@
  $attrib['name'] = '_receipt';
  $attrib['value'] = '1';
  $checkbox = new checkbox($attrib);
  $checkbox = new html_checkbox($attrib);
  $out = $form_start ? "$form_start\n" : '';
  $out .= $checkbox->show($MESSAGE['headers']->mdn_to ? 1 : 0);
@@ -828,7 +825,7 @@
      unset($attrib['checked']);
    $attrib['id'] = '_' . $value;
    $rb = new radiobutton($attrib);
    $rb = new html_radiobutton($attrib);
    $selector .= sprintf("%s<label for=\"%s\">%s</label>",
                         $rb->show($value),
                         $attrib['id'],
@@ -846,7 +843,7 @@
  $form_start = '';
  if (!strlen($MESSAGE_FORM))
  {
    $hiddenfields = new hiddenfield(array('name' => '_task', 'value' => $GLOBALS['_task']));
    $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $GLOBALS['_task']));
    $hiddenfields->add(array('name' => '_action', 'value' => 'send'));
    $form_start = empty($attrib['form']) ? '<form name="form" action="./" method="post">' : '';
@@ -862,7 +859,7 @@
  
  $MESSAGE_FORM = $form_name;
  return array($form_start, $form_end);
  return array($form_start, $form_end);
}
@@ -880,9 +877,6 @@
));
/****** get contacts for this user and add them to client scripts ********/
require_once('include/rcube_contacts.inc');
require_once('include/rcube_ldap.inc');
$CONTACTS = new rcube_contacts($DB, $USER->ID);
$CONTACTS->set_pagesize(1000);
@@ -928,5 +922,5 @@
  { 
     $OUTPUT->set_env('contacts', $a_contacts); 
  } 
parse_template('compose');
$OUTPUT->send('compose');
?>
program/steps/mail/func.inc
@@ -19,7 +19,6 @@
*/
require_once('lib/html2text.inc');
require_once('lib/enriched.inc');
require_once('include/rcube_smtp.inc');
@@ -1541,7 +1540,7 @@
  'messagecontentframe' => 'rcmail_messagecontent_frame',
  'messagepartframe' => 'rcmail_message_part_frame',
  'messagepartcontrols' => 'rcmail_message_part_controls',
  'searchform' => 'rcmail_search_form'
  'searchform' => array($OUTPUT, 'search_form'),
));
?>
program/steps/mail/get.inc
@@ -49,7 +49,7 @@
// show part page
if ($_GET['_frame'])
  {
  parse_template('messagepart');
  $OUTPUT->send('messagepart');
  exit;
  }
program/steps/mail/sendmail.inc
@@ -5,7 +5,7 @@
 | program/steps/mail/sendmail.inc                                       |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland                 |
 | Copyright (C) 2005-2008, RoundCube Dev. - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
@@ -19,11 +19,6 @@
 $Id$
*/
//require_once('lib/smtp.inc');
require_once('lib/html2text.inc');
require_once('lib/rc_mail_mime.inc');
if (!isset($_SESSION['compose']['id']))
@@ -70,7 +65,7 @@
 */
function rcmail_attach_emoticons(&$mime_message)
{
  global $CONFIG, $INSTALL_PATH;
  global $CONFIG;
  $htmlContents = $mime_message->getHtmlBody();
@@ -100,7 +95,7 @@
    if (! in_array($image_name, $included_images))
      {
      // add the image to the MIME message
      $img_file = $INSTALL_PATH . '/' . $searchstr . $image_name;
      $img_file = INSTALL_PATH . '/' . $searchstr . $image_name;
      if(! $mime_message->addHTMLImage($img_file, 'image/gif', '', true, '_' . $image_name))
        $OUTPUT->show_message("emoticonerror", 'error');
@@ -237,7 +232,7 @@
$isHtml = ($isHtmlVal == "1");
// create extended PEAR::Mail_mime instance
$MAIL_MIME = new rc_mail_mime(rcmail_header_delm());
$MAIL_MIME = new rcube_mail_mime(rcmail_header_delm());
// For HTML-formatted messages, construct the MIME message with both
// the HTML part and the plain-text part
program/steps/mail/sendmdn.inc
@@ -19,8 +19,6 @@
*/
require_once('lib/rc_mail_mime.inc');
if (!empty($_POST['_uid'])) {
  $sent = rcmail_send_mdn(get_input_value('_uid', RCUBE_INPUT_POST));
program/steps/mail/show.inc
@@ -19,9 +19,6 @@
*/
require_once('Mail/mimeDecode.php');
require_once('lib/rc_mail_mime.inc');
$PRINT_MODE = $_action=='print' ? TRUE : FALSE;
// similar code as in program/steps/mail/get.inc
@@ -39,7 +36,7 @@
    {
    $OUTPUT->show_message('messageopenerror', 'error');
    if ($_action=='preview' && template_exists('messagepreview'))
        parse_template('messagepreview');
        $OUTPUT->send('messagepreview');
    else
      {
      $_action = 'list';
@@ -79,14 +76,14 @@
  // mark message as read
  if (!$MESSAGE['headers']->seen)
  {
    $marked = $IMAP->set_flag($MESSAGE['UID'], 'SEEN');
    if($_action == 'preview' && $marked != -1)
    {
      $marked = $IMAP->set_flag($MESSAGE['UID'], 'SEEN');
      if($_action == 'preview' && $marked != -1)
    {
    $OUTPUT->command('set_unread_count_from_preview', $mbox_name, $IMAP->messagecount($mbox_name, 'UNSEEN'), ($mbox_name == 'INBOX'));
    $OUTPUT->command('mark_as_read_from_preview', $MESSAGE['UID']);
    }
      $OUTPUT->command('set_unread_count_from_preview', $mbox_name, $IMAP->messagecount($mbox_name, 'UNSEEN'), ($mbox_name == 'INBOX'));
      $OUTPUT->command('mark_as_read_from_preview', $MESSAGE['UID']);
    }
  }
  // give message uid to the client
  $OUTPUT->set_env('uid', $MESSAGE['UID']);
@@ -207,9 +204,9 @@
if ($_action=='print' && template_exists('printmessage'))
  parse_template('printmessage');
  $OUTPUT->send('printmessage');
else if ($_action=='preview' && template_exists('messagepreview'))
    parse_template('messagepreview');
    $OUTPUT->send('messagepreview');
else
  parse_template('message');
  $OUTPUT->send('message');
?>
program/steps/settings/edit_identity.inc
@@ -130,7 +130,7 @@
$OUTPUT->add_handler('identityform', 'rcube_identity_form');
if ($_action=='add-identity' && template_exists('addidentity'))
  parse_template('addidentity');
  $OUTPUT->send('addidentity');
parse_template('editidentity');
$OUTPUT->send('editidentity');
?>
program/steps/settings/func.inc
@@ -50,7 +50,7 @@
    asort($a_lang);
  
    $field_id = 'rcmfd_lang';
    $select_lang = new select(array('name' => '_language', 'id' => $field_id));
    $select_lang = new html_select(array('name' => '_language', 'id' => $field_id));
    $select_lang->add(array_values($a_lang), array_keys($a_lang));
  
    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
@@ -64,7 +64,7 @@
  if (!isset($no_override['timezone']))
    {
    $field_id = 'rcmfd_timezone';
    $select_timezone = new select(array('name' => '_timezone', 'id' => $field_id));
    $select_timezone = new html_select(array('name' => '_timezone', 'id' => $field_id));
    $select_timezone->add('(GMT -11:00) Midway Island, Samoa', '-11');
    $select_timezone->add('(GMT -10:00) Hawaii', '-10');
    $select_timezone->add('(GMT -9:30) Marquesas Islands', '-9.5');
@@ -116,7 +116,7 @@
  if (!isset($no_override['dst_active']))
    {
    $field_id = 'rcmfd_dst';
    $input_dst = new checkbox(array('name' => '_dst_active', 'id' => $field_id, 'value' => 1));
    $input_dst = new html_checkbox(array('name' => '_dst_active', 'id' => $field_id, 'value' => 1));
    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
                    $field_id,
                    Q(rcube_label('dstactive')),
@@ -127,7 +127,7 @@
  if (!isset($no_override['pagesize']))
    {
    $field_id = 'rcmfd_pgsize';
    $input_pagesize = new textfield(array('name' => '_pagesize', 'id' => $field_id, 'size' => 5));
    $input_pagesize = new html_inputfield(array('name' => '_pagesize', 'id' => $field_id, 'size' => 5));
    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
                    $field_id,
@@ -139,7 +139,7 @@
  if (!isset($no_override['prettydate']))
    {
    $field_id = 'rcmfd_prettydate';
    $input_prettydate = new checkbox(array('name' => '_pretty_date', 'id' => $field_id, 'value' => 1));
    $input_prettydate = new html_checkbox(array('name' => '_pretty_date', 'id' => $field_id, 'value' => 1));
    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
                    $field_id,
@@ -151,7 +151,7 @@
  if (!isset($no_override['prefer_html']))
    {
    $field_id = 'rcmfd_htmlmsg';
    $input_pagesize = new checkbox(array('name' => '_prefer_html', 'id' => $field_id, 'value' => 1));
    $input_pagesize = new html_checkbox(array('name' => '_prefer_html', 'id' => $field_id, 'value' => 1));
    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
                    $field_id,
@@ -163,7 +163,7 @@
  if (!isset($no_override['htmleditor']))
    {
    $field_id = 'rcmfd_htmleditor';
    $input_htmleditor = new checkbox(array('name' => '_htmleditor', 'id' => $field_id, 'value' => 1));
    $input_htmleditor = new html_checkbox(array('name' => '_htmleditor', 'id' => $field_id, 'value' => 1));
    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
                    $field_id,
                    Q(rcube_label('htmleditor')),
@@ -174,7 +174,7 @@
  if (!isset($no_override['preview_pane']))
    {
    $field_id = 'rcmfd_preview';
    $input_preview = new checkbox(array('name' => '_preview_pane', 'id' => $field_id, 'value' => 1));
    $input_preview = new html_checkbox(array('name' => '_preview_pane', 'id' => $field_id, 'value' => 1));
    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
                    $field_id,
                    Q(rcube_label('previewpane')),
@@ -184,7 +184,7 @@
  if (!empty($CONFIG['drafts_mbox']) && !isset($no_override['draft_autosave']))
    {
    $field_id = 'rcmfd_autosave';
    $select_autosave = new select(array('name' => '_draft_autosave', 'id' => $field_id));
    $select_autosave = new html_select(array('name' => '_draft_autosave', 'id' => $field_id));
    $select_autosave->add(rcube_label('never'), 0);
    foreach (array(3, 5, 10) as $i => $min)
      $select_autosave->add(rcube_label(array('name' => 'everynminutes', 'vars' => array('n' => $min))), $min*60);
@@ -199,7 +199,7 @@
  if (!isset($no_override['logout_purge']))
    {
    $field_id = 'rcmfd_logout_purge';
    $input_purge = new checkbox(array('name' => '_logout_purge', 'id' => $field_id, 'value' => 1));
    $input_purge = new html_checkbox(array('name' => '_logout_purge', 'id' => $field_id, 'value' => 1));
    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
                    $field_id,
                    Q(rcube_label('logoutclear')),
@@ -210,7 +210,7 @@
  if (!isset($no_override['logout_expunge']))
    {
    $field_id = 'rcmfd_logout_expunge';
    $input_expunge = new checkbox(array('name' => '_logout_expunge', 'id' => $field_id, 'value' => 1));
    $input_expunge = new html_checkbox(array('name' => '_logout_expunge', 'id' => $field_id, 'value' => 1));
    $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
                    $field_id,
                    Q(rcube_label('logoutcompact')),
@@ -254,7 +254,7 @@
  $form_start = '';
  if (!strlen($EDIT_FORM))
    {
    $hiddenfields = new hiddenfield(array('name' => '_task', 'value' => $GLOBALS['_task']));
    $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $GLOBALS['_task']));
    $hiddenfields->add(array('name' => '_action', 'value' => $action));
    
    if ($add_hidden)
program/steps/settings/identities.inc
@@ -45,5 +45,5 @@
$OUTPUT->add_handler('identityframe', 'rcmail_identity_frame');
parse_template('identities');
$OUTPUT->send('identities');
?>
program/steps/settings/manage_folders.inc
@@ -174,7 +174,7 @@
  $delimiter = $IMAP->get_hierarchy_delimiter();
  $a_js_folders = array();
 
  $checkbox_subscribe = new checkbox(array('name' => '_subscribed[]', 'onclick' => JS_OBJECT_NAME.".command(this.checked?'subscribe':'unsubscribe',this.value)"));
  $checkbox_subscribe = new html_checkbox(array('name' => '_subscribed[]', 'onclick' => JS_OBJECT_NAME.".command(this.checked?'subscribe':'unsubscribe',this.value)"));
  
  if (!empty($attrib['deleteicon']))
    $del_button = sprintf('<img src="%s%s" alt="%s" border="0" />', $CONFIG['skin_path'], $attrib['deleteicon'], rcube_label('delete'));
@@ -251,12 +251,12 @@
  // return the complete edit form as table
  $out = "$form_start\n";
  $input = new textfield(array('name' => '_folder_name'));
  $input = new html_inputfield(array('name' => '_folder_name'));
  $out .= $input->show();
  
  if (get_boolean($attrib['button']))
    {
    $button = new input_field(array('type' => 'button',
    $button = new html_inputfield(array('type' => 'button',
                                    'value' => rcube_label('create'),
                                    'onclick' => JS_OBJECT_NAME.".command('create-folder',this.form)"));
    $out .= $button->show();
@@ -278,7 +278,7 @@
  $out = "$form_start\n";
  $a_unsubscribed = $IMAP->list_unsubscribed();
  $select_folder = new select(array('name' => '_folder_oldname', 'id' => 'rcmfd_oldfolder'));
  $select_folder = new html_select(array('name' => '_folder_oldname', 'id' => 'rcmfd_oldfolder'));
  foreach ($a_unsubscribed as $i => $folder)
    {
@@ -291,12 +291,12 @@
  $out .= $select_folder->show();
  $out .= " to ";
  $inputtwo = new textfield(array('name' => '_folder_newname'));
  $inputtwo = new html_inputfield(array('name' => '_folder_newname'));
  $out .= $inputtwo->show();
  if (get_boolean($attrib['button']))
    {
    $button = new input_field(array('type' => 'button',
    $button = new html_inputfield(array('type' => 'button',
                                    'value' => rcube_label('rename'),
                                    'onclick' => JS_OBJECT_NAME.".command('rename-folder',this.form)"));
    $out .= $button->show();