diff options
63 files changed, 3192 insertions, 2716 deletions
@@ -29,6 +29,18 @@ The current development skin uses icons designed by Stephen Horlander and Kevin Gerich for Mozilla.org. +Installation: +------------- +For detailed instructions on how to install RoundCube webmail on your server, +please refer to the INSTALL document in the same directory as this document. + + +Licensing: +---------- +This product is distributed under the GPL. Please read through the file +LICENSE for more information about our license. + + How it works: ------------- The main authority for the RoundCube access is the IMAP server. If @@ -42,32 +54,20 @@ will be allowed. Code Layout: ------------ - Basic sequence (index.php): - - index.php -> load_gui -> parse_template + - index.php -> rcmail_load_gui -> new rcmail_template -> rcmail_template::send - authentication details in this sequence Tasks - index.php limits tasks to set list - can see task in roundcube link when you mouse over it - task templates stored in skins/default/templates - - templates "roundcube:" tokens that get replaced in parse_template + - templates "roundcube:" tokens that get replaced in rcmail_template class program/include/rcube_shared.inc - defines rcube_html_page, class that lays out a roundcube web page - defines form control classes - - -Installation: -------------- -For detailed instructions on how to install RoundCube webmail on your server, -please refer to the INSTALL document in the same directory as this document. - - -Licensing: ----------- -This product is distributed under the GPL. Please read through the file -LICENSE for more information about our license. + - provides common functions Contact: @@ -17,6 +17,8 @@ from version 1.0-beta2 $rcmail_config['preview_pane'] = TRUE; $rcmail_config['date_today'] = 'H:i'; $rcmail_config['double_auth'] = TRUE; +* If you have LDAP servers configured, change prop key 'mail_field' + to 'email_field' for each server confgured in /config/main.inc.php form version 0.1-beta diff --git a/bin/html2text.php b/bin/html2text.php new file mode 100644 index 000000000..e0e2679f7 --- /dev/null +++ b/bin/html2text.php @@ -0,0 +1,16 @@ +<?php + +require_once('../program/lib/html2text.inc'); + +$htmlText = $HTTP_RAW_POST_DATA; +$converter = new html2text($htmlText); + +header('Content-Type: text/plain; charset=UTF-8'); +$plaintext = $converter->get_text(); + +if (function_exists('html_entity_decode')) + print html_entity_decode($plaintext, ENT_COMPAT, 'UTF-8'); +else + print $plaintext; + +?>
\ No newline at end of file diff --git a/program/steps/mail/quotaimg.inc b/bin/quotaimg.php index 643ae1c55..47696ef69 100644 --- a/program/steps/mail/quotaimg.inc +++ b/bin/quotaimg.php @@ -2,7 +2,7 @@ /* +-----------------------------------------------------------------------+ - | program/steps/mail/quotaimg.inc | + | program/bin/quotaimg.php | | | | This file is part of the RoundCube Webmail client | | Copyright (C) 2005, RoundCube Dev. - Switzerland | @@ -81,32 +81,29 @@ function genQuota($used, $total, $width, $height) ***** DO NOT EDIT BELOW HERE ***** ****************************/ - if(ereg("^[^0-9?]*$", $used) || ereg("^[^0-9?]*$", $total)) - { + if (ereg("^[^0-9?]*$", $used) || ereg("^[^0-9?]*$", $total)) return false; - } - if(strpos($used, '?')!==false || strpos($total, '?')!==false && $used != 0) - { + + if (strpos($used, '?')!==false || strpos($total, '?')!==false && $used != 0) $unknown = true; - } $im = imagecreate($width, $height); - if($border) - { + if ($border) + { list($r, $g, $b) = explode(',', $color['border']); $borderc = imagecolorallocate($im, $r, $g, $b); imageline($im, 0, 0, $width, 0, $borderc); imageline($im, 0, $height-$border, 0, 0, $borderc); imageline($im, $width-1, 0, $width-$border, $height, $borderc); imageline($im, $width, $height-$border, 0, $height-$border, $borderc); - } + } list($r, $g, $b) = explode(',', $color['text']); $text = imagecolorallocate($im, $r, $g, $b); - if($unknown) - { + if ($unknown) + { list($r, $g, $b) = explode(',', $color['bg']['Unknown']); $background = imagecolorallocate($im, $r, $g, $b); imagefilledrectangle($im, 0, 0, $width, $height, $background); @@ -114,9 +111,9 @@ function genQuota($used, $total, $width, $height) $string = 'Unknown'; $mid = floor(($width-(strlen($string)*imagefontwidth($font)))/2)+1; imagestring($im, $font, $mid, $padding, $string, $text); - } - else if($used > $total) - { + } + else if ($used > $total) + { list($r, $g, $b) = explode(',', $color['bg']['OL']); $background = imagecolorallocate($im, $r, $g, $b); imagefilledrectangle($im, 0, 0, $width, $height, $background); @@ -124,30 +121,30 @@ function genQuota($used, $total, $width, $height) $string = 'Over Limit'; $mid = floor(($width-(strlen($string)*imagefontwidth($font)))/2)+1; imagestring($im, $font, $mid, $padding, $string, $text); - } + } else - { + { list($r, $g, $b) = explode(',', $color['bg']['quota']); $background = imagecolorallocate($im, $r, $b, $g); imagefilledrectangle($im, 0, 0, $width, $height, $background); $quota = ($used==0)?0:(round($used/$total, 2)*100); - if($quota >= $limit['high']) - { + if ($quota >= $limit['high']) + { list($r, $g, $b) = explode(',', $color['fill']['high']); $fill = imagecolorallocate($im, $r, $g, $b); - } + } elseif($quota >= $limit['mid']) - { + { list($r, $g, $b) = explode(',', $color['fill']['mid']); $fill = imagecolorallocate($im, $r, $g, $b); - } + } else // if($quota >= $limit['low']) - { + { list($r, $g, $b) = explode(',', $color['fill']['low']); $fill = imagecolorallocate($im, $r, $g, $b); - } + } $quota_width = $quota / 100 * $width; imagefilledrectangle($im, $border, 0, $quota, $height-2*$border, $fill); @@ -155,10 +152,10 @@ function genQuota($used, $total, $width, $height) $string = $quota.'%'; $mid = floor(($width-(strlen($string)*imagefontwidth($font)))/2)+1; imagestring($im, $font, $mid, $padding, $string, $text); // Print percent in black - } + } header('Content-Type: image/gif'); - header("Expires: ".gmdate("D, d M Y H:i:s", mktime()+86400)." GMT"); + header("Expires: ".gmdate("D, d M Y H:i:s", mktime()+86400)." GMT"); header("Cache-Control: "); header("Pragma: "); diff --git a/config/main.inc.php.dist b/config/main.inc.php.dist index c2c9d3947..894dfa4d8 100644 --- a/config/main.inc.php.dist +++ b/config/main.inc.php.dist @@ -190,16 +190,18 @@ $rcmail_config['mail_header_delimiter'] = NULL; // like the Verisign example below. if you would like to test, // simply uncomment the Verisign example. /** - * example config for Verisign directory + * example config for Verisign directory * - * $rcmail_config['ldap_public']['Verisign'] = array('hosts' => array('directory.verisign.com'), - * 'port' => 389, - * 'base_dn' => '', - * 'search_fields' => array('Email' => 'mail', 'Name' => 'cn'), - * 'name_field' => 'cn', - * 'mail_field' => 'mail', - * 'scope' => 'sub', - * 'fuzzy_search' => 0); + * $rcmail_config['ldap_public']['Verisign'] = array( + * 'name' => 'Verisign.com', + * 'hosts' => array('directory.verisign.com'), + * 'port' => 389, + * 'base_dn' => '', + * 'search_fields' => array('mail', 'cn'), // fields to search in + * 'name_field' => 'cn', // this field represents the contact's name + * 'email_field' => 'mail', // this field represents the contact's e-mail + * 'scope' => 'sub', // search mode: sub|base|list + * 'fuzzy_search' => true); // server allows wildcard search */ // don't allow these settings to be overriden by the user @@ -2,7 +2,7 @@ /* +-----------------------------------------------------------------------+ | RoundCube Webmail IMAP Client | - | Version 0.1-20070411 | + | Version 0.1-20070428 | | | | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | @@ -40,12 +40,13 @@ */ -define('RCMAIL_VERSION', '0.1-20070411'); +// application constants +define('RCMAIL_VERSION', '0.1-20070428'); +define('RCMAIL_CHARSET', 'UTF-8'); +define('JS_OBJECT_NAME', 'rcmail'); // define global vars -$CHARSET = 'UTF-8'; $OUTPUT_TYPE = 'html'; -$JS_OBJECT_NAME = 'rcmail'; $INSTALL_PATH = dirname(__FILE__); $MAIN_TASKS = array('mail','settings','addressbook','logout'); @@ -81,7 +82,6 @@ require_once('include/rcube_imap.inc'); require_once('include/bugs.inc'); require_once('include/main.inc'); require_once('include/cache.inc'); -require_once('lib/html2text.inc'); require_once('PEAR.php'); @@ -98,19 +98,16 @@ $_framed = (!empty($_GET['_framed']) || !empty($_POST['_framed'])); if (empty($_task) || !in_array($_task, $MAIN_TASKS)) $_task = 'mail'; -if (!empty($_GET['_remote'])) - $REMOTE_REQUEST = TRUE; - // set output buffering if ($_action != 'get' && $_action != 'viewsource') - { +{ // use gzip compression if supported if (function_exists('ob_gzhandler') && ini_get('zlib.output_compression')) ob_start('ob_gzhandler'); else ob_start(); - } +} // start session with requested task @@ -123,59 +120,45 @@ $SESS_HIDDEN_FIELD = ''; // add framed parameter if ($_framed) - { - $COMM_PATH .= '&_framed=1'; +{ + $COMM_PATH .= '&_framed=1'; $SESS_HIDDEN_FIELD .= "\n".'<input type="hidden" name="_framed" value="1" />'; - } +} // init necessary objects for GUI -load_gui(); +rcmail_load_gui(); // check DB connections and exit on failure if ($err_str = $DB->is_error()) - { - raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, - 'message' => $err_str), FALSE, TRUE); - } +{ + raise_error(array( + 'code' => 603, + 'type' => 'db', + 'message' => $err_str), FALSE, TRUE); +} // error steps if ($_action=='error' && !empty($_GET['_code'])) - { raise_error(array('code' => hexdec($_GET['_code'])), FALSE, TRUE); - } - -// handle HTML->text conversion -if ($_action=='html2text') - { - $htmlText = $HTTP_RAW_POST_DATA; - $converter = new html2text($htmlText); - - // TODO possibly replace with rcube_remote_response() - header('Content-Type: text/plain'); - $plaintext = $converter->get_text(); - print $plaintext; - - exit; - } // try to log in if ($_action=='login' && $_task=='mail') - { +{ $host = rcmail_autoselect_host(); // check if client supports cookies if (empty($_COOKIE)) - { - show_message("cookiesdisabled", 'warning'); - } + { + $OUTPUT->show_message("cookiesdisabled", 'warning'); + } else if ($_SESSION['temp'] && !empty($_POST['_user']) && isset($_POST['_pass']) && rcmail_login(get_input_value('_user', RCUBE_INPUT_POST), get_input_value('_pass', RCUBE_INPUT_POST, true, 'ISO-8859-1'), $host)) - { + { // create new session ID unset($_SESSION['temp']); sess_regenerate_id(); @@ -186,87 +169,84 @@ if ($_action=='login' && $_task=='mail') // send redirect header("Location: $COMM_PATH"); exit; - } + } else - { - show_message("loginfailed", 'warning'); + { + $OUTPUT->show_message("loginfailed", 'warning'); $_SESSION['user_id'] = ''; - } } +} // end session -else if ($_action=='logout' && isset($_SESSION['user_id'])) - { - show_message('loggedout'); +else if (($_task=='logout' || $_action=='logout') && isset($_SESSION['user_id'])) +{ + $OUTPUT->show_message('loggedout'); rcmail_kill_session(); - } +} // check session and auth cookie else if ($_action != 'login' && $_SESSION['user_id'] && $_action != 'send') - { +{ if (!rcmail_authenticate_session()) - { - $message = show_message('sessionerror', 'error'); + { + $OUTPUT->show_message('sessionerror', 'error'); rcmail_kill_session(); - } } +} // log in to imap server if (!empty($_SESSION['user_id']) && $_task=='mail') - { +{ $conn = $IMAP->connect($_SESSION['imap_host'], $_SESSION['username'], decrypt_passwd($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl']); if (!$conn) - { - show_message('imaperror', 'error'); + { + $OUTPUT->show_message('imaperror', 'error'); $_SESSION['user_id'] = ''; - } + } else rcmail_set_imap_prop(); - } +} // not logged in -> set task to 'login if (empty($_SESSION['user_id'])) - { - if ($REMOTE_REQUEST) - { - $message .= "setTimeout(\"location.href='\"+this.env.comm_path+\"'\", 2000);"; - rcube_remote_response($message); - } +{ + if ($OUTPUT->ajax_call) + $OUTPUT->remote_response("setTimeout(\"location.href='\"+this.env.comm_path+\"'\", 2000);"); $_task = 'login'; - } +} // set task and action to client -$script = sprintf("%s.set_env('task', '%s');", $JS_OBJECT_NAME, $_task); +$OUTPUT->set_env('task', $_task); if (!empty($_action)) - $script .= sprintf("\n%s.set_env('action', '%s');", $JS_OBJECT_NAME, $_action); - -$OUTPUT->add_script($script); + $OUTPUT->set_env('action', $_action); // not logged in -> show login page if (!$_SESSION['user_id']) - { - parse_template('login'); +{ + $OUTPUT->task = 'login'; + $OUTPUT->send('login'); exit; - } +} // handle keep-alive signal if ($_action=='keep-alive') - { - rcube_remote_response(''); +{ + $OUTPUT->reset(); + $OUTPUT->send(''); exit; - } +} // include task specific files if ($_task=='mail') - { +{ include_once('program/steps/mail/func.inc'); if ($_action=='show' || $_action=='preview' || $_action=='print') @@ -317,21 +297,18 @@ if ($_task=='mail') if ($_action=='rss') include('program/steps/mail/rss.inc'); - if ($_action=='quotaimg') - include('program/steps/mail/quotaimg.inc'); - if ($_action=='quotadisplay') include('program/steps/mail/quotadisplay.inc'); // make sure the message count is refreshed $IMAP->messagecount($_SESSION['mbox'], 'ALL', TRUE); - } +} // include task specific files if ($_task=='addressbook') - { +{ include_once('program/steps/addressbook/func.inc'); if ($_action=='save') @@ -349,14 +326,20 @@ if ($_task=='addressbook') if ($_action=='list' && $_GET['_remote']) include('program/steps/addressbook/list.inc'); - if ($_action=='ldappublicsearch') - include('program/steps/addressbook/ldapsearchform.inc'); - } + if ($_action=='search') + include('program/steps/addressbook/search.inc'); + + if ($_action=='copy') + include('program/steps/addressbook/copy.inc'); + + if ($_action=='mailto') + include('program/steps/addressbook/mailto.inc'); +} // include task specific files if ($_task=='settings') - { +{ include_once('program/steps/settings/func.inc'); if ($_action=='save-identity') @@ -378,18 +361,19 @@ if ($_task=='settings') $_action=='create-folder' || $_action=='rename-folder' || $_action=='delete-folder') include('program/steps/settings/manage_folders.inc'); - } +} // parse main template -parse_template($_task); +$OUTPUT->send($_task); // if we arrive here, something went wrong -raise_error(array('code' => 404, - 'type' => 'php', - 'line' => __LINE__, - 'file' => __FILE__, - 'message' => "Invalid request"), TRUE, TRUE); +raise_error(array( + 'code' => 404, + 'type' => 'php', + 'line' => __LINE__, + 'file' => __FILE__, + 'message' => "Invalid request"), TRUE, TRUE); ?> diff --git a/program/include/main.inc b/program/include/main.inc index 6d77d5a07..71534f6b1 100644 --- a/program/include/main.inc +++ b/program/include/main.inc @@ -5,7 +5,7 @@ | program/include/main.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev, - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev, - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -22,6 +22,7 @@ require_once('lib/des.inc'); require_once('lib/utf7.inc'); require_once('lib/utf8.class.php'); +require_once('include/rcmail_template.inc'); // define constannts for input reading @@ -34,7 +35,7 @@ define('RCUBE_INPUT_GPC', 0x0103); function rcmail_startup($task='mail') { global $sess_id, $sess_user_lang; - global $CONFIG, $INSTALL_PATH, $BROWSER, $OUTPUT, $_SESSION, $IMAP, $DB, $JS_OBJECT_NAME; + global $CONFIG, $INSTALL_PATH, $BROWSER, $OUTPUT, $_SESSION, $IMAP, $DB; // check client $BROWSER = rcube_browser(); @@ -103,11 +104,11 @@ function rcmail_startup($task='mail') // load roundcube configuration into global var function rcmail_load_config() { - global $INSTALL_PATH; + global $INSTALL_PATH; // load config file - include_once('config/main.inc.php'); - $conf = is_array($rcmail_config) ? $rcmail_config : array(); + include_once('config/main.inc.php'); + $conf = is_array($rcmail_config) ? $rcmail_config : array(); // load host-specific configuration rcmail_load_host_config($conf); @@ -208,7 +209,7 @@ function rcmail_authenticate_session() // create IMAP object and connect to server function rcmail_imap_init($connect=FALSE) { - global $CONFIG, $DB, $IMAP; + global $CONFIG, $DB, $IMAP, $OUTPUT; $IMAP = new rcube_imap($DB); $IMAP->debug_level = $CONFIG['debug_level']; @@ -219,7 +220,7 @@ function rcmail_imap_init($connect=FALSE) if ($connect) { if (!($conn = $IMAP->connect($_SESSION['imap_host'], $_SESSION['username'], decrypt_passwd($_SESSION['password']), $_SESSION['imap_port'], $_SESSION['imap_ssl']))) - show_message('imaperror', 'error'); + $OUTPUT->show_message('imaperror', 'error'); rcmail_set_imap_prop(); } @@ -360,34 +361,22 @@ function rcube_language_prop($lang, $prop='lang') // init output object for GUI and add common scripts -function load_gui() +function rcmail_load_gui() { - global $CONFIG, $OUTPUT, $COMM_PATH, $JS_OBJECT_NAME, $sess_user_lang; + global $CONFIG, $OUTPUT, $sess_user_lang; // init output page - $OUTPUT = new rcube_html_page(); - - // add common javascripts - $javascript = "var $JS_OBJECT_NAME = new rcube_webmail();\n"; - $javascript .= sprintf("%s.set_env('comm_path', '%s');\n", $JS_OBJECT_NAME, str_replace('&', '&', $COMM_PATH)); + $OUTPUT = new rcmail_template($CONFIG, $GLOBALS['_task']); + $OUTPUT->set_env('comm_path', $GLOBALS['COMM_PATH']); - if (isset($CONFIG['javascript_config'] )){ - foreach ($CONFIG['javascript_config'] as $js_config_var){ - $javascript .= "$JS_OBJECT_NAME.set_env('$js_config_var', '" . $CONFIG[$js_config_var] . "');\n"; - } + if (is_array($CONFIG['javascript_config'])) + { + foreach ($CONFIG['javascript_config'] as $js_config_var) + $OUTPUT->set_env($js_config_var, $CONFIG[$js_config_var]); } - // 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');"; - if (!empty($GLOBALS['_framed'])) - $javascript .= "$JS_OBJECT_NAME.set_env('framed', true);\n"; - - $OUTPUT->add_script($javascript, 'head'); - $OUTPUT->add_script($javascript_foot, 'foot'); - $OUTPUT->include_script('common.js'); - $OUTPUT->include_script('app.js'); - $OUTPUT->scripts_path = 'program/js/'; + $OUTPUT->set_env('framed', true); // set locale setting rcmail_set_locale($sess_user_lang); @@ -395,16 +384,25 @@ function load_gui() // set user-selected charset 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 - rcube_add_label('loading','checkingmail'); + if (!$OUTPUT->ajax_call) + rcube_add_label('loading'); } // set localization charset based on the given language function rcmail_set_locale($lang) { - global $OUTPUT, $CHARSET, $MBSTRING; + global $OUTPUT, $MBSTRING; static $s_mbstring_loaded = NULL; // settings for mbstring module (by Tadashi Jokagi) @@ -414,7 +412,7 @@ function rcmail_set_locale($lang) $MBSTRING = $s_mbstring_loaded = FALSE; if ($MBSTRING) - mb_internal_encoding($CHARSET); + mb_internal_encoding(RCMAIL_CHARSET); $OUTPUT->set_charset(rcube_language_prop($lang, 'charset')); } @@ -749,30 +747,35 @@ function rcmail_save_user_prefs($a_user_prefs) // overwrite action variable function rcmail_overwrite_action($action) { - global $OUTPUT, $JS_OBJECT_NAME; + global $OUTPUT; $GLOBALS['_action'] = $action; - - $OUTPUT->add_script(sprintf("\n%s.set_env('action', '%s');", $JS_OBJECT_NAME, $action)); + $OUTPUT->set_env('action', $action); } -function show_message($message, $type='notice', $vars=NULL) - { - global $OUTPUT, $JS_OBJECT_NAME, $REMOTE_REQUEST; +// compose a URL to the given action +function rcmail_self_url($action, $p=array(), $task=null) +{ + global $MAIN_TASKS, $COMM_PATH; + $qstring = ''; + $base = $COMM_PATH; - $framed = $GLOBALS['_framed']; - $command = sprintf("display_message('%s', '%s');", - JQ(rcube_label(array('name' => $message, 'vars' => $vars))), - $type); - - if ($REMOTE_REQUEST) - return 'this.'.$command; + if ($task && in_array($task, $MAIN_TASKS)) + $base = ereg_replace('_task=[a-z]+', '_task='.$task, $COMM_PATH); - else - $OUTPUT->add_script(sprintf("%s%s.%s\n", - $framed ? sprintf('if(parent.%s)parent.', $JS_OBJECT_NAME) : '', - $JS_OBJECT_NAME, - $command)); + if (is_array($p)) + foreach ($p as $key => $val) + $qstring .= '&'.urlencode($key).'='.urlencode($val); + + return $base . ($action ? '&_action='.$action : '') . $qstring; +} + + +// @deprecated +function show_message($message, $type='notice', $vars=NULL) + { + global $OUTPUT; + $OUTPUT->show_message($message, $type, $vars); } @@ -808,43 +811,6 @@ function get_des_key() } -// send correct response on a remote request -function rcube_remote_response($js_code, $flush=FALSE) - { - global $OUTPUT, $CHARSET; - static $s_header_sent = FALSE; - - if (!$s_header_sent) - { - $s_header_sent = TRUE; - send_nocacheing_headers(); - header('Content-Type: application/x-javascript; charset='.$CHARSET); - print '/** remote response ['.date('d/M/Y h:i:s O')."] **/\n"; - } - - // send response code - print rcube_charset_convert($js_code, $CHARSET, $OUTPUT->get_charset()); - - if ($flush) // flush the output buffer - flush(); - else // terminate script - exit; - } - - -// send correctly formatted response for a request posted to an iframe -function rcube_iframe_response($js_code='') - { - global $OUTPUT, $JS_OBJECT_NAME; - - if (!empty($js_code)) - $OUTPUT->add_script("if(parent.$JS_OBJECT_NAME){\n" . $js_code . "\n}"); - - $OUTPUT->write(); - exit; - } - - // read directory program/localization/ and return a list of available languages function rcube_list_languages() { @@ -875,14 +841,11 @@ function rcube_list_languages() // add a localized label to the client environment function rcube_add_label() { - global $OUTPUT, $JS_OBJECT_NAME; + global $OUTPUT; $arg_list = func_get_args(); foreach ($arg_list as $i => $name) - $OUTPUT->add_script(sprintf("%s.add_label('%s', '%s');", - $JS_OBJECT_NAME, - $name, - JQ(rcube_label($name)))); + $OUTPUT->command('add_label', $name, rcube_label($name)); } @@ -931,7 +894,7 @@ function rcmail_message_cache_gc() * * @param string Input string * @param string Suspected charset of the input string - * @param string Target charset to convert to; defaults to $GLOBALS['CHARSET'] + * @param string Target charset to convert to; defaults to RCMAIL_CHARSET * @return Converted string */ function rcube_charset_convert($str, $from, $to=NULL) @@ -939,7 +902,7 @@ function rcube_charset_convert($str, $from, $to=NULL) global $MBSTRING; $from = strtoupper($from); - $to = $to==NULL ? strtoupper($GLOBALS['CHARSET']) : strtoupper($to); + $to = $to==NULL ? strtoupper(RCMAIL_CHARSET) : strtoupper($to); if ($from==$to || $str=='' || empty($from)) return $str; @@ -1071,15 +1034,15 @@ function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) if ($enctype=='js') { if ($OUTPUT->get_charset()!='UTF-8') - $str = rcube_charset_convert($str, $GLOBALS['CHARSET'], $OUTPUT->get_charset()); + $str = rcube_charset_convert($str, RCMAIL_CHARSET, $OUTPUT->get_charset()); - return addslashes(preg_replace(array("/\r\n/", "/\r/"), array('\n', '\n'), 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 return $str; } - + /** * Quote a given string. Alias function for rep_specialchars_output * @see rep_specialchars_output @@ -1160,426 +1123,41 @@ function strip_newlines($str) } -// ************** template parsing and gui functions ************** - - -// return boolean if a specific template exists -function template_exists($name) - { - global $CONFIG, $OUTPUT; - $skin_path = $CONFIG['skin_path']; - - // check template file - return is_file("$skin_path/templates/$name.html"); - } - - -// get page template an replace variable -// similar function as used in nexImage -function parse_template($name='main', $exit=TRUE) - { - global $CONFIG, $OUTPUT; - $skin_path = $CONFIG['skin_path']; - - // read template file - $templ = ''; - $path = "$skin_path/templates/$name.html"; - - if($fp = @fopen($path, 'r')) - { - $templ = fread($fp, filesize($path)); - fclose($fp); - } - else - { - raise_error(array('code' => 500, - 'type' => 'php', - 'line' => __LINE__, - 'file' => __FILE__, - 'message' => "Error loading template for '$name'"), TRUE, TRUE); - return FALSE; - } - - - // parse for specialtags - $output = parse_rcube_xml(parse_rcube_conditions($templ)); - - // add debug console - if ($CONFIG['debug_level'] & 8) - $OUTPUT->footer = '<div style="position:absolute;top:5px;left:5px;width:400px;opacity:0.8;z-index:9000;"><form name="debugform"><textarea name="console" rows="15" cols="40" style="width:400px;border:none;font-size:x-small"></textarea></form>'; - - $OUTPUT->write(trim(parse_with_globals($output)), $skin_path); - - if ($exit) - exit; - } - - - -// replace all strings ($varname) with the content of the according global variable -function parse_with_globals($input) - { - $GLOBALS['__comm_path'] = $GLOBALS['COMM_PATH']; - $output = preg_replace('/\$(__[a-z0-9_\-]+)/e', '$GLOBALS["\\1"]', $input); - return $output; - } - - -// parse conditional code -function parse_rcube_conditions($input) - { - if (($matches = preg_split('/<roundcube:(if|elseif|else|endif)\s+([^>]+)>/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE)) && count($matches)==4) - { - if (preg_match('/^(else|endif)$/i', $matches[1])) - return $matches[0] . parse_rcube_conditions($matches[3]); - else - { - $attrib = parse_attrib_string($matches[2]); - if (isset($attrib['condition'])) - { - $condmet = rcube_xml_condition($attrib['condition']); - $submatches = preg_split('/<roundcube:(elseif|else|endif)\s+([^>]+)>/is', $matches[3], 2, PREG_SPLIT_DELIM_CAPTURE); - - if ($condmet) - $result = $submatches[0] . preg_replace('/.*<roundcube:endif\s+[^>]+>/is', '', $submatches[3]); - else - $result = "<roundcube:$submatches[1] $submatches[2]>" . $submatches[3]; - - return $matches[0] . parse_rcube_conditions($result); - } - else - { - raise_error(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 + * Compose an URL for a specific action * - * @return True if condition is valid, False is not - */ -function rcube_xml_condition($condition) - { - $condition = preg_replace( - array('/session:([a-z0-9_]+)/i', '/config:([a-z0-9_]+)/i', '/request:([a-z0-9_]+)/ie'), - array("\$_SESSION['\\1']", "\$GLOBALS['CONFIG']['\\1']", "get_input_value('\\1', RCUBE_INPUT_GPC)"), - $condition); - - return @eval("return (".$condition.");"); - } - - -function parse_rcube_xml($input) - { - $output = preg_replace('/<roundcube:([-_a-z]+)\s+([^>]+)>/Uie', "rcube_xml_command('\\1', '\\2')", $input); - return $output; - } - - -/** - * Convert a xml command tag into real content + * @param string Request action + * @param array More URL parameters + * @return The application URL */ -function rcube_xml_command($command, $str_attrib, $add_attrib=array()) - { - global $IMAP, $CONFIG, $OUTPUT; - - $command = strtolower($command); - $attrib = parse_attrib_string($str_attrib) + $add_attrib; - - // empty output if required condition is not met - if (!empty($attrib['condition']) && !rcube_xml_condition($attrib['condition'])) - return ''; - - // execute command - switch ($command) - { - // return a button - case 'button': - if ($attrib['command']) - return rcube_button($attrib); - break; - - // show a label - case 'label': - if ($attrib['name'] || $attrib['command']) - return Q(rcube_label($attrib + array('vars' => array('product' => $CONFIG['product_name'])))); - break; - - // create a menu item - case 'menu': - if ($attrib['command'] && $attrib['group']) - rcube_menu($attrib); - break; - - // include a file - case 'include': - $path = realpath($CONFIG['skin_path'].$attrib['file']); - - if($fp = @fopen($path, 'r')) - { - $incl = fread($fp, filesize($path)); - fclose($fp); - return parse_rcube_xml($incl); - } - break; - - // return code for a specific application object - case 'object': - $object = strtolower($attrib['name']); - - $object_handlers = array( - // GENERAL - 'loginform' => 'rcmail_login_form', - 'username' => 'rcmail_current_username', - - // MAIL - 'mailboxlist' => 'rcmail_mailbox_list', - 'message' => 'rcmail_message_container', - 'messages' => 'rcmail_message_list', - 'messagecountdisplay' => 'rcmail_messagecount_display', - 'quotadisplay' => 'rcmail_quota_display', - 'messageheaders' => 'rcmail_message_headers', - 'messagebody' => 'rcmail_message_body', - 'messageattachments' => 'rcmail_message_attachments', - 'blockedobjects' => 'rcmail_remote_objects_msg', - 'messagecontentframe' => 'rcmail_messagecontent_frame', - 'messagepartframe' => 'rcmail_message_part_frame', - 'messagepartcontrols' => 'rcmail_message_part_controls', - 'composeheaders' => 'rcmail_compose_headers', - 'composesubject' => 'rcmail_compose_subject', - 'composebody' => 'rcmail_compose_body', - 'composeattachmentlist' => 'rcmail_compose_attachment_list', - 'composeattachmentform' => 'rcmail_compose_attachment_form', - 'composeattachment' => 'rcmail_compose_attachment_field', - 'priorityselector' => 'rcmail_priority_selector', - 'charsetselector' => 'rcmail_charset_selector', - 'editorselector' => 'rcmail_editor_selector', - 'searchform' => 'rcmail_search_form', - 'receiptcheckbox' => 'rcmail_receipt_checkbox', - - // ADDRESS BOOK - 'addresslist' => 'rcmail_contacts_list', - 'addressframe' => 'rcmail_contact_frame', - 'recordscountdisplay' => 'rcmail_rowcount_display', - 'contactdetails' => 'rcmail_contact_details', - 'contacteditform' => 'rcmail_contact_editform', - 'ldappublicsearch' => 'rcmail_ldap_public_search_form', - 'ldappublicaddresslist' => 'rcmail_ldap_public_list', - - // USER SETTINGS - 'userprefs' => 'rcmail_user_prefs_form', - 'itentitieslist' => 'rcmail_identities_list', - 'identityframe' => 'rcmail_identity_frame', - 'identityform' => 'rcube_identity_form', - 'foldersubscription' => 'rcube_subscription_form', - 'createfolder' => 'rcube_create_folder_form', - 'renamefolder' => 'rcube_rename_folder_form', - 'composebody' => 'rcmail_compose_body' - ); - - - // execute object handler function - if ($object_handlers[$object] && function_exists($object_handlers[$object])) - return call_user_func($object_handlers[$object], $attrib); - - else if ($object=='productname') - { - $name = !empty($CONFIG['product_name']) ? $CONFIG['product_name'] : 'RoundCube Webmail'; - return Q($name); - } - else if ($object=='version') - { - return (string)RCMAIL_VERSION; - } - else if ($object=='pagetitle') - { - $task = $GLOBALS['_task']; - $title = !empty($CONFIG['product_name']) ? $CONFIG['product_name'].' :: ' : ''; - - if ($task=='login') - $title = rcube_label(array('name' => 'welcome', 'vars' => array('product' => $CONFIG['product_name']))); - else if ($task=='mail' && isset($GLOBALS['MESSAGE']['subject'])) - $title .= $GLOBALS['MESSAGE']['subject']; - else if (isset($GLOBALS['PAGE_TITLE'])) - $title .= $GLOBALS['PAGE_TITLE']; - else if ($task=='mail' && ($mbox_name = $IMAP->get_mailbox_name())) - $title .= rcube_charset_convert($mbox_name, 'UTF-7', 'UTF-8'); - else - $title .= ucfirst($task); - - return Q($title); - } +function rcmail_url($action, $param=NULL) +{ + $url = $GLOBALS['COMM_PATH'] . '&'.$action; - break; - } + if (is_array($param)) + foreach ($param as $p => $val) + $url .= sprintf('&%s=%s', urlencode($p), urlencode($val)); - return ''; - } + return $url; +} -// create and register a button -function rcube_button($attrib) +// return boolean if a specific template exists +function template_exists($name) { - global $CONFIG, $OUTPUT, $JS_OBJECT_NAME, $BROWSER, $COMM_PATH, $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'); - + global $CONFIG; $skin_path = $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']]; - - // add button to button stack - else if($attrib['image'] || $attrib['imageact'] || $attrib['imagepas'] || $attrib['class']) - { - if(!$attrib['name']) - $attrib['name'] = $command; - - if (!$attrib['image']) - $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact']; - - $sa_buttons[$attrib['name']] = $attrib; - } - - // get saved button for this command/name - else if ($command && $sa_buttons[$command]) - $attrib = $sa_buttons[$command]; - - //else - // return ''; - - - // 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']) - { - $OUTPUT->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'] = htmlentities(ereg_replace('_task=[a-z]+', '_task='.$attrib['command'], $COMM_PATH)); - else if (in_array($attrib['command'], $a_static_commands)) - $attrib['href'] = htmlentities($COMM_PATH.'&_action='.$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 = create_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 = create_attrib_string($attrib, array('type', 'value', 'onclick', 'id', 'class', 'style')); - $out = sprintf('<input%s disabled />', $attrib_str); - } - - // generate html code for button - if ($btn_content) - { - $attrib_str = create_attrib_string($attrib, $link_attrib); - $out = sprintf('<a%s>%s</a>', $attrib_str, $btn_content); - } - return $out; + // check template file + return is_file("$skin_path/templates/$name.html"); } -function rcube_menu($attrib) +// Wrapper for rcmail_template::parse() +// @deprecated +function parse_template($name='main', $exit=true) { - - return ''; + $GLOBALS['OUTPUT']->parse($name, $exit); } @@ -1685,6 +1263,24 @@ function rcmail_get_edit_field($col, $value, $attrib, $type='text') } +// return the mail domain configured for the given host +function rcmail_mail_domain($host) + { + global $CONFIG; + + $domain = $host; + if (is_array($CONFIG['mail_domain'])) + { + if (isset($CONFIG['mail_domain'][$host])) + $domain = $CONFIG['mail_domain'][$host]; + } + else if (!empty($CONFIG['mail_domain'])) + $domain = $CONFIG['mail_domain']; + + return $domain; + } + + // compose a valid attribute string for HTML tags function create_attrib_string($attrib, $allowed_attribs=array('id', 'class', 'style')) { @@ -1784,13 +1380,23 @@ function format_date($date, $format=NULL) } +function format_email_recipient($email, $name='') + { + if ($name && $name != $email) + return sprintf('%s <%s>', strpos($name, ",") ? '"'.$name.'"' : $name, $email); + else + return $email; + } + + + // ************** functions delivering gui objects ************** function rcmail_message_container($attrib) { - global $OUTPUT, $JS_OBJECT_NAME; + global $OUTPUT; if (!$attrib['id']) $attrib['id'] = 'rcmMessageContainer'; @@ -1799,7 +1405,7 @@ function rcmail_message_container($attrib) $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id')); $out = '<div' . $attrib_str . "></div>"; - $OUTPUT->add_script("$JS_OBJECT_NAME.gui_object('message', '$attrib[id]');"); + $OUTPUT->add_gui_object('message', $attrib['id']); return $out; } @@ -1837,28 +1443,10 @@ function rcmail_current_username($attrib) } -// return the mail domain configured for the given host -function rcmail_mail_domain($host) - { - global $CONFIG; - - $domain = $host; - if (is_array($CONFIG['mail_domain'])) - { - if (isset($CONFIG['mail_domain'][$host])) - $domain = $CONFIG['mail_domain'][$host]; - } - else if (!empty($CONFIG['mail_domain'])) - $domain = $CONFIG['mail_domain']; - - return $domain; - } - - // return code for the webmail login form function rcmail_login_form($attrib) { - global $CONFIG, $OUTPUT, $JS_OBJECT_NAME, $SESS_HIDDEN_FIELD; + global $CONFIG, $OUTPUT, $SESS_HIDDEN_FIELD; $labels = array(); $labels['user'] = rcube_label('username'); @@ -1911,7 +1499,7 @@ function rcmail_login_form($attrib) EOF; - $OUTPUT->add_script("$JS_OBJECT_NAME.gui_object('loginform', '$form_name');"); + $OUTPUT->add_gui_object('loginform', $form_name); $out = <<<EOF $form_start @@ -1972,6 +1560,36 @@ function rcmail_charset_selector($attrib) } +// return code for search function +function rcmail_search_form($attrib) + { + global $OUTPUT; + + // add some labels to client + rcube_add_label('searching'); + + $attrib['name'] = '_q'; + + if (empty($attrib['id'])) + $attrib['id'] = 'rcmqsearchbox'; + + $input_q = new textfield($attrib); + $out = $input_q->show(); + + $OUTPUT->add_gui_object('qsearchbox', $attrib['id']); + + // add form tag around text field + if (empty($attrib['form'])) + $out = sprintf( + '<form name="rcmqsearchform" action="./" '. + 'onsubmit="%s.command(\'search\');return false" style="display:inline;">%s</form>', + JS_OBJECT_NAME, + $out); + + return $out; + } + + /****** debugging functions ********/ diff --git a/program/include/rcmail_template.inc b/program/include/rcmail_template.inc new file mode 100644 index 000000000..e2fa682e4 --- /dev/null +++ b/program/include/rcmail_template.inc @@ -0,0 +1,631 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/rcmail_template.inc | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2007, 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: $ + +*/ + +require_once('include/rcube_shared.inc'); + + +class rcmail_template extends rcube_html_page +{ + var $config; + var $task = ''; + var $framed = false; + var $ajax_call = false; + var $pagetitle = ''; + var $env = array(); + var $js_env = array(); + var $js_commands = array(); + var $object_handlers = array(); + + + // PHP 5 constructor + function __construct(&$config, $task) + { + parent::__construct(); + + $this->task = $task; + $this->config = $config; + $this->ajax_call = !empty($_GET['_remote']) || !empty($_POST['_remote']); + + // add common javascripts + if (!$this->ajax_call) + { + $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'); + } + } + + // PHP 4 compatibility + function rcmail_template(&$config, $task) + { + $this->__construct($config, $task); + } + + + /** + * Set environment variable + */ + 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 + */ + function set_pagetitle($title) + { + $this->pagetitle = $title; + } + + + /** + * Register a template object handler + * + * @param string Object name + * @param string Function name to call + */ + 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 + */ + 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 + */ + 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 + */ + function command() + { + $this->js_commands[] = func_get_args(); + } + + + /** + * Invoke display_message command + */ + 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 + */ + 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) + */ + function send($templ=null, $exit=true) + { + if ($this->ajax_call) + $this->remote_response('', !$exit); + else if ($templ != 'iframe') + $this->parse($templ, false); + else + { + $this->framed = $templ == 'iframe' ? true : $this->framed; + $this->write(); + } + + if ($exit) + exit; + } + + + /** + * Send an AJAX response with executable JS code + * + * @param string Additional JS code + * @param boolean True if output buffer should be flushed + */ + 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='.RCMAIL_CHARSET); + print '/** ajax response ['.date('d/M/Y h:i:s O')."] **/\n"; + } + + // unset default env vars + unset($this->js_env['task'], $this->js_env['action'], $this->js_env['comm_path']); + + // send response code + print rcube_charset_convert($this->get_js_commands() . $add, RCMAIL_CHARSET, $this->get_charset()); + + if ($flush) // flush the output buffer + flush(); + } + + + /** + * @override + */ + function write($template='') + { + // 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 + * + * @param string Template name + * @param boolean Exit script + */ + 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')) + { + $templ = fread($fp, filesize($path)); + fclose($fp); + } + else + { + raise_error(array( + 'code' => 501, + 'type' => 'php', + 'line' => __LINE__, + 'file' => __FILE__, + 'message' => "Error loading template for '$name'"), TRUE, TRUE); + return FALSE; + } + + // parse for specialtags + $output = $this->parse_xml($this->parse_conditions($templ)); + + // 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>'); + + $this->write(trim($this->parse_with_globals($output)), $skin_path); + + if ($exit) + exit; + } + + + /** + * Return executable javascript code for all registered commands + * @private + */ + function get_js_commands() + { + $out = ''; + if (!$this->framed) + $out .= ($this->ajax_call ? 'this' : 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", + $this->ajax_call ? 'this' : ($parent ? 'parent.' : '') . JS_OBJECT_NAME, + preg_replace('/^parent\./', '', $method), + join(',', $args)); + } + + return $out; + } + + /** + * Make URLs starting with a slash point to skin directory + */ + 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. + */ + function parse_with_globals($input) + { + $GLOBALS['__comm_path'] = $GLOBALS['COMM_PATH']; + return preg_replace('/\$(__[a-z0-9_\-]+)/e', '$GLOBALS["\\1"]', $input); + } + + + /** + * Parse for conditional tags + */ + function parse_conditions($input) + { + if (($matches = preg_split('/<roundcube:(if|elseif|else|endif)\s+([^>]+)>/is', $input, 2, PREG_SPLIT_DELIM_CAPTURE)) && count($matches)==4) + { + if (preg_match('/^(else|endif)$/i', $matches[1])) + return $matches[0] . $this->parse_conditions($matches[3]); + else + { + $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] . preg_replace('/.*<roundcube:endif\s+[^>]+>/is', '', $submatches[3]); + else + $result = "<roundcube:$submatches[1] $submatches[2]>" . $submatches[3]; + + return $matches[0] . $this->parse_conditions($result); + } + else + { + raise_error(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 + * + * @return True if condition is valid, False is not + */ + 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', RCUBE_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 Altered input string + */ + 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 Tag/Object content string + */ + 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 ($fp = @fopen($path, 'r')) + { + $incl = fread($fp, filesize($path)); + fclose($fp); + return $this->parse_xml($incl); + } + break; + + // return code for a specific application object + case 'object': + $object = strtolower($attrib['name']); + + // execute object handler function + if ($this->object_handlers[$object] && function_exists($this->object_handlers[$object])) + return call_user_func($this->object_handlers[$object], $attrib); + + else if ($object=='productname') + { + $name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'RoundCube Webmail'; + return Q($name); + } + else if ($object=='version') + { + return (string)RCMAIL_VERSION; + } + else if ($object=='pagetitle') + { + $task = $this->task; + $title = !empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : ''; + + 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 ''; + } + + + /** + * Create and register a button + * + * @param array Button attributes + * @return HTML button + */ + function button($attrib) + { + global $CONFIG, $OUTPUT, $BROWSER, $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'); + + $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']]; + + // add button to button stack + else if($attrib['image'] || $attrib['imageact'] || $attrib['imagepas'] || $attrib['class']) + { + if (!$attrib['name']) + $attrib['name'] = $command; + + if (!$attrib['image']) + $attrib['image'] = $attrib['imagepas'] ? $attrib['imagepas'] : $attrib['imageact']; + + $sa_buttons[$attrib['name']] = $attrib; + } + + // get saved button for this command/name + else if ($command && $sa_buttons[$command]) + $attrib = $sa_buttons[$command]; + + //else + // return ''; + + + // 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_self_url(null, null, $attrib['command'])); + else if (in_array($attrib['command'], $a_static_commands)) + $attrib['href'] = Q(rcmail_self_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 = create_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 = create_attrib_string($attrib, array('type', 'value', 'onclick', 'id', 'class', 'style')); + $out = sprintf('<input%s disabled />', $attrib_str); + } + + // generate html code for button + if ($btn_content) + { + $attrib_str = create_attrib_string($attrib, $link_attrib); + $out = sprintf('<a%s>%s</a>', $attrib_str, $btn_content); + } + + return $out; + } + +} + +?>
\ No newline at end of file diff --git a/program/include/rcube_contacts.inc b/program/include/rcube_contacts.inc new file mode 100644 index 000000000..cc801c6db --- /dev/null +++ b/program/include/rcube_contacts.inc @@ -0,0 +1,429 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/include/rcube_contacts.inc | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2006-2007, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Interface to the local address book database | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: rcube_contacts.inc 328 2006-08-30 17:41:21Z thomasb $ + +*/ + +class rcube_contacts +{ + var $db = null; + var $db_name = ''; + var $user_id = 0; + var $filter = '1'; + var $result = null; + var $search_fields; + var $search_string; + var $table_cols = array('name', 'email', 'firstname', 'surname'); + + /** public properties */ + var $primary_key = 'contact_id'; + var $readonly = false; + var $list_page = 1; + var $page_size = 10; + var $ready = false; + + + /** + * Object constructor + * + * @param object Instance of the rcube_db class + * @param integer User-ID + */ + function __construct($dbconn, $user) + { + $this->db = $dbconn; + $this->db_name = get_table_name('contacts'); + $this->user_id = $user; + $this->ready = $this->db && !$this->db->is_error(); + } + + /** + * PHP 4 object constructor + * + * @see rcube_contacts::__construct + */ + function rcube_contacts($dbconn, $user) + { + $this->__construct($dbconn, $user); + } + + + /** + * Set internal list page + * + * @param number Page number to list + * @access public + */ + function set_page($page) + { + $this->list_page = (int)$page; + } + + + /** + * Set internal page size + * + * @param number Number of messages to display on one page + * @access public + */ + function set_pagesize($size) + { + $this->page_size = (int)$size; + } + + + /** + * Save a search string for future listings + * + * @param string SQL params to use in listing method + */ + function set_search_set($filter) + { + $this->filter = $filter; + } + + + /** + * Getter for saved search properties + * + * @return mixed Search properties used by this class + */ + function get_search_set() + { + return $this->filter; + } + + + /** + * Reset all saved results and search parameters + */ + function reset() + { + $this->result = null; + $this->filter = '1'; + $this->search_fields = null; + $this->search_string = null; + } + + + /** + * List the current set of contact records + * + * @param array List of cols to show + * @return array Indexed list of contact records, each a hash array + */ + function list_records($cols=null, $subset=0) + { + // count contacts for this user + $this->result = $this->count(); + $sql_result = NULL; + + // get contacts from DB + if ($this->result->count) + { + $start_row = $subset < 0 ? $this->result->first + $this->page_size + $subset : $this->result->first; + $length = $subset != 0 ? abs($subset) : $this->page_size; + + $sql_result = $this->db->limitquery( + "SELECT * FROM ".$this->db_name." + WHERE del<>1 + AND user_id=? + AND (".$this->filter.") + ORDER BY name", + $start_row, + $length, + $this->user_id); + } + + while ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) + { + $sql_arr['ID'] = $sql_arr[$this->primary_key]; + // make sure we have a name to display + if (empty($sql_arr['name'])) + $sql_arr['name'] = $sql_arr['email']; + $this->result->add($sql_arr); + } + + return $this->result; + } + + + /** + * Search contacts + * + * @param array List of fields to search in + * @param string Search value + * @param boolean True if results are requested, False if count only + * @return Indexed list of contact records and 'count' value + */ + function search($fields, $value, $select=true) + { + if (!is_array($fields)) + $fields = array($fields); + + $add_where = array(); + foreach ($fields as $col) + { + if ($col == 'ID' || $col == $this->primary_key) + { + $ids = !is_array($value) ? split(',', $value) : $value; + $add_where[] = $this->primary_key." IN (".join(',', $ids).")"; + } + else + $add_where[] = $this->db->quoteIdentifier($col)." LIKE ".$this->db->quote(strlen($value)>2 ? "%$value%" : "$value%"); + } + + if (!empty($add_where)) + { + $this->set_search_set(join(' OR ', $add_where)); + if ($select) + $this->list_records(); + else + $this->result = $this->count(); + } + + return $this->result; + } + + + /** + * Count number of available contacts in database + * + * @return Result array with values for 'count' and 'first' + */ + function count() + { + // count contacts for this user + $sql_result = $this->db->query( + "SELECT COUNT(contact_id) AS rows + FROM ".$this->db_name." + WHERE del<>1 + AND user_id=? + AND (".$this->filter.")", + $this->user_id); + + $sql_arr = $this->db->fetch_assoc($sql_result); + return new rcube_result_set($sql_arr['rows'], ($this->list_page-1) * $this->page_size);; + } + + + /** + * Return the last result set + * + * @return Result array or NULL if nothing selected yet + */ + function get_result($as_res=true) + { + return $this->result; + } + + + /** + * Get a specific contact record + * + * @param mixed record identifier(s) + * @return Result object with all record fields or False if not found + */ + function get_record($id, $assoc=false) + { + // return cached result + if ($this->result && ($first = $this->result->first()) && $first[$this->primary_key] == $id) + return $assoc ? $first : $this->result; + + $this->db->query( + "SELECT * FROM ".$this->db_name." + WHERE contact_id=? + AND user_id=? + AND del<>1", + $id, + $this->user_id); + + if ($sql_arr = $this->db->fetch_assoc()) + { + $sql_arr['ID'] = $sql_arr[$this->primary_key]; + $this->result = new rcube_result_set(1); + $this->result->add($sql_arr); + } + + return $assoc && $sql_arr ? $sql_arr : $this->result; + } + + + /** + * Create a new contact record + * + * @param array Assoziative array with save data + * @return The created record ID on success, False on error + */ + function insert($save_data, $check=false) + { + if (is_object($save_data) && is_a($save_data, rcube_result_set)) + return $this->insert_recset($save_data, $check); + + $insert_id = $existing = false; + + if ($check) + $existing = $this->search('email', $save_data['email'], false); + + $a_insert_cols = $a_insert_values = array(); + foreach ($this->table_cols as $col) + if (isset($save_data[$col])) + { + $a_insert_cols[] = $this->db->quoteIdentifier($col); + $a_insert_values[] = $this->db->quote($save_data[$col]); + } + + if (!$existing->count && !empty($a_insert_cols)) + { + $this->db->query( + "INSERT INTO ".$this->db_name." + (user_id, changed, del, ".join(', ', $a_insert_cols).") + VALUES (?, ".$this->db->now().", 0, ".join(', ', $a_insert_values).")", + $this->user_id); + + $insert_id = $this->db->insert_id(get_sequence_name('contacts')); + } + + return $insert_id; + } + + + /** + * Insert new contacts for each row in set + */ + function insert_recset($result, $check=false) + { + $ids = array(); + while ($row = $result->next()) + { + if ($insert = $this->insert($row, $check)) + $ids[] = $insert; + } + return $ids; + } + + + /** + * Update a specific contact record + * + * @param mixed Record identifier + * @param array Assoziative array with save data + * @return True on success, False on error + */ + function update($id, $save_cols) + { + $updated = false; + $write_sql = array(); + foreach ($this->table_cols as $col) + if (isset($save_cols[$col])) + $write_sql[] = sprintf("%s=%s", $this->db->quoteIdentifier($col), $this->db->quote($save_cols[$col])); + + if (!empty($write_sql)) + { + $this->db->query( + "UPDATE ".$this->db_name." + SET changed=".$this->db->now().", ".join(', ', $write_sql)." + WHERE contact_id=? + AND user_id=? + AND del<>1", + $id, + $this->user_id); + + $updated = $this->db->affected_rows(); + } + + return $updated; + } + + + /** + * Mark one or more contact records as deleted + * + * @param array Record identifiers + */ + function delete($ids) + { + if (is_array($ids)) + $ids = join(',', $ids); + + $this->db->query( + "UPDATE ".$this->db_name." + SET del=1 + WHERE user_id=? + AND contact_id IN (".$ids.")", + $this->user_id); + + return $this->db->affected_rows(); + } + +} + + +/** + * 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; + } + +} + + +?>
\ No newline at end of file diff --git a/program/include/rcube_db.inc b/program/include/rcube_db.inc index 6f362a31d..626cb64df 100755 --- a/program/include/rcube_db.inc +++ b/program/include/rcube_db.inc @@ -5,7 +5,7 @@ | program/include/rcube_db.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -102,7 +102,7 @@ class rcube_db $this->db_error = TRUE; $this->db_error_msg = $dbh->getMessage(); - raise_error(array('code' => 500, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, + raise_error(array('code' => 603, 'type' => 'db', 'line' => __LINE__, 'file' => __FILE__, 'message' => $this->db_error_msg), TRUE, FALSE); return FALSE; diff --git a/program/include/rcube_imap.inc b/program/include/rcube_imap.inc index 3f4f2ebbd..c0016d332 100644 --- a/program/include/rcube_imap.inc +++ b/program/include/rcube_imap.inc @@ -2107,9 +2107,9 @@ class rcube_imap * --------------------------------*/ - function decode_address_list($input, $max=NULL) + function decode_address_list($input, $max=null, $decode=true) { - $a = $this->_parse_address_list($input); + $a = $this->_parse_address_list($input, $decode); $out = array(); if (!is_array($a)) @@ -2146,9 +2146,7 @@ class rcube_imap { $str = $this->decode_mime_string((string)$input); if ($str{0}=='"' && $remove_quotes) - { $str = str_replace('"', '', $str); - } return $str; } @@ -2159,7 +2157,7 @@ class rcube_imap * * @access static */ - function decode_mime_string($input, $recursive=false) + function decode_mime_string($input, $fallback=null) { $out = ''; @@ -2176,13 +2174,13 @@ class rcube_imap $rest = substr($input, $end_pos+2); $out .= rcube_imap::_decode_mime_string_part($encstr); - $out .= rcube_imap::decode_mime_string($rest); + $out .= rcube_imap::decode_mime_string($rest, $fallback); return $out; } - // no encoding information, defaults to what is specified in the class header - return rcube_charset_convert($input, 'ISO-8859-1'); + // no encoding information, use fallback + return rcube_charset_convert($input, !empty($fallback) ? $fallback : 'ISO-8859-1'); } @@ -2473,7 +2471,7 @@ class rcube_imap } - function _parse_address_list($str) + function _parse_address_list($str, $decode=true) { // remove any newlines and carriage returns before $a = $this->_explode_quoted_string('[,;]', preg_replace( "/[\r\n]/", " ", $str)); @@ -2482,7 +2480,7 @@ class rcube_imap foreach ($a as $key => $val) { $val = preg_replace("/([\"\w])</", "$1 <", $val); - $sub_a = $this->_explode_quoted_string(' ', $this->decode_header($val)); + $sub_a = $this->_explode_quoted_string(' ', $decode ? $this->decode_header($val) : $val); $result[$key]['name'] = ''; foreach ($sub_a as $k => $v) diff --git a/program/include/rcube_ldap.inc b/program/include/rcube_ldap.inc index 7cb9dee53..06a99ad0b 100644 --- a/program/include/rcube_ldap.inc +++ b/program/include/rcube_ldap.inc @@ -5,255 +5,432 @@ | program/include/rcube_ldap.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2006-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | - | Manage an LDAP connection | + | Interface to an LDAP address directory | | | +-----------------------------------------------------------------------+ - | Author: Jeremy Jongsma <jeremy@jongsma.org> | + | Author: Thomas Bruederli <roundcube@gmail.com> | +-----------------------------------------------------------------------+ $Id$ */ -require_once("bugs.inc"); - class rcube_ldap - { +{ var $conn; - var $host; - var $port; - var $protocol; - var $base_dn; - var $bind_dn; - var $bind_pass; - - // PHP 5 constructor - function __construct() - { - } + var $prop = array(); + var $fieldmap = array(); + + var $filter = ''; + var $result = null; + var $ldap_result = null; + var $sort_col = ''; + + /** public properties */ + var $primary_key = 'ID'; + var $readonly = true; + var $list_page = 1; + var $page_size = 10; + var $ready = false; + + + /** + * Object constructor + * + * @param array LDAP connection properties + * @param integer User-ID + */ + function __construct($p) + { + $this->prop = $p; + + foreach ($p as $prop => $value) + if (preg_match('/^(.+)_field$/', $prop, $matches)) + $this->fieldmap[$matches[1]] = $value; + + // $this->filter = "(dn=*)"; + $this->connect(); + } - // PHP 4 constructor - function rcube_ldap() - { - $this->__construct(); - } + /** + * PHP 4 object constructor + * + * @see rcube_ldap::__construct + */ + function rcube_ldap($p) + { + $this->__construct($p); + } + - function connect($hosts, $port=389, $protocol=3) - { + /** + * Establish a connection to the LDAP server + */ + function connect() + { if (!function_exists('ldap_connect')) - raise_error(array("type" => "ldap", - "message" => "No ldap support in this installation of php."), - TRUE); + raise_error(array('type' => 'ldap', 'message' => "No ldap support in this installation of PHP"), true); if (is_resource($this->conn)) - return TRUE; + return true; - if (!is_array($hosts)) - $hosts = array($hosts); + if (!is_array($this->prop['hosts'])) + $this->prop['hosts'] = array($this->prop['hosts']); - foreach ($hosts as $host) + foreach ($this->prop['hosts'] as $host) + { + if ($lc = @ldap_connect($host, $this->prop['port'])) { - if ($lc = @ldap_connect($host, $port)) - { - @ldap_set_option($lc, LDAP_OPT_PROTOCOL_VERSION, $protocol); - $this->host = $host; - $this->port = $port; - $this->protocol = $protocol; + ldap_set_option($lc, LDAP_OPT_PROTOCOL_VERSION, $this->prop['port']); + $this->prop['host'] = $host; $this->conn = $lc; - return TRUE; - } + break; } - - if (!is_resource($this->conn)) - raise_error(array("type" => "ldap", - "message" => "Could not connect to any LDAP server, tried $host:$port last"), - TRUE); } + + if (is_resource($this->conn)) + $this->ready = true; + else + raise_error(array('type' => 'ldap', 'message' => "Could not connect to any LDAP server, tried $host:{$this->prop[port]} last"), true); + } - function close() - { - if ($this->conn) - { - if (@ldap_unbind($this->conn)) - return TRUE; - else - raise_error(array("code" => ldap_errno($this->conn), - "type" => "ldap", - "message" => "Could not close connection to LDAP server: ".ldap_error($this->conn)), - TRUE); - } - return FALSE; - } - // Merge with connect()? + /** + * Merge with connect()? + */ function bind($dn=null, $pass=null) - { + { if ($this->conn) - { + { if ($dn) + { if (@ldap_bind($this->conn, $dn, $pass)) - return TRUE; + return true; else - raise_error(array("code" => ldap_errno($this->conn), - "type" => "ldap", - "message" => "Bind failed for dn=$dn: ".ldap_error($this->conn)), - TRUE); + raise_error(array('code' => ldap_errno($this->conn), + 'type' => 'ldap', + 'message' => "Bind failed for dn=$dn: ".ldap_error($this->conn)), + true); + } else + { if (@ldap_bind($this->conn)) - return TRUE; + return true; else - raise_error(array("code" => ldap_errno($this->conn), - "type" => "ldap", - "message" => "Anonymous bind failed: ".ldap_error($this->conn)), - TRUE); - } + raise_error(array('code' => ldap_errno($this->conn), + 'type' => 'ldap', + 'message' => "Anonymous bind failed: ".ldap_error($this->conn)), + true); + } + } else - raise_error(array("type" => "ldap", - "message" => "Attempted bind on nonexistent connection"), TRUE); - return FALSE; + raise_error(array('type' => 'ldap', 'message' => "Attempted bind on nonexistent connection"), true); + + return false; } - function count($base, $filter=null, $attributes=null, $scope="sub") - { + + /** + * Close connection to LDAP server + */ + function close() + { if ($this->conn) - { - if ($scope === 'sub') - $sr = @ldap_search($this->conn, $base, $filter, $attributes, 0, $limit); - else if ($scope === 'one') - $sr = @ldap_list($this->conn, $base, $filter, $attributes, 0, $limit); - else if ($scope === 'base') - $sr = @ldap_read($this->conn, $base, $filter, $attributes, 0, $limit); - if ($sr) - return @ldap_count_entries($this->conn, $sr); - } - else - raise_error(array("type" => "ldap", - "message" => "Attempted count search on nonexistent connection"), TRUE); - return FALSE; + @ldap_unbind($this->conn); + } + + + /** + * Set internal list page + * + * @param number Page number to list + * @access public + */ + function set_page($page) + { + $this->list_page = (int)$page; + } + + + /** + * Set internal page size + * + * @param number Number of messages to display on one page + * @access public + */ + function set_pagesize($size) + { + $this->page_size = (int)$size; + } + + + /** + * Save a search string for future listings + * + * @param string ?? + */ + function set_search_set($filter) + { + $this->filter = $filter; + } + + + /** + * Getter for saved search properties + * + * @return mixed Search properties used by this class + */ + function get_search_set() + { + return $this->filter; + } + + + /** + * Reset all saved results and search parameters + */ + function reset() + { + $this->result = null; + $this->ldap_result = null; + $this->filter = ''; + } + + + /** + * List the current set of contact records + * + * @param array List of cols to show + * @return array Indexed list of contact records, each a hash array + */ + function list_records($cols=null, $subset=0) + { + // exec LDAP search if no result resource is stored + if ($this->conn && !$this->ldap_result) + $this->_exec_search(); + + // count contacts for this user + $this->result = $this->count(); + + // we have a search result resource + if ($this->ldap_result && $this->result->count > 0) + { + if ($this->sort_col && $this->prop['scope'] !== "base") + @ldap_sort($this->conn, $this->ldap_result, $this->sort_col); + + $entries = ldap_get_entries($this->conn, $this->ldap_result); + for ($i = $this->result->first; $i < min($entries['count'], $this->result->first + $this->page_size); $i++) + $this->result->add($this->_ldap2result($entries[$i])); } - function search($base, $filter=null, $attributes=null, $scope='sub', $sort=null, $limit=0) + return $this->result; + } + + + /** + * Search contacts + * + * @param array List of fields to search in + * @param string Search value + * @param boolean True if results are requested, False if count only + * @return Indexed list of contact records and 'count' value + */ + function search($fields, $value, $select=true) + { + // special treatment for ID-based search + if ($fields == 'ID' || $fields == $this->primary_key) { - if ($this->conn) - { - if ($scope === 'sub') - $sr = @ldap_search($this->conn, $base, $filter, $attributes, 0, $limit); - else if ($scope === 'one') - $sr = @ldap_list($this->conn, $base, $filter, $attributes, 0, $limit); - else if ($scope === 'base') - $sr = @ldap_read($this->conn, $base, $filter, $attributes, 0, $limit); - if ($sr) + $ids = explode(',', $value); + $result = new rcube_result_set(); + foreach ($ids as $id) + if ($rec = $this->get_record($id, true)) { - if ($sort && $scope !== "base") - { - if (is_array($sort)) - { - // Start from the end so first sort field has highest priority - $sortfields = array_reverse($sort); - foreach ($sortfields as $sortfield) - @ldap_sort($this->conn, $sr, $sortfield); - } - else - @ldap_sort($this->conn, $sr, $sort); - } - return @ldap_get_entries($this->conn, $sr); + $result->add($rec); + $result->count++; } - } - else - raise_error(array("type" => "ldap", - "message" => "Attempted search on nonexistent connection"), TRUE); - return FALSE; + + return $result; } - - function add($dn, $object) + + $filter = '(|'; + $wc = $this->prop['fuzzy_search'] ? '*' : ''; + if (is_array($this->prop['search_fields'])) { - if ($this->conn) - { - if (@ldap_add($this->conn, $dn, $object)) - return TRUE; - else - raise_error(array("code" => ldap_errno($this->conn), - "type" => "ldap", - "message" => "Add object failed: ".ldap_error($this->conn)), - TRUE); - } + foreach ($this->prop['search_fields'] as $k => $field) + $filter .= "($field=$wc" . rcube_ldap::quote_string($value) . "$wc)"; + } else - raise_error(array("type" => "ldap", - "message" => "Add object faile: no connection"), - TRUE); - return FALSE; + { + foreach ((array)$fields as $field) + if ($f = $this->_map_field($field)) + $filter .= "($f=$wc" . rcube_ldap::quote_string($value) . "$wc)"; } + $filter .= ')'; - function modify($dn, $object) - { - if ($this->conn) - { - if (@ldap_modify($this->conn, $dn, $object)) - return TRUE; - else - raise_error(array("code" => ldap_errno($this->conn), - "type" => "ldap", - "message" => "Modify object failed: ".ldap_error($this->conn)), - TRUE); - } + // set filter string and execute search + $this->set_search_set($filter); + $this->_exec_search(); + + if ($select) + $this->list_records(); else - raise_error(array("type" => "ldap", - "message" => "Modify object failed: no connection"), - TRUE); - return FALSE; - } + $this->result = $this->count(); + + return $this->result; + } - function rename($dn, $newrdn, $parentdn) - { - if ($this->protocol < 3) - { - raise_error(array("type" => "ldap", - "message" => "rename() support requires LDAPv3 or above "), - TRUE); - return FALSE; - } - if ($this->conn) + /** + * Count number of available contacts in database + * + * @return Result array with values for 'count' and 'first' + */ + function count() + { + $count = 0; + if ($this->conn && $this->ldap_result) + $count = ldap_count_entries($this->conn, $this->ldap_result); + + return new rcube_result_set($count, ($this->list_page-1) * $this->page_size); + } + + + /** + * Return the last result set + * + * @return Result array or NULL if nothing selected yet + */ + function get_result() + { + return $this->result; + } + + + /** + * Get a specific contact record + * + * @param mixed record identifier + * @return Hash array with all record fields or False if not found + */ + function get_record($dn, $assoc=false) + { + $res = null; + if ($this->conn && $dn) + { + $this->ldap_result = @ldap_read($this->conn, base64_decode($dn), "(objectclass=*)", array_values($this->fieldmap)); + $entry = @ldap_first_entry($this->conn, $this->ldap_result); + + if ($entry && ($rec = ldap_get_attributes($this->conn, $entry))) { - if (@ldap_rename($this->conn, $dn, $newrdn, $parentdn, TRUE)) - return TRUE; - else - raise_error(array("code" => ldap_errno($this->conn), - "type" => "ldap", - "message" => "Rename object failed: ".ldap_error($this->conn)), - TRUE); + $res = $this->_ldap2result($rec); + $this->result = new rcube_result_set(1); + $this->result->add($res); } - else - raise_error(array("type" => "ldap", - "message" => "Rename object failed: no connection"), - TRUE); - return FALSE; } - function delete($dn) + return $assoc ? $res : $this->result; + } + + + /** + * Create a new contact record + * + * @param array Assoziative array with save data + * @return The create record ID on success, False on error + */ + function insert($save_cols) + { + // TODO + return false; + } + + + /** + * Update a specific contact record + * + * @param mixed Record identifier + * @param array Assoziative array with save data + * @return True on success, False on error + */ + function update($id, $save_cols) + { + // TODO + return false; + } + + + /** + * Mark one or more contact records as deleted + * + * @param array Record identifiers + */ + function delete($ids) + { + // TODO + return false; + } + + + /** + * Execute the LDAP search based on the stored credentials + * + * @private + */ + function _exec_search() + { + if ($this->conn && $this->filter) { - if ($this->conn) - { - if (@ldap_delete($this->conn, $dn)) - return TRUE; - else - raise_error(array("code" => ldap_errno($this->conn), - "type" => "ldap", - "message" => "Delete object failed: ".ldap_error($this->conn)), - TRUE); - } + $function = $this->prop['scope'] == 'sub' ? 'ldap_search' : ($this->prop['scope'] == 'base' ? 'ldap_read' : 'ldap_list'); + $this->ldap_result = @$function($this->conn, $this->prop['base_dn'], $this->filter, array_values($this->fieldmap), 0, 0); + return true; + } else - raise_error(array("type" => "ldap", - "message" => "Delete object failed: no connection"), - TRUE); - return FALSE; + return false; + } + + + /** + * @private + */ + function _ldap2result($rec) + { + $out = array(); + + if ($rec['dn']) + $out[$this->primary_key] = base64_encode($rec['dn']); + + foreach ($this->fieldmap as $rf => $lf) + { + if ($rec[$lf]['count']) + $out[$rf] = $rec[$lf][0]; } - + + return $out; + } + + + /** + * @private + */ + function _map_field($field) + { + return $this->fieldmap[$field]; } + + + /** + * @static + */ + function quote_string($str) + { + return strtr($str, array('*'=>'\2a', '('=>'\28', ')'=>'\29', '\\'=>'\5c')); + } + + +} -// vi: et ts=2 sw=2 -?> +?>
\ No newline at end of file diff --git a/program/include/rcube_shared.inc b/program/include/rcube_shared.inc index 0d502f81c..0f8be06c2 100644 --- a/program/include/rcube_shared.inc +++ b/program/include/rcube_shared.inc @@ -5,7 +5,7 @@ | rcube_shared.inc | | | | This file is part of the RoundCube PHP suite | - | Copyright (C) 2005-2006, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | CONTENTS: | @@ -84,11 +84,20 @@ class rcube_html_page function add_script($script, $position='head') { if (!isset($this->scripts[$position])) - $this->scripts[$position] = "\n$script"; + $this->scripts[$position] = "\n".rtrim($script); else - $this->scripts[$position] .= "\n$script"; + $this->scripts[$position] .= "\n".rtrim($script); } + function add_header($str) + { + $this->header .= "\n".$str; + } + + function add_footer($str) + { + $this->footer .= "\n".$str; + } function set_title($t) { @@ -121,6 +130,8 @@ class rcube_html_page $this->script_files = array(); $this->scripts = array(); $this->title = ''; + $this->header = ''; + $this->footer = ''; } @@ -150,39 +161,37 @@ class rcube_html_page foreach ($this->script_files['head'] as $file) $__page_header .= sprintf($this->script_tag_file, $this->scripts_path, $file); - if (is_array($this->external_scripts['head'])) - { + if (is_array($this->external_scripts['head'])) foreach ($this->external_scripts['head'] as $xscript) - { - $__page_header .= sprintf($this->tag_format_external_script, $xscript); - } - } + $__page_header .= sprintf($this->tag_format_external_script, $xscript); + + $head_script = $this->scripts['head_top'] . $this->scripts['head']; + if (!empty($head_script)) + $__page_header .= sprintf($this->script_tag, $head_script); + + if (!empty($this->header)) + $__page_header .= $this->header; - if (!empty($this->scripts['head'])) - $__page_header .= sprintf($this->script_tag, $this->scripts['head']); - 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 ($this->footer) - $__page_footer .= "\n" . $this->footer; + if (!empty($this->footer)) + $__page_footer .= $this->footer; $__page_header .= $this->css->show(); // find page header - if($hpos = rc_strpos(rc_strtolower($output), '</head>')) + if($hpos = strpos(strtolower($output), '</head>')) $__page_header .= "\n"; else { if (!is_numeric($hpos)) - $hpos = rc_strpos(rc_strtolower($output), '<body'); - if (!is_numeric($hpos) && ($hpos = rc_strpos(rc_strtolower($output), '<html'))) + $hpos = strpos(strtolower($output), '<body'); + if (!is_numeric($hpos) && ($hpos = strpos(strtolower($output), '<html'))) { while($output[$hpos]!='>') $hpos++; @@ -194,27 +203,27 @@ class rcube_html_page // add page hader if($hpos) - $output = rc_substr($output,0,$hpos) . $__page_header . rc_substr($output,$hpos,rc_strlen($output)); + $output = substr($output,0,$hpos) . $__page_header . substr($output,$hpos,strlen($output)); else $output = $__page_header . $output; // find page body - if($bpos = rc_strpos(rc_strtolower($output), '<body')) + if($bpos = strpos(strtolower($output), '<body')) { while($output[$bpos]!='>') $bpos++; $bpos++; } else - $bpos = rc_strpos(rc_strtolower($output), '</head>')+7; + $bpos = strpos(strtolower($output), '</head>')+7; // add page body if($bpos && $__page_body) - $output = rc_substr($output,0,$bpos) . "\n$__page_body\n" . rc_substr($output,$bpos,rc_strlen($output)); + $output = substr($output,0,$bpos) . "\n$__page_body\n" . substr($output,$bpos,strlen($output)); // find and add page footer - $output_lc = rc_strtolower($output); + $output_lc = strtolower($output); if(($fpos = strrstr($output_lc, '</body>')) || ($fpos = strrstr($output_lc, '</html>'))) $output = substr($output, 0, $fpos) . "$__page_footer\n" . substr($output, $fpos); @@ -1016,10 +1025,10 @@ class select extends base_form_element in_array($option['value'], $select, TRUE)) || (in_array($option['text'], $select, TRUE))) ? $this->_conv_case(' selected', 'attrib') : ''; - + $options_str .= sprintf("<%s%s%s>%s</%s>\n", $this->_conv_case('option', 'tag'), - isset($option['value']) ? sprintf($value_str, $option['value']) : '', + !empty($option['value']) ? sprintf($value_str, Q($option['value'])) : '', $selected, Q($option['text'], 'strict', FALSE), $this->_conv_case('option', 'tag')); @@ -1258,89 +1267,71 @@ function send_modified_header($mdate, $etag=null) } -// function to convert an array to a javascript array -function array2js($arr, $type='') +/** + * Convert a variable into a javascript notation string + */ +function json_serialize($var) { - if (!$type) - $type = 'mixed'; + if (is_object($var)) + $var = get_object_vars($var); - if (is_array($arr)) + if (is_array($var)) { - // no items in array - if (!sizeof($arr)) - return 'new Array()'; - else + // empty array + if (!sizeof($var)) + return '[]'; + else { - $a_pairs = array(); - $keys_arr = array_keys($arr); - $is_assoc = $have_numeric = 0; + $keys_arr = array_keys($var); + $is_assoc = $have_numeric = 0; - for ($i=0; $i<sizeof($keys_arr); ++$i) + for ($i=0; $i<sizeof($keys_arr); ++$i) { - if(is_numeric($keys_arr[$i])) - $have_numeric = 1; - if (!is_numeric($keys_arr[$i]) || $keys_arr[$i]!=$i) - $is_assoc = 1; - if($is_assoc && $have_numeric) - break; + if (is_numeric($keys_arr[$i])) + $have_numeric = 1; + if (!is_numeric($keys_arr[$i]) || $keys_arr[$i] != $i) + $is_assoc = 1; + if ($is_assoc && $have_numeric) + break; } + + $brackets = $is_assoc ? '{}' : '[]'; + $pairs = array(); - $previous_was_array = false; - while (list($key, $value) = each($arr)) + foreach ($var as $key => $value) { - // enclose key with quotes if it is not variable-name conform - if (!ereg("^[_a-zA-Z]{1}[_a-zA-Z0-9]*$", $key) /* || is_js_reserved_word($key) */) - $key = "'$key'"; + // enclose key with quotes if it is not variable-name conform + if (!ereg("^[_a-zA-Z]{1}[_a-zA-Z0-9]*$", $key) /* || is_js_reserved_word($key) */) + $key = "'$key'"; - if (!is_array($value) && is_string($value)) - { - $value = str_replace("\r\n", '\n', $value); - $value = str_replace("\n", '\n', $value); - } - - $is_string = false; - if (!is_array($value)) - { - if ($type=='string') - $is_string = true; - else if (($type == 'mixed' && is_bool($value)) || $type == 'bool') - { - $is_string = false; - $value = $value ? "true" : "false"; - } - else if ((($type=='mixed' && is_numeric($value)) || $type=='int') && rc_strlen($value)<16) // js interprets numbers with digits >15 as ...e+... - $is_string = FALSE; - else - $is_string = TRUE; - } - - if ($is_string) - $value = "'".preg_replace("/(?<!\\\)'/", "\'", $value)."'"; - - $a_pairs[] = sprintf("%s%s", - $is_assoc ? "$key:" : '', - is_array($value) ? array2js($value, $type) : $value); - } - - if ($a_pairs) - { - if ($is_assoc) - $return = '{'.implode(',', $a_pairs).'}'; - else - $return = '['.implode(',', $a_pairs).']'; + $pairs[] = sprintf("%s%s", $is_assoc ? "$key:" : '', json_serialize($value)); } - return $return; + return $brackets{0} . implode(',', $pairs) . $brackets{1}; } } - else - { - return $arr; - } + else if (is_numeric($var) && strval(intval($var)) === strval($var)) + return $var; + else if (is_bool($var)) + return $var ? '1' : '0'; + else + return "'".JQ($var)."'"; + + } + +/** + * function to convert an array to a javascript array + * @deprecated + */ +function array2js($arr, $type='') + { + return json_serialize($arr); } -// similar function as in_array() ut case-insensitive +/** + * Similar function as in_array() but case-insensitive + */ function in_array_nocase($needle, $haystack) { foreach ($haystack as $value) @@ -1353,8 +1344,9 @@ function in_array_nocase($needle, $haystack) } - -// find out if the string content means TRUE or FALSE +/** + * Find out if the string content means TRUE or FALSE + */ function get_boolean($str) { $str = strtolower($str); @@ -1469,7 +1461,7 @@ function rc_strtolower($str) } // wrapper function for substr -function rc_substr($str, $start, $len) +function rc_substr($str, $start, $len=null) { if (function_exists('mb_substr')) return mb_substr($str, $start, $len); diff --git a/program/js/app.js b/program/js/app.js index 7406df2ff..8d97a512a 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -37,7 +37,7 @@ function rcube_webmail() this.dblclick_time = 500; this.message_time = 5000; - this.mbox_expression = new RegExp('[^0-9a-z\-_]', 'gi'); + this.identifier_expr = new RegExp('[^0-9a-z\-_]', 'gi'); // mimetypes supported by the browser (default settings) this.mimetypes = new Array('text/plain', 'text/html', 'text/xml', @@ -49,12 +49,19 @@ function rcube_webmail() this.env.keep_alive = 60; // seconds this.env.request_timeout = 180; // seconds this.env.draft_autosave = 0; // seconds + this.env.comm_path = './'; + this.env.bin_path = './bin/'; + this.env.blankpage = 'program/blank.gif'; - // set environment variable - this.set_env = function(name, value) + // set environment variable(s) + this.set_env = function(p, value) { - this.env[name] = value; + if (p != null && typeof(p) == 'object' && !value) + for (var n in p) + this.env[n] = p[n]; + else + this.env[p] = value; }; @@ -162,7 +169,7 @@ function rcube_webmail() if (this.env.action == 'preview' && this.env.framed && parent.rcmail) { this.enable_command('compose', 'add-contact', false); - parent.rcmail.show_messageframe(true); + parent.rcmail.show_contentframe(true); parent.rcmail.mark_message('read', this.uid); } @@ -206,7 +213,10 @@ function rcube_webmail() // get unread count for each mailbox if (this.gui_objects.mailboxlist) + { + this.gui_objects.folderlist = this.gui_objects.mailboxlist; this.http_request('getunread', ''); + } break; @@ -214,9 +224,11 @@ function rcube_webmail() case 'addressbook': if (this.gui_objects.contactslist) { - this.contact_list = new rcube_list_widget(this.gui_objects.contactslist, {multiselect:true, draggable:false, keyboard:true}); + this.contact_list = new rcube_list_widget(this.gui_objects.contactslist, {multiselect:true, draggable:true, keyboard:true}); this.contact_list.addEventListener('keypress', function(o){ p.contactlist_keypress(o); }); this.contact_list.addEventListener('select', function(o){ p.contactlist_select(o); }); + this.contact_list.addEventListener('dragstart', function(o){ p.drag_active = true; }); + this.contact_list.addEventListener('dragend', function(o){ p.drag_active = false; }); this.contact_list.init(); if (this.env.cid) @@ -232,17 +244,20 @@ function rcube_webmail() } this.set_page_buttons(); - + + var writeable; + if ((writeable = this.env.address_sources && !this.env.address_sources[this.env.source].readonly)) + this.enable_command('add', true); + if (this.env.cid) this.enable_command('show', 'edit', true); - if ((this.env.action=='add' || this.env.action=='edit') && this.gui_objects.editform) + if ((this.env.action=='add' || this.env.action=='edit') && writeable && this.gui_objects.editform) this.enable_command('save', true); + else + this.enable_command('search', 'reset-search', 'moveto', true); - this.enable_command('list', 'add', true); - - // this.enable_command('ldappublicsearch', this.env.ldappublicsearch); - + this.enable_command('list', true); break; @@ -380,7 +395,7 @@ function rcube_webmail() this.set_caret2start(input_message); // get summary of all field values - this.cmp_hash = this.compose_field_hash(); + this.compose_field_hash(true); // start the auto-save timer this.auto_save_start(); @@ -470,7 +485,13 @@ function rcube_webmail() this.list_mailbox(props); } else if (this.task=='addressbook') - this.list_contacts(); + { + if (this.env.search_request<0 || (this.env.search_request && props != this.env.source)) + this.reset_qsearch(); + + this.list_contacts(props); + this.enable_command('add', (this.env.address_sources && !this.env.address_sources[props].readonly)); + } break; @@ -559,18 +580,6 @@ function rcube_webmail() case 'add': if (this.task=='addressbook') this.load_contact(0, 'add'); - - /* LDAP stuff, has to be re-written with new address book - if (!window.frames[this.env.contentframe].rcmail) - this.load_contact(0, 'add'); - else - { - if (window.frames[this.env.contentframe].rcmail.selection.length) - this.add_ldap_contacts(); - else - this.load_contact(0, 'add'); - } - */ else if (this.task=='settings') { this.identity_list.clear_selection(); @@ -638,7 +647,10 @@ function rcube_webmail() // mail task commands case 'move': case 'moveto': - this.move_messages(props); + if (this.task == 'mail') + this.move_messages(props); + else if (this.task == 'addressbook' && this.drag_active) + this.copy_contact(null, props); break; case 'toggle_status': @@ -726,55 +738,42 @@ function rcube_webmail() var uid; if (uid = this.get_single_uid()) url += '&_draft_uid='+uid+'&_mbox='+urlencode(this.env.mailbox); - } + } // modify url if we're in addressbook else if (this.task=='addressbook') { - url = this.get_task_url('mail', url); - var a_cids = new Array(); + // switch to mail compose step directly + if (props && props.indexOf('@') > 0) + { + url = this.get_task_url('mail', url); + this.redirect(url + '&_to='+urlencode(props)); + break; + } // use contact_id passed as command parameter + var a_cids = new Array(); if (props) a_cids[a_cids.length] = props; // get selected contacts - else + else if (this.contact_list) { var selection = this.contact_list.get_selection(); for (var n=0; n<selection.length; n++) a_cids[a_cids.length] = selection[n]; - - /* LDAP stuff, has to be re-written with new address book - if (!window.frames[this.env.contentframe].rcmail.selection.length) - { - for (var n=0; n<selection.length; n++) - a_cids[a_cids.length] = selection[n]; - } - else - { - var frameRcmail = window.frames[this.env.contentframe].rcmail; - // get the email address(es) - for (var n=0; n<frameRcmail.selection.length; n++) - a_cids[a_cids.length] = frameRcmail.ldap_contact_rows[frameRcmail.selection[n]].obj.cells[1].innerHTML; - } - */ } + if (a_cids.length) - url += '&_to='+a_cids.join(','); - else - break; + this.http_request('mailto', '_cid='+urlencode(a_cids.join(','))+'&_source='+urlencode(this.env.source), true); + + break; } else if (props) url += '&_to='+urlencode(props); // don't know if this is necessary... url = url.replace(/&_framed=1/, ""); - this.set_busy(true); - // need parent in case we are coming from the contact frame - if (this.env.framed) - parent.location.href = url; - else - location.href = url; + this.redirect(url); break; case 'spellcheck': @@ -875,31 +874,27 @@ function rcube_webmail() this.add_contact(props); break; - // mail quicksearch + // quicksearch case 'search': if (!props && this.gui_objects.qsearchbox) props = this.gui_objects.qsearchbox.value; if (props) - this.qsearch(urlencode(props), this.env.mailbox); - break; + { + this.qsearch(props); + break; + } // reset quicksearch case 'reset-search': var s = this.env.search_request; this.reset_qsearch(); - if (s) + if (s && this.env.mailbox) this.list_mailbox(this.env.mailbox); + else if (s && this.task == 'addressbook') + this.list_contacts(this.env.source); break; - // ldap search - case 'ldappublicsearch': - if (this.gui_objects.ldappublicsearchform) - this.gui_objects.ldappublicsearchform.submit(); - else - this.ldappublicsearch(command); - break; - // user settings commands case 'preferences': @@ -1013,8 +1008,7 @@ function rcube_webmail() if (task=='mail') url += '&_mbox=INBOX'; - this.set_busy(true); - location.href = url; + this.redirect(url); }; @@ -1048,22 +1042,32 @@ function rcube_webmail() this.contact_list.blur(); }; + this.focus_folder = function(id) + { + var li; + if (this.drag_active && this.check_droptarget(id) && (li = this.get_folder_li(id))) + this.set_classname(li, 'droptarget', true); + } + + this.unfocus_folder = function(id) + { + var li; + if (this.drag_active && (li = this.get_folder_li(id))) + this.set_classname(li, 'droptarget', false); + } - // onmouseup handler for mailboxlist item - this.mbox_mouse_up = function(mbox) + // onmouseup handler for folder list item + this.folder_mouse_up = function(id) { if (this.drag_active) { - this.unfocus_mailbox(mbox); - this.command('moveto', mbox); + this.unfocus_folder(id); + this.command('moveto', id); } - else - this.command('list', mbox); return false; }; - this.click_on_list = function(e) { if (this.message_list) @@ -1072,7 +1076,7 @@ function rcube_webmail() this.contact_list.focus(); var mbox_li; - if (mbox_li = this.get_mailbox_li()) + if (mbox_li = this.get_folder_li()) this.set_classname(mbox_li, 'unfocused', true); rcube_event.cancel(e); @@ -1100,7 +1104,7 @@ function rcube_webmail() if (selected && this.env.contentframe) this.preview_timer = setTimeout(function(){ ref.msglist_get_preview(); }, this.dblclick_time + 10); else if (this.env.contentframe) - this.show_messageframe(false); + this.show_contentframe(false); }; @@ -1129,10 +1133,19 @@ function rcube_webmail() this.msglist_get_preview = function() { var uid = this.get_single_uid(); - if (uid && this.env.contentframe) + if (uid && this.env.contentframe && !this.drag_active) this.show_message(uid, false, true); else if (this.env.contentframe) - this.show_messageframe(false); + this.show_contentframe(false); + }; + + + this.check_droptarget = function(id) + { + if (this.task == 'mail') + return (id != this.env.mailbox); + else if (this.task == 'addressbook') + return (id != this.env.source && this.env.address_sources[id] && !this.env.address_sources[id].readonly); }; @@ -1160,7 +1173,7 @@ function rcube_webmail() { var url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.env.mailbox)+add_url; if (action == 'preview' && String(target.location.href).indexOf(url) >= 0) - this.show_messageframe(true); + this.show_contentframe(true); else { this.set_busy(true, 'loading'); @@ -1170,14 +1183,15 @@ function rcube_webmail() }; - this.show_messageframe = function(show) + this.show_contentframe = function(show) { var frm; if (this.env.contentframe && (frm = rcube_find_object(this.env.contentframe))) { - if (window.frames[this.env.contentframe] && !show) - window.frames[this.env.contentframe].location.href = 'program/blank.gif'; - frm.style.display = show ? 'block' : 'none'; + if (!show && window.frames[this.env.contentframe] && frames[this.env.contentframe].location.href.indexOf(this.env.blankpage)<0) + frames[this.env.contentframe].location.href = this.env.blankpage; + if (!bw.safari) + frm.style.display = show ? 'block' : 'none'; } if (!show && this.busy) @@ -1204,7 +1218,7 @@ function rcube_webmail() if (this.task=='mail') this.list_mailbox(this.env.mailbox, page); else if (this.task=='addressbook') - this.list_contacts(page); + this.list_contacts(this.env.source, page); } }; @@ -1222,6 +1236,10 @@ function rcube_webmail() // add sort to url if set if (sort) add_url += '&_sort=' + sort; + + // also send search request to get the right messages + if (this.env.search_request) + add_url += '&_search='+this.env.search_request; // set page=1 if changeing to another mailbox if (!page && mbox != this.env.mailbox) @@ -1231,14 +1249,11 @@ function rcube_webmail() this.env.current_page = page; if (this.message_list) this.message_list.clear_selection(); - this.show_messageframe(false); + this.show_contentframe(false); } - // also send search request to get the right messages - if (this.env.search_request) - add_url += '&_search='+this.env.search_request; - - this.select_mailbox(mbox); + this.select_folder(mbox, this.env.mailbox); + this.env.mailbox = mbox; // load message list remotely if (this.gui_objects.messagelist) @@ -1315,20 +1330,7 @@ function rcube_webmail() this.http_request('purge', url+add_url, lock); return true; }; - - this.focus_mailbox = function(mbox) - { - var mbox_li; - if (this.drag_active && mbox != this.env.mailbox && (mbox_li = this.get_mailbox_li(mbox))) - this.set_classname(mbox_li, 'droptarget', true); - } - - this.unfocus_mailbox = function(mbox) - { - var mbox_li; - if (this.drag_active && (mbox_li = this.get_mailbox_li(mbox))) - this.set_classname(mbox_li, 'droptarget', false); - } + // move selected messages to the specified mailbox this.move_messages = function(mbox) @@ -1350,7 +1352,7 @@ function rcube_webmail() this.set_busy(true, 'movingmessage'); } else - this.show_messageframe(false); + this.show_contentframe(false); this._with_selected_messages('moveto', lock, add_url); }; @@ -1401,7 +1403,7 @@ function rcube_webmail() if (!this.env.uid && (!this.message_list || !this.message_list.get_selection().length)) return; - this.show_messageframe(false); + this.show_contentframe(false); this._with_selected_messages('delete', false, '&_from='+(this.env.action ? this.env.action : '')); }; @@ -1425,9 +1427,9 @@ function rcube_webmail() this.message_list.select_next(); } - - // also send search request to get the right messages - if (this.env.search_request) + + // also send search request to get the right messages + if (this.env.search_request) add_url += '&_search='+this.env.search_request; // send request to server @@ -1619,18 +1621,6 @@ function rcube_webmail() }; - this.get_mailbox_li = function(mbox) - { - if (this.gui_objects.mailboxlist) - { - mbox = String((mbox ? mbox : this.env.mailbox)).toLowerCase().replace(this.mbox_expression, ''); - return document.getElementById('rcmbx'+mbox); - } - - return null; - }; - - /*********************************************************/ /********* login form methods *********/ /*********************************************************/ @@ -1648,7 +1638,7 @@ function rcube_webmail() return false; } }; - + /*********************************************************/ /********* message compose methods *********/ @@ -1709,6 +1699,13 @@ function rcube_webmail() }; + this.set_draft_id = function(id) + { + var f; + if (f = rcube_find_object('_draft_saveid')) + f.value = id; + }; + this.auto_save_start = function() { if (this.env.draft_autosave) @@ -1716,7 +1713,7 @@ function rcube_webmail() }; - this.compose_field_hash = function() + this.compose_field_hash = function(save) { // check input fields var input_to = rcube_find_object('_to'); @@ -1736,7 +1733,10 @@ function rcube_webmail() str += input_subject.value+':'; if (input_message && input_message.value) str += input_message.value; - + + if (save) + this.cmp_hash = str; + return str; }; @@ -1936,19 +1936,27 @@ function rcube_webmail() this.add_contact = function(value) { if (value) - this.http_request('addcontact', '_address='+value); + this.http_post('addcontact', '_address='+value); return true; }; - // send remote request to search mail - this.qsearch = function(value, mbox) + // send remote request to search mail or contacts + this.qsearch = function(value) { - if (value && mbox) + if (value != '') { - this.message_list.clear(); + if (this.message_list) + this.message_list.clear(); + else if (this.contact_list) { + this.contact_list.clear(true); + this.show_contentframe(false); + } + + // reset vars + this.env.current_page = 1; this.set_busy(true, 'searching'); - this.http_request('search', '_search='+value+'&_mbox='+mbox, true); + this.http_request('search', '_q='+urlencode(value)+(this.env.mailbox ? '&_mbox='+this.env.mailbox : '')+(this.env.source ? '&_source='+urlencode(this.env.source) : ''), true); } return true; }; @@ -2209,33 +2217,47 @@ function rcube_webmail() this.contactlist_select = function(list) { - var id, frame; + if (this.preview_timer) + clearTimeout(this.preview_timer); + + var id, frame, ref = this; if (id = list.get_single_selection()) - this.load_contact(id, 'show'); - else if (frame = document.getElementById(this.env.contentframe)) - frame.style.visibility = 'hidden'; + this.preview_timer = setTimeout(function(){ ref.load_contact(id, 'show'); }, this.dblclick_time + 10); + else if (this.env.contentframe) + this.show_contentframe(false); this.enable_command('edit', id?true:false); + this.enable_command('compose', list.selection.length > 0); + this.enable_command('delete', list.selection.length && this.env.address_sources && !this.env.address_sources[this.env.source].readonly); - if (list.selection.length) - this.enable_command('delete', 'compose', true); - - return false; + return false; }; - this.list_contacts = function(page) + this.list_contacts = function(src, page) { var add_url = ''; var target = window; - if (page && this.current_page==page) + if (!src) + src = this.env.source; + + if (page && this.current_page==page && src == this.env.source) return false; + + if (src != this.env.source) + { + page = 1; + this.env.current_page = page; + } + + this.select_folder(src, this.env.source); + this.env.source = src; // load contacts remotely if (this.gui_objects.contactslist) { - this.list_contacts_remote(page); + this.list_contacts_remote(src, page); return; } @@ -2245,19 +2267,31 @@ function rcube_webmail() add_url = '&_framed=1'; } + // also send search request to get the correct listing + if (this.env.search_request) + add_url += '&_search='+this.env.search_request; + this.set_busy(true, 'loading'); - target.location.href = this.env.comm_path+(page ? '&_page='+page : '')+add_url; + target.location.href = this.env.comm_path+(src ? '&_source='+urlencode(src) : '')+(page ? '&_page='+page : '')+add_url; }; // send remote request to load contacts list - this.list_contacts_remote = function(page) + this.list_contacts_remote = function(src, page) { // clear message list first - this.contact_list.clear(); + this.contact_list.clear(true); + this.show_contentframe(false); + this.enable_command('delete', 'compose', false); // send request to server - var url = page ? '&_page='+page : ''; + var url = (src ? '&_source='+urlencode(src) : '') + (page ? '&_page='+page : ''); + this.env.source = src; + + // also send search request to get the right messages + if (this.env.search_request) + url += '&_search='+this.env.search_request; + this.set_busy(true, 'loading'); this.http_request('list', url, true); }; @@ -2272,19 +2306,29 @@ function rcube_webmail() { add_url = '&_framed=1'; target = window.frames[this.env.contentframe]; - document.getElementById(this.env.contentframe).style.visibility = 'inherit'; + this.show_contentframe(true); } else if (framed) return false; - - if (action && (cid || action=='add')) + + if (action && (cid || action=='add') && !this.drag_active) { this.set_busy(true); - target.location.href = this.env.comm_path+'&_action='+action+'&_cid='+cid+add_url; + target.location.href = this.env.comm_path+'&_action='+action+'&_source='+urlencode(this.env.source)+'&_cid='+urlencode(cid) + add_url; } return true; }; + // copy a contact to the specified target (group or directory) + this.copy_contact = function(cid, to) + { + if (!cid) + cid = this.contact_list.get_selection().join(','); + + if (to != this.env.source && cid && this.env.address_sources[to] && !this.env.address_sources[to].readonly) + this.http_post('copy', '_cid='+urlencode(cid)+'&_source='+urlencode(this.env.source)+'&_to='+urlencode(to)); + }; + this.delete_contacts = function() { @@ -2308,15 +2352,12 @@ function rcube_webmail() } // hide content frame if we delete the currently displayed contact - if (selection.length==1 && this.env.contentframe) - { - var elm = document.getElementById(this.env.contentframe); - elm.style.visibility = 'hidden'; - } + if (selection.length == 1) + this.show_contentframe(false); } // send request to server - this.http_request('delete', '_cid='+a_cids.join(',')+'&_from='+(this.env.action ? this.env.action : '')); + this.http_request('delete', '_cid='+urlencode(a_cids.join(','))+'&_from='+(this.env.action ? this.env.action : '')); return true; }; @@ -2337,51 +2378,6 @@ function rcube_webmail() return false; }; - // load ldap search form - // deprecated - this.ldappublicsearch = function(action) - { - var add_url = ''; - var target = window; - if (this.env.contentframe && window.frames && window.frames[this.env.contentframe]) - { - add_url = '&_framed=1'; - target = window.frames[this.env.contentframe]; - document.getElementById(this.env.contentframe).style.visibility = 'inherit'; - } - else - return false; - - if (action == 'ldappublicsearch') - target.location.href = this.env.comm_path+'&_action='+action+add_url; - - return true; - }; - - // add ldap contacts to address book - this.add_ldap_contacts = function() - { - if (window.frames[this.env.contentframe].rcmail) - { - var frame = window.frames[this.env.contentframe]; - - // build the url - var url = '&_framed=1'; - var emails = '&_emails='; - var names = '&_names='; - var end = ''; - for (var n=0; n<frame.rcmail.selection.length; n++) - { - end = n < frame.rcmail.selection.length - 1 ? ',' : ''; - emails += frame.rcmail.ldap_contact_rows[frame.rcmail.selection[n]].obj.cells[1].innerHTML + end; - names += frame.rcmail.ldap_contact_rows[frame.rcmail.selection[n]].obj.cells[0].innerHTML + end; - } - - frame.location.href = this.env.comm_path + '&_action=save&_framed=1' + emails + names; - } - return false; - } - /*********************************************************/ /********* user settings methods *********/ @@ -2418,7 +2414,6 @@ function rcube_webmail() }; - this.delete_identity = function(id) { // exit if no mailbox specified or if selection is empty @@ -2429,15 +2424,6 @@ function rcube_webmail() if (!id) id = this.env.iid ? this.env.iid : selection[0]; -/* - // 'remove' row from list (just hide it) - if (this.identity_rows && this.identity_rows[id].obj) - { - this.clear_selection(); - this.identity_rows[id].obj.style.display = 'none'; - } -*/ - // if (this.env.framed && id) this.goto_url('delete-identity', '_iid='+id, true); return true; @@ -2928,6 +2914,10 @@ function rcube_webmail() // display a system message this.display_message = function(msg, type, hold) { + // pass command to parent window + if (this.env.framed && parent.rcmail ) + return parent.rcmail.display_message(msg, type, hold); + this.set_busy(false); if (!this.loaded) // save message in order to display after page loaded { @@ -2969,38 +2959,37 @@ function rcube_webmail() // mark a mailbox as selected and set environment variable - this.select_mailbox = function(mbox) + this.select_folder = function(name, old) + { + if (this.gui_objects.folderlist) { - if (this.gui_objects.mailboxlist ) - { - var item, reg, text_obj; - var current_li = this.get_mailbox_li(); - var mbox_li = this.get_mailbox_li(mbox); + var current_li, target_li; - if (current_li) - { + if ((current_li = this.get_folder_li(old))) + { this.set_classname(current_li, 'selected', false); this.set_classname(current_li, 'unfocused', false); - } - - if (mbox_li || this.env.mailbox == mbox) - { - this.set_classname(mbox_li, 'unfocused', false); - this.set_classname(mbox_li, 'selected', true); - } } - // also update mailbox name in window title - if (document.title) + if ((target_li = this.get_folder_li(name))) { - var doc_title = String(document.title); - var reg = new RegExp(this.env.mailbox.toLowerCase(), 'i'); - if (this.env.mailbox && doc_title.match(reg)) - document.title = doc_title.replace(reg, mbox).replace(/^\([0-9]+\)\s+/i, ''); + this.set_classname(target_li, 'unfocused', false); + this.set_classname(target_li, 'selected', true); } - - this.env.mailbox = mbox; - }; + } + }; + + // helper method to find a folder list item + this.get_folder_li = function(name) + { + if (this.gui_objects.folderlist) + { + name = String(name).replace(this.identifier_expr, ''); + return document.getElementById('rcmli'+name); + } + + return null; + }; // for reordering column array, Konqueror workaround @@ -3092,14 +3081,14 @@ function rcube_webmail() }; // replace content of quota display - this.set_quota = function() - { - if (this.gui_objects.quotadisplay && - this.gui_objects.quotadisplay.attributes.getNamedItem('display') && - this.gui_objects.quotadisplay.attributes.getNamedItem('id')) - this.http_request('quotadisplay', '_display='+ - this.gui_objects.quotadisplay.attributes.getNamedItem('display').nodeValue+ - '&_id='+this.gui_objects.quotadisplay.attributes.getNamedItem('id').nodeValue, false); + this.set_quota = function() + { + if (this.gui_objects.quotadisplay && + this.gui_objects.quotadisplay.attributes.getNamedItem('display') && + this.gui_objects.quotadisplay.attributes.getNamedItem('id')) + this.http_request('quotadisplay', '_display='+ + this.gui_objects.quotadisplay.attributes.getNamedItem('display').nodeValue+ + '&_id='+this.gui_objects.quotadisplay.attributes.getNamedItem('id').nodeValue, false); }; @@ -3113,8 +3102,8 @@ function rcube_webmail() set_title = true; var reg, text_obj; - var item = this.get_mailbox_li(mbox); - mbox = String(mbox).toLowerCase().replace(this.mbox_expression, ''); + var item = this.get_folder_li(mbox); + mbox = String(mbox).toLowerCase().replace(this.identifier_expr, ''); if (item && item.className && item.className.indexOf('mailbox '+mbox)>=0) { @@ -3198,6 +3187,14 @@ function rcube_webmail() /********* remote request methods *********/ /********************************************************/ + this.redirect = function(url) + { + this.set_busy(true); + if (this.env.framed && window.parent) + parent.location.href = url; + else + location.href = url; + }; this.goto_url = function(action, query, lock) { @@ -3205,7 +3202,7 @@ function rcube_webmail() this.set_busy(true); var querystring = query ? '&'+query : ''; - location.href = this.env.comm_path+'&_action='+action+querystring; + this.redirect(this.env.comm_path+'&_action='+action+querystring); }; @@ -3241,12 +3238,12 @@ function rcube_webmail() // send request if (request_obj) { - // prompt('request', this.env.comm_path+'&_action='+urlencode(action)+'&'+querystring); - console('HTTP request: '+this.env.comm_path+'&_action='+action+'&'+querystring); + console.log('HTTP request: '+this.env.comm_path+'&_action='+action+'&'+querystring); if (lock) this.set_busy(true); + var rcm = this; request_obj.__lock = lock ? true : false; request_obj.__action = action; request_obj.onerror = function(o){ ref.http_error(o); }; @@ -3255,6 +3252,31 @@ function rcube_webmail() } }; + // send a http POST request to the server + this.http_post = function(action, postdata, lock) + { + var request_obj; + if (postdata && typeof(postdata) == 'object') + postdata._remote = 1; + else + postdata += (postdata ? '&' : '') + '_remote=1'; + + // send request + if (request_obj = this.get_request_obj()) + { + console.log('HTTP POST: '+this.env.comm_path+'&_action='+action); + + if (lock) + this.set_busy(true); + + var rcm = this; + request_obj.__lock = lock ? true : false; + request_obj.__action = action; + request_obj.onerror = function(o){ rcm.http_error(o); }; + request_obj.oncomplete = function(o){ rcm.http_response(o); }; + request_obj.POST(this.env.comm_path+'&_action='+action, postdata); + } + }; // handle HTTP response this.http_response = function(request_obj) @@ -3268,7 +3290,7 @@ function rcube_webmail() this.set_busy(false); - console(request_obj.get_text()); + console.log(request_obj.get_text()); // if we get javascript code from server -> execute it if (request_obj.get_text() && (ctype=='text/javascript' || ctype=='application/x-javascript')) @@ -3450,7 +3472,10 @@ function rcube_http_request() if (window.XMLHttpRequest) this.xmlhttp = new XMLHttpRequest(); else if (window.ActiveXObject) - this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); + { + try { this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } + catch(e) { this.xmlhttp = null; } + } else { @@ -3481,8 +3506,8 @@ function rcube_http_request() this.POST = function(url, body, contentType) { // default value for contentType if not provided - contentType = typeof(contentType) != 'undefined' ? - contentType : 'application/x-www-form-urlencoded'; + if (typeof(contentType) == 'undefined') + contentType = 'application/x-www-form-urlencoded'; this.build(); @@ -3491,15 +3516,23 @@ function rcube_http_request() this.onerror(this); return false; } + + var req_body = body; + if (typeof(body) == 'object') + { + req_body = ''; + for (var p in body) + req_body += (req_body ? '&' : '') + p+'='+urlencode(body[p]); + } - var ref=this; + var ref = this; this.url = url; this.busy = true; this.xmlhttp.onreadystatechange = function() { ref.xmlhttp_onreadystatechange(); }; this.xmlhttp.open('POST', url, true); this.xmlhttp.setRequestHeader('Content-Type', contentType); - this.xmlhttp.send(body); + this.xmlhttp.send(req_body); }; @@ -3563,9 +3596,3 @@ function call_init(o) setTimeout(o+'.init()', 200); } -function console(str) - { - if (document.debugform && document.debugform.console) - document.debugform.console.value += str+'\n--------------------------------------\n'; - } - diff --git a/program/js/common.js b/program/js/common.js index be9a131c2..d9216a58d 100644 --- a/program/js/common.js +++ b/program/js/common.js @@ -602,4 +602,25 @@ function getCookie(name) roundcube_browser.prototype.get_cookie = getCookie; +// tiny replacement for Firebox functionality +function rcube_console() +{ + this.box = rcube_find_object('console'); + + this.log = function(msg) + { + if (this.box) + this.box.value += str+'\n--------------------------------------\n'; + }; + + this.reset = function() + { + if (this.box) + this.box.value = ''; + }; +} + var bw = new roundcube_browser(); + +if (!window.console) + console = new rcube_console(); diff --git a/program/js/editor.js b/program/js/editor.js index 590388ccf..536ad2ada 100644 --- a/program/js/editor.js +++ b/program/js/editor.js @@ -99,8 +99,8 @@ function rcmail_html2plain(htmlText) http_request.onerror = function(o) { rcmail_handle_toggle_error(o); }; http_request.oncomplete = function(o) { rcmail_set_text_value(o); }; - var url=rcmail.env.comm_path+'&_action=html2text'; - console('HTTP request: ' + url); + var url = rcmail.env.bin_path+'html2text.php'; + console.log('HTTP request: ' + url); http_request.POST(url, htmlText, 'application/octet-stream'); } diff --git a/program/js/list.js b/program/js/list.js index 0797295ee..719585893 100644 --- a/program/js/list.js +++ b/program/js/list.js @@ -95,7 +95,7 @@ init: function() init_row: function(row) { // make references in internal array and set event handlers - if (row && String(row.id).match(/rcmrow([0-9]+)/)) + if (row && String(row.id).match(/rcmrow([a-z0-9\-_=]+)/i)) { var p = this; var uid = RegExp.$1; @@ -117,12 +117,14 @@ init_row: function(row) /** * */ -clear: function() +clear: function(sel) { var tbody = document.createElement('TBODY'); this.list.insertBefore(tbody, this.list.tBodies[0]); this.list.removeChild(this.list.tBodies[1]); - this.rows = new Array(); + this.rows = new Array(); + + if (sel) this.clear_selection(); }, diff --git a/program/localization/de_CH/messages.inc b/program/localization/de_CH/messages.inc index dab8057fe..3cf497f14 100644 --- a/program/localization/de_CH/messages.inc +++ b/program/localization/de_CH/messages.inc @@ -37,6 +37,8 @@ $messages['contactexists'] = 'Es existiert bereits ein Eintrag mit dieser E-Mail $messages['blockedimages'] = 'Um Ihre Privatsphäre zur schützen, wurden externe Bilder blockiert.'; $messages['encryptedmessage'] = 'Dies ist eine verschlüsselte Nachricht und kann leider nicht angezeigt werden.'; $messages['nocontactsfound'] = 'Keine Kontakte gefunden'; +$messages['contactnotfound'] = 'Die gewählte Adresse wurde nicht gefunden'; + $messages['sendingfailed'] = 'Versand der Nachricht fehlgeschlagen'; $messages['errorsaving'] = 'Beim Speichern ist ein Fehler aufgetreten'; $messages['errormoving'] = 'Nachricht konnte nicht verschoben werden'; diff --git a/program/localization/en_GB/labels.inc b/program/localization/en_GB/labels.inc index e478016d2..71e73c830 100644 --- a/program/localization/en_GB/labels.inc +++ b/program/localization/en_GB/labels.inc @@ -158,15 +158,6 @@ $labels['contactsfromto'] = 'Contacts $from to $to of $count'; $labels['print'] = 'Print'; $labels['export'] = 'Export'; -// LDAP search -$labels['ldapsearch'] = 'LDAP directory search'; - -$labels['ldappublicsearchname'] = 'Contact name'; -$labels['ldappublicsearchtype'] = 'Exact match?'; -$labels['ldappublicserverselect'] = 'Select servers'; -$labels['ldappublicsearchfield'] = 'Search on'; -$labels['ldappublicsearchform'] = 'Look for a contact'; -$labels['ldappublicsearch'] = 'Search'; // settings $labels['settingsfor'] = 'Settings for'; diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc index 530a8ece5..201af0bd5 100644 --- a/program/localization/en_US/labels.inc +++ b/program/localization/en_US/labels.inc @@ -182,16 +182,8 @@ $labels['firstpage'] = 'Show first set'; $labels['nextpage'] = 'Show next set'; $labels['lastpage'] = 'Show last set'; - -// LDAP search -$labels['ldapsearch'] = 'LDAP directory search'; - -$labels['ldappublicsearchname'] = 'Contact name'; -$labels['ldappublicsearchtype'] = 'Exact match?'; -$labels['ldappublicserverselect'] = 'Select servers'; -$labels['ldappublicsearchfield'] = 'Search on'; -$labels['ldappublicsearchform'] = 'Look for a contact'; -$labels['ldappublicsearch'] = 'Search'; +$labels['groups'] = 'Groups'; +$labels['personaladrbook'] = 'Personal Addresses'; // settings diff --git a/program/localization/en_US/messages.inc b/program/localization/en_US/messages.inc index 51cc313c7..bb132a583 100644 --- a/program/localization/en_US/messages.inc +++ b/program/localization/en_US/messages.inc @@ -38,6 +38,8 @@ $messages['contactexists'] = 'A contact with this e-mail address already exists' $messages['blockedimages'] = 'To protect your privacy, remote images are blocked in this message.'; $messages['encryptedmessage'] = 'This is an encrypted message and can not be displayed. Sorry!'; $messages['nocontactsfound'] = 'No contacts found'; +$messages['contactnotfound'] = 'The requested contact was not found'; + $messages['sendingfailed'] = 'Failed to send message'; $messages['errorsaving'] = 'An error occured while saving'; $messages['errormoving'] = 'Could not move the message'; @@ -69,4 +71,9 @@ $messages['messageopenerror'] = 'Could not load message from server'; $messages['fileuploaderror'] = 'File upload failed'; $messages['filesizeerror'] = 'The uploaded file exceeds the maximum size of $size'; -?>
\ No newline at end of file +$messages['copysuccess'] = 'Successfully copied $nr addresses'; +$messages['copyerror'] = 'Could not copy any addresses'; +$messages['sourceisreadonly'] = 'This address source is read only'; +$messages['errorsavingcontact'] = 'Could not save the contact address'; + +?> diff --git a/program/steps/addressbook/copy.inc b/program/steps/addressbook/copy.inc new file mode 100644 index 000000000..e6d917e92 --- /dev/null +++ b/program/steps/addressbook/copy.inc @@ -0,0 +1,44 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/addressbook/copy.inc | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2007, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Copy a contact record from one direcotry to another | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: copy.inc 471 2007-02-09 21:25:50Z thomasb $ + +*/ + +$cid = get_input_value('_cid', RCUBE_INPUT_POST); +$target = get_input_value('_to', RCUBE_INPUT_POST); +if ($cid && preg_match('/^[a-z0-9\-_=]+(,[a-z0-9\-_=]+)*$/i', $cid) && strlen($target) && $target != $source) +{ + if ($target != '0') + $TARGET = new rcube_ldap($CONFIG['ldap_public'][$target]); + else + $TARGET = new rcube_contacts($DB, $_SESSION['user_id']); + + $success = false; + if ($TARGET && $TARGET->ready && !$TARGET->readonly) + $success = $TARGET->insert($CONTACTS->search($CONTACTS->primary_key, $cid), true); + + if (empty($success)) + $OUTPUT->show_message('copyerror', 'error'); + else + $OUTPUT->show_message('copysuccess', 'notice', array('nr' => count($success))); +} + +// send response +$OUTPUT->send(); + +?>
\ No newline at end of file diff --git a/program/steps/addressbook/delete.inc b/program/steps/addressbook/delete.inc index 3e33cd864..e5c762844 100644 --- a/program/steps/addressbook/delete.inc +++ b/program/steps/addressbook/delete.inc @@ -5,7 +5,7 @@ | program/steps/addressbook/delete.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -19,80 +19,29 @@ */ -$REMOTE_REQUEST = TRUE; - -if ($_GET['_cid'] && preg_match('/^[0-9]+(,[0-9]+)*$/',$_GET['_cid'])) +if (($cid = get_input_value('_cid', RCUBE_INPUT_GPC)) && preg_match('/^[0-9]+(,[0-9]+)*$/', $cid)) { - $DB->query("UPDATE ".get_table_name('contacts')." - SET del=1 - WHERE user_id=? - AND contact_id IN (".$_GET['_cid'].")", - $_SESSION['user_id']); - - $count = $DB->affected_rows(); - if (!$count) + $deleted = $CONTACTS->delete($cid); + if (!$deleted) { // send error message exit; } - // count contacts for this user - $sql_result = $DB->query("SELECT COUNT(contact_id) AS rows - FROM ".get_table_name('contacts')." - WHERE del<>1 - AND user_id=?", - $_SESSION['user_id']); - - $sql_arr = $DB->fetch_assoc($sql_result); - $rowcount = $sql_arr['rows']; + $result = $CONTACTS->count(); // update message count display - $pages = ceil($rowcount/$CONFIG['pagesize']); - $commands = sprintf("this.set_rowcount('%s');\n", rcmail_get_rowcount_text($rowcount)); - $commands .= sprintf("this.set_env('pagecount', %d);\n", $pages); - + $OUTPUT->set_env('pagecount', ceil($result->count / $CONTACTS->page_size)); + $OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($result->count)); // add new rows from next page (if any) - if ($_GET['_from']!='show' && $pages>1 && $_SESSION['page'] < $pages) - { - $start_row = ($_SESSION['page'] * $CONFIG['pagesize']) - $count; - - // get contacts from DB - $sql_result = $DB->limitquery("SELECT * FROM ".get_table_name('contacts')." - WHERE del<>1 - AND user_id=? - ORDER BY name", - $start_row, - $count, - $_SESSION['user_id']); - - $commands .= rcmail_js_contacts_list($sql_result); - -/* - // define list of cols to be displayed - $a_show_cols = array('name', 'email'); - - while ($sql_arr = $DB->fetch_assoc($sql_result)) - { - $a_row_cols = array(); - - // format each col - foreach ($a_show_cols as $col) - { - $cont = rep_specialchars_output($sql_arr[$col]); - $a_row_cols[$col] = $cont; - } - - $commands .= sprintf("this.add_contact_row(%s, %s);\n", - $sql_arr['contact_id'], - array2js($a_row_cols)); - } -*/ - } + $pages = ceil(($result->count + $deleted) / $CONTACTS->page_size); + if ($_GET['_from'] != 'show' && $pages > 1 && $CONTACTS->list_page < $pages) + rcmail_js_contacts_list($CONTACTS->list_records(null, -$deleted)); // send response - rcube_remote_response($commands); + $OUTPUT->send(); } exit; diff --git a/program/steps/addressbook/edit.inc b/program/steps/addressbook/edit.inc index 245c02409..47db7197d 100644 --- a/program/steps/addressbook/edit.inc +++ b/program/steps/addressbook/edit.inc @@ -5,7 +5,7 @@ | program/steps/addressbook/edit.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -20,30 +20,27 @@ */ -if (($_GET['_cid'] || $_POST['_cid']) && $_action=='edit') - { - $cid = $_POST['_cid'] ? $_POST['_cid'] : $_GET['_cid']; - $DB->query("SELECT * FROM ".get_table_name('contacts')." - WHERE contact_id=? - AND user_id=? - AND del<>1", - $cid, - $_SESSION['user_id']); - - $CONTACT_RECORD = $DB->fetch_assoc(); - - if (is_array($CONTACT_RECORD)) - $OUTPUT->add_script(sprintf("%s.set_env('cid', '%s');", $JS_OBJECT_NAME, $CONTACT_RECORD['contact_id'])); - } - +if (($cid = get_input_value('_cid', RCUBE_INPUT_GPC)) && ($record = $CONTACTS->get_record($cid, true))) + $OUTPUT->set_env('cid', $record['ID']); +// adding not allowed here +if ($CONTACTS->readonly) +{ + $OUTPUT->show_message('sourceisreadonly'); + rcmail_overwrite_action('show'); + return; +} function rcmail_contact_editform($attrib) - { - global $CONTACT_RECORD, $JS_OBJECT_NAME; +{ + global $CONTACTS, $OUTPUT; - if (!$CONTACT_RECORD && $GLOBALS['_action']!='add') - return rcube_label('contactnotfound'); + // check if we have a valid result + if ($GLOBALS['_action'] != 'add' && !(($result = $CONTACTS->get_result()) && ($record = $result->first()))) + { + $OUTPUT->show_message('contactnotfound'); + return false; + } // add some labels to client rcube_add_label('noemailwarning'); @@ -51,15 +48,14 @@ function rcmail_contact_editform($attrib) list($form_start, $form_end) = get_form_tags($attrib); unset($attrib['form']); - // a specific part is requested if ($attrib['part']) - { + { $out = $form_start; - $out .= rcmail_get_edit_field($attrib['part'], $CONTACT_RECORD[$attrib['part']], $attrib); + $out .= rcmail_get_edit_field($attrib['part'], $record[$attrib['part']], $attrib); return $out; - } + } // return the complete address edit form as table @@ -67,38 +63,37 @@ function rcmail_contact_editform($attrib) $a_show_cols = array('name', 'firstname', 'surname', 'email'); foreach ($a_show_cols as $col) - { + { $attrib['id'] = 'rcmfd_'.$col; - $title = rcube_label($col); - $value = rcmail_get_edit_field($col, $CONTACT_RECORD[$col], $attrib); + $value = rcmail_get_edit_field($col, $record[$col], $attrib); $out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n", $attrib['id'], - $title, + Q(rcube_label($col)), $value); - } + } $out .= "\n</table>$form_end"; return $out; - } +} + +$OUTPUT->add_handler('contacteditform', 'rcmail_contact_editform'); // similar function as in /steps/settings/edit_identity.inc function get_form_tags($attrib) { - global $CONTACT_RECORD, $OUTPUT, $JS_OBJECT_NAME, $EDIT_FORM, $SESS_HIDDEN_FIELD; + global $CONTACTS, $OUTPUT, $EDIT_FORM, $SESS_HIDDEN_FIELD; + $result = $CONTACTS->get_result(); $form_start = ''; if (!strlen($EDIT_FORM)) { $hiddenfields = new hiddenfield(array('name' => '_task', 'value' => $GLOBALS['_task'])); - $hiddenfields->add(array('name' => '_action', 'value' => 'save')); - - if ($GLOBALS['_framed']) - $hiddenfields->add(array('name' => '_framed', 'value' => 1)); + $hiddenfields->add(array('name' => '_action', 'value' => 'save', 'source' => get_input_value('_source', RCUBE_INPUT_GPC))); - if ($CONTACT_RECORD['contact_id']) - $hiddenfields->add(array('name' => '_cid', 'value' => $CONTACT_RECORD['contact_id'])); + if (($result = $CONTACTS->get_result()) && ($record = $result->first())) + $hiddenfields->add(array('name' => '_cid', 'value' => $record['ID'])); $form_start = !strlen($attrib['form']) ? '<form name="form" action="./" method="post">' : ''; $form_start .= "\n$SESS_HIDDEN_FIELD\n"; @@ -109,7 +104,7 @@ function get_form_tags($attrib) $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form'; if (!strlen($EDIT_FORM)) - $OUTPUT->add_script("$JS_OBJECT_NAME.gui_object('editform', '$form_name');"); + $OUTPUT->add_gui_object('editform', $form_name); $EDIT_FORM = $form_name; @@ -118,7 +113,7 @@ function get_form_tags($attrib) -if (!$CONTACT_RECORD && template_exists('addcontact')) +if (!$CONTACTS->get_result() && template_exists('addcontact')) parse_template('addcontact'); // this will be executed if no template for addcontact exists diff --git a/program/steps/addressbook/func.inc b/program/steps/addressbook/func.inc index 1f993a9d3..5329270c2 100644 --- a/program/steps/addressbook/func.inc +++ b/program/steps/addressbook/func.inc @@ -5,7 +5,7 @@ | program/steps/addressbook/func.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -19,152 +19,182 @@ */ -$CONTACTS_LIST = array(); +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]); +else + $CONTACTS = new rcube_contacts($DB, $_SESSION['user_id']); + +$CONTACTS->set_pagesize($CONFIG['pagesize']); // set list properties and session vars -if (strlen($_GET['_page'])) +if (!empty($_GET['_page'])) { - $CONTACTS_LIST['page'] = $_GET['_page']; + $CONTACTS->set_page(intval($_GET['_page'])); $_SESSION['page'] = $_GET['_page']; } else - $CONTACTS_LIST['page'] = $_SESSION['page'] ? $_SESSION['page'] : 1; + $CONTACTS->set_page(isset($_SESSION['page']) ?$_SESSION['page'] : 1); + +// set message set for search result +if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) + $CONTACTS->set_search_set($_SESSION['search'][$_REQUEST['_search']]); + +// set data source env +$OUTPUT->set_env('source', $source ? $source : '0'); +$OUTPUT->set_env('readonly', $CONTACTS->readonly, false); + + +function rcmail_directory_list($attrib) +{ + global $CONFIG, $OUTPUT; + + if (!$attrib['id']) + $attrib['id'] = 'rcmdirectorylist'; + + $local_id = '0'; + $current = get_input_value('_source', RCUBE_INPUT_GPC); + $line_templ = '<li id="%s" class="%s"><a href="%s"' . + ' onclick="return %s.command(\'list\',\'%s\',this)"' . + ' onmouseover="return %s.focus_folder(\'%s\')"' . + ' onmouseout="return %s.unfocus_folder(\'%s\')"' . + ' onmouseup="return %s.folder_mouse_up(\'%s\')">%s'. + "</a></li>\n"; + + $js_list = array("$local_id" => array('id' => $local_id, 'readonly' => false)); + + // allow the following attributes to be added to the <ul> tag + $out = '<ul' . create_attrib_string($attrib, array('style', 'class', 'id')) . ">\n"; + $out .= sprintf($line_templ, + 'rcmli'.$local_id, + !$current ? 'selected' : '', + Q(rcmail_self_url('list', array('_source' => 0))), + JS_OBJECT_NAME, + $local_id, + JS_OBJECT_NAME, + $local_id, + JS_OBJECT_NAME, + $local_id, + JS_OBJECT_NAME, + $local_id, + rcube_label('personaladrbook')); + + foreach ((array)$CONFIG['ldap_public'] as $id => $prop) + { + $js_id = JQ($id); + $dom_id = preg_replace('/[^a-z0-9\-_]/i', '', $id); + $out .= sprintf($line_templ, + 'rcmli'.$dom_id, + $current == $id ? 'selected' : '', + Q(rcmail_self_url('list', array('_source' => $id))), + JS_OBJECT_NAME, + $js_id, + JS_OBJECT_NAME, + $js_id, + JS_OBJECT_NAME, + $js_id, + JS_OBJECT_NAME, + $js_id, + !empty($prop['name']) ? Q($prop['name']) : Q($id)); + + $js_list[$id] = array('id' => $id, 'readonly' => !$prop['writeable']); + } + + $out .= '</ul>'; -// disable the ldap public search button if there's no servers configured -$enable_ldap = 'true'; -if (!$CONFIG['ldap_public']) - $enable_ldap = 'false'; + $OUTPUT->add_gui_object('folderlist', $attrib['id']); + $OUTPUT->set_env('address_sources', $js_list); -$OUTPUT->add_script("$JS_OBJECT_NAME.set_env('ldappublicsearch', $enable_ldap);"); + return $out; +} + // return the message list as HTML table function rcmail_contacts_list($attrib) { - global $DB, $CONFIG, $OUTPUT, $CONTACTS_LIST, $JS_OBJECT_NAME; - - //$skin_path = $CONFIG['skin_path']; - //$image_tag = '<img src="%s%s" alt="%s" border="0" />'; + global $CONTACTS, $OUTPUT; // count contacts for this user - $sql_result = $DB->query("SELECT COUNT(contact_id) AS rows - FROM ".get_table_name('contacts')." - WHERE del<>1 - AND user_id=?", - $_SESSION['user_id']); - - $sql_arr = $DB->fetch_assoc($sql_result); - $rowcount = $sql_arr['rows']; - - if ($rowcount) - { - $start_row = ($CONTACTS_LIST['page']-1) * $CONFIG['pagesize']; - - // get contacts from DB - $sql_result = $DB->limitquery("SELECT * FROM ".get_table_name('contacts')." - WHERE del<>1 - AND user_id= ? - ORDER BY name", - $start_row, - $CONFIG['pagesize'], - $_SESSION['user_id']); - } - else - $sql_result = NULL; - - + $result = $CONTACTS->list_records(); + // add id to message list table if not specified if (!strlen($attrib['id'])) $attrib['id'] = 'rcmAddressList'; - + // define list of cols to be displayed - $a_show_cols = array('name', 'email'); - - // create XHTML table - $out = rcube_table_output($attrib, $sql_result, $a_show_cols, 'contact_id'); + $a_show_cols = array('name'); - // set client env - $javascript = sprintf("%s.gui_object('contactslist', '%s');\n", $JS_OBJECT_NAME, $attrib['id']); - $javascript .= sprintf("%s.set_env('current_page', %d);\n", $JS_OBJECT_NAME, $CONTACTS_LIST['page']); - $javascript .= sprintf("%s.set_env('pagecount', %d);\n", $JS_OBJECT_NAME, ceil($rowcount/$CONFIG['pagesize'])); - $javascript .= "rcmail.set_env('newcontact', '" . rcube_label('newcontact') . "');"; - //$javascript .= sprintf("%s.set_env('contacts', %s);", $JS_OBJECT_NAME, array2js($a_js_message_arr)); + // create XHTML table + $out = rcube_table_output($attrib, $result->records, $a_show_cols, $CONTACTS->primary_key); - $OUTPUT->add_script($javascript); + // set client env + $OUTPUT->add_gui_object('contactslist', $attrib['id']); + $OUTPUT->set_env('current_page', (int)$CONTACTS->list_page); + $OUTPUT->set_env('pagecount', ceil($result->count/$CONTACTS->page_size)); $OUTPUT->include_script('list.js'); - + // add some labels to client rcube_add_label('deletecontactconfirm'); - + return $out; } - -function rcmail_js_contacts_list($sql_result, $obj_name='this') +function rcmail_js_contacts_list($result, $prefix='') { - global $DB; + global $OUTPUT; - $commands = ''; - - if (!$sql_result) - return ''; + if (empty($result) || $result->count == 0) + return; // define list of cols to be displayed - $a_show_cols = array('name', 'email'); - - while ($sql_arr = $DB->fetch_assoc($sql_result)) + $a_show_cols = array('name'); + + while ($row = $result->next()) { $a_row_cols = array(); - + // format each col foreach ($a_show_cols as $col) - { - $cont = Q($sql_arr[$col]); - $a_row_cols[$col] = $cont; - } - - $commands .= sprintf("%s.add_contact_row(%s, %s);\n", - $obj_name, - $sql_arr['contact_id'], - array2js($a_row_cols)); - } + $a_row_cols[$col] = $row[$col]; - return $commands; + $OUTPUT->command($prefix.'add_contact_row', $row['ID'], $a_row_cols); + } } // similar function as /steps/settings/identities.inc::rcmail_identity_frame() function rcmail_contact_frame($attrib) { - global $OUTPUT, $JS_OBJECT_NAME; + global $OUTPUT; if (!$attrib['id']) $attrib['id'] = 'rcmcontactframe'; $attrib['name'] = $attrib['id']; - - $OUTPUT->add_script(sprintf("%s.set_env('contentframe', '%s');", $JS_OBJECT_NAME, $attrib['name'])); - $attrib_str = create_attrib_string($attrib, array('name', 'id', 'class', 'style', 'src', 'width', 'height', 'frameborder')); - $out = '<iframe'. $attrib_str . '></iframe>'; - - return $out; + + $OUTPUT->set_env('contentframe', $attrib['name']); + $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/blank.gif'); + return '<iframe'. $attrib_str . '></iframe>'; } function rcmail_rowcount_display($attrib) { - global $OUTPUT, $JS_OBJECT_NAME; + global $OUTPUT; if (!$attrib['id']) $attrib['id'] = 'rcmcountdisplay'; - $OUTPUT->add_script(sprintf("%s.gui_object('countdisplay', '%s');", $JS_OBJECT_NAME, $attrib['id'])); + $OUTPUT->add_gui_object('countdisplay', $attrib['id']); // allow the following attributes to be added to the <span> tag $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id')); - $out = '<span' . $attrib_str . '>'; $out .= rcmail_get_rowcount_text(); $out .= '</span>'; @@ -173,32 +203,37 @@ function rcmail_rowcount_display($attrib) -function rcmail_get_rowcount_text($max=NULL) +function rcmail_get_rowcount_text() { - global $CONTACTS_LIST, $CONFIG, $DB; + global $CONTACTS; - $start_row = ($CONTACTS_LIST['page']-1) * $CONFIG['pagesize'] + 1; - - // get nr of contacts - if ($max===NULL) - { - $sql_result = $DB->query("SELECT 1 FROM ".get_table_name('contacts')." - WHERE del<>1 - AND user_id=?", - $_SESSION['user_id']); - - $max = $DB->num_rows($sql_result); - } - - if ($max==0) + // read nr of contacts + $result = $CONTACTS->get_result(); + if (!$result) + $result = $CONTACTS->count(); + + if ($result->count == 0) $out = rcube_label('nocontactsfound'); else - $out = rcube_label(array('name' => 'contactsfromto', - 'vars' => array('from' => $start_row, - 'to' => min($max, $start_row + $CONFIG['pagesize'] - 1), - 'count' => $max))); + $out = rcube_label(array( + 'name' => 'contactsfromto', + 'vars' => array( + 'from' => $result->first + 1, + 'to' => min($result->count, $result->first + $CONTACTS->page_size), + 'count' => $result->count) + )); return $out; } + + +// register UI objects +$OUTPUT->add_handlers(array( + 'directorylist' => 'rcmail_directory_list', + 'addresslist' => 'rcmail_contacts_list', + 'addressframe' => 'rcmail_contact_frame', + 'recordscountdisplay' => 'rcmail_rowcount_display', + 'searchform' => 'rcmail_search_form' +)); ?> diff --git a/program/steps/addressbook/ldapsearchform.inc b/program/steps/addressbook/ldapsearchform.inc deleted file mode 100644 index a4e08dcdc..000000000 --- a/program/steps/addressbook/ldapsearchform.inc +++ /dev/null @@ -1,277 +0,0 @@ -<?php - -/* - +-----------------------------------------------------------------------+ - | program/steps/addressbook/ldapsearch.inc | - | | - | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | - | Licensed under the GNU GPL | - | | - | PURPOSE: | - | Show an ldap search form in the addressbook | - | | - +-----------------------------------------------------------------------+ - | Author: Justin Randell <justin.randell@gmail.com> | - +-----------------------------------------------------------------------+ - - $Id$ - -*/ -require_once 'include/rcube_ldap.inc'; - -/** - * draw the ldap public search form - */ -function rcmail_ldap_public_search_form($attrib) - { - global $CONFIG, $JS_OBJECT_NAME, $OUTPUT; - if (!isset($CONFIG['ldap_public'])) - { - // no ldap servers to search - show_message('noldapserver', 'warning'); - rcmail_overwrite_action('add'); - return false; - } - else - { - // store some information in the session - $_SESSION['ldap_public']['server_count'] = $server_count = count($CONFIG['ldap_public']); - $_SESSION['ldap_public']['server_names'] = $server_names = array_keys($CONFIG['ldap_public']); - } - - list($form_start, $form_end) = get_form_tags($attrib); - $out = "$form_start<table id=\"ldap_public_search_table\">\n\n"; - - // search name field - $search_name = new textfield(array('name' => '_ldap_public_search_name', - 'id' => 'rcmfd_ldap_public_search_name')); - $out .= "<tr><td class=\"title\"><label for=\"rcmfd_ldap_public_search_name\">" . - rep_specialchars_output(rcube_label('ldappublicsearchname')) . - "</label></td><td>" . $search_name->show() . "</td></tr>\n"; - - - // there's more than one server to search for, show a dropdown menu - if ($server_count > 1) - { - $select_server = new select(array('name' => '_ldap_public_servers', - 'id' => 'rcfmd_ldap_public_servers')); - - $select_server->add($server_names, $server_names); - - $out .= '<tr><td class="title"><label for="rcfmd_ldap_public_servers">' . - rep_specialchars_output(rcube_label('ldappublicserverselect')) . - "</label></td><td>" . $select_server->show() . "</td></tr>\n"; - } - - // foreach configured ldap server, set up the search fields - for ($i = 0; $i < $server_count; $i++) - { - $server = $CONFIG['ldap_public'][$server_names[$i]]; - - // only display one search fields select - js takes care of the rest - if (!$i) - { - $field_name = '_ldap_public_search_field'; - $field_id = 'rcfmd_ldap_public_search_field'; - - $search_fields = new select(array('name' => $field_name, - 'id' => $field_id)); - - $search_fields->add(array_keys($server['search_fields']), array_values($server['search_fields'])); - $out .= '<tr><td class="title"><label for="' . $field_id . '">' . - rep_specialchars_output(rcube_label('ldappublicsearchfield')) . - "</label></td><td>" . $search_fields->show() . "</td></tr>\n"; - - $attributes = array('name' => '_ldap_public_search_type', - 'id' => 'rcmfd_ldap_public_search_type'); - - // if there's only one server, and it doesn't accept fuzzy searches, - // then check and disable the check box - thanks pieter - if ($server_count == 1 && !$server['fuzzy_search']) - { - $attributes['CHECKED'] = 'CHECKED'; - $attributes['disabled'] = 'disabled'; - } - - $search_type = new checkbox($attributes); - - $out .= '<tr id="ldap_fuzzy_search"><td class="title"><label for="rcmfd_ldap_public_search_type">' . - rep_specialchars_output(rcube_label('ldappublicsearchtype')) . - "</label></td><td>" . $search_type->show() . "</td></tr>\n"; - } - - if ($server_count > 1) - { - // store the search fields in a js array for each server - $js = ''; - foreach ($server['search_fields'] as $search_name => $search_value) - $js .= "['$search_name', '$search_value'], "; - - // store whether this server accepts fuzzy search as last item in array - $js .= $server['fuzzy_search'] ? "'fuzzy'" : "'exact'"; - $OUTPUT->add_script("rcmail.set_env('{$server_names[$i]}_search_fields', new Array($js));"); - } - } - - // add contact button label text - $OUTPUT->add_script("rcmail.set_env('addcontact', '" . rcube_label('addcontact') . "');"); - - $out .= "\n</table>$form_end"; - return $out; - } - -/** - * get search values and return ldap contacts - */ -function rcmail_ldap_public_list() - { - // just return if we are not being called from a search form - if (!isset($_POST['_action'])) - return null; - - global $CONFIG, $OUTPUT, $JS_OBJECT_NAME; - - // show no search name warning and exit - if (empty($_POST['_ldap_public_search_name']) || trim($_POST['_ldap_public_search_name']) == '') - { - show_message('nosearchname', 'warning'); - return false; - } - - // set up ldap server(s) array or bail - if ($_SESSION['ldap_public']['server_count'] > 1) - // show no ldap server warning and exit - if (empty($_POST['_ldap_public_servers'])) - { - show_message('noldappublicserver', 'warning'); - return false; - } - else - $server_name = $_POST['_ldap_public_servers']; - else if ($_SESSION['ldap_public']['server_count'] == 1) - $server_name = $_SESSION['ldap_public']['server_names'][0]; - else - return false; - - // get search parameters - $search_value = $_POST['_ldap_public_search_name']; - $search_field = $_POST['_ldap_public_search_field']; - - // only use the post var for search type if the ldap server allows 'like' - $exact = true; - if ($CONFIG['ldap_public'][$server_name]['fuzzy_search']) - $exact = isset($_POST['_ldap_public_search_type']) ? true : false; - - // perform an ldap search - $contacts = rcmail_ldap_contact_search($search_value, - $search_field, - $CONFIG['ldap_public'][$server_name], - $exact); - - // if no results, show a warning and return - if (!$contacts) - { - show_message('nocontactsreturned', 'warning'); - return false; - } - - // add id to message list table if not specified - if (!strlen($attrib['id'])) - $attrib['id'] = 'ldapAddressList'; - - // define table class - $attrib['class'] = 'records-table'; - $attrib['cellspacing'] = 0; - - // define list of cols to be displayed - $a_show_cols = array('name', 'email'); - - // create XHTML table - $out = rcube_table_output($attrib, $contacts, $a_show_cols, 'row_id'); - - // set client env - $javascript = "$JS_OBJECT_NAME.gui_object('ldapcontactslist', '{$attrib['id']}');\n"; - $OUTPUT->add_script($javascript); - - return $out; - } - -/** - * perform search for contacts from given public ldap server - */ -function rcmail_ldap_contact_search($search_value, $search_field, $server, $exact=true) - { - global $CONFIG; - - $attributes = array($server['name_field'], $server['mail_field']); - - $LDAP = new rcube_ldap(); - if ($LDAP->connect($server['hosts'], $server['port'], $server['protocol'])) - { - $filter = "$search_field=" . ($exact ? $search_value : "*$search_value*"); - $result = $LDAP->search($server['base_dn'], - $filter, - $attributes, - $server['scope'], - $sort=null); - - // add any results to contact array - if ($result['count']) - { - for ($n = 0; $n < $result['count']; $n++) - { - $contacts[$n]['name'] = $result[$n][$server['name_field']][0]; - $contacts[$n]['email'] = $result[$n][$server['mail_field']][0]; - $contacts[$n]['row_id'] = $n + 1; - } - } - } - else - return false; - - // cleanup - $LDAP->close(); - - if (!$result['count']) - return false; - - // weed out duplicate emails - for ($n = 0; $n < $result['count']; $n++) - for ($i = 0; $i < $result['count']; $i++) - if ($contacts[$i]['email'] == $contacts[$n]['email'] && $i != $n) - unset($contacts[$n]); - - return $contacts; - } - -function get_form_tags($attrib) - { - global $OUTPUT, $JS_OBJECT_NAME, $EDIT_FORM, $SESS_HIDDEN_FIELD; - - $form_start = ''; - if (!strlen($EDIT_FORM)) - { - $hiddenfields = new hiddenfield(array('name' => '_task', 'value' => $GLOBALS['_task'])); - $hiddenfields->add(array('name' => '_action', 'value' => 'ldappublicsearch')); - - if ($_framed) - $hiddenfields->add(array('name' => '_framed', 'value' => 1)); - - $form_start .= !strlen($attrib['form']) ? '<form name="form" action="./" method="post">' : ''; - $form_start .= "\n$SESS_HIDDEN_FIELD\n"; - $form_start .= $hiddenfields->show(); - } - - $form_end = (strlen($EDIT_FORM) && !strlen($attrib['form'])) ? '</form>' : ''; - $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form'; - - $OUTPUT->add_script("$JS_OBJECT_NAME.gui_object('ldappublicsearchform', '$form_name');"); - - $EDIT_FORM = $form_name; - - return array($form_start, $form_end); - } - -parse_template('ldappublicsearch'); -?> diff --git a/program/steps/addressbook/list.inc b/program/steps/addressbook/list.inc index 0aa4873b3..71b9379b1 100644 --- a/program/steps/addressbook/list.inc +++ b/program/steps/addressbook/list.inc @@ -5,7 +5,7 @@ | program/steps/addressbook/list.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -19,38 +19,17 @@ */ -$REMOTE_REQUEST = TRUE; - -// count contacts for this user -$sql_result = $DB->query("SELECT COUNT(contact_id) AS rows - FROM ".get_table_name('contacts')." - WHERE del<>1 - AND user_id=?", - $_SESSION['user_id']); - -$sql_arr = $DB->fetch_assoc($sql_result); -$rowcount = $sql_arr['rows']; +// get contacts for this user +$result = $CONTACTS->list_records(); // update message count display -$pages = ceil($rowcount/$CONFIG['pagesize']); -$commands = sprintf("this.set_rowcount('%s');\n", rcmail_get_rowcount_text($rowcount)); -$commands .= sprintf("this.set_env('pagecount', %d);\n", $pages); - -$start_row = ($CONTACTS_LIST['page']-1) * $CONFIG['pagesize']; +$OUTPUT->set_env('pagecount', ceil($result->count / $CONTACTS->page_size)); +$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text($rowcount)); -// get contacts from DB -$sql_result = $DB->limitquery("SELECT * FROM ".get_table_name('contacts')." - WHERE del<>1 - AND user_id=? - ORDER BY name", - $start_row, - $CONFIG['pagesize'], - $_SESSION['user_id']); - -$commands .= rcmail_js_contacts_list($sql_result); +// create javascript list +rcmail_js_contacts_list($result); // send response -rcube_remote_response($commands); +$OUTPUT->send(); -exit; ?>
\ No newline at end of file diff --git a/program/steps/addressbook/mailto.inc b/program/steps/addressbook/mailto.inc new file mode 100644 index 000000000..ddbec30d0 --- /dev/null +++ b/program/steps/addressbook/mailto.inc @@ -0,0 +1,48 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/addressbook/mailto.inc | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2007, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Compose a recipient list with all selected contacts | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: copy.inc 471 2007-02-09 21:25:50Z thomasb $ + +*/ + +$cid = get_input_value('_cid', RCUBE_INPUT_GET); +$recipients = null; +$mailto = array(); + +if ($cid && preg_match('/^[a-z0-9\-_=]+(,[a-z0-9\-_=]+)*$/i', $cid) && $CONTACTS->ready) +{ + $recipients = $CONTACTS->search($CONTACTS->primary_key, $cid); + + while (is_object($recipients) && ($rec = $recipients->iterate())) + $mailto[] = format_email_recipient($rec['email'], $rec['name']); +} + +if (!empty($mailto)) +{ + $mailto_str = join(', ', $mailto); + $mailto_id = substr(md5($mailto_str), 0, 16); + $_SESSION['mailto'][$mailto_id] = $mailto_str; + $OUTPUT->command('redirect', rcmail_self_url('compose', array('_mailto' => $mailto_id), 'mail')); +} +else + $OUTPUT->show_message('nocontactsfound', 'warning'); + + +// send response +$OUTPUT->send(); + +?>
\ No newline at end of file diff --git a/program/steps/addressbook/save.inc b/program/steps/addressbook/save.inc index a50d0388a..72e54b173 100644 --- a/program/steps/addressbook/save.inc +++ b/program/steps/addressbook/save.inc @@ -5,7 +5,7 @@ | program/steps/addressbook/save.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -19,240 +19,108 @@ */ +// cannot edit record +if ($CONTACTS->readonly) +{ + $OUTPUT->show_message('contactreadonly', 'error'); + rcmail_overwrite_action(empty($_POST['_cid']) ? 'add' : 'show'); + return; +} + // check input -if ((empty($_POST['_name']) || empty($_POST['_email'])) && empty($_GET['_framed'])) - { - show_message('formincomplete', 'warning'); +if ((!get_input_value('_name', RCUBE_INPUT_POST) || !get_input_value('_email', RCUBE_INPUT_POST)) && $_framed) +{ + $OUTPUT->show_message('formincomplete', 'warning'); rcmail_overwrite_action(empty($_POST['_cid']) ? 'add' : 'show'); return; - } +} + // setup some vars we need $a_save_cols = array('name', 'firstname', 'surname', 'email'); -$contacts_table = get_table_name('contacts'); +$a_record = array(); +$cid = get_input_value('_cid', RCUBE_INPUT_POST); + +// read POST values into hash array +foreach ($a_save_cols as $col) +{ + $fname = '_'.$col; + if (isset($_POST[$fname])) + $a_record[$col] = get_input_value($fname, RCUBE_INPUT_POST); +} // update an existing contact -if (!empty($_POST['_cid'])) +if (!empty($cid)) +{ + if ($CONTACTS->update($cid, $a_record)) { - $a_write_sql = array(); - - foreach ($a_save_cols as $col) - { - $fname = '_'.$col; - if (!isset($_POST[$fname])) - continue; - - $a_write_sql[] = sprintf("%s=%s", - $DB->quoteIdentifier($col), - $DB->quote(get_input_value($fname, RCUBE_INPUT_POST))); - } - - if (sizeof($a_write_sql)) - { - $DB->query("UPDATE $contacts_table - SET changed=".$DB->now().", ".join(', ', $a_write_sql)." - WHERE contact_id=? - AND user_id=? - AND del<>1", - $_POST['_cid'], - $_SESSION['user_id']); - - $updated = $DB->affected_rows(); - } - - if ($updated) - { if ($_framed) - { + { // define list of cols to be displayed - $a_show_cols = array('name', 'email'); $a_js_cols = array(); - - $sql_result = $DB->query("SELECT * FROM $contacts_table - WHERE contact_id=? - AND user_id=? - AND del<>1", - $_POST['_cid'], - $_SESSION['user_id']); - - $sql_arr = $DB->fetch_assoc($sql_result); - foreach ($a_show_cols as $col) - $a_js_cols[] = (string)$sql_arr[$col]; + $record = $CONTACTS->get_record($cid, true); - // update the changed col in list - $OUTPUT->add_script(sprintf("if(parent.%s)parent.%s.update_contact_row('%d', %s);", - $JS_OBJECT_NAME, - $JS_OBJECT_NAME, - $_POST['_cid'], - array2js($a_js_cols))); + foreach (array('name', 'email') as $col) + $a_js_cols[] = (string)$record[$col]; - } + // update the changed col in list + $OUTPUT->command('parent.update_contact_row', $cid, $a_js_cols); + } // show confirmation - show_message('successfullysaved', 'confirmation'); + $OUTPUT->show_message('successfullysaved', 'confirmation'); rcmail_overwrite_action('show'); - } + } else - { + { // show error message - show_message('errorsaving', 'error'); + $OUTPUT->show_message('errorsaving', 'error'); rcmail_overwrite_action('show'); - } } +} // insert a new contact else - { - $a_insert_cols = $a_insert_values = array(); - +{ // check for existing contacts - $sql = "SELECT 1 FROM $contacts_table - WHERE user_id = {$_SESSION['user_id']} - AND del <> '1' "; - - // get email and name, build sql for existing user check - if (isset($_GET['_emails']) && isset($_GET['_names'])) - { - $sql .= "AND email IN ("; - $emails = explode(',', get_input_value('_emails', RCUBE_INPUT_GET)); - $names = explode(',', get_input_value('_names', RCUBE_INPUT_GET)); - $count = count($emails); - $n = 0; - foreach ($emails as $email) - { - $end = (++$n == $count) ? '' : ','; - $sql .= $DB->quote($email) . $end; - } - $sql .= ")"; - $ldap_form = true; - } - else if (isset($_POST['_email'])) - $sql .= "AND email = " . $DB->quote(get_input_value('_email', RCUBE_INPUT_POST)); - - $sql_result = $DB->query($sql); - + $existing = $CONTACTS->search('email', $a_record['email'], false); + // show warning message - if ($DB->num_rows($sql_result)) - { - show_message('contactexists', 'warning'); - - if ($ldap_form) - rcmail_overwrite_action('ldappublicsearch'); - else - rcmail_overwrite_action('add'); - + if ($existing->count) + { + $OUTPUT->show_message('contactexists', 'warning'); + rcmail_overwrite_action('add'); return; - } + } - if ($ldap_form) - { - $n = 0; - foreach ($emails as $email) - { - $DB->query("INSERT INTO $contacts_table - (user_id, name, email) - VALUES ({$_SESSION['user_id']}," . $DB->quote($names[$n++]) . "," . - $DB->quote($email) . ")"); - $insert_id[] = $DB->insert_id(); - } - } - else - { - foreach ($a_save_cols as $col) - { - $fname = '_'.$col; - if (!isset($_POST[$fname])) - continue; - - $a_insert_cols[] = $col; - $a_insert_values[] = $DB->quote(get_input_value($fname, RCUBE_INPUT_POST)); - } - - if (sizeof($a_insert_cols)) - { - $DB->query("INSERT INTO $contacts_table - (user_id, changed, del, ".join(', ', $a_insert_cols).") - VALUES (?, ".$DB->now().", 0, ".join(', ', $a_insert_values).")", - $_SESSION['user_id']); - - $insert_id = $DB->insert_id(get_sequence_name('contacts')); - } - } - - if ($insert_id) + // insert record and send response + if ($insert_id = $CONTACTS->insert($a_record)) + { + if ($_framed) { - if (!$ldap_form) - { - if ($_framed) - { - // add contact row or jump to the page where it should appear - $commands = sprintf("if(parent.%s)parent.", $JS_OBJECT_NAME); - $sql_result = $DB->query("SELECT * FROM $contacts_table - WHERE contact_id=? - AND user_id=?", - $insert_id, - $_SESSION['user_id']); - $commands .= rcmail_js_contacts_list($sql_result, $JS_OBJECT_NAME); - - $commands .= sprintf("if(parent.%s)parent.%s.contact_list.select('%d');\n", - $JS_OBJECT_NAME, - $JS_OBJECT_NAME, - $insert_id); - - // update record count display - $commands .= sprintf("if(parent.%s)parent.%s.set_rowcount('%s');\n", - $JS_OBJECT_NAME, - $JS_OBJECT_NAME, - rcmail_get_rowcount_text()); - - $OUTPUT->add_script($commands); - } - - // show confirmation - show_message('successfullysaved', 'confirmation'); - $_GET['_cid'] = $insert_id; - } - else - { // add contact row or jump to the page where it should appear - $commands = ''; - foreach ($insert_id as $id) - { - $sql_result = $DB->query("SELECT * FROM $contacts_table - WHERE contact_id = $id - AND user_id = {$_SESSION['user_id']}"); - - $commands .= sprintf("if(parent.%s)parent.", $JS_OBJECT_NAME); - $commands .= rcmail_js_contacts_list($sql_result, $JS_OBJECT_NAME); - $last_id = $id; - } + $CONTACTS->reset(); + $result = $CONTACTS->search($CONTACTS->primary_key, $insert_id); - // display the last insert id - $commands .= sprintf("if(parent.%s)parent.%s.contact_list.select('%d');\n", - $JS_OBJECT_NAME, - $JS_OBJECT_NAME, - $last_id); + rcmail_js_contacts_list($result, 'parent.'); + $OUTPUT->command('parent.contact_list.select', $insert_id); // update record count display - $commands .= sprintf("if(parent.%s)parent.%s.set_rowcount('%s');\n", - $JS_OBJECT_NAME, - $JS_OBJECT_NAME, - rcmail_get_rowcount_text()); - - $OUTPUT->add_script($commands); - rcmail_overwrite_action('ldappublicsearch'); - } + $CONTACTS->reset(); + $OUTPUT->command('parent.set_rowcount', rcmail_get_rowcount_text()); + } // show confirmation - show_message('successfullysaved', 'confirmation'); + $OUTPUT->show_message('successfullysaved', 'confirmation'); rcmail_overwrite_action('show'); - } + $_GET['_cid'] = $insert_id; + } else - { + { // show error message - show_message('errorsaving', 'error'); + $OUTPUT->show_message('errorsaving', 'error'); rcmail_overwrite_action('add'); - } } +} ?> diff --git a/program/steps/addressbook/search.inc b/program/steps/addressbook/search.inc new file mode 100644 index 000000000..01233a0bd --- /dev/null +++ b/program/steps/addressbook/search.inc @@ -0,0 +1,53 @@ +<?php + +/* + +-----------------------------------------------------------------------+ + | program/steps/addressbook/search.inc | + | | + | This file is part of the RoundCube Webmail client | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | + | Licensed under the GNU GPL | + | | + | PURPOSE: | + | Search step for address book contacts | + | | + +-----------------------------------------------------------------------+ + | Author: Thomas Bruederli <roundcube@gmail.com> | + +-----------------------------------------------------------------------+ + + $Id: search.inc 456 2007-01-10 12:34:33Z thomasb $ + +*/ + +$CONTACTS->set_page(1); +$_SESSION['page'] = 1; + +$search = trim(get_input_value('_q', RCUBE_INPUT_GET)); +$search_request = md5('addr'.$search); + +// get contacts for this user +$result = $CONTACTS->search(array('name','email'), $search); + +if ($result->count > 0) +{ + // save search settings in session + $_SESSION['search'][$search_request] = $CONTACTS->get_search_set(); + + // create javascript list + rcmail_js_contacts_list($result); +} +else +{ + $OUTPUT->show_message('nocontactsfound', 'warning'); + $search_request = -1; +} + +// update message count display +$OUTPUT->set_env('search_request', $search_request); +$OUTPUT->set_env('pagecount', ceil($result->count / $CONTACTS->page_size)); +$OUTPUT->command('set_rowcount', rcmail_get_rowcount_text()); + +// send response +$OUTPUT->send(); + +?>
\ No newline at end of file diff --git a/program/steps/addressbook/show.inc b/program/steps/addressbook/show.inc index 960ea1c45..75f1e7452 100644 --- a/program/steps/addressbook/show.inc +++ b/program/steps/addressbook/show.inc @@ -5,7 +5,7 @@ | program/steps/addressbook/show.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -20,35 +20,25 @@ */ -if ($_GET['_cid'] || $_POST['_cid']) - { - $cid = $_POST['_cid'] ? $_POST['_cid'] : $_GET['_cid']; - $DB->query("SELECT * FROM ".get_table_name('contacts')." - WHERE contact_id=? - AND user_id=? - AND del<>1", - $cid, - $_SESSION['user_id']); - - $CONTACT_RECORD = $DB->fetch_assoc(); - - if (is_array($CONTACT_RECORD)) - $OUTPUT->add_script(sprintf("%s.set_env('cid', '%s');", $JS_OBJECT_NAME, $CONTACT_RECORD['contact_id'])); - } - +// read contact record +if (($cid = get_input_value('_cid', RCUBE_INPUT_GPC)) && ($record = $CONTACTS->get_record($cid, true))) + $OUTPUT->set_env('cid', $record['ID']); function rcmail_contact_details($attrib) { - global $CONTACT_RECORD, $JS_OBJECT_NAME; + global $CONTACTS, $OUTPUT; - if (!$CONTACT_RECORD) - return show_message('contactnotfound'); + // check if we have a valid result + if (!(($result = $CONTACTS->get_result()) && ($record = $result->first()))) + { + $OUTPUT->show_message('contactnotfound'); + return false; + } // a specific part is requested if ($attrib['part']) - return rep_specialchars_output($CONTACT_RECORD[$attrib['part']]); - + return Q($record[$attrib['part']]); // return the complete address record as table $out = "<table>\n\n"; @@ -56,25 +46,28 @@ function rcmail_contact_details($attrib) $a_show_cols = array('name', 'firstname', 'surname', 'email'); foreach ($a_show_cols as $col) { - if ($col=='email' && $CONTACT_RECORD[$col]) - $value = sprintf('<a href="#compose" onclick="%s.command(\'compose\', %d)" title="%s">%s</a>', - $JS_OBJECT_NAME, - $CONTACT_RECORD['contact_id'], - rcube_label('composeto'), - $CONTACT_RECORD[$col]); + if ($col=='email' && !empty($record[$col])) + $value = sprintf( + '<a href="#compose" onclick="%s.command(\'compose\', \'%s\')" title="%s">%s</a>', + JS_OBJECT_NAME, + JQ($record[$col]), + rcube_label('composeto'), + Q($record[$col])); else - $value = rep_specialchars_output($CONTACT_RECORD[$col]); + $value = Q($record[$col]); - $title = rcube_label($col); - $out .= sprintf("<tr><td class=\"title\">%s</td><td>%s</td></tr>\n", $title, $value); + $out .= sprintf("<tr><td class=\"title\">%s</td><td>%s</td></tr>\n", + Q(rcube_label($col)), + $value); } - - + $out .= "\n</table>"; return $out; } -parse_template('showcontact'); +//$OUTPUT->framed = $_framed; +$OUTPUT->add_handler('contactdetails', 'rcmail_contact_details'); +$OUTPUT->send('showcontact'); ?>
\ No newline at end of file diff --git a/program/steps/error.inc b/program/steps/error.inc index 2eb50eb7b..dd533060a 100644 --- a/program/steps/error.inc +++ b/program/steps/error.inc @@ -64,7 +64,7 @@ EOF; } // database connection error -else if ($ERROR_CODE==0x01f4) +else if ($ERROR_CODE==603) { $__error_title = "DATABASE ERROR: CONNECTION FAILED!"; $__error_text = <<<EOF diff --git a/program/steps/mail/addcontact.inc b/program/steps/mail/addcontact.inc index b040581aa..484b0d4ba 100644 --- a/program/steps/mail/addcontact.inc +++ b/program/steps/mail/addcontact.inc @@ -5,7 +5,7 @@ | program/steps/mail/addcontact.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -19,49 +19,37 @@ */ -$REMOTE_REQUEST = TRUE; +require_once('include/rcube_contacts.inc'); -if (!empty($_GET['_address'])) - { - $contact_arr = $IMAP->decode_address_list(get_input_value('_address', RCUBE_INPUT_GET, TRUE)); - if (sizeof($contact_arr)) - { - $contact = $contact_arr[1]; - - if ($contact['mailto']) - $sql_result = $DB->query("SELECT 1 FROM ".get_table_name('contacts')." - WHERE user_id=? - AND email=? - AND del<>1", - $_SESSION['user_id'],$contact['mailto']); - - // contact entry with this mail address exists - if ($sql_result && $DB->num_rows($sql_result)) - $existing_contact = TRUE; - - else if ($contact['mailto']) - { - $DB->query("INSERT INTO ".get_table_name('contacts')." - (user_id, changed, del, name, email) - VALUES (?, ".$DB->now().", 0, ?, ?)", - $_SESSION['user_id'], - $contact['name'], - $contact['mailto']); +$done = false; - $added = $DB->insert_id(get_sequence_name('contacts')); - } - } - - if ($added) - $commands = show_message('addedsuccessfully', 'confirmation'); - else if ($existing_contact) - $commands = show_message('contactexists', 'warning'); +if (!empty($_POST['_address'])) +{ + $CONTACTS = new rcube_contacts($DB, $_SESSION['user_id']); + $contact_arr = $IMAP->decode_address_list(get_input_value('_address', RCUBE_INPUT_POST, true), 1, false); + + if (!empty($contact_arr[1]['mailto'])) + { + $contact = array( + 'email' => $contact_arr[1]['mailto'], + 'name' => $contact_arr[1]['name'] + ); + + // use email address part for name + if (empty($contact['name']) || $contact['name'] == $contact['email']) + $contact['name'] = ucfirst(preg_replace('/[\.\-]/', ' ', substr($contact['email'], 0, strpos($contact['email'], '@')))); + + // check for existing contacts + $existing = $CONTACTS->search('email', $contact['email'], false); + if ($done = $existing->count) + $OUTPUT->show_message('contactexists', 'warning'); + else if ($done = $CONTACTS->insert($contact)) + $OUTPUT->show_message('addedsuccessfully', 'confirmation'); } +} +if (!$done) + $OUTPUT->show_message('errorsavingcontact', 'warning'); -if (!$commands) - $commands = show_message('errorsavingcontact', 'warning'); - -rcube_remote_response($commands); -exit; +$OUTPUT->send(); ?>
\ No newline at end of file diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc index ca35725ea..119d481ab 100644 --- a/program/steps/mail/check_recent.inc +++ b/program/steps/mail/check_recent.inc @@ -5,7 +5,7 @@ | program/steps/mail/check_recent.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -19,8 +19,6 @@ */ -$REMOTE_REQUEST = TRUE; - $a_mailboxes = $IMAP->list_mailboxes(); foreach ($a_mailboxes as $mbox_name) @@ -32,10 +30,10 @@ foreach ($a_mailboxes as $mbox_name) $count = $IMAP->messagecount(NULL, 'ALL', TRUE); $unread_count = $IMAP->messagecount(NULL, 'UNSEEN', TRUE); - $commands .= sprintf("this.set_unread_count('%s', %d);\n", addslashes($mbox_name), $unread_count); - $commands .= sprintf("this.set_env('messagecount', %d);\n", $count); - $commands .= sprintf("this.set_rowcount('%s');\n", rcmail_get_messagecount_text($count)); - $commands .= sprintf("this.set_quota('%s');\n", $IMAP->get_quota()); + $OUTPUT->set_env('messagecount', $count); + $OUTPUT->command('set_unread_count', $mbox_name, $unread_count); + $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text()); + $OUTPUT->command('set_quota', $IMAP->get_quota()); // add new message headers to list $a_headers = array(); @@ -46,15 +44,16 @@ foreach ($a_mailboxes as $mbox_name) $a_headers[] = $header; } - $commands .= rcmail_js_message_list($a_headers, TRUE); + rcmail_js_message_list($a_headers, TRUE); } } else { if ($IMAP->messagecount($mbox_name, 'RECENT')) - $commands .= sprintf("this.set_unread_count('%s', %d);\n", addslashes($mbox_name), $IMAP->messagecount($mbox_name, 'UNSEEN')); + $OUTPUT->command('set_unread_count', $mbox_name, $IMAP->messagecount($mbox_name, 'UNSEEN')); } } -rcube_remote_response($commands); +$OUTPUT->send(); + ?> diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index 24057a224..4e73b4ba1 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -36,8 +36,8 @@ if ($_action=='remove-attachment' && preg_match('/^rcmfile([0-9]+)$/', $_GET['_f { @unlink($_SESSION['compose']['attachments'][$id]['path']); $_SESSION['compose']['attachments'][$id] = NULL; - $commands = sprintf("parent.%s.remove_from_attachment_list('rcmfile%d');\n", $JS_OBJECT_NAME, $id); - rcube_remote_response($commands); + $OUTPUT->command('remove_from_attachment_list', "rcmfile$id"); + $OUTPUT->send(); exit; } } @@ -61,7 +61,7 @@ if (!is_array($_SESSION['compose']) || $_SESSION['compose']['id'] != get_input_v rcube_add_label('nosubject', 'norecipientwarning', 'nosubjectwarning', 'nobodywarning', 'notsentwarning', 'savingmessage', 'sendingmessage', 'messagesaved', 'converting'); // add config parameter to client script -$OUTPUT->add_script(sprintf("%s.set_env('draft_autosave', %d);", $JS_OBJECT_NAME, !empty($CONFIG['drafts_mbox']) ? $CONFIG['draft_autosave'] : 0)); +$OUTPUT->set_env('draft_autosave', !empty($CONFIG['drafts_mbox']) ? $CONFIG['draft_autosave'] : 0); // get reference message and set compose mode @@ -125,24 +125,10 @@ function rcmail_compose_headers($attrib) case 'to': $fname = '_to'; $header = 'to'; - - // we have contact id's as get parameters - if (!empty($_GET['_to']) && preg_match('/^[0-9]+(,[0-9]+)*$/', $_GET['_to'])) - { - $a_recipients = array(); - $sql_result = $DB->query("SELECT name, email - FROM ".get_table_name('contacts')." - WHERE user_id=? - AND del<>1 - AND contact_id IN (".$_GET['_to'].")", - $_SESSION['user_id']); - - while ($sql_arr = $DB->fetch_assoc($sql_result)) - $a_recipients[] = format_email_recipient($sql_arr['email'], $sql_arr['name']); - - if (sizeof($a_recipients)) - $fvalue = join(', ', $a_recipients); - } + + // we have a set of recipients stored is session + if (($mailto_id = get_input_value('_mailto', RCUBE_INPUT_GET)) && $_SESSION['mailto'][$mailto_id]) + $fvalue = $_SESSION['mailto'][$mailto_id]; else if (!empty($_GET['_to'])) $fvalue = get_input_value('_to', RCUBE_INPUT_GET); @@ -246,7 +232,7 @@ function rcmail_compose_headers($attrib) function rcmail_compose_header_from($attrib) { - global $IMAP, $MESSAGE, $DB, $OUTPUT, $JS_OBJECT_NAME, $compose_mode; + global $IMAP, $MESSAGE, $DB, $OUTPUT, $compose_mode; // pass the following attributes to the form class $field_attrib = array('name' => '_from'); @@ -291,7 +277,7 @@ function rcmail_compose_header_from($attrib) $from_id = 0; $a_signatures = array(); - $field_attrib['onchange'] = "$JS_OBJECT_NAME.change_identity(this)"; + $field_attrib['onchange'] = JS_OBJECT_NAME.".change_identity(this)"; $select_from = new select($field_attrib); while ($sql_arr = $DB->fetch_assoc($sql_result)) @@ -330,7 +316,7 @@ function rcmail_compose_header_from($attrib) $out = $select_from->show($from_id); // add signatures to client - $OUTPUT->add_script(sprintf("%s.set_env('signatures', %s);", $JS_OBJECT_NAME, array2js($a_signatures))); + $OUTPUT->set_env('signatures', $a_signatures); } else { @@ -348,7 +334,7 @@ function rcmail_compose_header_from($attrib) function rcmail_compose_body($attrib) { - global $CONFIG, $OUTPUT, $MESSAGE, $JS_OBJECT_NAME, $compose_mode; + global $CONFIG, $OUTPUT, $MESSAGE, $compose_mode; list($form_start, $form_end) = get_form_tags($attrib); unset($attrib['form']); @@ -470,7 +456,7 @@ function rcmail_compose_body($attrib) $lang_set, substr($_SESSION['user_lang'], 0, 2), $attrib['id'], - $JS_OBJECT_NAME), 'foot'); + JS_OBJECT_NAME), 'foot'); rcube_add_label('checking'); } @@ -666,7 +652,7 @@ function rcmail_compose_subject($attrib) function rcmail_compose_attachment_list($attrib) { - global $OUTPUT, $JS_OBJECT_NAME, $CONFIG; + global $OUTPUT, $CONFIG; // add ID if not given if (!$attrib['id']) @@ -690,14 +676,14 @@ function rcmail_compose_attachment_list($attrib) foreach ($_SESSION['compose']['attachments'] as $id => $a_prop) $out .= sprintf('<li id="rcmfile%d"><a href="#delete" onclick="return %s.command(\'remove-attachment\',\'rcmfile%d\', this)" title="%s">%s</a>%s</li>', $id, - $JS_OBJECT_NAME, + JS_OBJECT_NAME, $id, Q(rcube_label('delete')), $button, Q($a_prop['name'])); } - $OUTPUT->add_script(sprintf("%s.gui_object('attachmentlist', '%s');", $JS_OBJECT_NAME, $attrib['id'])); + $OUTPUT->add_gui_object('attachmentlist', $attrib['id']); $out .= '</ul>'; return $out; @@ -707,7 +693,7 @@ function rcmail_compose_attachment_list($attrib) function rcmail_compose_attachment_form($attrib) { - global $OUTPUT, $JS_OBJECT_NAME, $SESS_HIDDEN_FIELD; + global $OUTPUT, $SESS_HIDDEN_FIELD; // add ID if not given if (!$attrib['id']) @@ -718,6 +704,7 @@ function rcmail_compose_attachment_form($attrib) $input_field = rcmail_compose_attachment_field(array()); $label_send = rcube_label('upload'); $label_close = rcube_label('close'); + $js_instance = JS_OBJECT_NAME; $out = <<<EOF <div$attrib_str> @@ -725,13 +712,13 @@ function rcmail_compose_attachment_form($attrib) $SESS_HIDDEN_FIELD $input_field<br /> <input type="button" value="$label_close" class="button" onclick="document.getElementById('$attrib[id]').style.visibility='hidden'" /> -<input type="button" value="$label_send" class="button" onclick="$JS_OBJECT_NAME.command('send-attachment', this.form)" /> +<input type="button" value="$label_send" class="button" onclick="$js_instance.command('send-attachment', this.form)" /> </form> </div> EOF; - $OUTPUT->add_script(sprintf("%s.gui_object('uploadbox', '%s');", $JS_OBJECT_NAME, $attrib['id'])); + $OUTPUT->add_gui_object('uploadbox', $attrib['id']); return $out; } @@ -829,7 +816,7 @@ function rcmail_editor_selector($attrib) $attrib['id'] = '_' . $value; $rb = new radiobutton($attrib); - $selector .= sprintf("<td>%s</td><td class=\"title\"><label for=\"%s\">%s</label></td>", + $selector .= sprintf("%s<label for=\"%s\">%s</label>", $rb->show($value), $attrib['id'], rcube_label($text)); @@ -841,7 +828,7 @@ function rcmail_editor_selector($attrib) function get_form_tags($attrib) { - global $CONFIG, $OUTPUT, $JS_OBJECT_NAME, $MESSAGE_FORM, $SESS_HIDDEN_FIELD; + global $CONFIG, $OUTPUT, $MESSAGE_FORM, $SESS_HIDDEN_FIELD; $form_start = ''; if (!strlen($MESSAGE_FORM)) @@ -858,7 +845,7 @@ function get_form_tags($attrib) $form_name = !empty($attrib['form']) ? $attrib['form'] : 'form'; if (!strlen($MESSAGE_FORM)) - $OUTPUT->add_script("$JS_OBJECT_NAME.gui_object('messageform', '$form_name');"); + $OUTPUT->add_gui_object('messageform', $form_name); $MESSAGE_FORM = $form_name; @@ -866,38 +853,35 @@ function get_form_tags($attrib) } -function format_email_recipient($email, $name='') - { - if ($name && $name != $email) - return sprintf('%s <%s>', strpos($name, ",") ? '"'.$name.'"' : $name, $email); - else - return $email; - } - - -function rcmail_charset_pulldown($selected='ISO-8859-1') - { - $select = new select(); - - - return $select->show($selected); - } +// register UI objects +$OUTPUT->add_handlers(array( + 'composeheaders' => 'rcmail_compose_headers', + 'composesubject' => 'rcmail_compose_subject', + 'composebody' => 'rcmail_compose_body', + 'composeattachmentlist' => 'rcmail_compose_attachment_list', + 'composeattachmentform' => 'rcmail_compose_attachment_form', + 'composeattachment' => 'rcmail_compose_attachment_field', + 'priorityselector' => 'rcmail_priority_selector', + 'editorselector' => 'rcmail_editor_selector', + 'receiptcheckbox' => 'rcmail_receipt_checkbox', +)); /****** get contacts for this user and add them to client scripts ********/ -$sql_result = $DB->query("SELECT name, email - FROM ".get_table_name('contacts')." WHERE user_id=? - AND del<>1",$_SESSION['user_id']); +require_once('include/rcube_contacts.inc'); + +$CONTACTS = new rcube_contacts($DB, $_SESSION['user_id']); +$CONTACTS->set_pagesize(1000); -if ($DB->num_rows($sql_result)) +if ($result = $CONTACTS->list_records()) { $a_contacts = array(); - while ($sql_arr = $DB->fetch_assoc($sql_result)) + while ($sql_arr = $result->iterate()) if ($sql_arr['email']) $a_contacts[] = format_email_recipient($sql_arr['email'], JQ($sql_arr['name'])); - $OUTPUT->add_script(sprintf("$JS_OBJECT_NAME.set_env('contacts', %s);", array2js($a_contacts))); + $OUTPUT->set_env('contacts', $a_contacts); } diff --git a/program/steps/mail/folders.inc b/program/steps/mail/folders.inc index 1b7007c39..a97057e2c 100644 --- a/program/steps/mail/folders.inc +++ b/program/steps/mail/folders.inc @@ -18,44 +18,40 @@ $Id$ */ -$REMOTE_REQUEST = TRUE; $mbox_name = $IMAP->get_mailbox_name(); - // send EXPUNGE command if ($_action=='expunge') - { +{ $success = $IMAP->expunge(get_input_value('_mbox', RCUBE_INPUT_GET)); // reload message list if current mailbox if ($success && !empty($_GET['_reload'])) - { - rcube_remote_response('this.message_list.clear();', TRUE); + { + $OUTPUT->command('message_list.clear'); $_action = 'list'; return; - } + } else $commands = "// expunged: $success\n"; - } +} // clear mailbox else if ($_action=='purge') - { +{ $success = $IMAP->clear_mailbox(get_input_value('_mbox', RCUBE_INPUT_GET)); if ($success && !empty($_GET['_reload'])) - { - $commands = "this.message_list.clear();\n"; - $commands .= "this.set_env('messagecount', 0);\n"; - $commands .= "this.set_env('pagecount', 0);\n"; - $commands .= sprintf("this.set_rowcount('%s');\n", rcmail_get_messagecount_text()); - $commands .= sprintf("this.set_unread_count('%s', 0);\n", addslashes($mbox_name)); - } + { + $OUTPUT->set_env('messagecount', 0); + $OUTPUT->set_env('pagecount', 0); + $OUTPUT->command('message_list.clear'); + $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text()); + $OUTPUT->command('set_unread_count', $mbox_name, 0); + } else $commands = "// purged: $success"; - } - - +} -rcube_remote_response($commands); +$OUTPUT->send($commands); ?>
\ No newline at end of file diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index a0bdf0995..7416fb5d4 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -5,7 +5,7 @@ | program/steps/mail/func.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -25,9 +25,8 @@ require_once('lib/enriched.inc'); $EMAIL_ADDRESS_PATTERN = '/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/i'; -if (empty($_SESSION['mbox'])){ +if (empty($_SESSION['mbox'])) $_SESSION['mbox'] = $IMAP->get_mailbox_name(); -} // set imap properties and session vars if ($mbox = get_input_value('_mbox', RCUBE_INPUT_GPC)) @@ -63,21 +62,24 @@ if (strlen($_GET['_uid'])) // set current mailbox in client environment -$OUTPUT->add_script(sprintf("%s.set_env('mailbox', '%s');", $JS_OBJECT_NAME, $IMAP->get_mailbox_name())); +$OUTPUT->set_env('mailbox', $IMAP->get_mailbox_name()); +//$OUTPUT->set_pagetitle(rcube_charset_convert($IMAP->get_mailbox_name(), 'UTF-7', 'UTF-8')); if ($CONFIG['trash_mbox']) - $OUTPUT->add_script(sprintf("%s.set_env('trash_mailbox', '%s');", $JS_OBJECT_NAME, $CONFIG['trash_mbox'])); - + $OUTPUT->set_env('trash_mailbox', $CONFIG['trash_mbox']); if ($CONFIG['drafts_mbox']) - $OUTPUT->add_script(sprintf("%s.set_env('drafts_mailbox', '%s');", $JS_OBJECT_NAME, $CONFIG['drafts_mbox'])); - + $OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']); if ($CONFIG['junk_mbox']) - $OUTPUT->add_script(sprintf("%s.set_env('junk_mailbox', '%s');", $JS_OBJECT_NAME, $CONFIG['junk_mbox'])); + $OUTPUT->set_env('junk_mailbox', $CONFIG['junk_mbox']); + +if (!$OUTPUT->ajax_call) + rcube_add_label('checkingmail'); + // return the mailboxlist in HTML function rcmail_mailbox_list($attrib) { - global $IMAP, $CONFIG, $OUTPUT, $JS_OBJECT_NAME, $COMM_PATH; + global $IMAP, $CONFIG, $OUTPUT, $COMM_PATH; static $s_added_script = FALSE; static $a_mailboxes; @@ -136,7 +138,7 @@ function rcmail_mailbox_list($attrib) if ($type=='ul') - $OUTPUT->add_script(sprintf("%s.gui_object('mailboxlist', '%s');", $JS_OBJECT_NAME, $attrib['id'])); + $OUTPUT->add_gui_object('mailboxlist', $attrib['id']); return $out . "</$type>"; } @@ -176,7 +178,7 @@ function rcmail_build_folder_tree(&$arrFolders, $folder, $delm='/', $path='') // return html for a structured list <ul> for the mailbox tree function rcmail_render_folder_tree_html(&$arrFolders, &$special, &$mbox_name, $maxlength, $nestLevel=0) { - global $JS_OBJECT_NAME, $COMM_PATH, $IMAP, $CONFIG, $OUTPUT; + global $COMM_PATH, $IMAP, $CONFIG, $OUTPUT; $idx = 0; $out = ''; @@ -207,7 +209,8 @@ function rcmail_render_folder_tree_html(&$arrFolders, &$special, &$mbox_name, $m $foldername .= sprintf(' (%d)', $unread_count); // make folder name safe for ids and class names - $folder_css = $class_name = preg_replace('/[^a-z0-9\-_]/', '', $folder_lc); + $folder_id = preg_replace('/[^A-Za-z0-9\-_]/', '', $folder['id']); + $class_name = preg_replace('/[^a-z0-9\-_]/', '', $folder_lc); // set special class for Sent, Drafts, Trash and Junk if ($folder['id']==$CONFIG['sent_mbox']) @@ -220,25 +223,24 @@ function rcmail_render_folder_tree_html(&$arrFolders, &$special, &$mbox_name, $m $class_name = 'junk'; $js_name = htmlspecialchars(JQ($folder['id'])); - $out .= sprintf('<li id="rcmbx%s" class="mailbox %s %s%s%s"><a href="%s&_mbox=%s"'. - ' onclick="return %s.command(\'list\',\'%s\')"'. - ' onmouseover="return %s.focus_mailbox(\'%s\')"' . - ' onmouseout="return %s.unfocus_mailbox(\'%s\')"' . - ' onmouseup="return %s.mbox_mouse_up(\'%s\')"%s>%s</a>', - $folder_css, + $out .= sprintf('<li id="rcmli%s" class="mailbox %s %s%s%s"><a href="%s"'. + ' onclick="return %s.command(\'list\',\'%s\',this)"'. + ' onmouseover="return %s.focus_folder(\'%s\')"' . + ' onmouseout="return %s.unfocus_folder(\'%s\')"' . + ' onmouseup="return %s.folder_mouse_up(\'%s\')"%s>%s</a>', + $folder_id, $class_name, $zebra_class, $unread_count ? ' unread' : '', $folder['id']==$mbox_name ? ' selected' : '', - $COMM_PATH, - urlencode($folder['id']), - $JS_OBJECT_NAME, + Q(rcmail_self_url('', array('_mbox' => $folder['id']))), + JS_OBJECT_NAME, $js_name, - $JS_OBJECT_NAME, + JS_OBJECT_NAME, $js_name, - $JS_OBJECT_NAME, + JS_OBJECT_NAME, $js_name, - $JS_OBJECT_NAME, + JS_OBJECT_NAME, $js_name, $title, Q($foldername)); @@ -293,7 +295,7 @@ function rcmail_render_folder_tree_select(&$arrFolders, &$special, &$mbox_name, // return the message list as HTML table function rcmail_message_list($attrib) { - global $IMAP, $CONFIG, $COMM_PATH, $OUTPUT, $JS_OBJECT_NAME; + global $IMAP, $CONFIG, $COMM_PATH, $OUTPUT; $skin_path = $CONFIG['skin_path']; $image_tag = '<img src="%s%s" alt="%s" border="0" />'; @@ -358,28 +360,30 @@ function rcmail_message_list($attrib) // asc link if (!empty($attrib['sortascbutton'])) { - $sort .= rcube_button(array('command' => 'sort', - 'prop' => $col.'_ASC', - 'image' => $attrib['sortascbutton'], - 'align' => 'absmiddle', - 'title' => 'sortasc')); + $sort .= $OUTPUT->button(array( + 'command' => 'sort', + 'prop' => $col.'_ASC', + 'image' => $attrib['sortascbutton'], + 'align' => 'absmiddle', + 'title' => 'sortasc')); } // desc link if (!empty($attrib['sortdescbutton'])) { - $sort .= rcube_button(array('command' => 'sort', - 'prop' => $col.'_DESC', - 'image' => $attrib['sortdescbutton'], - 'align' => 'absmiddle', - 'title' => 'sortdesc')); + $sort .= $OUTPUT->button(array( + 'command' => 'sort', + 'prop' => $col.'_DESC', + 'image' => $attrib['sortdescbutton'], + 'align' => 'absmiddle', + 'title' => 'sortdesc')); } } // just add a link tag to the header else { $col_name = sprintf('<a href="./#sort" onclick="return %s.command(\'sort\',\'%s\',this)" title="%s">%s</a>', - $JS_OBJECT_NAME, + JS_OBJECT_NAME, $col, rcube_label('sortby'), $col_name); @@ -430,7 +434,7 @@ function rcmail_message_list($attrib) else if ($attrib['messageicon']) $message_icon = $attrib['messageicon']; - // set attachment icon + // set attachment icon if ($attrib['attachmenticon'] && preg_match("/multipart\/[mr]/i", $header->ctype)) $attach_icon = $attrib['attachmenticon']; @@ -441,7 +445,7 @@ function rcmail_message_list($attrib) $zebra_class); $out .= sprintf("<td class=\"icon\">%s</td>\n", $message_icon ? sprintf($image_tag, $skin_path, $message_icon, '') : ''); - + // format each col foreach ($a_show_cols as $col) { @@ -449,15 +453,13 @@ function rcmail_message_list($attrib) $cont = Q(rcmail_address_string($header->$col, 3, $attrib['addicon']), 'show'); else if ($col=='subject') { - $cont = Q($IMAP->decode_header($header->$col)); - if (!$cont) $cont = Q(rcube_label('nosubject')); - // firefox/mozilla temporary workaround to pad subject with content so that whitespace in rows responds to drag+drop - $cont .= '<img src="./program/blank.gif" height="5" width="1000" alt="" />'; + $cont = Q(rcube_imap::decode_mime_string($header->$col, $header->charset)); + if (empty($cont)) $cont = Q(rcube_label('nosubject')); } else if ($col=='size') $cont = show_bytes($header->$col); else if ($col=='date') - $cont = format_date($header->date); //date('m.d.Y G:i:s', strtotime($header->date)); + $cont = format_date($header->date); else $cont = Q($header->$col); @@ -478,50 +480,46 @@ function rcmail_message_list($attrib) $message_count = $IMAP->messagecount(); // set client env - $javascript .= sprintf("%s.gui_object('mailcontframe', '%s');\n", $JS_OBJECT_NAME, 'mailcontframe'); - $javascript .= sprintf("%s.gui_object('messagelist', '%s');\n", $JS_OBJECT_NAME, $attrib['id']); - $javascript .= sprintf("%s.set_env('messagecount', %d);\n", $JS_OBJECT_NAME, $message_count); - $javascript .= sprintf("%s.set_env('current_page', %d);\n", $JS_OBJECT_NAME, $IMAP->list_page); - $javascript .= sprintf("%s.set_env('pagecount', %d);\n", $JS_OBJECT_NAME, ceil($message_count/$IMAP->page_size)); - $javascript .= sprintf("%s.set_env('sort_col', '%s');\n", $JS_OBJECT_NAME, $sort_col); - $javascript .= sprintf("%s.set_env('sort_order', '%s');\n", $JS_OBJECT_NAME, $sort_order); + $OUTPUT->add_gui_object('mailcontframe', 'mailcontframe'); + $OUTPUT->add_gui_object('messagelist', $attrib['id']); + $OUTPUT->set_env('messagecount', $message_count); + $OUTPUT->set_env('current_page', $IMAP->list_page); + $OUTPUT->set_env('pagecount', ceil($message_count/$IMAP->page_size)); + $OUTPUT->set_env('sort_col', $sort_col); + $OUTPUT->set_env('sort_order', $sort_order); if ($attrib['messageicon']) - $javascript .= sprintf("%s.set_env('messageicon', '%s%s');\n", $JS_OBJECT_NAME, $skin_path, $attrib['messageicon']); + $OUTPUT->set_env('messageicon', $skin_path . $attrib['messageicon']); if ($attrib['deletedicon']) - $javascript .= sprintf("%s.set_env('deletedicon', '%s%s');\n", $JS_OBJECT_NAME, $skin_path, $attrib['deletedicon']); + $OUTPUT->set_env('deletedicon', $skin_path . $attrib['deletedicon']); if ($attrib['unreadicon']) - $javascript .= sprintf("%s.set_env('unreadicon', '%s%s');\n", $JS_OBJECT_NAME, $skin_path, $attrib['unreadicon']); + $OUTPUT->set_env('unreadicon', $skin_path . $attrib['unreadicon']); if ($attrib['repliedicon']) - $javascript .= sprintf("%s.set_env('repliedicon', '%s%s');\n", $JS_OBJECT_NAME, $skin_path, $attrib['repliedicon']); + $OUTPUT->set_env('repliedicon', $skin_path . $attrib['repliedicon']); if ($attrib['attachmenticon']) - $javascript .= sprintf("%s.set_env('attachmenticon', '%s%s');\n", $JS_OBJECT_NAME, $skin_path, $attrib['attachmenticon']); - - $javascript .= sprintf("%s.set_env('messages', %s);", $JS_OBJECT_NAME, array2js($a_js_message_arr)); + $OUTPUT->set_env('attachmenticon', $skin_path . $attrib['attachmenticon']); + + $OUTPUT->set_env('messages', array2js($a_js_message_arr)); - $OUTPUT->add_script($javascript); $OUTPUT->include_script('list.js'); return $out; } - - // return javascript commands to add rows to the message list function rcmail_js_message_list($a_headers, $insert_top=FALSE) { - global $CONFIG, $IMAP; + global $CONFIG, $IMAP, $OUTPUT; - $commands = ''; $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject'); // show 'to' instead of from in sent messages - if (($IMAP->get_mailbox_name()==$CONFIG['sent_mbox'] || $IMAP->get_mailbox_name()==$CONFIG['drafts_mbox']) - && ($f = array_search('from', $a_show_cols)) && !array_search('to', $a_show_cols)) + if (($IMAP->get_mailbox_name() == $CONFIG['sent_mbox'] || $IMAP->get_mailbox_name() == $CONFIG['drafts_mbox']) + && (($f = array_search('from', $a_show_cols)) !== false) && array_search('to', $a_show_cols) === false) $a_show_cols[$f] = 'to'; - $commands .= sprintf("this.set_message_coltypes(%s);\n", array2js($a_show_cols)); + $OUTPUT->command('set_message_coltypes', $a_show_cols); // loop through message headers for ($n=0; $a_headers[$n]; $n++) @@ -529,7 +527,7 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE) $header = $a_headers[$n]; $a_msg_cols = array(); $a_msg_flags = array(); - + // format each col; similar as in rcmail_message_list() foreach ($a_show_cols as $col) { @@ -537,13 +535,13 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE) $cont = Q(rcmail_address_string($header->$col, 3), 'show'); else if ($col=='subject') { - $cont = Q($IMAP->decode_header($header->$col)); + $cont = Q(rcube_imap::decode_mime_string($header->$col, $header->charset)); if (!$cont) $cont = Q(rcube_label('nosubject')); } else if ($col=='size') $cont = show_bytes($header->$col); else if ($col=='date') - $cont = format_date($header->date); //date('m.d.Y G:i:s', strtotime($header->date)); + $cont = format_date($header->date); else $cont = Q($header->$col); @@ -553,22 +551,20 @@ function rcmail_js_message_list($a_headers, $insert_top=FALSE) $a_msg_flags['deleted'] = $header->deleted ? 1 : 0; $a_msg_flags['unread'] = $header->seen ? 0 : 1; $a_msg_flags['replied'] = $header->answered ? 1 : 0; - $commands .= sprintf("this.add_message_row(%s, %s, %s, %b, %b);\n", - $header->uid, - array2js($a_msg_cols), - array2js($a_msg_flags), - preg_match("/multipart\/m/i", $header->ctype), - $insert_top); + $OUTPUT->command('add_message_row', + $header->uid, + $a_msg_cols, + $a_msg_flags, + preg_match("/multipart\/m/i", $header->ctype), + $insert_top); } - - return $commands; } // return an HTML iframe for loading mail content function rcmail_messagecontent_frame($attrib) { - global $OUTPUT, $JS_OBJECT_NAME; + global $OUTPUT; if (empty($attrib['id'])) $attrib['id'] = 'rcmailcontentwindow'; @@ -581,52 +577,21 @@ function rcmail_messagecontent_frame($attrib) $framename, $attrib_str); - $OUTPUT->add_script("$JS_OBJECT_NAME.set_env('contentframe', '$framename');"); + $OUTPUT->set_env('contentframe', $framename); + $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/blank.gif'); return $out; } -// return code for search function -function rcmail_search_form($attrib) - { - global $OUTPUT, $JS_OBJECT_NAME; - - // add some labels to client - rcube_add_label('searching'); - - $attrib['name'] = '_q'; - - if (empty($attrib['id'])) - $attrib['id'] = 'rcmqsearchbox'; - - $input_q = new textfield($attrib); - $out = $input_q->show(); - - $OUTPUT->add_script(sprintf("%s.gui_object('qsearchbox', '%s');", - $JS_OBJECT_NAME, - $attrib['id'])); - - // add form tag around text field - if (empty($attrib['form'])) - $out = sprintf('<form name="rcmqsearchform" action="./" '. - 'onsubmit="%s.command(\'search\');return false" style="display:inline;">%s</form>', - $JS_OBJECT_NAME, - $out); - - return $out; - } - function rcmail_messagecount_display($attrib) { - global $IMAP, $OUTPUT, $JS_OBJECT_NAME; + global $IMAP, $OUTPUT; if (!$attrib['id']) $attrib['id'] = 'rcmcountdisplay'; - $OUTPUT->add_script(sprintf("%s.gui_object('countdisplay', '%s');", - $JS_OBJECT_NAME, - $attrib['id'])); + $OUTPUT->add_gui_object('countdisplay', $attrib['id']); // allow the following attributes to be added to the <span> tag $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id')); @@ -641,12 +606,12 @@ function rcmail_messagecount_display($attrib) function rcmail_quota_display($attrib) { - global $OUTPUT, $JS_OBJECT_NAME, $COMM_PATH; + global $OUTPUT, $COMM_PATH; if (!$attrib['id']) $attrib['id'] = 'rcmquotadisplay'; - $OUTPUT->add_script(sprintf("%s.gui_object('quotadisplay', '%s');", $JS_OBJECT_NAME, $attrib['id'])); + $OUTPUT->add_gui_object('quotadisplay', $attrib['id']); // allow the following attributes to be added to the <span> tag $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id')); @@ -675,8 +640,7 @@ function rcmail_quota_content($display) if ($display == 'image' && function_exists('imagegif')) { $attrib = array('width' => 100, 'height' => 14); - $quota_text = sprintf('<img src="%s&_action=quotaimg&u=%s&q=%d&w=%d&h=%d" width="%d" height="%d" alt="%s" title="%s / %s" />', - $COMM_PATH, + $quota_text = sprintf('<img src="./bin/quotaimg.php?u=%s&q=%d&w=%d&h=%d" width="%d" height="%d" alt="%s" title="%s / %s" />', $quota['used'], $quota['total'], $attrib['width'], $attrib['height'], $attrib['width'], $attrib['height'], @@ -723,7 +687,7 @@ function rcmail_get_messagecount_text($count=NULL, $page=NULL) function rcmail_print_body($part, $safe=FALSE, $plain=FALSE) { - global $IMAP, $REMOTE_OBJECTS, $JS_OBJECT_NAME; + global $IMAP, $REMOTE_OBJECTS; $body = is_array($part->replaces) ? strtr($part->body, $part->replaces) : $part->body; @@ -795,7 +759,7 @@ function rcmail_print_body($part, $safe=FALSE, $plain=FALSE) $convert_replaces[] = "rcmail_str_replacement('\\1<a href=\"http://\\2\\3\" target=\"_blank\">\\2\\3</a>', \$replace_strings)"; $convert_patterns[] = '/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/ie'; - $convert_replaces[] = "rcmail_str_replacement('<a href=\"mailto:\\1\" onclick=\"return $JS_OBJECT_NAME.command(\'compose\',\'\\1\',this)\">\\1</a>', \$replace_strings)"; + $convert_replaces[] = "rcmail_str_replacement('<a href=\"mailto:\\1\" onclick=\"return ".JS_OBJECT_NAME.".command(\'compose\',\'\\1\',this)\">\\1</a>', \$replace_strings)"; if ($part->ctype_parameters['format'] != 'flowed') $body = wordwrap(trim($body), 80); @@ -1052,7 +1016,7 @@ function rcmail_message_headers($attrib, $headers=NULL) // get associative array of headers object if (!$headers) $headers = is_object($MESSAGE['headers']) ? get_object_vars($MESSAGE['headers']) : $MESSAGE['headers']; - + $header_count = 0; // allow the following attributes to be added to the <table> tag @@ -1072,7 +1036,7 @@ function rcmail_message_headers($attrib, $headers=NULL) else if (in_array($hkey, array('from', 'to', 'cc', 'bcc', 'reply-to'))) $header_value = Q(rcmail_address_string($headers[$hkey], NULL, $attrib['addicon']), 'show'); else - $header_value = Q($IMAP->decode_header($headers[$hkey])); + $header_value = Q(rcube_imap::decode_mime_string($headers[$hkey], $headers['charset'])); $out .= "\n<tr>\n"; $out .= '<td class="header-title">'.Q(rcube_label($hkey)).": </td>\n"; @@ -1089,7 +1053,7 @@ function rcmail_message_headers($attrib, $headers=NULL) function rcmail_message_body($attrib) { - global $CONFIG, $OUTPUT, $MESSAGE, $IMAP, $GET_URL, $REMOTE_OBJECTS, $JS_OBJECT_NAME; + global $CONFIG, $OUTPUT, $MESSAGE, $IMAP, $GET_URL, $REMOTE_OBJECTS; if (!is_array($MESSAGE['parts']) && !$MESSAGE['body']) return ''; @@ -1169,7 +1133,7 @@ function rcmail_message_body($attrib) // tell client that there are blocked remote objects if ($REMOTE_OBJECTS && !$safe_mode) - $OUTPUT->add_script(sprintf("%s.set_env('blockedobjects', true);", $JS_OBJECT_NAME)); + $OUTPUT->set_env('blockedobjects', true); $out .= "\n</div>"; return $out; @@ -1261,7 +1225,7 @@ function rcmail_alter_html_link($in) if (stristr((string)$attrib['href'], 'mailto:')) $attrib['onclick'] = sprintf("return %s.command('compose','%s',this)", - $GLOBALS['JS_OBJECT_NAME'], + JS_OBJECT_NAME, JQ(substr($attrib['href'], 7))); else if (!empty($attrib['href']) && $attrib['href']{0}!='#') $attrib['target'] = '_blank'; @@ -1383,7 +1347,7 @@ function rcmail_first_text_part($message_struct) // decode address string and re-format it as HTML links function rcmail_address_string($input, $max=NULL, $addicon=NULL) { - global $IMAP, $PRINT_MODE, $CONFIG, $OUTPUT, $JS_OBJECT_NAME, $EMAIL_ADDRESS_PATTERN; + global $IMAP, $PRINT_MODE, $CONFIG, $OUTPUT, $EMAIL_ADDRESS_PATTERN; $a_parts = $IMAP->decode_address_list($input); @@ -1403,14 +1367,14 @@ function rcmail_address_string($input, $max=NULL, $addicon=NULL) { $out .= sprintf('<a href="mailto:%s" onclick="return %s.command(\'compose\',\'%s\',this)" class="rcmContactAddress" title="%s">%s</a>', Q($part['mailto']), - $JS_OBJECT_NAME, + JS_OBJECT_NAME, JQ($part['mailto']), Q($part['mailto']), Q($part['name'])); if ($addicon) $out .= sprintf(' <a href="#add" onclick="return %s.command(\'add-contact\',\'%s\',this)" title="%s"><img src="%s%s" alt="add" border="0" /></a>', - $JS_OBJECT_NAME, + JS_OBJECT_NAME, urlencode($part['string']), rcube_label('addtoaddressbook'), $CONFIG['skin_path'], @@ -1500,6 +1464,20 @@ function rcmail_compose_cleanup() unset($_SESSION['compose']); } - - + + +// register UI objects +$OUTPUT->add_handlers(array( + 'mailboxlist' => 'rcmail_mailbox_list', + 'messages' => 'rcmail_message_list', + 'messagecountdisplay' => 'rcmail_messagecount_display', + 'quotadisplay' => 'rcmail_quota_display', + 'messageheaders' => 'rcmail_message_headers', + 'messagebody' => 'rcmail_message_body', + 'messagecontentframe' => 'rcmail_messagecontent_frame', + 'messagepartframe' => 'rcmail_message_part_frame', + 'messagepartcontrols' => 'rcmail_message_part_controls', + 'searchform' => 'rcmail_search_form' +)); + ?>
\ No newline at end of file diff --git a/program/steps/mail/getunread.inc b/program/steps/mail/getunread.inc index ed4a5fb77..e6b3843e4 100644 --- a/program/steps/mail/getunread.inc +++ b/program/steps/mail/getunread.inc @@ -19,18 +19,13 @@ */ -$REMOTE_REQUEST = TRUE; - $a_folders = $IMAP->list_mailboxes(); if (!empty($a_folders)) - { +{ foreach ($a_folders as $mbox_row) - { - $commands = sprintf("this.set_unread_count('%s', %d);\n", addslashes($mbox_row), $IMAP->messagecount($mbox_row, 'UNSEEN')); - rcube_remote_response($commands, TRUE); - } - } + $OUTPUT->command('set_unread_count', $mbox_row, $IMAP->messagecount($mbox_row, 'UNSEEN')); +} -exit; +$OUTPUT->send(); ?> diff --git a/program/steps/mail/list.inc b/program/steps/mail/list.inc index 6e0637441..162624c36 100644 --- a/program/steps/mail/list.inc +++ b/program/steps/mail/list.inc @@ -19,25 +19,23 @@ */ -$REMOTE_REQUEST = TRUE; $OUTPUT_TYPE = 'js'; - // is there a sort type for this request? if ($sort = get_input_value('_sort', RCUBE_INPUT_GET)) - { +{ // yes, so set the sort vars list($sort_col, $sort_order) = explode('_', $sort); // set session vars for sort (so next page and task switch know how to sort) $_SESSION['sort_col'] = $sort_col; $_SESSION['sort_order'] = $sort_order; - } +} else - { +{ // use session settings if set, defaults if not $sort_col = isset($_SESSION['sort_col']) ? $_SESSION['sort_col'] : $CONFIG['message_sort_col']; $sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order']; - } +} // fetch message headers @@ -48,22 +46,20 @@ $unseen = $IMAP->messagecount($mbox_name, 'UNSEEN', !empty($_GET['_refresh']) ? // update message count display $pages = ceil($count/$IMAP->page_size); -$commands = sprintf("this.set_env('messagecount', %d);\n", $count); -$commands .= sprintf("this.set_env('pagecount', %d);\n", $pages); -$commands .= sprintf("this.set_rowcount('%s');\n", rcmail_get_messagecount_text($count)); +$OUTPUT->set_env('messagecount', $count); +$OUTPUT->set_env('pagecount', $pages); +$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count)); // update mailboxlist -$mbox_name = $IMAP->get_mailbox_name(); -$commands .= sprintf("this.set_unread_count('%s', %d);\n", addslashes($mbox_name), $unseen); +$OUTPUT->command('set_unread_count', $IMAP->get_mailbox_name(), $unseen); // add message rows if (isset($a_headers) && count($a_headers)) - $commands .= rcmail_js_message_list($a_headers); + rcmail_js_message_list($a_headers); // send response -rcube_remote_response($commands); +$OUTPUT->send(); -exit; ?>
\ No newline at end of file diff --git a/program/steps/mail/mark.inc b/program/steps/mail/mark.inc index 780bf5c6e..0dd781e08 100644 --- a/program/steps/mail/mark.inc +++ b/program/steps/mail/mark.inc @@ -4,7 +4,7 @@ | program/steps/mail/mark.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -18,24 +18,24 @@ */ -$REMOTE_REQUEST = TRUE; - -$a_flags_map = array('undelete' => 'UNDELETED', - 'delete' => 'DELETED', - 'read' => 'SEEN', - 'unread' => 'UNSEEN'); +$a_flags_map = array( + 'undelete' => 'UNDELETED', + 'delete' => 'DELETED', + 'read' => 'SEEN', + 'unread' => 'UNSEEN'); if (($uids = get_input_value('_uid', RCUBE_INPUT_GET)) && ($flag = get_input_value('_flag', RCUBE_INPUT_GET))) - { +{ $flag = $a_flags_map[$flag] ? $a_flags_map[$flag] : strtoupper($flag); $marked = $IMAP->set_flag($uids, $flag); + if ($marked != -1) - { + { $mbox_name = $IMAP->get_mailbox_name(); - $commands = sprintf("this.set_unread_count('%s', %d);\n", $mbox_name, $IMAP->messagecount($mbox_name, 'UNSEEN')); - rcube_remote_response($commands); - } + $OUTPUT->command('set_unread_count', $mbox_name, $IMAP->messagecount($mbox_name, 'UNSEEN')); + $OUTPUT->send(); } +} exit; ?>
\ No newline at end of file diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc index 8d31e3aa5..fb8a0af4c 100644 --- a/program/steps/mail/move_del.inc +++ b/program/steps/mail/move_del.inc @@ -5,7 +5,7 @@ | program/steps/mail/move_del.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -19,46 +19,42 @@ */ -$REMOTE_REQUEST = TRUE; - // move messages if ($_action=='moveto' && !empty($_GET['_uid']) && !empty($_GET['_target_mbox'])) - { +{ $count = sizeof(explode(',', ($uids = get_input_value('_uid', RCUBE_INPUT_GET)))); $target = get_input_value('_target_mbox', RCUBE_INPUT_GET); $moved = $IMAP->move_message($uids, $target, get_input_value('_mbox', RCUBE_INPUT_GET)); if (!$moved) - { + { // send error message - $commands = "this.list_mailbox();\n"; - $commands .= show_message('errormoving', 'error'); - rcube_remote_response($commands); + $OUTPUT->command('list_mailbox'); + $OUTPUT->show_message('errormoving', 'error'); + $OUTPUT->send(); exit; - } } +} // delete messages else if ($_action=='delete' && !empty($_GET['_uid'])) - { +{ $count = sizeof(explode(',', ($uids = get_input_value('_uid', RCUBE_INPUT_GET)))); $del = $IMAP->delete_message($uids, get_input_value('_mbox', RCUBE_INPUT_GET)); if (!$del) - { + { // send error message - $commands = "this.list_mailbox();\n"; - $commands .= show_message('errordeleting', 'error'); - rcube_remote_response($commands); + $OUTPUT->command('list_mailbox'); + $OUTPUT->show_message('errordeleting', 'error'); + $OUTPUT->send(); exit; - } } +} // unknown action or missing query param else - { exit; - } // refresh saved seach set after moving some messages if (($search_request = get_input_value('_search', RCUBE_INPUT_GPC)) && $IMAP->search_set) @@ -68,34 +64,33 @@ if (($search_request = get_input_value('_search', RCUBE_INPUT_GPC)) && $IMAP->se // update message count display $msg_count = $IMAP->messagecount(); $pages = ceil($msg_count / $IMAP->page_size); -$commands = sprintf("this.set_rowcount('%s');\n", rcmail_get_messagecount_text($msg_count)); -$commands .= sprintf("this.set_env('pagecount', %d);\n", $pages); +$OUTPUT->set_env('pagecount', $pages); +$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count)); // update mailboxlist $mbox = $IMAP->get_mailbox_name(); -$commands .= sprintf("this.set_unread_count('%s', %d);\n", $mbox, $IMAP->messagecount($mbox, 'UNSEEN')); +$OUTPUT->command('set_unread_count', $mbox, $IMAP->messagecount($mbox, 'UNSEEN')); if ($_action=='moveto' && $target) - $commands .= sprintf("this.set_unread_count('%s', %d);\n", $target, $IMAP->messagecount($target, 'UNSEEN')); + $OUTPUT->command('set_unread_count', $target, $IMAP->messagecount($target, 'UNSEEN')); -$commands .= sprintf("this.set_quota('%s');\n", $IMAP->get_quota()); +$OUTPUT->command('set_quota', $IMAP->get_quota()); // add new rows from next page (if any) if ($_GET['_from']!='show' && $pages>1 && $IMAP->list_page < $pages) - { +{ $sort_col = isset($_SESSION['sort_col']) ? $_SESSION['sort_col'] : $CONFIG['message_sort_col']; $sort_order = isset($_SESSION['sort_order']) ? $_SESSION['sort_order'] : $CONFIG['message_sort_order']; $a_headers = $IMAP->list_headers($mbox, NULL, $sort_col, $sort_order); $a_headers = array_slice($a_headers, -$count, $count); - $commands .= rcmail_js_message_list($a_headers); - } + rcmail_js_message_list($a_headers); +} // send response -rcube_remote_response($commands); +$OUTPUT->send(); -exit; ?> diff --git a/program/steps/mail/quotadisplay.inc b/program/steps/mail/quotadisplay.inc index c96a7a7ee..accecdb91 100644 --- a/program/steps/mail/quotadisplay.inc +++ b/program/steps/mail/quotadisplay.inc @@ -22,8 +22,7 @@ $display = isset($_GET['_display']) ? $_GET['_display'] : 'text'; $id = isset($_GET['_id']) ? $_GET['_id'] : 'rcmquotadisplay'; $quota = rcmail_quota_content($display); -$command = sprintf("this.gui_objects.%s.innerHTML = '%s';\n", $id, $quota); -rcube_remote_response($command); +$OUTPUT->remote_response(sprintf("this.gui_objects.%s.innerHTML = '%s';\n", $id, $quota)); exit; ?> diff --git a/program/steps/mail/search.inc b/program/steps/mail/search.inc index c4b843b55..bef821b40 100644 --- a/program/steps/mail/search.inc +++ b/program/steps/mail/search.inc @@ -25,7 +25,7 @@ $_SESSION['page'] = 1; $imap_charset = 'UTF-8'; // get search string -$str = get_input_value('_search', RCUBE_INPUT_GET); +$str = get_input_value('_q', RCUBE_INPUT_GET); $mbox = get_input_value('_mbox', RCUBE_INPUT_GET); $search_request = md5($mbox.$str); @@ -71,16 +71,14 @@ else // execute IMAP search $result = $IMAP->search($mbox, $subject, $search, $imap_charset); - -$commands = ''; $count = 0; // Make sure our $result is legit.. if (is_array($result) && $result[0] != '') - { +{ // Get the headers $result_h = $IMAP->list_header_set($mbox, $result, 1, $_SESSION['sort_col'], $_SESSION['sort_order']); - $count = count($result); + $count = count($result_h); // save search results in session if (!is_array($_SESSION['search'])) @@ -88,24 +86,24 @@ if (is_array($result) && $result[0] != '') // Make sure we got the headers if ($result_h != NULL) - { + { $_SESSION['search'][$search_request] = $IMAP->get_search_set(); - $commands = rcmail_js_message_list($result_h); - $commands .= show_message('searchsuccessful', 'confirmation', array('nr' => $count)); - } + rcmail_js_message_list($result_h); + $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count)); } +} else - { - $commands = show_message('searchnomatch', 'warning'); +{ + $OUTPUT->show_message('searchnomatch', 'warning'); $search_request = -1; - } +} // update message count display $pages = ceil($count/$IMAP->page_size); -$commands .= sprintf("\nthis.set_env('search_request', '%s')\n", $search_request); -$commands .= sprintf("this.set_env('messagecount', %d);\n", $count); -$commands .= sprintf("this.set_env('pagecount', %d);\n", $pages); -$commands .= sprintf("this.set_rowcount('%s');\n", rcmail_get_messagecount_text($count, 1)); -rcube_remote_response($commands); +$OUTPUT->set_env('search_request', $search_request); +$OUTPUT->set_env('messagecount', $count); +$OUTPUT->set_env('pagecount', $pages); +$OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count, 1)); +$OUTPUT->send(); ?>
\ No newline at end of file diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index 4a65ee390..bc454b309 100644 --- a/program/steps/mail/sendmail.inc +++ b/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, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -39,7 +39,7 @@ if (!isset($_SESSION['compose']['id'])) function rcmail_get_identity($id) { - global $DB, $CHARSET, $OUTPUT; + global $DB, $OUTPUT; // get identity record $sql_result = $DB->query("SELECT *, email AS mailto @@ -55,7 +55,7 @@ function rcmail_get_identity($id) $out = $sql_arr; $name = strpos($sql_arr['name'], ",") ? '"'.$sql_arr['name'].'"' : $sql_arr['name']; $out['string'] = sprintf('%s <%s>', - rcube_charset_convert($name, $CHARSET, $OUTPUT->get_charset()), + rcube_charset_convert($name, RCMAIL_CHARSET, $OUTPUT->get_charset()), $sql_arr['mailto']); return $out; } @@ -110,9 +110,8 @@ function rcmail_attach_emoticons(&$mime_message) // add the image to the MIME message $img_file = $INSTALL_PATH . '/' . $searchstr . $image_name; if(! $mime_message->addHTMLImage($img_file, 'image/gif', '', true, '_' . $image_name)) - { - show_message("emoticonerror", 'error'); - } + $OUTPUT->show_message("emoticonerror", 'error'); + array_push($included_images, $image_name); } @@ -132,7 +131,7 @@ $savedraft = !empty($_POST['_draft']) ? TRUE : FALSE; // remove all scripts and act as called in frame $OUTPUT->reset(); -$_framed = TRUE; +$OUTPUT->framed = TRUE; /****** check submission and compose message ********/ @@ -140,8 +139,8 @@ $_framed = TRUE; if (!$savedraft && empty($_POST['_to']) && empty($_POST['_subject']) && $_POST['_message']) { - show_message("sendingfailed", 'error'); - rcube_iframe_response(); + $OUTPUT->show_message("sendingfailed", 'error'); + $OUTPUT->send('iframe'); return; } @@ -168,7 +167,7 @@ if (empty($identity_arr['string'])) // compose headers array $headers = array('Date' => date('D, j M Y H:i:s O'), - 'From' => rcube_charset_convert($identity_arr['string'], $CHARSET, $message_charset), + 'From' => rcube_charset_convert($identity_arr['string'], RCMAIL_CHARSET, $message_charset), 'To' => $mailto); // additional recipients @@ -304,7 +303,7 @@ if ($MBSTRING && function_exists("mb_encode_mimeheader")) { mb_internal_encoding($message_charset); $mb_subject = mb_encode_mimeheader($headers['Subject'], $message_charset, 'Q'); - mb_internal_encoding($CHARSET); + mb_internal_encoding(RCMAIL_CHARSET); } // Begin SMTP Delivery Block @@ -334,13 +333,8 @@ if (!$savedraft) { // log error if (!$sent) - { - raise_error(array('code' => 800, - 'type' => 'smtp', - 'line' => __LINE__, - 'file' => __FILE__, + raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__, 'message' => "SMTP error: ".join("\n", $smtp_response)), TRUE, FALSE); - } } // send mail using PHP's mail() function @@ -368,8 +362,8 @@ if (!$savedraft) { // return to compose page if sending failed if (!$sent) { - show_message("sendingfailed", 'error'); - rcube_iframe_response(); + $OUTPUT->show_message("sendingfailed", 'error'); + $OUTPUT->send('iframe'); return; } @@ -409,13 +403,11 @@ if ($CONFIG[$store_target]) // raise error if saving failed if (!$saved) { - raise_error(array('code' => 800, - 'type' => 'imap', - 'file' => __FILE__, + raise_error(array('code' => 800, 'type' => 'imap', 'file' => __FILE__, 'message' => "Could not save message in $CONFIG[$store_target]"), TRUE, FALSE); - show_message('errorsaving', 'error'); - rcube_iframe_response($errorout); + $OUTPUT->show_message('errorsaving', 'error'); + $OUTPUT->send('iframe'); } if ($olddraftmessageid) @@ -426,41 +418,36 @@ if ($CONFIG[$store_target]) // raise error if deletion of old draft failed if (!$deleted) - raise_error(array('code' => 800, - 'type' => 'imap', - 'file' => __FILE__, + raise_error(array('code' => 800, 'type' => 'imap', 'file' => __FILE__, 'message' => "Could not delete message from ".$CONFIG['drafts_mbox']), TRUE, FALSE); } } if ($savedraft) { - // clear the "saving message" busy status, and display success - show_message('messagesaved', 'confirmation'); - - // update "_draft_saveid" on the page, which is used to delete a previous draft - $frameout = "var foundid = parent.rcube_find_object('_draft_saveid', parent.document);\n"; - $frameout .= sprintf("foundid.value = '%s';\n", str_replace(array('<','>'), "", $message_id)); + // display success + $OUTPUT->show_message('messagesaved', 'confirmation'); - // update the "cmp_hash" to prevent "Unsaved changes" warning - $frameout .= sprintf("parent.%s.cmp_hash = parent.%s.compose_field_hash();\n", $JS_OBJECT_NAME, $JS_OBJECT_NAME); + // update "_draft_saveid" and the "cmp_hash" to prevent "Unsaved changes" warning + $OUTPUT->command('set_draft_id', str_replace(array('<','>'), "", $message_id)); + $OUTPUT->command('compose_field_hash', true); // start the auto-save timer again - $frameout .= sprintf("parent.%s.auto_save_start();", $JS_OBJECT_NAME); + $OUTPUT->command('auto_save_start'); - // send html page with JS calls as response - rcube_iframe_response($frameout); + $OUTPUT->send('iframe'); } else { if ($CONFIG['smtp_log']) { - $log_entry = sprintf("[%s] User: %d on %s; Message for %s; %s\n", - date("d-M-Y H:i:s O", mktime()), - $_SESSION['user_id'], - $_SERVER['REMOTE_ADDR'], - $mailto, - !empty($smtp_response) ? join('; ', $smtp_response) : ''); + $log_entry = sprintf( + "[%s] User: %d on %s; Message for %s; %s\n", + date("d-M-Y H:i:s O", mktime()), + $_SESSION['user_id'], + $_SERVER['REMOTE_ADDR'], + $mailto, + !empty($smtp_response) ? join('; ', $smtp_response) : ''); if ($fp = @fopen($CONFIG['log_dir'].'/sendmail', 'a')) { @@ -470,8 +457,8 @@ else } rcmail_compose_cleanup(); - rcube_iframe_response(sprintf("parent.$JS_OBJECT_NAME.sent_successfully('%s');", - JQ(rcube_label('messagesent')))); + $OUTPUT->command('sent_successfully', rcube_label('messagesent')); + $OUTPUT->send('iframe'); } diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc index 19e6e56a9..6c247aea9 100644 --- a/program/steps/mail/show.inc +++ b/program/steps/mail/show.inc @@ -5,7 +5,7 @@ | program/steps/mail/show.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -32,7 +32,7 @@ if ($_GET['_uid']) // go back to list if message not found (wrong UID) if (!$MESSAGE['headers']) { - show_message('messageopenerror', 'error'); + $OUTPUT->show_message('messageopenerror', 'error'); if ($_action=='preview' && template_exists('messagepreview')) parse_template('messagepreview'); else @@ -51,8 +51,8 @@ if ($_GET['_uid']) else send_modified_header($_SESSION['login_time'], $etag); - - $MESSAGE['subject'] = $IMAP->decode_header($MESSAGE['headers']->subject); + $MESSAGE['subject'] = rcube_imap::decode_mime_string($MESSAGE['headers']->subject, $MESSAGE['headers']->charset); + $OUTPUT->set_pagetitle($MESSAGE['subject']); if ($MESSAGE['structure'] = $IMAP->get_structure($MESSAGE['UID'])) list($MESSAGE['parts'], $MESSAGE['attachments']) = rcmail_parse_message( @@ -70,8 +70,8 @@ if ($_GET['_uid']) $IMAP->set_flag($MESSAGE['UID'], 'SEEN'); // give message uid to the client - $javascript = sprintf("%s.set_env('uid', '%s');\n", $JS_OBJECT_NAME, $MESSAGE['UID']); - $javascript .= sprintf("%s.set_env('safemode', '%b');", $JS_OBJECT_NAME, $_GET['_safe']); + $OUTPUT->set_env('uid', $MESSAGE['UID']); + $OUTPUT->set_env('safemode', (bool)$_GET['_safe']); $next = $prev = -1; // get previous, first, next and last message UID @@ -99,22 +99,20 @@ if ($_GET['_uid']) } if ($prev > 0) - $javascript .= sprintf("\n%s.set_env('prev_uid', '%s');", $JS_OBJECT_NAME, $prev); + $OUTPUT->set_env('prev_uid', $prev); if ($first >0) - $javascript .= sprintf("\n%s.set_env('first_uid', '%s');", $JS_OBJECT_NAME, $first); + $OUTPUT->set_env('first_uid', $first); if ($next > 0) - $javascript .= sprintf("\n%s.set_env('next_uid', '%s');", $JS_OBJECT_NAME, $next); + $OUTPUT->set_env('next_uid', $next); if ($last >0) - $javascript .= sprintf("\n%s.set_env('last_uid', '%s');", $JS_OBJECT_NAME, $last); - - $OUTPUT->add_script($javascript); + $OUTPUT->set_env('last_uid', $last); } function rcmail_message_attachments($attrib) { - global $CONFIG, $OUTPUT, $PRINT_MODE, $MESSAGE, $GET_URL, $JS_OBJECT_NAME; + global $CONFIG, $OUTPUT, $PRINT_MODE, $MESSAGE, $GET_URL; if (sizeof($MESSAGE['attachments'])) { @@ -132,7 +130,7 @@ function rcmail_message_attachments($attrib) $out .= sprintf('<li><a href="%s&_part=%s" onclick="return %s.command(\'load-attachment\',{part:\'%s\', mimetype:\'%s\'},this)">%s</a></li>'."\n", htmlspecialchars($GET_URL), $attach_prop->mime_id, - $JS_OBJECT_NAME, + JS_OBJECT_NAME, $attach_prop->mime_id, $attach_prop->mimetype, $attach_prop->filename); @@ -147,7 +145,7 @@ function rcmail_message_attachments($attrib) function rcmail_remote_objects_msg($attrib) { - global $CONFIG, $OUTPUT, $JS_OBJECT_NAME; + global $CONFIG, $OUTPUT; if (!$attrib['id']) $attrib['id'] = 'rcmremoteobjmsg'; @@ -158,16 +156,21 @@ function rcmail_remote_objects_msg($attrib) $out .= sprintf('%s <a href="#loadimages" onclick="%s.command(\'load-images\')">%s</a>', Q(rcube_label('blockedimages')), - $JS_OBJECT_NAME, + JS_OBJECT_NAME, Q(rcube_label('showimages'))); $out .= '</div>'; - $OUTPUT->add_script(sprintf("%s.gui_object('remoteobjectsmsg', '%s');", $JS_OBJECT_NAME, $attrib['id'])); + $OUTPUT->add_gui_object('remoteobjectsmsg', $attrib['id']); return $out; } +$OUTPUT->add_handlers(array( + 'messageattachments' => 'rcmail_message_attachments', + 'blockedobjects' => 'rcmail_remote_objects_msg')); + + if ($_action=='print' && template_exists('printmessage')) parse_template('printmessage'); else if ($_action=='preview' && template_exists('messagepreview')) diff --git a/program/steps/mail/upload.inc b/program/steps/mail/upload.inc index 06ed26591..a28c3e8e2 100644 --- a/program/steps/mail/upload.inc +++ b/program/steps/mail/upload.inc @@ -47,23 +47,22 @@ foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) 'path' => $tmpfname); if (is_file($CONFIG['skin_path'] . '/images/icons/remove-attachment.png')) - $button = sprintf('<img src="%s/images/icons/remove-attachment.png" alt="%s" border="0" style="padding-right:2px;vertical-align:middle" />', - $CONFIG['skin_path'], - Q(rcube_label('delete'))); + $button = sprintf( + '<img src="%s/images/icons/remove-attachment.png" alt="%s" border="0" style="padding-right:2px;vertical-align:middle" />', + $CONFIG['skin_path'], + Q(rcube_label('delete'))); else $button = Q(rcube_label('delete')); - $content = sprintf('<a href="#delete" onclick="return %s.command(\\\'remove-attachment\\\', \\\'rcmfile%d\\\', this)" title="%s">%s</a>%s', - $JS_OBJECT_NAME, - $id, - Q(rcube_label('delete')), - $button, - Q($_FILES['_attachments']['name'][$i])); - - $response .= sprintf('parent.%s.add2attachment_list(\'rcmfile%d\',\'%s\');', - $JS_OBJECT_NAME, - $id, - $content); + $content = sprintf( + '<a href="#delete" onclick="return %s.command(\'remove-attachment\', \'rcmfile%d\', this)" title="%s">%s</a>%s', + JS_OBJECT_NAME, + $id, + Q(rcube_label('delete')), + $button, + Q($_FILES['_attachments']['name'][$i])); + + $OUTPUT->command('add2attachment_list', "rcmfile$id", $content); } else // upload failed { @@ -73,18 +72,14 @@ foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) else $msg = rcube_label('fileuploaderror'); - $response = sprintf("parent.%s.display_message('%s', 'error');", $JS_OBJECT_NAME, JQ($msg)); + $OUTPUT->command('display_message', $msg, 'error'); } } // send html page with JS calls as response -$frameout = <<<EOF -$response -parent.$JS_OBJECT_NAME.show_attachment_form(false); -parent.$JS_OBJECT_NAME.auto_save_start(); -EOF; - -rcube_iframe_response($frameout); +$OUTPUT->command('show_attachment_form', false); +$OUTPUT->command('auto_save_start', false); +$OUTPUT->send('iframe'); ?> diff --git a/program/steps/settings/delete_identity.inc b/program/steps/settings/delete_identity.inc index 560a2b10b..3614a3e96 100644 --- a/program/steps/settings/delete_identity.inc +++ b/program/steps/settings/delete_identity.inc @@ -5,7 +5,7 @@ | program/steps/settings/delete_identity.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -20,32 +20,29 @@ */ if (($ids = get_input_value('_iid', RCUBE_INPUT_GET)) && preg_match('/^[0-9]+(,[0-9]+)*$/', $ids)) - { - $DB->query("UPDATE ".get_table_name('identities')." - SET del=1 - WHERE user_id=? - AND identity_id IN (".$ids.")", - $_SESSION['user_id']); +{ + $DB->query( + "UPDATE ".get_table_name('identities')." + SET del=1 + WHERE user_id=? + AND identity_id IN (".$ids.")", + $_SESSION['user_id']); $count = $DB->affected_rows(); if ($count) - { - $commands = show_message('deletedsuccessfully', 'confirmation'); - } + $OUTPUT->show_message('deletedsuccessfully', 'confirmation'); // send response - if ($REMOTE_REQUEST) - rcube_remote_response($commands); - } + if ($OUTPUT->ajax_call) + $OUTPUT->send(); +} -if ($REMOTE_REQUEST) +if ($OUTPUT->ajax_call) exit; // go to identities page -$_action = 'identities'; +rcmail_overwrite_action('identities'); -// overwrite action variable -$OUTPUT->add_script(sprintf("\n%s.set_env('action', '%s');", $JS_OBJECT_NAME, $_action)); ?> diff --git a/program/steps/settings/edit_identity.inc b/program/steps/settings/edit_identity.inc index 5fa531a11..51a0cd0a0 100644 --- a/program/steps/settings/edit_identity.inc +++ b/program/steps/settings/edit_identity.inc @@ -5,7 +5,7 @@ | program/steps/settings/edit_identity.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -31,12 +31,12 @@ if (($_GET['_iid'] || $_POST['_iid']) && $_action=='edit-identity') $IDENTITY_RECORD = $DB->fetch_assoc(); if (is_array($IDENTITY_RECORD)) - $OUTPUT->add_script(sprintf("%s.set_env('iid', '%s');", $JS_OBJECT_NAME, $IDENTITY_RECORD['identity_id'])); - - $PAGE_TITLE = rcube_label('edititem'); + $OUTPUT->set_env('iid', $IDENTITY_RECORD['identity_id']); + + $OUTPUT->set_pagetitle(rcube_label('edititem')); } else - $PAGE_TITLE = rcube_label('newitem'); + $OUTPUT->set_pagetitle(rcube_label('newitem')); $OUTPUT->include_script('list.js'); @@ -44,7 +44,7 @@ $OUTPUT->include_script('list.js'); function rcube_identity_form($attrib) { - global $IDENTITY_RECORD, $JS_OBJECT_NAME, $OUTPUT; + global $IDENTITY_RECORD, $OUTPUT; $OUTPUT->include_script('tiny_mce/tiny_mce_src.js'); $OUTPUT->add_script("tinyMCE.init({ mode : 'specific_textareas'," . @@ -63,8 +63,7 @@ function rcube_identity_form($attrib) return rcube_label('notfound'); // add some labels to client - rcube_add_label('noemailwarning'); - rcube_add_label('nonamewarning'); + rcube_add_label('noemailwarning', 'nonamewarning'); list($form_start, $form_end) = get_form_tags($attrib, 'save-identity', array('name' => '_iid', 'value' => $IDENTITY_RECORD['identity_id'])); @@ -136,7 +135,7 @@ function rcube_identity_form($attrib) return $out; } - +$OUTPUT->add_handler('identityform', 'rcube_identity_form'); if ($_action=='add-identity' && template_exists('addidentity')) parse_template('addidentity'); diff --git a/program/steps/settings/func.inc b/program/steps/settings/func.inc index e51f6838e..91212e174 100644 --- a/program/steps/settings/func.inc +++ b/program/steps/settings/func.inc @@ -5,7 +5,7 @@ | program/steps/settings/func.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -26,7 +26,7 @@ $sql_result = $DB->query("SELECT username, mail_host FROM ".get_table_name('user $_SESSION['user_id']); if ($USER_DATA = $DB->fetch_assoc($sql_result)) - $PAGE_TITLE = sprintf('%s %s@%s', rcube_label('settingsfor'), $USER_DATA['username'], $USER_DATA['mail_host']); + $OUTPUT->set_pagetitle(sprintf('%s %s@%s', rcube_label('settingsfor'), $USER_DATA['username'], $USER_DATA['mail_host'])); @@ -202,7 +202,7 @@ function rcmail_user_prefs_form($attrib) function rcmail_identities_list($attrib) { - global $DB, $CONFIG, $OUTPUT, $JS_OBJECT_NAME; + global $DB, $CONFIG, $OUTPUT; // get contacts from DB @@ -224,8 +224,7 @@ function rcmail_identities_list($attrib) $out = rcube_table_output($attrib, $sql_result, $a_show_cols, 'identity_id'); // set client env - $javascript = sprintf("%s.gui_object('identitieslist', '%s');\n", $JS_OBJECT_NAME, $attrib['id']); - $OUTPUT->add_script($javascript); + $OUTPUT->add_gui_object('identitieslist', $attrib['id']); return $out; } @@ -235,7 +234,7 @@ function rcmail_identities_list($attrib) // similar function as in /steps/addressbook/edit.inc function get_form_tags($attrib, $action, $add_hidden=array()) { - global $OUTPUT, $JS_OBJECT_NAME, $EDIT_FORM, $SESS_HIDDEN_FIELD; + global $OUTPUT, $EDIT_FORM, $SESS_HIDDEN_FIELD; $form_start = ''; if (!strlen($EDIT_FORM)) @@ -258,7 +257,7 @@ function get_form_tags($attrib, $action, $add_hidden=array()) $form_name = strlen($attrib['form']) ? $attrib['form'] : 'form'; if (!strlen($EDIT_FORM)) - $OUTPUT->add_script("$JS_OBJECT_NAME.gui_object('editform', '$form_name');"); + $OUTPUT->add_gui_object('editform', $form_name); $EDIT_FORM = $form_name; @@ -266,4 +265,11 @@ function get_form_tags($attrib, $action, $add_hidden=array()) } +// register UI objects +$OUTPUT->add_handlers(array( + 'userprefs' => 'rcmail_user_prefs_form', + 'itentitieslist' => 'rcmail_identities_list' +)); + + ?>
\ No newline at end of file diff --git a/program/steps/settings/identities.inc b/program/steps/settings/identities.inc index caaa45342..9284e525d 100644 --- a/program/steps/settings/identities.inc +++ b/program/steps/settings/identities.inc @@ -5,7 +5,7 @@ | program/steps/settings/identities.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -20,7 +20,7 @@ */ if ($USER_DATA = $DB->fetch_assoc($sql_result)) - $PAGE_TITLE = sprintf('%s (%s@%s)', rcube_label('identities'), $USER_DATA['username'], $USER_DATA['mail_host']); + $OUTPUT->set_pagetitle(sprintf('%s (%s@%s)', rcube_label('identities'), $USER_DATA['username'], $USER_DATA['mail_host'])); $OUTPUT->include_script('list.js'); @@ -28,14 +28,14 @@ $OUTPUT->include_script('list.js'); // similar function as /steps/addressbook/func.inc::rcmail_contact_frame() function rcmail_identity_frame($attrib) { - global $OUTPUT, $JS_OBJECT_NAME; + global $OUTPUT; if (!$attrib['id']) $attrib['id'] = 'rcmIdentityFrame'; $attrib['name'] = $attrib['id']; - $OUTPUT->add_script(sprintf("%s.set_env('contentframe', '%s');", $JS_OBJECT_NAME, $attrib['name'])); + $OUTPUT->set_env('contentframe', $attrib['name']); $attrib_str = create_attrib_string($attrib, array('name', 'id', 'class', 'style', 'src', 'width', 'height', 'frameborder')); $out = '<iframe'. $attrib_str . '></iframe>'; @@ -43,7 +43,7 @@ function rcmail_identity_frame($attrib) return $out; } - +$OUTPUT->add_handler('identityframe', 'rcmail_identity_frame'); parse_template('identities'); ?>
\ No newline at end of file diff --git a/program/steps/settings/manage_folders.inc b/program/steps/settings/manage_folders.inc index 8dd898d26..7499fe3d4 100644 --- a/program/steps/settings/manage_folders.inc +++ b/program/steps/settings/manage_folders.inc @@ -5,7 +5,7 @@ | program/steps/settings/manage_folders.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -29,8 +29,8 @@ if ($_action=='subscribe') if ($mboxes = get_input_value('_mboxes', RCUBE_INPUT_GET)) $IMAP->subscribe(array($mboxes)); - if ($REMOTE_REQUEST) - rcube_remote_response('// subscribed'); + if ($OUTPUT->ajax_call) + $OUTPUT->remote_response('// subscribed'); } // unsubscribe one or more mailboxes @@ -39,8 +39,8 @@ else if ($_action=='unsubscribe') if ($mboxes = get_input_value('_mboxes', RCUBE_INPUT_GET)) $IMAP->unsubscribe(array($mboxes)); - if ($REMOTE_REQUEST) - rcube_remote_response('// unsubscribed'); + if ($OUTPUT->ajax_call) + $OUTPUT->remote_response('// unsubscribed'); } // create a new mailbox @@ -49,47 +49,40 @@ else if ($_action=='create-folder') if (!empty($_GET['_name'])) $create = $IMAP->create_mailbox(trim(get_input_value('_name', RCUBE_INPUT_GET, FALSE, 'UTF-7')), TRUE); - if ($create && $REMOTE_REQUEST) + if ($create && $OUTPUT->ajax_call) { - $commands = sprintf("this.add_folder_row('%s','%s')", - JQ($create), - JQ(rcube_charset_convert($create, 'UTF-7'))); - rcube_remote_response($commands); + $OUTPUT->command('add_folder_row', $create, rcube_charset_convert($create, 'UTF-7')); + $OUTPUT->send(); } - else if (!$create && $REMOTE_REQUEST) + else if (!$create && $OUTPUT->ajax_call) { - $commands = show_message('errorsaving', 'error'); - rcube_remote_response($commands); + $OUTPUT->show_message('errorsaving', 'error'); + $OUTPUT->remote_response(); } else if (!$create) - show_message('errorsaving', 'error'); + $OUTPUT->show_message('errorsaving', 'error'); } // rename a mailbox else if ($_action=='rename-folder') { if (!empty($_GET['_folder_oldname']) && !empty($_GET['_folder_newname'])) - $rename = $IMAP->rename_mailbox(get_input_value('_folder_oldname', RCUBE_INPUT_GET), trim(get_input_value('_folder_newname', RCUBE_INPUT_GET, FALSE, 'UTF-7'))); + $rename = $IMAP->rename_mailbox(($oldname = get_input_value('_folder_oldname', RCUBE_INPUT_GET)), trim(get_input_value('_folder_newname', RCUBE_INPUT_GET, FALSE, 'UTF-7'))); - if ($rename && $REMOTE_REQUEST) + if ($rename && $OUTPUT->ajax_call) { - $commands = sprintf("this.replace_folder_row('%s','%s','%s');\n", - JQ(get_input_value('_folder_oldname', RCUBE_INPUT_GET)), - JQ($rename), - JQ(rcube_charset_convert($rename, 'UTF-7'))); - - $commands .= "this.reset_folder_rename();\n"; - - rcube_remote_response($commands); + $OUTPUT->command('replace_folder_row', $oldname, $rename, rcube_charset_convert($rename, 'UTF-7')); + $OUTPUT->command('reset_folder_rename'); + $OUTPUT->send(); } - else if (!$rename && $REMOTE_REQUEST) + else if (!$rename && $OUTPUT->ajax_call) { - $commands = "this.reset_folder_rename();\n"; - $commands .= show_message('errorsaving', 'error'); - rcube_remote_response($commands); + $OUTPUT->command('reset_folder_rename'); + $OUTPUT->show_message('errorsaving', 'error'); + $OUTPUT->send(); } else if (!$rename) - show_message('errorsaving', 'error'); + $OUTPUT->show_message('errorsaving', 'error'); } // delete an existing IMAP mailbox @@ -98,16 +91,16 @@ else if ($_action=='delete-folder') if ($mboxes = get_input_value('_mboxes', RCUBE_INPUT_GET)) $deleted = $IMAP->delete_mailbox(array($mboxes)); - if ($REMOTE_REQUEST && $deleted) + if ($OUTPUT->ajax_call && $deleted) { - $commands = sprintf("this.remove_folder_row('%s');\n", JQ(get_input_value('_mboxes', RCUBE_INPUT_GET))); - $commands .= show_message('folderdeleted', 'confirmation'); - rcube_remote_response($commands); + $OUTPUT->command('remove_folder_row', get_input_value('_mboxes', RCUBE_INPUT_GET)); + $OUTPUT->show_message('folderdeleted', 'confirmation'); + $OUTPUT->send(); } - else if ($REMOTE_REQUEST) + else if ($OUTPUT->ajax_call) { - $commands = show_message('errorsaving', 'error'); - rcube_remote_response($commands); + $OUTPUT->show_message('errorsaving', 'error'); + $OUTPUT->send(); } } @@ -116,7 +109,7 @@ else if ($_action=='delete-folder') // build table with all folders listed by server function rcube_subscription_form($attrib) { - global $IMAP, $CONFIG, $OUTPUT, $JS_OBJECT_NAME; + global $IMAP, $CONFIG, $OUTPUT; list($form_start, $form_end) = get_form_tags($attrib, 'folders'); unset($attrib['form']); @@ -147,7 +140,7 @@ function rcube_subscription_form($attrib) $a_subscribed = $IMAP->list_mailboxes(); $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 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')); @@ -166,11 +159,10 @@ function rcube_subscription_form($attrib) $protected = ($CONFIG['protect_default_folders'] == TRUE && in_array($folder,$CONFIG['default_imap_folders'])); $zebra_class = $i%2 ? 'even' : 'odd'; $folder_js = JQ($folder); - $folder_js_enc = JQ(rcube_charset_convert($folder, 'UTF-7')); $folder_html = $CONFIG['protect_default_folders'] && in_array($folder, $CONFIG['default_imap_folders']) ? rcube_label(strtolower($folder)) : rcube_charset_convert($folder, 'UTF-7'); if (!$protected) - $a_js_folders['rcmrow'.($i+1)] = array($folder_js, $folder_js_enc); + $a_js_folders['rcmrow'.($i+1)] = array($folder, rcube_charset_convert($folder, 'UTF-7')); $out .= sprintf('<tr id="rcmrow%d" class="%s"><td>%s</td>', $i+1, @@ -186,11 +178,11 @@ function rcube_subscription_form($attrib) if (!$protected) $out .= sprintf('<td><a href="#rename" onclick="%s.command(\'rename-folder\',\'%s\')" title="%s">%s</a>'. '<td><a href="#delete" onclick="%s.command(\'delete-folder\',\'%s\')" title="%s">%s</a></td>', - $JS_OBJECT_NAME, + JS_OBJECT_NAME, $folder_js, rcube_label('renamefolder'), $edit_button, - $JS_OBJECT_NAME, + JS_OBJECT_NAME, $folder_js, rcube_label('deletefolder'), $del_button); @@ -203,10 +195,8 @@ function rcube_subscription_form($attrib) $out .= "</tbody>\n</table>"; $out .= "\n$form_end"; - - $javascript = sprintf("%s.gui_object('subscriptionlist', '%s');\n", $JS_OBJECT_NAME, $attrib['id']); - $javascript .= sprintf("%s.set_env('subscriptionrows', %s);", $JS_OBJECT_NAME, array2js($a_js_folders)); - $OUTPUT->add_script($javascript); + $OUTPUT->add_gui_object('subscriptionlist', $attrib['id']); + $OUTPUT->set_env('subscriptionrows', $a_js_folders); return $out; } @@ -214,8 +204,6 @@ function rcube_subscription_form($attrib) function rcube_create_folder_form($attrib) { - global $JS_OBJECT_NAME; - list($form_start, $form_end) = get_form_tags($attrib, 'create-folder'); unset($attrib['form']); @@ -230,7 +218,7 @@ function rcube_create_folder_form($attrib) { $button = new input_field(array('type' => 'button', 'value' => rcube_label('create'), - 'onclick' => "$JS_OBJECT_NAME.command('create-folder',this.form)")); + 'onclick' => JS_OBJECT_NAME.".command('create-folder',this.form)")); $out .= $button->show(); } @@ -241,7 +229,7 @@ function rcube_create_folder_form($attrib) function rcube_rename_folder_form($attrib) { - global $CONFIG, $IMAP, $JS_OBJECT_NAME; + global $CONFIG, $IMAP; list($form_start, $form_end) = get_form_tags($attrib, 'rename-folder'); unset($attrib['form']); @@ -270,7 +258,7 @@ function rcube_rename_folder_form($attrib) { $button = new input_field(array('type' => 'button', 'value' => rcube_label('rename'), - 'onclick' => "$JS_OBJECT_NAME.command('rename-folder',this.form)")); + 'onclick' => JS_OBJECT_NAME.".command('rename-folder',this.form)")); $out .= $button->show(); } @@ -280,9 +268,15 @@ function rcube_rename_folder_form($attrib) } +// register UI objects +$OUTPUT->add_handlers(array( + 'foldersubscription' => 'rcube_subscription_form', + 'createfolder' => 'rcube_create_folder_form', + 'renamefolder' => 'rcube_rename_folder_form' +)); + // add some labels to client rcube_add_label('deletefolderconfirm'); - -parse_template('managefolders'); +$OUTPUT->send('managefolders'); ?> diff --git a/program/steps/settings/save_identity.inc b/program/steps/settings/save_identity.inc index ce1c6f6b4..8079b589a 100644 --- a/program/steps/settings/save_identity.inc +++ b/program/steps/settings/save_identity.inc @@ -27,7 +27,7 @@ $updated = $default_id = false; // check input if (empty($_POST['_name']) || empty($_POST['_email'])) { - show_message('formincomplete', 'warning'); + $OUTPUT->show_message('formincomplete', 'warning'); rcmail_overwrite_action('edit-identitiy'); return; } @@ -72,7 +72,7 @@ if ($_POST['_iid']) if ($updated) { - show_message('successfullysaved', 'confirmation'); + $OUTPUT->show_message('successfullysaved', 'confirmation'); if (!empty($_POST['_standard'])) $default_id = get_input_value('_iid', RCUBE_INPUT_POST); @@ -86,7 +86,7 @@ if ($_POST['_iid']) else if ($DB->is_error()) { // show error message - show_message('errorsaving', 'error'); + $OUTPUT->show_message('errorsaving', 'error'); rcmail_overwrite_action('edit-identitiy'); return; } @@ -133,7 +133,7 @@ else else { // show error message - show_message('errorsaving', 'error'); + $OUTPUT->show_message('errorsaving', 'error'); rcmail_overwrite_action('edit-identity'); return; } @@ -152,6 +152,6 @@ if ($default_id) $default_id); // go to next step -rcmail_overwrite_action($_POST['_framed'] ? 'edit-identity' : 'identities'); +rcmail_overwrite_action($_framed ? 'edit-identity' : 'identities'); ?>
\ No newline at end of file diff --git a/program/steps/settings/save_prefs.inc b/program/steps/settings/save_prefs.inc index fd254f9f3..4945a4fff 100644 --- a/program/steps/settings/save_prefs.inc +++ b/program/steps/settings/save_prefs.inc @@ -5,7 +5,7 @@ | program/steps/settings/save_prefs.inc | | | | This file is part of the RoundCube Webmail client | - | Copyright (C) 2005, RoundCube Dev. - Switzerland | + | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland | | Licensed under the GNU GPL | | | | PURPOSE: | @@ -43,13 +43,10 @@ if (isset($_POST['_language'])) } if (rcmail_save_user_prefs($a_user_prefs)) - show_message('successfullysaved', 'confirmation'); + $OUTPUT->show_message('successfullysaved', 'confirmation'); // go to next step -$_action = 'preferences'; - -// overwrite action variable -$OUTPUT->add_script(sprintf("\n%s.set_env('action', '%s');", $JS_OBJECT_NAME, $_action)); +rcmail_overwrite_action('preferences'); ?> diff --git a/skins/default/addresses.css b/skins/default/addresses.css index 0ff1b28a9..363a63477 100644 --- a/skins/default/addresses.css +++ b/skins/default/addresses.css @@ -17,8 +17,8 @@ #abookcountbar { position: absolute; - top: 60px; - left: 490px; + bottom: 16px; + left: 185px; width: 240px; height: 20px; text-align: left; @@ -30,21 +30,70 @@ color: #333333; } - -#addresslist +#directorylist, #addresslist { position: absolute; top: 85px; - left: 20px; - width: 450px; bottom: 40px; border: 1px solid #999999; background-color: #F9F9F9; overflow: auto; /* css hack for IE */ - height: expression((parseInt(document.documentElement.clientHeight)-135)+'px'); + height: expression((parseInt(document.documentElement.clientHeight)-135)+'px'); +} + +#directorylist +{ + left: 20px; + width: 150px; +} + +#addresslist +{ + left: 185px; + width: 340px; +} + +#directorylist ul +{ + list-style: none; + margin: 0; + padding: 0; +} + +#directorylist ul +{ + font-size: 11px; + border-bottom: 1px solid #EBEBEB; +} + +#directorylist ul li a +{ + display: block; + padding-left: 6px; + padding-top: 2px; + padding-bottom: 2px; + text-decoration: none; +} + +#directorylist li.selected +{ + background-color: #929292; + border-bottom: 1px solid #898989; +} + +#directorylist li.selected a +{ + color: #FFF; + font-weight: bold; +} + +#directorylist li.droptarget +{ + background-color: #FFFFA6; } + #contacts-table { width: 100%; @@ -64,26 +113,26 @@ { position: absolute; top: 85px; - left: 490px; - right: 40px; + left: 540px; + right: 30px; bottom: 40px; border: 1px solid #999999; overflow: hidden; /* css hack for IE */ - width: expression((parseInt(document.documentElement.clientWidth)-80-document.getElementById('addresslist').offsetWidth)+'px'); + width: expression((parseInt(document.documentElement.clientWidth)-70-document.getElementById('addresslist').offsetWidth)+'px'); height: expression((parseInt(document.documentElement.clientHeight)-135)+'px'); } #addressviewsplitter { - background-position: 6px center; + background-position: 4px center; } #addressviewsplitter .splitterLine { margin-left: 3px; - width: 9px; + width: 6px; } @@ -99,15 +148,33 @@ body.iframe, /* visibility: hidden; */ } +#contact-title, #groups-title +{ + height: 12px !important; +/* height: 20px; */ + padding: 4px 5px 3px 5px; + border-bottom: 1px solid #999; + color: #333; + font-size: 11px; + font-weight: bold; + background-color: #EBEBEB; + background-image: url(images/listheader_aqua.gif); + white-space: nowrap; +} + +#contact-title +{ + padding: 4px 10px 3px 10px; +} #contact-details { - padding: 15px 20px 10px 20px; + padding: 15px 10px 10px 10px; } #contact-details table td.title { - color: #666666; + color: #666; font-weight: bold; text-align: right; padding-right: 10px; diff --git a/skins/default/common.css b/skins/default/common.css index b3c234f89..2ce3dffad 100755 --- a/skins/default/common.css +++ b/skins/default/common.css @@ -127,7 +127,7 @@ img width: 600px; height: 37px; background: url(images/taskbar.gif) top right no-repeat; - padding: 10px 24px 10px 0px; + padding: 10px 14px 10px 0px; text-align: right; white-space: nowrap; z-index: 2; @@ -251,6 +251,10 @@ a.button-logout background-image: url(images/listheader_aqua.gif); } +.radios-left label +{ + padding-left: 0.3em; +} /***** common table settings ******/ @@ -292,8 +296,6 @@ table.records-table tr.selected td table.records-table tr.focused td { - border-bottom: thin dotted; - border-top: thin dotted; } table.records-table tr.unfocused td @@ -304,8 +306,84 @@ table.records-table tr.unfocused td } +/***** mac-style quicksearch field *****/ + +#quicksearchbar +{ + position: absolute; + top: 60px; + right: 30px; + width: 182px; + height: 20px; + text-align: right; + background: url('images/searchfield.gif') top left no-repeat; +} + +#quicksearchbar a +{ + position: absolute; + top: 3px; + right: 4px; + text-decoration: none; +} + +#quicksearchbar img +{ + vertical-align: middle; +} + +#quicksearchbox +{ + position: absolute; + top: 2px; + left: 20px; + width: 140px; + font-size: 11px; + padding: 0px; + border: none; +} + + +/*\*/ +html>body*#quicksearchbar[id$="quicksearchbar"]:not([class="none"]) { background-image: none; } +html>body*#quicksearchbar[id$="quicksearchbar"]:not([class="none"]) a { top: 5px; } +html>body*#quicksearchbar[id$="quicksearchbar"]:not([class="none"]) #quicksearchbox { width: 180px; top:0px; right: 1px; left: auto; } +/**/ + + /***** roundcube webmail pre-defined classes *****/ +#rcversion +{ + position: absolute; + top: 67px; + left: 20px; + width: 160px; + text-align: center; + + font-weight: normal; + font-size: x-small; + font-variant: small-caps; + + color: #999999; + /*border: 1px solid #308014; + background-color: #b4eeb4;*/ +} + +#rcmdraglayer +{ + width: 300px; + border: 1px solid #999999; + background-color: #F9F9F9; + padding-left: 8px; + padding-right: 8px; + padding-top: 3px; + padding-bottom: 3px; + font-size: 11px; + opacity: 0.6; + -moz-opacity: 0.6; +} + a.rcmContactAddress { text-decoration: none; diff --git a/skins/default/ldapsearchform.css b/skins/default/ldapsearchform.css deleted file mode 100644 index 9661442eb..000000000 --- a/skins/default/ldapsearchform.css +++ /dev/null @@ -1,54 +0,0 @@ -/***** RoundCube|Mail address book task styles *****/ - - -body.iframe, -{ - background-color: #F9F9F9; -} - -#ldapsearch-title -{ - height: 12px !important; -/* height: 20px; */ - padding: 4px 20px 3px 20px; - border-bottom: 1px solid #999999; - color: #333333; - font-size: 11px; - font-weight: bold; - background-color: #EBEBEB; - background-image: url(images/listheader_aqua.gif); -} - -#ldapsearch-details -{ - padding: 15px 20px 10px 20px; -} - -#ldapsearch-details table td.title -{ - color: #666666; - font-weight: bold; - text-align: right; - padding-right: 10px; -} - -#ldapAddressList -{ - width: 100%; - table-layout: fixed; - /* css hack for IE */ - width: expression(document.getElementById('addresslist').clientWidth); -} - -#ldapAddressList table -{ - border-top: 1px solid #999999; -} - -#ldap-search-results div -{ - width: 100%; - color: red; - background-color: green; -} - diff --git a/skins/default/mail.css b/skins/default/mail.css index 11364baa0..67f2bbb10 100644 --- a/skins/default/mail.css +++ b/skins/default/mail.css @@ -83,7 +83,7 @@ { position: absolute; bottom: 16px; - right: 40px; + right: 30px; width: 300px; height: 20px; text-align: right; @@ -110,13 +110,13 @@ position: absolute; top: 85px; left: 200px; - right: 40px; + right: 30px; bottom: 40px; border: 1px solid #999999; background-color: #F9F9F9; overflow: auto; /* css hack for IE */ - width: expression((parseInt(document.documentElement.clientWidth)-240)+'px'); + width: expression((parseInt(document.documentElement.clientWidth)-230)+'px'); height: expression((parseInt(document.documentElement.clientHeight)-125)+'px'); } @@ -125,12 +125,12 @@ position: absolute; top: 305px; left: 200px; - right: 40px; + right: 30px; bottom: 40px; border: 1px solid #999999; background-color: #F9F9F9; /* css hack for IE */ - width: expression((parseInt(document.documentElement.clientWidth)-240)+'px'); + width: expression((parseInt(document.documentElement.clientWidth)-230)+'px'); height: expression((parseInt(document.documentElement.clientHeight)-135-document.getElementById('mailcontframe').offsetHeight)+'px'); } @@ -186,20 +186,6 @@ html>body*#messagecontframe font-weight: bold; } -#rcmdraglayer -{ - width: 300px; - border: 1px solid #999999; - background-color: #F9F9F9; - padding-left: 8px; - padding-right: 8px; - padding-top: 3px; - padding-bottom: 3px; - font-size: 11px; - opacity: 0.6; - -moz-opacity: 0.6; -} - /** mailbox list styles */ @@ -524,65 +510,6 @@ body.messagelist color: #CCCCCC; } -#quicksearchbar -{ - position: absolute; - top: 60px; - right: 40px; - width: 182px; - height: 20px; - text-align: right; - background: url('images/searchfield.gif') top left no-repeat; -} - -#quicksearchbar a -{ - position: absolute; - top: 3px; - right: 4px; - text-decoration: none; -} - -#quicksearchbar img -{ - vertical-align: middle; -} - -#quicksearchbox -{ - position: absolute; - top: 2px; - left: 20px; - width: 140px; - font-size: 11px; - padding: 0px; - border: none; -} - - -/*\*/ -html>body*#quicksearchbar[id$="quicksearchbar"]:not([class="none"]) { background-image: none; } -html>body*#quicksearchbar[id$="quicksearchbar"]:not([class="none"]) a { top: 5px; } -html>body*#quicksearchbar[id$="quicksearchbar"]:not([class="none"]) #quicksearchbox { width: 180px; top:0px; right: 1px; left: auto; } -/**/ - - -#rcversion -{ - position: absolute; - top: 67px; - left: 20px; - width: 160px; - text-align: center; - - font-weight: normal; - font-size: x-small; - font-variant: small-caps; - - color: #999999; - /*border: 1px solid #308014; - background-color: #b4eeb4;*/ -} #quotadisplay { @@ -604,9 +531,9 @@ html>body*#quicksearchbar[id$="quicksearchbar"]:not([class="none"]) #quicksearch #messageframe { position: absolute; - top: 95px; + top: 85px; left: 200px; - right: 40px; + right: 30px; bottom: 40px; border: 1px solid #cccccc; background-color: #FFFFFF; diff --git a/skins/default/print.css b/skins/default/print.css index 5f0dbddc3..a36f87a1f 100644 --- a/skins/default/print.css +++ b/skins/default/print.css @@ -108,7 +108,7 @@ div.message-part div.pre margin: 0; padding: 0; white-space: pre; - font-size: 9pt; + font-family: monospace; } div.message-part blockquote diff --git a/skins/default/templates/addcontact.html b/skins/default/templates/addcontact.html index d4fc9cc59..e52b8c737 100644 --- a/skins/default/templates/addcontact.html +++ b/skins/default/templates/addcontact.html @@ -17,6 +17,7 @@ <roundcube:button command="save" type="input" class="button" label="save" /> </p> +</form> </div> diff --git a/skins/default/templates/addressbook.html b/skins/default/templates/addressbook.html index e5b5a104b..c70b00c92 100644 --- a/skins/default/templates/addressbook.html +++ b/skins/default/templates/addressbook.html @@ -17,15 +17,15 @@ <roundcube:button command="compose" imageSel="/images/buttons/compose_sel.png" imageAct="/images/buttons/compose_act.png" imagePas="/images/buttons/compose_pas.png" width="32" height="32" title="composeto" /> <roundcube:button command="print" imageSel="/images/buttons/print_sel.png" imageAct="/images/buttons/print_act.png" imagePas="/images/buttons/print_pas.png" width="32" height="32" title="print" /> <roundcube:button command="export" imageSel="/images/buttons/download_sel.png" imageAct="/images/buttons/download_act.png" imagePas="/images/buttons/download_pas.png" width="32" height="32" title="export" /> -<roundcube:button command="ldappublicsearch" imageSel="/images/buttons/contacts_sel.png" imageAct="/images/buttons/contacts_act.png" imagePas="/images/buttons/contacts_pas.png" width="32" height="32" title="ldapsearch" /> </div> -<div id="abookcountbar"> -<roundcube:button command="firstpage" imageSel="/images/buttons/first_sel.png" imageAct="/images/buttons/first_act.png" imagePas="/images/buttons/first_pas.png" width="11" height="11" title="firstpage" /> -<roundcube:button command="previouspage" imageSel="/images/buttons/previous_sel.png" imageAct="/images/buttons/previous_act.png" imagePas="/images/buttons/previous_pas.png" width="11" height="11" title="previouspage" /> - <roundcube:object name="recordsCountDisplay" /> -<roundcube:button command="nextpage" imageSel="/images/buttons/next_sel.png" imageAct="/images/buttons/next_act.png" imagePas="/images/buttons/next_pas.png" width="11" height="11" title="nextpage" /> -<roundcube:button command="lastpage" imageSel="/images/buttons/last_sel.png" imageAct="/images/buttons/last_act.png" imagePas="/images/buttons/last_pas.png" width="11" height="11" title="lastpage" /> +<div id="quicksearchbar"> +<roundcube:object name="searchform" type="search" results="5" id="quicksearchbox" /><roundcube:button command="reset-search" id="searchreset" image="/images/icons/reset.gif" title="resetsearch" /> +</div> + +<div id="directorylist"> +<div id="groups-title"><roundcube:label name="groups" /></div> +<roundcube:object name="directorylist" id="directories-list" /> </div> <div id="addresslist"> @@ -41,5 +41,13 @@ <roundcube:object name="addressframe" id="contact-frame" width="100%" height="100%" frameborder="0" src="/watermark.html" /> </div> +<div id="abookcountbar"> +<roundcube:button command="firstpage" imageSel="/images/buttons/first_sel.png" imageAct="/images/buttons/first_act.png" imagePas="/images/buttons/first_pas.png" width="11" height="11" title="firstpage" /> +<roundcube:button command="previouspage" imageSel="/images/buttons/previous_sel.png" imageAct="/images/buttons/previous_act.png" imagePas="/images/buttons/previous_pas.png" width="11" height="11" title="previouspage" /> + <roundcube:object name="recordsCountDisplay" /> +<roundcube:button command="nextpage" imageSel="/images/buttons/next_sel.png" imageAct="/images/buttons/next_act.png" imagePas="/images/buttons/next_pas.png" width="11" height="11" title="nextpage" /> +<roundcube:button command="lastpage" imageSel="/images/buttons/last_sel.png" imageAct="/images/buttons/last_act.png" imagePas="/images/buttons/last_pas.png" width="11" height="11" title="lastpage" /> +</div> + </body> </html> diff --git a/skins/default/templates/compose.html b/skins/default/templates/compose.html index 3c8348843..63d5b2c2b 100644 --- a/skins/default/templates/compose.html +++ b/skins/default/templates/compose.html @@ -97,19 +97,18 @@ function rcmail_toggle_display(id) <td style="width:100%; height:98%; vertical-align:top;"> <roundcube:object name="composeBody" id="compose-body" form="form" cols="80" rows="20" wrap="virtual" tabindex="7" /> -<table border="0" cellspacing="0" width="100%" summary=""><tbody><tr> - +<table border="0" cellspacing="0" width="100%" summary=""><tbody> +<tr> <td> <roundcube:button type="input" command="send" class="button" label="sendmessage" /> <roundcube:button type="input" command="list" class="button" label="cancel" /> </td> <td align="right"> -<roundcube:label name="charset" />: <roundcube:object name="charsetSelector" tabindex="8" /> + <roundcube:label name="editortype" />: + <span class="radios-left"><roundcube:object name="editorSelector" tabindex="9" /></span> </td> -<td align="right"> - <roundcube:label name="editortype" />: </td> -<roundcube:object name="editorSelector" tabindex="9" /> -</tr></tbody></table> +</tr> +</tbody></table> </td> diff --git a/skins/default/templates/ldappublicsearch.html b/skins/default/templates/ldappublicsearch.html deleted file mode 100644 index d9714cb85..000000000 --- a/skins/default/templates/ldappublicsearch.html +++ /dev/null @@ -1,31 +0,0 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> -<title><roundcube:object name="pagetitle" /></title> -<link rel="stylesheet" type="text/css" href="/common.css" /> -<link rel="stylesheet" type="text/css" href="/ldapsearchform.css" /> -</head> -<body class="iframe"> - -<div id="ldapsearch-title"><roundcube:label name="ldappublicsearchform" /></div> - -<div id="ldapsearch-details"> -<roundcube:object name="ldappublicsearch" size="40" /> -<p> -<roundcube:button command="ldappublicsearch" type="input" class="button" label="ldappublicsearch" /> -<input type="button" value="<roundcube:label name="cancel" />" class="button" onclick="history.back()" /> -<br /></p> -</div> - - -<div id="ldapsearch-results"> -<roundcube:object name="ldappublicaddresslist" - id="ldappublicaddresslist" - cellspacing="0" - summary="LDAP email address list" /> -</div> - -<roundcube:include file="/includes/ldapscripts.html" /> - -</body> -</html> diff --git a/skins/default/templates/showcontact.html b/skins/default/templates/showcontact.html index 53bc08b5c..79304578c 100644 --- a/skins/default/templates/showcontact.html +++ b/skins/default/templates/showcontact.html @@ -12,7 +12,7 @@ <div id="contact-details"> <roundcube:object name="contactdetails" /> -<p><br /><roundcube:button command="edit" type="input" class="button" label="editcontact" /></p> +<p><br /><roundcube:button command="edit" type="input" class="button" label="editcontact" condition="!ENV:readonly" /></p> </div> </body> |