Changeset 2401 in subversion
- Timestamp:
- Apr 19, 2009 1:44:29 PM (4 years ago)
- Location:
- trunk/roundcubemail
- Files:
-
- 42 edited
- 37 copied
-
config/main.inc.php.dist (modified) (2 diffs)
-
index.php (modified) (5 diffs)
-
plugins (copied) (copied from branches/devel-api/plugins)
-
plugins/additional_message_headers (copied) (copied from branches/devel-api/plugins/additional_message_headers)
-
plugins/additional_message_headers/additional_message_headers.php (copied) (copied from branches/devel-api/plugins/additional_message_headers/additional_message_headers.php)
-
plugins/database_attachments (copied) (copied from branches/devel-api/plugins/database_attachments)
-
plugins/database_attachments/database_attachments.php (copied) (copied from branches/devel-api/plugins/database_attachments/database_attachments.php)
-
plugins/filesystem_attachments (copied) (copied from branches/devel-api/plugins/filesystem_attachments)
-
plugins/filesystem_attachments/filesystem_attachments.php (copied) (copied from branches/devel-api/plugins/filesystem_attachments/filesystem_attachments.php) (1 diff)
-
plugins/http_authentication (copied) (copied from branches/devel-api/plugins/http_authentication)
-
plugins/http_authentication/http_authentication.php (copied) (copied from branches/devel-api/plugins/http_authentication/http_authentication.php)
-
plugins/markasjunk (copied) (copied from branches/devel-api/plugins/markasjunk)
-
plugins/markasjunk/junk_act.png (copied) (copied from branches/devel-api/plugins/markasjunk/junk_act.png)
-
plugins/markasjunk/junk_pas.png (copied) (copied from branches/devel-api/plugins/markasjunk/junk_pas.png)
-
plugins/markasjunk/localization (copied) (copied from branches/devel-api/plugins/markasjunk/localization)
-
plugins/markasjunk/localization/en_US.inc (copied) (copied from branches/devel-api/plugins/markasjunk/localization/en_US.inc)
-
plugins/markasjunk/markasjunk.js (copied) (copied from branches/devel-api/plugins/markasjunk/markasjunk.js)
-
plugins/markasjunk/markasjunk.php (copied) (copied from branches/devel-api/plugins/markasjunk/markasjunk.php)
-
plugins/new_user_identity (copied) (copied from branches/devel-api/plugins/new_user_identity)
-
plugins/new_user_identity/new_user_identity.php (copied) (copied from branches/devel-api/plugins/new_user_identity/new_user_identity.php)
-
plugins/password (copied) (copied from branches/devel-api/plugins/password)
-
plugins/password/localization (copied) (copied from branches/devel-api/plugins/password/localization)
-
plugins/password/localization/en_US.inc (copied) (copied from branches/devel-api/plugins/password/localization/en_US.inc)
-
plugins/password/localization/pl_PL.inc (copied) (copied from branches/devel-api/plugins/password/localization/pl_PL.inc)
-
plugins/password/password.js (copied) (copied from branches/devel-api/plugins/password/password.js)
-
plugins/password/password.php (copied) (copied from branches/devel-api/plugins/password/password.php)
-
plugins/show_additional_headers (copied) (copied from branches/devel-api/plugins/show_additional_headers)
-
plugins/show_additional_headers/show_additional_headers.php (copied) (copied from branches/devel-api/plugins/show_additional_headers/show_additional_headers.php) (1 diff)
-
plugins/subscriptions_option (copied) (copied from branches/devel-api/plugins/subscriptions_option)
-
plugins/subscriptions_option/localization (copied) (copied from branches/devel-api/plugins/subscriptions_option/localization)
-
plugins/subscriptions_option/localization/en_US.inc (copied) (copied from branches/devel-api/plugins/subscriptions_option/localization/en_US.inc)
-
plugins/subscriptions_option/subscriptions_option.php (copied) (copied from branches/devel-api/plugins/subscriptions_option/subscriptions_option.php)
-
plugins/vcard_attachments (copied) (copied from branches/devel-api/plugins/vcard_attachments)
-
plugins/vcard_attachments/vcard_attachments.php (copied) (copied from branches/devel-api/plugins/vcard_attachments/vcard_attachments.php)
-
plugins/vcard_attachments/vcardattach.js (copied) (copied from branches/devel-api/plugins/vcard_attachments/vcardattach.js)
-
program/include/html.php (modified) (2 diffs)
-
program/include/iniset.php (modified) (1 diff)
-
program/include/main.inc (modified) (4 diffs)
-
program/include/rcmail.php (modified) (9 diffs)
-
program/include/rcube_addressbook.php (copied) (copied from branches/devel-api/program/include/rcube_addressbook.php)
-
program/include/rcube_config.php (modified) (1 diff)
-
program/include/rcube_contacts.php (modified) (4 diffs)
-
program/include/rcube_html_page.php (modified) (4 diffs)
-
program/include/rcube_imap.php (modified) (8 diffs)
-
program/include/rcube_json_output.php (modified) (4 diffs)
-
program/include/rcube_ldap.php (modified) (1 diff)
-
program/include/rcube_message.php (modified) (1 diff)
-
program/include/rcube_plugin.php (copied) (copied from branches/devel-api/program/include/rcube_plugin.php)
-
program/include/rcube_plugin_api.php (copied) (copied from branches/devel-api/program/include/rcube_plugin_api.php)
-
program/include/rcube_template.php (modified) (13 diffs)
-
program/include/rcube_user.php (modified) (5 diffs)
-
program/include/rcube_vcard.php (modified) (1 diff)
-
program/js/app.js (modified) (88 diffs)
-
program/js/common.js (modified) (13 diffs)
-
program/js/editor.js (modified) (1 diff)
-
program/js/list.js (modified) (23 diffs)
-
program/lib/imap.inc (modified) (7 diffs)
-
program/steps/addressbook/func.inc (modified) (2 diffs)
-
program/steps/mail/attachments.inc (modified) (5 diffs)
-
program/steps/mail/compose.inc (modified) (5 diffs)
-
program/steps/mail/func.inc (modified) (5 diffs)
-
program/steps/mail/sendmail.inc (modified) (4 diffs)
-
program/steps/mail/show.inc (modified) (1 diff)
-
program/steps/settings/func.inc (modified) (6 diffs)
-
program/steps/settings/manage_folders.inc (modified) (1 diff)
-
program/steps/settings/save_prefs.inc (modified) (1 diff)
-
skins/default/common.css (modified) (1 diff)
-
skins/default/functions.js (modified) (4 diffs)
-
skins/default/includes/settingstabs.html (modified) (1 diff)
-
skins/default/includes/taskbar.html (modified) (1 diff)
-
skins/default/mail.css (modified) (1 diff)
-
skins/default/splitter.js (modified) (10 diffs)
-
skins/default/templates/addressbook.html (modified) (2 diffs)
-
skins/default/templates/identities.html (modified) (1 diff)
-
skins/default/templates/mail.html (modified) (1 diff)
-
skins/default/templates/managefolders.html (modified) (1 diff)
-
skins/default/templates/message.html (modified) (1 diff)
-
skins/default/templates/plugin.html (copied) (copied from branches/devel-api/skins/default/templates/plugin.html)
-
skins/default/templates/settings.html (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/roundcubemail/config/main.inc.php.dist
r2388 r2401 36 36 $rcmail_config['temp_dir'] = 'temp/'; 37 37 38 // use this folder to search for plugin sources 39 $rcmail_config['plugins_dir'] = 'plugins/'; 40 41 // List of active plugins. Add the name of a directory found in 'plugins_dir' 42 $rcmail_config['plugins'] = array(); 43 38 44 // enable caching of messages and mailbox data in the local database. 39 45 // this is recommended if the IMAP server does not run on the same machine … … 153 159 154 160 // add this user-agent to message headers when sending 155 $rcmail_config['useragent'] = 'RoundCube Webmail/0. 2-beta';161 $rcmail_config['useragent'] = 'RoundCube Webmail/0.3-beta'; 156 162 157 163 // use this name to compose page titles -
trunk/roundcubemail/index.php
r2347 r2401 3 3 +-------------------------------------------------------------------------+ 4 4 | RoundCube Webmail IMAP Client | 5 | Version 0. 2-20080829 |5 | Version 0.3-20090419 | 6 6 | | 7 7 | Copyright (C) 2005-2009, RoundCube Dev. - Switzerland | … … 36 36 // init output class 37 37 $OUTPUT = !empty($_REQUEST['_remote']) ? $RCMAIL->init_json() : $RCMAIL->load_gui(!empty($_REQUEST['_framed'])); 38 39 // init plugin API 40 $RCMAIL->plugins->init(); 38 41 39 42 // set output buffering … … 71 74 } 72 75 76 77 // trigger startup plugin hook 78 $startup = $RCMAIL->plugins->exec_hook('startup', array('task' => $RCMAIL->task, 'action' => $RCMAIL->action)); 79 $RCMAIL->set_task($startup['task']); 80 $RCMAIL->action = $startup['action']; 81 82 73 83 // try to log in 74 84 if ($RCMAIL->action=='login' && $RCMAIL->task=='mail') { 75 85 // purge the session in case of new login when a session already exists 76 $RCMAIL->kill_session(); 77 78 // set IMAP host 79 $host = $RCMAIL->autoselect_host(); 80 86 $RCMAIL->kill_session(); 87 88 $auth = $RCMAIL->plugins->exec_hook('authenticate', array( 89 'host' => $RCMAIL->autoselect_host(), 90 'user' => trim(get_input_value('_user', RCUBE_INPUT_POST)), 91 )) + array('pass' => get_input_value('_pass', RCUBE_INPUT_POST, true, 'ISO-8859-1')); 92 81 93 // check if client supports cookies 82 94 if (empty($_COOKIE)) { 83 95 $OUTPUT->show_message("cookiesdisabled", 'warning'); 84 96 } 85 else if ($_SESSION['temp'] && !empty($_POST['_user']) && !empty($_POST['_pass']) && 86 $RCMAIL->login(trim(get_input_value('_user', RCUBE_INPUT_POST), ' '), 87 get_input_value('_pass', RCUBE_INPUT_POST, true, 'ISO-8859-1'), $host)) { 97 else if ($_SESSION['temp'] && !empty($auth['user']) && !empty($auth['host']) && isset($auth['pass']) && 98 $RCMAIL->login($auth['user'], $auth['pass'], $auth['host'])) { 88 99 // create new session ID 89 100 unset($_SESSION['temp']); … … 100 111 $_SERVER['REMOTE_ADDR'])); 101 112 } 113 114 // restore original request parameters 115 $query = array(); 116 if ($url = get_input_value('_url', RCUBE_INPUT_POST)) 117 parse_str($url, $query); 118 119 // allow plugins to control the redirect url after login success 120 $redir = $RCMAIL->plugins->exec_hook('login_after', $query + array('task' => $RCMAIL->task)); 121 unset($redir['abort']); 102 122 103 123 // send redirect 104 $OUTPUT->redirect( );124 $OUTPUT->redirect($redir); 105 125 } 106 126 else { 107 127 $OUTPUT->show_message($IMAP->error_code < -1 ? 'imaperror' : 'loginfailed', 'warning'); 128 $RCMAIL->plugins->exec_hook('login_failed', array('code' => $IMAP->error_code, 'host' => $auth['host'], 'user' => $auth['user'])); 108 129 $RCMAIL->kill_session(); 109 130 } … … 209 230 $stepfile = !empty($action_map[$RCMAIL->task][$RCMAIL->action]) ? 210 231 $action_map[$RCMAIL->task][$RCMAIL->action] : strtr($RCMAIL->action, '-', '_') . '.inc'; 211 232 233 // execute a plugin action 234 if (eregi('^plugin.', $RCMAIL->action)) { 235 $RCMAIL->plugins->exec_action($RCMAIL->action); 236 break; 237 } 212 238 // try to include the step file 213 if (is_file(($incfile = 'program/steps/'.$RCMAIL->task.'/'.$stepfile))) {239 else if (is_file(($incfile = 'program/steps/'.$RCMAIL->task.'/'.$stepfile))) { 214 240 include($incfile); 215 241 $redirects++; -
trunk/roundcubemail/plugins/filesystem_attachments/filesystem_attachments.php
r2400 r2401 50 50 $args['status'] = false; 51 51 $rcmail = rcmail::get_instance(); 52 52 53 53 // use common temp dir for file uploads 54 $temp_dir = unslashify($rcmail->config->get('temp_dir')); 54 // #1484529: we need absolute path on Windows for move_uploaded_file() 55 $temp_dir = realpath($rcmail->config->get('temp_dir')); 55 56 $tmpfname = tempnam($temp_dir, 'rcmAttmnt'); 56 57 if (move_uploaded_file($args['path'], $tmpfname) ) {57 58 if (move_uploaded_file($args['path'], $tmpfname) && file_exists($tmpfname)) { 58 59 $args['id'] = count($_SESSION['plugins']['filesystem_attachments']['tmp_files'])+1; 59 60 $args['path'] = $tmpfname; -
trunk/roundcubemail/plugins/show_additional_headers/show_additional_headers.php
r2400 r2401 38 38 function message_headers($p) 39 39 { 40 console($p['headers']);41 40 $rcmail = rcmail::get_instance(); 42 41 foreach ($rcmail->config->get('show_additional_headers', array()) as $header) { -
trunk/roundcubemail/program/include/html.php
r2237 r2401 34 34 35 35 public static $common_attrib = array('id','class','style','title','align'); 36 public static $containers = array('iframe','div','span','p','h1','h2','h3','form','textarea','table','tr','th','td','style' );36 public static $containers = array('iframe','div','span','p','h1','h2','h3','form','textarea','table','tr','th','td','style','script'); 37 37 public static $lc_tags = true; 38 38 … … 600 600 } 601 601 602 /** 603 * Remove a column from a table 604 * Useful for plugins making alterations 605 * 606 * @param string $class 607 */ 608 public function remove_column($class) 609 { 610 // Remove the header 611 foreach($this->header as $index=>$header){ 612 if($header->attrib['class'] == $class){ 613 unset($this->header[$index]); 614 break; 615 } 616 } 617 618 // Remove cells from rows 619 foreach($this->rows as $i=>$row){ 620 foreach($row->cells as $j=>$cell){ 621 if($cell->attrib['class'] == $class){ 622 unset($this->rows[$i]->cells[$j]); 623 break; 624 } 625 } 626 } 627 } 628 629 602 630 /** 603 631 * Jump to next row -
trunk/roundcubemail/program/include/iniset.php
r2345 r2401 23 23 24 24 // application constants 25 define('RCMAIL_VERSION', '0. 2-trunk');25 define('RCMAIL_VERSION', '0.3-trunk'); 26 26 define('RCMAIL_CHARSET', 'UTF-8'); 27 27 define('JS_OBJECT_NAME', 'rcmail'); -
trunk/roundcubemail/program/include/main.inc
r2352 r2401 89 89 * @see rcmail::gettext() 90 90 */ 91 function rcube_label($p )92 { 93 return rcmail::get_instance()->gettext($p );91 function rcube_label($p, $domain=null) 92 { 93 return rcmail::get_instance()->gettext($p, $domain); 94 94 } 95 95 … … 303 303 function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) 304 304 { 305 global $OUTPUT;306 305 static $html_encode_arr = false; 307 306 static $js_rep_table = false; 308 307 static $xml_rep_table = false; 309 308 310 $charset = $OUTPUT->get_charset();309 $charset = rcmail::get_instance()->config->get('charset', RCMAIL_CHARSET); 311 310 $is_iso_8859_1 = false; 312 311 if ($charset == 'ISO-8859-1') { … … 693 692 694 693 // convert attributes to an associative array (name => value) 695 if ($regs) 696 foreach ($regs as $attr) 697 {698 $attrib[strtolower($attr[1])] = $attr[3] . $attr[4];699 }694 if ($regs) { 695 foreach ($regs as $attr) { 696 $attrib[strtolower($attr[1])] = html_entity_decode($attr[3] . $attr[4]); 697 } 698 } 700 699 701 700 return $attrib; … … 830 829 function console() 831 830 { 831 $args = func_get_args(); 832 if (class_exists('rcmail', false)) 833 rcmail::get_instance()->plugins->exec_hook('console', $args); 834 832 835 $msg = array(); 833 foreach ( func_get_args()as $arg)834 $msg[] = !is_string($arg) ? var_export($arg, true) : $arg;836 foreach ($args as $arg) 837 $msg[] = !is_string($arg) ? var_export($arg, true) : $arg; 835 838 836 839 if (!($GLOBALS['CONFIG']['debug_level'] & 4)) -
trunk/roundcubemail/program/include/rcmail.php
r2388 r2401 38 38 public $imap; 39 39 public $output; 40 public $plugins; 40 41 public $task = 'mail'; 41 42 public $action = ''; … … 89 90 openlog($syslog_id, LOG_ODELAY, $syslog_facility); 90 91 } 91 92 92 93 // set task and action properties 93 94 $this->set_task(strip_quotes(get_input_value('_task', RCUBE_INPUT_GPC))); … … 132 133 if ($this->task == 'mail') 133 134 $this->imap_init(); 135 136 // create plugin API and load plugins 137 $this->plugins = rcube_plugin_api::get_instance(); 134 138 } 135 139 … … 256 260 $ldap_config = (array)$this->config->get('ldap_public'); 257 261 $abook_type = strtolower($this->config->get('address_book_type')); 258 259 if ($id && $ldap_config[$id]) { 262 263 $plugin = $this->plugins->exec_hook('get_address_book', array('id' => $id, 'writeable' => $writeable)); 264 265 // plugin returned instance of a rcube_addressbook 266 if ($plugin['instance'] instanceof rcube_addressbook) { 267 $contacts = $plugin['instance']; 268 } 269 else if ($id && $ldap_config[$id]) { 260 270 $contacts = new rcube_ldap($ldap_config[$id]); 271 } 272 else if ($id === '0') { 273 $contacts = new rcube_contacts($this->db, $this->user->ID); 261 274 } 262 275 else if ($abook_type == 'ldap') { … … 599 612 * @return string Localized text 600 613 */ 601 public function gettext($attrib )614 public function gettext($attrib, $domain=null) 602 615 { 603 616 // load localization files if not done yet … … 614 627 $command_name = !empty($attrib['command']) ? $attrib['command'] : NULL; 615 628 $alias = $attrib['name'] ? $attrib['name'] : ($command_name && $command_label_map[$command_name] ? $command_label_map[$command_name] : ''); 616 629 630 // check for text with domain 631 if ($domain && ($text_item = $this->texts[$domain.'.'.$alias])) 632 ; 617 633 // text does not exist 618 if (!($text_item = $this->texts[$alias])) {634 else if (!($text_item = $this->texts[$alias])) { 619 635 /* 620 636 raise_error(array( … … 678 694 * @param string Language ID 679 695 */ 680 public function load_language($lang = null )696 public function load_language($lang = null, $add = array()) 681 697 { 682 698 $lang = $this->language_prop(($lang ? $lang : $_SESSION['language'])); … … 708 724 $_SESSION['language'] = $lang; 709 725 } 726 727 // append additional texts (from plugin) 728 if (is_array($add) && !empty($add)) 729 $this->texts += $add; 710 730 } 711 731 … … 921 941 if (!is_array($p)) 922 942 $p = array('_action' => @func_get_arg(0)); 923 924 if (!$p['task'] || !in_array($p['task'], rcmail::$main_tasks)) 925 $p['task'] = $this->task; 926 927 $p['_task'] = $p['task']; 943 944 $task = $p['_task'] ? $p['_task'] : $p['task']; 945 if (!$task || !in_array($task, rcmail::$main_tasks)) 946 $task = $this->task; 947 948 $p['_task'] = $task; 928 949 unset($p['task']); 929 950 930 951 $url = './'; 931 952 $delm = '?'; 932 foreach (array_reverse($p) as $ par=> $val)953 foreach (array_reverse($p) as $key => $val) 933 954 { 934 955 if (!empty($val)) { 956 $par = $key[0] == '_' ? $key : '_'.$key; 935 957 $url .= $delm.urlencode($par).'='.urlencode($val); 936 958 $delm = '&'; -
trunk/roundcubemail/program/include/rcube_config.php
r2237 r2401 75 75 $this->prop['log_dir'] = $this->prop['log_dir'] ? unslashify($this->prop['log_dir']) : INSTALL_PATH . 'logs'; 76 76 $this->prop['temp_dir'] = $this->prop['temp_dir'] ? unslashify($this->prop['temp_dir']) : INSTALL_PATH . 'temp'; 77 $this->prop['plugins_dir'] = $this->prop['plugins_dir'] ? unslashify($this->prop['plugins_dir']) : INSTALL_PATH . 'plugins'; 77 78 78 79 // fix default imap folders encoding -
trunk/roundcubemail/program/include/rcube_contacts.php
r2237 r2401 26 26 * @package Addressbook 27 27 */ 28 class rcube_contacts 28 class rcube_contacts extends rcube_addressbook 29 29 { 30 30 var $db = null; … … 61 61 62 62 /** 63 * Set internal list page64 *65 * @param number Page number to list66 * @access public67 */68 function set_page($page)69 {70 $this->list_page = (int)$page;71 }72 73 74 /**75 * Set internal page size76 *77 * @param number Number of messages to display on one page78 * @access public79 */80 function set_pagesize($size)81 {82 $this->page_size = (int)$size;83 }84 85 86 /**87 63 * Save a search string for future listings 88 64 * … … 116 92 $this->search_string = null; 117 93 } 118 119 120 /**121 * Close connection to source122 * Called on script shutdown123 */124 function close(){}125 94 126 95 … … 234 203 * @return Result array or NULL if nothing selected yet 235 204 */ 236 function get_result( $as_res=true)205 function get_result() 237 206 { 238 207 return $this->result; -
trunk/roundcubemail/program/include/rcube_html_page.php
r2237 r2401 32 32 protected $charset = 'UTF-8'; 33 33 34 protected $script_tag_file = "<script type=\"text/javascript\" src=\"%s %s\"></script>\n";35 protected $script_tag = "<script type=\"text/javascript\">\n<!--\n%s\n\n//-->\n</script>\n";34 protected $script_tag_file = "<script type=\"text/javascript\" src=\"%s\"></script>\n"; 35 protected $script_tag = "<script type=\"text/javascript\">\n/* <![CDATA[ */\n%s\n/* ]]> */\n</script>"; 36 36 protected $default_template = "<html>\n<head><title></title></head>\n<body></body>\n</html>"; 37 37 … … 54 54 { 55 55 static $sa_files = array(); 56 57 if (!ereg('^https?://', $file) && $file[0] != '/') 58 $file = $this->scripts_path . $file; 56 59 57 60 if (in_array($file, $sa_files)) { … … 166 169 if (is_array($this->script_files['head'])) { 167 170 foreach ($this->script_files['head'] as $file) { 168 $__page_header .= sprintf($this->script_tag_file, $ this->scripts_path, $file);171 $__page_header .= sprintf($this->script_tag_file, $file); 169 172 } 170 173 } … … 181 184 if (is_array($this->script_files['foot'])) { 182 185 foreach ($this->script_files['foot'] as $file) { 183 $__page_footer .= sprintf($this->script_tag_file, $ this->scripts_path, $file);186 $__page_footer .= sprintf($this->script_tag_file, $file); 184 187 } 185 188 } -
trunk/roundcubemail/program/include/rcube_imap.php
r2389 r2401 56 56 var $default_folders = array('INBOX'); 57 57 var $default_folders_lc = array('inbox'); 58 var $fetch_add_headers = ''; 58 59 var $cache = array(); 59 60 var $cache_keys = array(); … … 429 430 return $a_mboxes; 430 431 431 // retrieve list of folders from IMAP server 432 $a_folders = iil_C_ListSubscribed($this->conn, $this->_mod_mailbox($root), $filter); 432 // Give plugins a chance to provide a list of mailboxes 433 $data = rcmail::get_instance()->plugins->exec_hook('list_mailboxes',array('root'=>$root,'filter'=>$filter)); 434 if (isset($data['folders'])) { 435 $a_folders = $data['folders']; 436 } 437 else{ 438 // retrieve list of folders from IMAP server 439 $a_folders = iil_C_ListSubscribed($this->conn, $this->_mod_mailbox($root), $filter); 440 } 441 433 442 434 443 if (!is_array($a_folders) || !sizeof($a_folders)) … … 776 785 777 786 // fetch reuested headers from server 778 $a_header_index = iil_C_FetchHeaders($this->conn, $mailbox, $msgs );787 $a_header_index = iil_C_FetchHeaders($this->conn, $mailbox, $msgs, false, $this->fetch_add_headers); 779 788 $deleted_count = 0; 780 789 … … 830 839 $this->search('', $this->search_string, $this->search_charset, $this->sort_field); 831 840 832 if ($this->sort_order == 'DESC')841 if ($this->sort_order == 'DESC') 833 842 $this->cache[$key] = array_reverse($this->search_set); 834 else835 $this->cache[$key] = $this->search_set;843 else 844 $this->cache[$key] = $this->search_set; 836 845 } 837 846 else 838 847 { 839 $a_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, join(',', $this->search_set), $this->sort_field);848 $a_index = iil_C_FetchHeaderIndex($this->conn, $mailbox, join(',', $this->search_set), $this->sort_field, false); 840 849 841 850 if ($this->sort_order=="ASC") … … 924 933 925 934 // fetch complete headers and add to cache 926 $headers = iil_C_FetchHeader($this->conn, $mailbox, $id );935 $headers = iil_C_FetchHeader($this->conn, $mailbox, $id, false, $this->fetch_add_headers); 927 936 $this->add_message_cache($cache_key, $headers->id, $headers); 928 937 } … … 1063 1072 return $headers; 1064 1073 1065 $headers = iil_C_FetchHeader($this->conn, $mailbox, $id, $is_uid, $bodystr );1074 $headers = iil_C_FetchHeader($this->conn, $mailbox, $id, $is_uid, $bodystr, $this->fetch_add_headers); 1066 1075 1067 1076 // write headers cache … … 2228 2237 { 2229 2238 // get highest index 2230 $header = iil_C_FetchHeader($this->conn, $mailbox, "$msg_count" );2239 $header = iil_C_FetchHeader($this->conn, $mailbox, "$msg_count", false, $this->fetch_add_headers); 2231 2240 $cache_uid = array_pop($cache_index); 2232 2241 … … 2278 2287 // featch headers if unserialize failed 2279 2288 if (empty($this->cache[$cache_key][$uid])) 2280 $this->cache[$cache_key][$uid] = iil_C_FetchHeader($this->conn, preg_replace('/.msg$/', '', $key), $uid, true );2289 $this->cache[$cache_key][$uid] = iil_C_FetchHeader($this->conn, preg_replace('/.msg$/', '', $key), $uid, true, $this->fetch_add_headers); 2281 2290 } 2282 2291 } -
trunk/roundcubemail/program/include/rcube_json_output.php
r2237 r2401 197 197 * @deprecated 198 198 */ 199 public function remote_response($add='' , $flush=false)199 public function remote_response($add='') 200 200 { 201 201 static $s_header_sent = false; … … 204 204 $s_header_sent = true; 205 205 send_nocacheing_headers(); 206 header('Content-Type: application/x-javascript; charset=' . $this->get_charset());206 header('Content-Type: text/plain; charset=' . $this->get_charset()); 207 207 print '/** ajax response ['.date('d/M/Y h:i:s O')."] **/\n"; 208 208 } … … 211 211 unset($this->env['task'], $this->env['action'], $this->env['comm_path']); 212 212 213 $rcmail = rcmail::get_instance(); 214 $response = array('action' => $rcmail->action, 'unlock' => (bool)$_REQUEST['_unlock']); 215 216 if (!empty($this->env)) 217 $response['env'] = $this->env; 218 219 if (!empty($this->texts)) 220 $response['texts'] = $this->texts; 221 213 222 // send response code 214 echo $this->get_js_commands() . $add; 215 216 // flush the output buffer 217 if ($flush) 218 flush(); 223 $response['exec'] = $this->get_js_commands() . $add; 224 225 echo json_serialize($response); 219 226 } 220 227 … … 228 235 { 229 236 $out = ''; 230 231 if (sizeof($this->env))232 $out .= 'this.set_env('.json_serialize($this->env).");\n";233 237 234 foreach($this->texts as $name => $text) {235 $out .= sprintf("this.add_label('%s', '%s');\n", $name, JQ($text));236 }237 238 238 foreach ($this->commands as $i => $args) { 239 239 $method = array_shift($args); -
trunk/roundcubemail/program/include/rcube_ldap.php
r2237 r2401 25 25 * @package Addressbook 26 26 */ 27 class rcube_ldap 27 class rcube_ldap extends rcube_addressbook 28 28 { 29 29 var $conn; -
trunk/roundcubemail/program/include/rcube_message.php
r2294 r2401 85 85 $this->body = $this->imap->get_body($uid); 86 86 } 87 88 // notify plugins and let them analyze this structured message object 89 $this->app->plugins->exec_hook('message_load', array('object' => $this)); 87 90 } 88 91 -
trunk/roundcubemail/program/include/rcube_template.php
r2237 r2401 67 67 68 68 // don't wait for page onload. Call init at the bottom of the page (delayed) 69 $javascript_foot = "if (window.call_init)\n call_init('".JS_OBJECT_NAME."');";69 $javascript_foot = '$(document).ready(function(){ '.JS_OBJECT_NAME.'.init(); });'; 70 70 71 71 $this->add_script($javascript, 'head_top'); 72 72 $this->add_script($javascript_foot, 'foot'); 73 73 $this->scripts_path = 'program/js/'; 74 $this->include_script('http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js'); 74 75 $this->include_script('common.js'); 75 76 $this->include_script('app.js'); … … 209 210 public function add_label() 210 211 { 211 $arg_list = func_get_args(); 212 foreach ($arg_list as $i => $name) { 212 $args = func_get_args(); 213 if (count($args) == 1 && is_array($args[0])) 214 $args = $args[0]; 215 216 foreach ($args as $name) { 213 217 $this->command('add_label', $name, rcube_label($name)); 214 218 } … … 376 380 $out .= sprintf( 377 381 "%s.%s(%s);\n", 378 ($parent ? 'parent.' : '') . JS_OBJECT_NAME,379 preg_replace('/^parent\./', '', $method),380 implode(',', $args)382 ($parent ? 'if(window.parent && parent.'.JS_OBJECT_NAME.') parent.' : '') . JS_OBJECT_NAME, 383 preg_replace('/^parent\./', '', $method), 384 implode(',', $args) 381 385 ); 382 386 } … … 512 516 private function parse_xml($input) 513 517 { 514 return preg_replace_callback('/<roundcube:([-_a-z]+)\s+([^>]+)>/Ui', array($this, 'xml_command_callback'), $input); 515 } 516 517 518 /** 519 * This is a callback function for preg_replace_callback (see #1485286) 520 * It's only purpose is to reconfigure parameters for xml_command, so that the signature isn't disturbed 521 */ 522 private function xml_command_callback($matches) 523 { 524 $str_attrib = isset($matches[2]) ? $matches[2] : ''; 525 $add_attrib = isset($matches[3]) ? $matches[3] : array(); 526 527 $command = $matches[1]; 528 //matches[0] is the entire matched portion of the string 529 530 return $this->xml_command($command, $str_attrib, $add_attrib); 531 } 532 533 534 /** 535 * Convert a xml command tag into real content 536 * 537 * @param string Tag command: object,button,label, etc. 538 * @param string Attribute string 518 return preg_replace_callback('/<roundcube:([-_a-z]+)\s+([^>]+)>/Ui', array($this, 'xml_command'), $input); 519 } 520 521 522 /** 523 * Callback function for parsing an xml command tag 524 * and turn it into real html content 525 * 526 * @param array Matches array of preg_replace_callback 539 527 * @return string Tag/Object content 540 528 */ 541 private function xml_command($ command, $str_attrib, $add_attrib = array())542 { 543 $command = strtolower($ command);544 $attrib = parse_attrib_string($ str_attrib) + $add_attrib;529 private function xml_command($matches) 530 { 531 $command = strtolower($matches[1]); 532 $attrib = parse_attrib_string($matches[2]); 545 533 546 534 // empty output if required condition is not met … … 573 561 } 574 562 else { 575 $incl = file_get_contents($path);576 }563 $incl = file_get_contents($path); 564 } 577 565 return $this->parse_xml($incl); 578 566 } … … 580 568 581 569 case 'plugin.include': 582 //rcube::tfk_debug(var_export($this->config['skin_path'], true));583 $path = realpath($this->config['skin_path'].$attrib['file']);584 if (!$path) {585 //rcube::tfk_debug("Does not exist:");586 //rcube::tfk_debug($this->config['skin_path']);587 //rcube::tfk_debug($attrib['file']);588 //rcube::tfk_debug($path);589 }590 $incl = file_get_contents($path);591 if ($incl) {592 return $ this->parse_xml($incl);570 $hook = $this->app->plugins->exec_hook("template_plugin_include", $attrib); 571 return $hook['content']; 572 break; 573 574 // define a container block 575 case 'container': 576 if ($attrib['name'] && $attrib['id']) { 577 $this->command('gui_container', $attrib['name'], $attrib['id']); 578 // let plugins insert some content here 579 $hook = $this->app->plugins->exec_hook("template_container", $attrib); 580 return $hook['content']; 593 581 } 594 582 break; … … 597 585 case 'object': 598 586 $object = strtolower($attrib['name']); 587 $content = ''; 599 588 600 589 // we are calling a class/method … … 602 591 if ((is_object($handler[0]) && method_exists($handler[0], $handler[1])) || 603 592 (is_string($handler[0]) && class_exists($handler[0]))) 604 return call_user_func($handler, $attrib); 605 } 593 $content = call_user_func($handler, $attrib); 594 } 595 // execute object handler function 606 596 else if (function_exists($handler)) { 607 // execute object handler function 608 return call_user_func($handler, $attrib); 609 } 610 611 if ($object=='productname') { 597 $content = call_user_func($handler, $attrib); 598 } 599 else if ($object == 'productname') { 612 600 $name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'RoundCube Webmail'; 613 returnQ($name);614 } 615 if ($object=='version') {601 $content = Q($name); 602 } 603 else if ($object == 'version') { 616 604 $ver = (string)RCMAIL_VERSION; 617 605 if (is_file(INSTALL_PATH . '.svn/entries')) { … … 619 607 $ver .= ' [SVN r'.$regs[1].']'; 620 608 } 621 return $ver;622 } 623 if ($object=='steptitle') {624 returnQ($this->get_pagetitle());625 } 626 if ($object=='pagetitle') {609 $content = Q($ver); 610 } 611 else if ($object == 'steptitle') { 612 $content = Q($this->get_pagetitle()); 613 } 614 else if ($object == 'pagetitle') { 627 615 $title = !empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : ''; 628 616 $title .= $this->get_pagetitle(); 629 return Q($title); 630 } 631 break; 617 $content = Q($title); 618 } 619 620 // exec plugin hooks for this template object 621 $hook = $this->app->plugins->exec_hook("template_object_$object", $attrib + array('content' => $content)); 622 return $hook['content']; 632 623 633 624 // return code for a specified eval expression 634 625 case 'exp': 635 $value = $this->parse_expression($attrib['expression']);626 $value = $this->parse_expression($attrib['expression']); 636 627 return eval("return Q($value);"); 637 628 … … 703 694 704 695 // these commands can be called directly via url 705 $a_static_commands = array('compose', 'list' );696 $a_static_commands = array('compose', 'list', 'preferences', 'folders', 'identities'); 706 697 707 698 if (!($attrib['command'] || $attrib['name'])) { … … 942 933 943 934 $_SESSION['temp'] = true; 935 936 // save original url 937 $url = get_input_value('_url', RCUBE_INPUT_POST); 938 if (empty($url) && !preg_match('/_action=logout/', $_SERVER['QUERY_STRING'])) 939 $url = $_SERVER['QUERY_STRING']; 944 940 945 941 $input_user = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30) + $attrib); … … 947 943 $input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login')); 948 944 $input_tzone = new html_hiddenfield(array('name' => '_timezone', 'id' => 'rcmlogintz', 'value' => '_default_')); 945 $input_url = new html_hiddenfield(array('name' => '_url', 'id' => 'rcmloginurl', 'value' => $url)); 949 946 $input_host = null; 950 947 … … 986 983 $out = $input_action->show(); 987 984 $out .= $input_tzone->show(); 985 $out .= $input_url->show(); 988 986 $out .= $table->show(); 989 987 -
trunk/roundcubemail/program/include/rcube_user.php
r2384 r2401 347 347 static function create($user, $host) 348 348 { 349 $user_name = ''; 349 350 $user_email = ''; 350 351 $rcmail = rcmail::get_instance(); 352 353 $data = $rcmail->plugins->exec_hook('create_user', array('user'=>$user, 'user_name'=>$user_name, 'user_email'=>$user_email)); 354 $user_name = $data['user_name']; 355 $user_email = $data['user_email']; 356 351 357 $dbh = $rcmail->get_dbh(); 352 358 353 359 // try to resolve user in virtuser table and file 354 if ( !strpos($user, '@')) {360 if ($user_email != '' && !strpos($user, '@')) { 355 361 if ($email_list = self::user2email($user, false)) 356 362 $user_email = $email_list[0]; 357 363 } 358 364 359 365 $dbh->query( 360 366 "INSERT INTO ".get_table_name('users')." … … 373 379 $user_email = strpos($user, '@') ? $user : sprintf('%s@%s', $user, $mail_domain); 374 380 375 $user_name = $user != $user_email ? $user : ''; 381 if ($user_name == '') { 382 $user_name = $user != $user_email ? $user : ''; 383 } 376 384 377 385 if (empty($email_list)) … … 386 394 VALUES (?, 0, ?, ?, ?)", 387 395 $user_id, 388 $standard,396 $standard, 389 397 strip_newlines($user_name), 390 398 preg_replace('/^@/', $user . '@', $email)); 391 $standard = 0;399 $standard = 0; 392 400 } 393 401 } … … 447 455 if (strpos($sql_arr[0], '@')) { 448 456 $result[] = $sql_arr[0]; 449 if ($first)450 return $result[0];451 }457 if ($first) 458 return $result[0]; 459 } 452 460 } 453 461 // File lookup … … 461 469 $result[] = trim(str_replace('\\@', '@', $arr[0])); 462 470 463 if ($first)471 if ($first) 464 472 return $result[0]; 465 473 } -
trunk/roundcubemail/program/include/rcube_vcard.php
r2283 r2401 264 264 } 265 265 266 if (!preg_match('/^(BEGIN|END)$/ ', $line[1]) && preg_match_all('/([^\\;]+);?/', $line[1], $regs2)) {266 if (!preg_match('/^(BEGIN|END)$/i', $line[1]) && preg_match_all('/([^\\;]+);?/', $line[1], $regs2)) { 267 267 $entry = array(''); 268 $field = $regs2[1][0];268 $field = strtoupper($regs2[1][0]); 269 269 270 270 foreach($regs2[1] as $attrid => $attr) { -
trunk/roundcubemail/program/js/app.js
r2394 r2401 11 11 | Charles McNulty <charles@charlesmcnulty.com> | 12 12 +-----------------------------------------------------------------------+ 13 | Requires: common.js, list.js|13 | Requires: jquery.js, common.js, list.js | 14 14 +-----------------------------------------------------------------------+ 15 15 … … 18 18 19 19 20 var rcube_webmail_client;21 22 20 function rcube_webmail() 23 {21 { 24 22 this.env = new Object(); 25 23 this.labels = new Object(); 26 24 this.buttons = new Object(); 27 25 this.gui_objects = new Object(); 26 this.gui_containers = new Object(); 28 27 this.commands = new Object(); 28 this.command_handlers = new Object(); 29 29 this.onloads = new Array(); 30 30 31 31 // create protected reference to myself 32 rcube_webmail_client = this; 33 this.ref = 'rcube_webmail_client'; 32 this.ref = 'rcmail'; 34 33 var ref = this; 35 34 … … 54 53 this.env.blankpage = 'program/blank.gif'; 55 54 55 // set jQuery ajax options 56 jQuery.ajaxSetup({ cache:false, 57 error:function(request, status, err){ ref.http_error(request, status, err); }, 58 beforeSend:function(xmlhttp){ xmlhttp.setRequestHeader('X-RoundCube-Referer', bw.get_cookie('roundcube_sessid')); } 59 }); 60 56 61 // set environment variable(s) 57 62 this.set_env = function(p, value) … … 90 95 }; 91 96 97 // register a container object 98 this.gui_container = function(name, id) 99 { 100 this.gui_containers[name] = id; 101 }; 102 103 // add a GUI element (html node) to a specified container 104 this.add_element = function(elm, container) 105 { 106 if (this.gui_containers[container] && this.gui_containers[container].jquery) 107 this.gui_containers[container].append(elm); 108 }; 109 110 // register an external handler for a certain command 111 this.register_command = function(command, callback, enable) 112 { 113 this.command_handlers[command] = callback; 114 115 if (enable) 116 this.enable_command(command, true); 117 }; 118 92 119 // execute the given script on load 93 120 this.add_onload = function(f) 94 {95 this.onloads[this.onloads.length] = f;96 };121 { 122 this.onloads[this.onloads.length] = f; 123 }; 97 124 98 125 // initialize webmail client … … 109 136 } 110 137 138 // find all registered gui containers 139 for (var n in this.gui_containers) 140 this.gui_containers[n] = $('#'+this.gui_containers[n]); 141 111 142 // find all registered gui objects 112 143 for (var n in this.gui_objects) … … 136 167 this.message_list.addEventListener('dragmove', function(o, e){ p.drag_move(e); }); 137 168 this.message_list.addEventListener('dragend', function(o){ p.drag_active = false; }); 169 document.onmouseup = function(e){ return p.doc_mouse_up(e); }; 138 170 139 171 this.message_list.init(); … … 141 173 142 174 if (this.gui_objects.mailcontframe) 143 {144 175 this.gui_objects.mailcontframe.onmousedown = function(e){ return p.click_on_list(e); }; 145 document.onmouseup = function(e){ return p.doc_mouse_up(e); };146 }147 176 else 148 177 this.message_list.focus(); … … 197 226 this.env.spellcheck.spelling_state_observer = function(s){ ref.set_spellcheck_state(s); }; 198 227 this.set_spellcheck_state('ready'); 199 if ( rcube_find_object('_is_html').value== '1')228 if ($("input[name='_is_html']").val() == '1') 200 229 this.display_spellcheck_controls(false); 201 230 } … … 264 293 else 265 294 this.contact_list.focus(); 295 296 this.gui_objects.folderlist = this.gui_objects.contactslist; 266 297 } 267 298 … … 317 348 318 349 case 'login': 319 var input_user = rcube_find_object('rcmloginuser'); 320 var input_pass = rcube_find_object('rcmloginpwd'); 321 var input_tz = rcube_find_object('rcmlogintz'); 322 323 if (input_user) 324 input_user.onkeyup = function(e){ return rcmail.login_user_keyup(e); }; 325 if (input_user && input_user.value=='') 350 var input_user = $('#rcmloginuser'); 351 input_user.bind('keypress', function(e){ return rcmail.login_user_keyup(e); }); 352 353 if (input_user.val() == '') 326 354 input_user.focus(); 327 else if (input_pass)328 input_pass.focus();355 else 356 $('#rcmloginpwd').focus(); 329 357 330 358 // detect client timezone 331 if (input_tz) 332 input_tz.value = new Date().getTimezoneOffset() / -60; 359 $('#rcmlogintz').val(new Date().getTimezoneOffset() / -60); 333 360 334 361 this.enable_command('login', true); … … 348 375 if (this.pending_message) 349 376 this.display_message(this.pending_message[0], this.pending_message[1]); 350 351 // start keep-alive interval 352 this.start_keepalive(); 377 378 // map implicit containers 379 if (this.gui_objects.folderlist) 380 this.gui_containers.foldertray = $(this.gui_objects.folderlist); 381 382 // trigger init event hook 383 this.triggerEvent('init', { task:this.task, action:this.env.action }); 353 384 354 385 // execute all foreign onload scripts 386 // @deprecated 355 387 for (var i=0; i<this.onloads.length; i++) 356 388 { … … 360 392 this.onloads[i](); 361 393 } 362 }; 394 395 // start keep-alive interval 396 this.start_keepalive(); 397 }; 363 398 364 399 // start interval for keep-alive/recent_check signal … … 418 453 419 454 //this.messageform = this.gui_objects.messageform; 420 var input_from = rcube_find_object('_from'); 421 var input_to = rcube_find_object('_to'); 422 var input_cc = rcube_find_object('_cc'); 423 var input_bcc = rcube_find_object('_bcc'); 424 var input_replyto = rcube_find_object('_replyto'); 425 var input_subject = rcube_find_object('_subject'); 426 var input_message = rcube_find_object('_message'); 427 var draftid = rcube_find_object('_draft_saveid'); 455 var input_from = $("[name='_from']"); 456 var input_to = $("[name='_to']"); 457 var input_subject = $("input[name='_subject']"); 458 var input_message = $("[name='_message']").get(0); 428 459 429 460 // init live search events 430 if (input_to) 431 this.init_address_input_events(input_to); 432 if (input_cc) 433 this.init_address_input_events(input_cc); 434 if (input_bcc) 435 this.init_address_input_events(input_bcc); 461 this.init_address_input_events(input_to); 462 this.init_address_input_events($("[name='_cc']")); 463 this.init_address_input_events($("[name='_bcc']")); 436 464 437 465 // add signature according to selected identity 438 if (input_from && input_from.type=='select-one' && (!draftid || draftid.value=='') 439 // if we have HTML editor, signature is added in callback 440 && rcube_find_object('_is_html').value != '1') 441 { 442 this.change_identity(input_from); 443 } 444 445 if (input_to && input_to.value=='') 466 if (input_from.attr('type') == 'select-one' && $("input[name='_draft_saveid']").val() == '' 467 && $("input[name='_is_html']").val() != '1') { // if we have HTML editor, signature is added in callback 468 this.change_identity(input_from[0]); 469 } 470 471 if (input_to.val() == '') 446 472 input_to.focus(); 447 else if (input_subject && input_subject.value=='')473 else if (input_subject.val() == '') 448 474 input_subject.focus(); 449 475 else if (input_message) … … 460 486 { 461 487 var handler = function(e){ return ref.ksearch_keypress(e,this); }; 462 463 if (obj.addEventListener) 464 obj.addEventListener(bw.safari ? 'keydown' : 'keypress', handler, false); 465 else 466 obj.onkeydown = handler; 467 468 obj.setAttribute('autocomplete', 'off'); 488 obj.bind((bw.safari ? 'keydown' : 'keypress'), handler); 489 obj.attr('autocomplete', 'off'); 469 490 }; 470 491 … … 500 521 } 501 522 502 // process command 523 // process external commands 524 if (typeof this.command_handlers[command] == 'function') 525 { 526 var ret = this.command_handlers[command](props, obj); 527 return ret !== null ? ret : (obj ? false : true); 528 } 529 else if (typeof this.command_handlers[command] == 'string') 530 { 531 var ret = window[this.command_handlers[command]](props, obj); 532 return ret !== null ? ret : (obj ? false : true); 533 } 534 535 // trigger plugin hook 536 var event_ret = this.triggerEvent('before'+command, props); 537 if (typeof event_ret != 'undefined') { 538 // abort if one the handlers returned false 539 if (event_ret === false) 540 return false; 541 else 542 props = event_ret; 543 } 544 545 // process internal command 503 546 switch (command) 504 547 { … … 510 553 case 'logout': 511 554 this.goto_url('logout', '', true); 512 break; 555 break; 513 556 514 557 // commands to switch task … … 559 602 var sort_col = a_sort[0]; 560 603 var sort_order = a_sort[1] ? a_sort[1].toUpperCase() : null; 561 var header;562 604 563 605 // no sort order specified: toggle … … 574 616 575 617 // set table header class 576 if (header = document.getElementById('rcm'+this.env.sort_col)) 577 this.set_classname(header, 'sorted'+(this.env.sort_order.toUpperCase()), false); 578 if (header = document.getElementById('rcm'+sort_col)) 579 this.set_classname(header, 'sorted'+sort_order, true); 618 $('#rcm'+this.env.sort_col).removeClass('sorted'+(this.env.sort_order.toUpperCase())); 619 $('#rcm'+sort_col).addClass('sorted'+sort_order); 580 620 581 621 // save new sort properties … … 658 698 if (this.gui_objects.editform) 659 699 { 660 var input_pagesize = rcube_find_object('_pagesize');661 var input_name = rcube_find_object('_name');662 var input_email = rcube_find_object('_email');700 var input_pagesize = $("input[name='_pagesize']"); 701 var input_name = $("input[name='_name']"); 702 var input_email = $("input[name='_email']"); 663 703 664 704 // user prefs 665 if (input_pagesize && isNaN(parseInt(input_pagesize.value)))705 if (input_pagesize.length && isNaN(parseInt(input_pagesize.val()))) 666 706 { 667 707 alert(this.get_label('nopagesizewarning')); … … 672 712 else 673 713 { 674 if (input_name && input_name.value== '')714 if (input_name.length && input_name.val() == '') 675 715 { 676 716 alert(this.get_label('nonamewarning')); … … 678 718 break; 679 719 } 680 else if (input_email && !rcube_check_email(input_email.value))720 else if (input_email.length && !rcube_check_email(input_email.val())) 681 721 { 682 722 alert(this.get_label('noemailwarning')); … … 1063 1103 1064 1104 } 1105 1106 this.triggerEvent('after'+command, props); 1065 1107 1066 1108 return obj ? false : true; … … 1115 1157 1116 1158 // return a localized string 1117 this.get_label = function(name) 1118 { 1119 if (this.labels[name]) 1159 this.get_label = function(name, domain) 1160 { 1161 if (domain && this.labels[domain+'.'+name]) 1162 return this.labels[domain+'.'+name]; 1163 else if (this.labels[name]) 1120 1164 return this.labels[name]; 1121 1165 else 1122 1166 return name; 1123 1167 }; 1168 1169 // alias for convenience reasons 1170 this.gettext = this.get_label; 1124 1171 1125 1172 // switch to another application task … … 1158 1205 this.doc_mouse_up = function(e) 1159 1206 { 1160 var model, li ;1207 var model, list, li; 1161 1208 1162 1209 if (this.message_list) { 1163 1210 if (!rcube_mouse_is_over(e, this.message_list.list)) 1164 1211 this.message_list.blur(); 1212 list = this.message_list; 1165 1213 model = this.env.mailboxes; 1166 1214 } … … 1168 1216 if (!rcube_mouse_is_over(e, this.contact_list.list)) 1169 1217 this.contact_list.blur(); 1218 list = this.contact_list; 1170 1219 model = this.env.address_sources; 1171 1220 } … … 1176 1225 // handle mouse release when dragging 1177 1226 if (this.drag_active && model && this.env.last_folder_target) { 1178 this.set_classname(this.get_folder_li(this.env.last_folder_target), 'droptarget', false);1227 $(this.get_folder_li(this.env.last_folder_target)).removeClass('droptarget'); 1179 1228 this.command('moveto', model[this.env.last_folder_target].id); 1180 1229 this.env.last_folder_target = null; 1230 list.draglayer.hide(); 1181 1231 } 1182 1232 }; … … 1197 1247 { 1198 1248 var li, pos, list, height; 1199 list = rcube_find_object(this.task == 'mail' ? 'mailboxlist' : 'directorylist');1200 pos = rcube_get_object_pos(list);1201 this.env.folderlist_coords = { x1:pos.x, y1:pos.y, x2:pos.x + list.offsetWidth, y2:pos.y + list.offsetHeight};1249 list = $(this.gui_objects.folderlist); 1250 pos = list.offset(); 1251 this.env.folderlist_coords = { x1:pos.left, y1:pos.top, x2:pos.left + list.width(), y2:pos.top + list.height() }; 1202 1252 1203 1253 this.env.folder_coords = new Array(); 1204 1254 for (var k in model) { 1205 if (li = this.get_folder_li(k)) 1206 { 1207 pos = rcube_get_object_pos(li.firstChild); 1208 // only visible folders 1209 if (height = li.firstChild.offsetHeight) 1210 this.env.folder_coords[k] = {x1:pos.x, y1:pos.y, x2:pos.x + li.firstChild.offsetWidth, y2:pos.y + height}; 1211 } 1212 } 1213 } 1255 if (li = this.get_folder_li(k)) { 1256 pos = $(li.firstChild).offset(); 1257 // only visible folders 1258 if (height = li.firstChild.offsetHeight) 1259 this.env.folder_coords[k] = { x1:pos.left, y1:pos.top, x2:pos.left + li.firstChild.offsetWidth, y2:pos.top + height }; 1260 } 1261 } 1262 } 1214 1263 }; 1215 1264 1216 1265 this.drag_move = function(e) 1217 { 1218 if (this.gui_objects.folderlist && this.env.folder_coords) 1219 { 1266 { 1267 if (this.gui_objects.folderlist && this.env.folder_coords) { 1220 1268 // offsets to compensate for scrolling while dragging a message 1221 1269 var boffset = bw.ie ? -document.documentElement.scrollTop : this.initialBodyScrollTop; … … 1230 1278 1231 1279 // if mouse pointer is outside of folderlist 1232 if (mouse.x < pos.x1 || mouse.x >= pos.x2 1233 || mouse.y < pos.y1 || mouse.y >= pos.y2) 1234 { 1235 if (this.env.last_folder_target) { 1236 this.set_classname(this.get_folder_li(this.env.last_folder_target), 'droptarget', false); 1280 if (mouse.x < pos.x1 || mouse.x >= pos.x2 || mouse.y < pos.y1 || mouse.y >= pos.y2) { 1281 if (this.env.last_folder_target) { 1282 $(this.get_folder_li(this.env.last_folder_target)).removeClass('droptarget'); 1237 1283 this.env.last_folder_target = null; 1238 }1239 return;1240 }1284 } 1285 return; 1286 } 1241 1287 1242 1288 // over the folders 1243 for (var k in this.env.folder_coords) 1244 { 1245 pos = this.env.folder_coords[k]; 1246 if (this.check_droptarget(k) && ((mouse.x >= pos.x1) && (mouse.x < pos.x2) 1247 && (mouse.y >= pos.y1) && (mouse.y < pos.y2))) 1248 { 1249 this.set_classname(this.get_folder_li(k), 'droptarget', true); 1250 this.env.last_folder_target = k; 1251 } 1252 else 1253 this.set_classname(this.get_folder_li(k), 'droptarget', false); 1254 } 1255 } 1256 }; 1289 for (var k in this.env.folder_coords) { 1290 pos = this.env.folder_coords[k]; 1291 if (this.check_droptarget(k) && ((mouse.x >= pos.x1) && (mouse.x < pos.x2) 1292 && (mouse.y >= pos.y1) && (mouse.y < pos.y2))) { 1293 $(this.get_folder_li(k)).addClass('droptarget'); 1294 this.env.last_folder_target = k; 1295 } 1296 else { 1297 $(this.get_folder_li(k)).removeClass('droptarget'); 1298 if (k == this.env.last_folder_target) 1299 this.env.last_folder_target = null; 1300 } 1301 } 1302 } 1303 }; 1257 1304 1258 1305 this.collapse_folder = function(id) … … 1260 1307 var div; 1261 1308 if ((li = this.get_folder_li(id)) && 1262 (div = li.getElementsByTagName("div")[0]) && 1263 (div.className.match(/collapsed/) || div.className.match(/expanded/))) 1264 { 1265 var ul = li.getElementsByTagName("ul")[0]; 1266 if (div.className.match(/collapsed/)) 1267 { 1268 ul.style.display = ''; 1269 this.set_classname(div, 'collapsed', false); 1270 this.set_classname(div, 'expanded', true); 1309 (div = $(li.getElementsByTagName("div")[0])) && 1310 (div.hasClass('collapsed') || div.hasClass('expanded'))) 1311 { 1312 var ul = $(li.getElementsByTagName("ul")[0]); 1313 if (div.hasClass('collapsed')) 1314 { 1315 ul.show(); 1316 div.removeClass('collapsed').addClass('expanded'); 1271 1317 var reg = new RegExp('&'+urlencode(id)+'&'); 1272 1318 this.set_env('collapsed_folders', this.env.collapsed_folders.replace(reg, '')); … … 1274 1320 else 1275 1321 { 1276 ul.style.display = 'none'; 1277 this.set_classname(div, 'expanded', false); 1278 this.set_classname(div, 'collapsed', true); 1322 ul.hide(); 1323 div.removeClass('expanded').addClass('collapsed'); 1279 1324 this.set_env('collapsed_folders', this.env.collapsed_folders+'&'+urlencode(id)+'&'); 1280 1325 … … 1309 1354 else if (this.contact_list) 1310 1355 this.contact_list.focus(); 1311 1312 var mbox_li;1313 if (mbox_li = this.get_folder_li())1314 this.set_classname(mbox_li, 'unfocused', true);1315 1356 1316 1357 return rcube_event.get_button(e) == 2 ? true : rcube_event.cancel(e); … … 1413 1454 if (this.env.search_request) 1414 1455 add_url += '&_search='+this.env.search_request; 1456 1415 1457 var url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.env.mailbox)+add_url; 1416 1458 if (action == 'preview' && String(target.location.href).indexOf(url) >= 0) … … 1425 1467 { 1426 1468 this.set_message(id, 'unread', false); 1427 if (this.env.unread_counts[this.env.mailbox])1428 {1429 this.env.unread_counts[this.env.mailbox] -= 1;1430 this.set_unread_count(this.env.mailbox, this.env.unread_counts[this.env.mailbox], this.env.mailbox == 'INBOX');1431 }1432 }1469 if (this.env.unread_counts[this.env.mailbox]) 1470 { 1471 this.env.unread_counts[this.env.mailbox] -= 1; 1472 this.set_unread_count(this.env.mailbox, this.env.unread_counts[this.env.mailbox], this.env.mailbox == 'INBOX'); 1473 } 1474 } 1433 1475 } 1434 1476 }; … … 1437 1479 { 1438 1480 var frm; 1439 if (this.env.contentframe && (frm = rcube_find_object(this.env.contentframe)))1481 if (this.env.contentframe && (frm = $('#'+this.env.contentframe)) && frm.length) 1440 1482 { 1441 1483 if (!show && window.frames[this.env.contentframe]) … … 1445 1487 } 1446 1488 else if (!bw.safari && !bw.konq) 1447 frm .style.display = show ? 'block' : 'none';1489 frm[show ? 'show' : 'hide'](); 1448 1490 } 1449 1491 … … 1678 1720 this.set_message_status(uid, flag, status); 1679 1721 1722 var rowobj = $(rows[uid].obj); 1680 1723 if (rows[uid].unread && rows[uid].classname.indexOf('unread')<0) 1681 1724 { 1682 1725 rows[uid].classname += ' unread'; 1683 this.set_classname(rows[uid].obj, 'unread', true);1726 rowobj.addClass('unread'); 1684 1727 } 1685 1728 else if (!rows[uid].unread && rows[uid].classname.indexOf('unread')>=0) 1686 1729 { 1687 1730 rows[uid].classname = rows[uid].classname.replace(/\s*unread/, ''); 1688 this.set_classname(rows[uid].obj, 'unread', false);1731 rowobj.removeClass('unread'); 1689 1732 } 1690 1733 … … 1692 1735 { 1693 1736 rows[uid].classname += ' deleted'; 1694 this.set_classname(rows[uid].obj, 'deleted', true);1737 rowobj.addClass('deleted'); 1695 1738 } 1696 1739 else if (!rows[uid].deleted && rows[uid].classname.indexOf('deleted')>=0) 1697 1740 { 1698 1741 rows[uid].classname = rows[uid].classname.replace(/\s*deleted/, ''); 1699 this.set_classname(rows[uid].obj, 'deleted', false);1742 rowobj.removeClass('deleted'); 1700 1743 } 1701 1744 … … 1703 1746 { 1704 1747 rows[uid].classname += ' flagged'; 1705 this.set_classname(rows[uid].obj, 'flagged', true);1748 rowobj.addClass('flagged'); 1706 1749 } 1707 1750 else if (!rows[uid].flagged && rows[uid].classname.indexOf('flagged')>=0) 1708 1751 { 1709 1752 rows[uid].classname = rows[uid].classname.replace(/\s*flagged/, ''); 1710 this.set_classname(rows[uid].obj, 'flagged', false);1753 rowobj.removeClass('flagged'); 1711 1754 } 1712 1755 … … 1812 1855 this.set_message_status(id, 'deleted', true); 1813 1856 if (this.env.read_when_deleted) 1814 this.set_message_status(id, 'unread', false);1815 this.set_message(id);1857 this.set_message_status(id, 'unread', false); 1858 this.set_message(id); 1816 1859 } 1817 1860 } … … 2000 2043 { 2001 2044 var key = rcube_event.get_keycode(e); 2002 var elm;2045 var passwd = $('#rcmloginpwd'); 2003 2046 2004 2047 // enter 2005 if ((key==13) && (elm = rcube_find_object('_pass'))) 2006 { 2007 elm.focus(); 2008 return false; 2009 } 2048 if (key == 13 && passwd.length && !passwd.val()) { 2049 passwd.focus(); 2050 return rcube_event.cancel(e); 2051 } 2052 2053 return true; 2010 2054 }; 2011 2055 … … 2019 2063 { 2020 2064 // check input fields 2021 var input_to = rcube_find_object('_to');2022 var input_cc = rcube_find_object('_cc');2023 var input_bcc = rcube_find_object('_bcc');2024 var input_from = rcube_find_object('_from');2025 var input_subject = rcube_find_object('_subject');2026 var input_message = rcube_find_object('_message');2065 var input_to = $("[name='_to']"); 2066 var input_cc = $("[name='_cc']"); 2067 var input_bcc = $("[name='_bcc']"); 2068 var input_from = $("[name='_from']"); 2069 var input_subject = $("[name='_subject']"); 2070 var input_message = $("[name='_message']"); 2027 2071 2028 2072 // check sender (if have no identities) 2029 if (input_from. type == 'text' && !rcube_check_email(input_from.value, true))2073 if (input_from.attr('type') == 'text' && !rcube_check_email(input_from.val(), true)) 2030 2074 { 2031 2075 alert(this.get_label('nosenderwarning')); … … 2035 2079 2036 2080 // check for empty recipient 2037 var recipients = input_to.val ue ? input_to.value : (input_cc.value ? input_cc.value : input_bcc.value);2081 var recipients = input_to.val() ? input_to.val() : (input_cc.val() ? input_cc.val() : input_bcc.val()); 2038 2082 if (!rcube_check_email(recipients.replace(/^\s+/, '').replace(/[\s,;]+$/, ''), true)) 2039 2083 { … … 2044 2088 2045 2089 // display localized warning for missing subject 2046 if (input_subject && input_subject.value== '')2090 if (input_subject.val() == '') 2047 2091 { 2048 2092 var subject = prompt(this.get_label('nosubjectwarning'), this.get_label('nosubject')); … … 2056 2100 else 2057 2101 { 2058 input_subject.val ue = subject ? subject : this.get_label('nosubject');2102 input_subject.val((subject ? subject : this.get_label('nosubject'))); 2059 2103 } 2060 2104 } 2061 2105 2062 2106 // check for empty body 2063 if ((!window.tinyMCE || !tinyMCE.get('compose-body')) && input_message.val ue== '' && !confirm(this.get_label('nobodywarning')))2107 if ((!window.tinyMCE || !tinyMCE.get('compose-body')) && input_message.val() == '' && !confirm(this.get_label('nobodywarning'))) 2064 2108 { 2065 2109 input_message.focus(); … … 2106 2150 this.set_draft_id = function(id) 2107 2151 { 2108 var f; 2109 if (f = rcube_find_object('_draft_saveid')) 2110 f.value = id; 2152 $("input[name='_draft_saveid']").val(id); 2111 2153 }; 2112 2154 … … 2123 2165 { 2124 2166 // check input fields 2125 var input_to = rcube_find_object('_to'); 2126 var input_cc = rcube_find_object('_cc'); 2127 var input_bcc = rcube_find_object('_bcc'); 2128 var input_subject = rcube_find_object('_subject'); 2129 var editor, input_message; 2167 var value_to = $("[name='_to']").val(); 2168 var value_cc = $("[name='_cc']").val(); 2169 var value_bcc = $("[name='_bcc']").val(); 2170 var value_subject = $("[name='_subject']").val(); 2130 2171 var str = ''; 2131 2172 2132 if (input_to && input_to.value) 2133 str += input_to.value+':'; 2134 if (input_cc && input_cc.value) 2135 str += input_cc.value+':'; 2136 if (input_bcc && input_bcc.value) 2137 str += input_bcc.value+':'; 2138 if (input_subject && input_subject.value) 2139 str += input_subject.value+':'; 2140 2141 if (editor = tinyMCE.get('compose-body')) 2173 if (value_to) 2174 str += value_to+':'; 2175 if (value_cc) 2176 str += value_cc+':'; 2177 if (value_bcc) 2178 str += value_bcc+':'; 2179 if (value_subject) 2180 str += value_subject+':'; 2181 2182 var editor = tinyMCE.get('compose-body'); 2183 if (editor) 2142 2184 str += editor.getContent(); 2143 2185 else 2144 { 2145 input_message = rcube_find_object('_message'); 2146 str += input_message.value; 2147 } 2186 str += $("[name='_message']").val(); 2148 2187 2149 2188 if (save) … … 2159 2198 2160 2199 var id = obj.options[obj.selectedIndex].value; 2161 var input_message = rcube_find_object('_message');2162 var message = input_message ? input_message.value : '';2163 var is_html = ( rcube_find_object('_is_html').value== '1');2200 var input_message = $("[name='_message']"); 2201 var message = input_message.val(); 2202 var is_html = ($("input[name='_is_html']").val() == '1'); 2164 2203 var sig, p; 2165 2204 … … 2175 2214 sig = this.env.signatures[this.env.identity]['plain_text']; 2176 2215 else 2177 sig = this.env.signatures[this.env.identity]['text'];2216 sig = this.env.signatures[this.env.identity]['text']; 2178 2217 2179 if (sig.indexOf('-- ')!=0)2218 if (sig.indexOf('-- ')!=0) 2180 2219 sig = '-- \n'+sig; 2181 2220 … … 2208 2247 // Append the signature as a div within the body 2209 2248 var sigElem = editor.dom.get('_rc_sig'); 2210 var newsig = '';2211 var htmlsig = true;2249 var newsig = ''; 2250 var htmlsig = true; 2212 2251 2213 2252 if (!sigElem) 2214 2253 { 2215 // add empty line before signature on IE2216 if (bw.ie)2254 // add empty line before signature on IE 2255 if (bw.ie) 2217 2256 editor.getBody().appendChild(editor.getDoc().createElement('br')); 2218 2257 2219 sigElem = editor.getDoc().createElement('div');2258 sigElem = editor.getDoc().createElement('div'); 2220 2259 sigElem.setAttribute('id', '_rc_sig'); 2221 2260 editor.getBody().appendChild(sigElem); 2222 2261 } 2223 2262 2224 if (this.env.signatures[id])2225 {2226 newsig = this.env.signatures[id]['text'];2227 htmlsig = this.env.signatures[id]['is_html'];2228 2229 if (newsig) {2230 if (htmlsig && this.env.signatures[id]['plain_text'].indexOf('-- ')!=0)2263 if (this.env.signatures[id]) 2264 { 2265 newsig = this.env.signatures[id]['text']; 2266 htmlsig = this.env.signatures[id]['is_html']; 2267 2268 if (newsig) { 2269 if (htmlsig && this.env.signatures[id]['plain_text'].indexOf('-- ')!=0) 2231 2270 newsig = '<p>-- </p>' + newsig; 2232 else if (!htmlsig && newsig.indexOf('-- ')!=0)2271 else if (!htmlsig && newsig.indexOf('-- ')!=0) 2233 2272 newsig = '-- \n' + newsig; 2234 }2235 }2273 } 2274 } 2236 2275 2237 2276 if (htmlsig) … … 2242 2281 } 2243 2282 2244 if (input_message) 2245 input_message.value = message; 2283 input_message.val(message); 2246 2284 2247 2285 this.env.identity = id; … … 2257 2295 if (elm = this.gui_objects.uploadbox) 2258 2296 { 2259 if (a && (list = this.gui_objects.attachmentlist)) 2260 { 2261 var pos = rcube_get_object_pos(list); 2262 var left = pos.x; 2263 var top = pos.y + list.offsetHeight + 10; 2264 2265 elm.style.top = top+'px'; 2266 elm.style.left = left+'px'; 2297 if (a && (list = this.gui_objects.attachmentlist)) 2298 { 2299 var pos = $(list).offset(); 2300 elm.style.top = (pos.top + list.offsetHeight + 10) + 'px'; 2301 elm.style.left = pos.left + 'px'; 2267 2302 } 2268 2303 … … 2271 2306 2272 2307 // clear upload form 2273 try {2308 try { 2274 2309 if (!a && this.gui_objects.attachmentform != this.gui_objects.messageform) 2275 this.gui_objects.attachmentform.reset();2276 }2277 catch(e){} // ignore errors2278 2279 return true; 2310 this.gui_objects.attachmentform.reset(); 2311 } 2312 catch(e){} // ignore errors 2313 2314 return true; 2280 2315 }; 2281 2316 … … 2337 2372 return false; 2338 2373 2339 var li = document.createElement('LI'); 2340 li.id = name; 2341 li.innerHTML = content; 2342 this.gui_objects.attachmentlist.appendChild(li); 2374 $('<li>').attr('id', name).html(content).appendTo(this.gui_objects.attachmentlist); 2343 2375 return true; 2344 2376 }; … … 2440 2472 highlight = document.getElementById('rcmksearchSelected'); 2441 2473 if (!highlight) 2442 highlight = this.ksearch_pane. ul.firstChild;2474 highlight = this.ksearch_pane.__ul.firstChild; 2443 2475 2444 2476 if (highlight) … … 2480 2512 this.ksearch_select = function(node) 2481 2513 { 2482 var current = document.getElementById('rcmksearchSelected'); 2483 if (current && node) { 2484 current.removeAttribute('id'); 2485 this.set_classname(current, 'selected', false); 2514 var current = $('#rcmksearchSelected'); 2515 if (current[0] && node) { 2516 current.removeAttr('id').removeClass('selected'); 2486 2517 } 2487 2518 2488 2519 if (node) { 2489 node.setAttribute('id', 'rcmksearchSelected'); 2490 this.set_classname(node, 'selected', true); 2520 $(node).attr('id', 'rcmksearchSelected').addClass('selected'); 2491 2521 this.ksearch_selected = node._rcm_id; 2492 2522 } … … 2522 2552 return; 2523 2553 2524 if (this.ksearch_pane && this.ksearch_pane. visible)2525 this.ksearch_pane. show(0);2554 if (this.ksearch_pane && this.ksearch_pane.is(":visible")) 2555 this.ksearch_pane.hide(); 2526 2556 2527 2557 // get string from current cursor pos to last comma … … 2562 2592 // create results pane if not present 2563 2593 if (!this.ksearch_pane) { 2564 ul = document.createElement('UL'); 2565 this.ksearch_pane = new rcube_layer('rcmKSearchpane', {vis:0, zindex:30000}); 2566 this.ksearch_pane.elm.appendChild(ul); 2567 this.ksearch_pane.ul = ul; 2568 } 2569 else 2570 ul = this.ksearch_pane.ul; 2594 ul = $('<ul>'); 2595 this.ksearch_pane = $('<div>').attr('id', 'rcmKSearchpane').css({ position:'absolute', 'z-index':30000 }).append(ul).appendTo(document.body); 2596 this.ksearch_pane.__ul = ul[0]; 2597 } 2571 2598 2572 2599 // remove all search results 2600 ul = this.ksearch_pane.__ul; 2573 2601 ul.innerHTML = ''; 2574 2602 … … 2584 2612 2585 2613 // select the first 2586 ul.firstChild.setAttribute('id', 'rcmksearchSelected'); 2587 this.set_classname(ul.firstChild, 'selected', true); 2614 $(ul.firstChild).attr('id', 'rcmksearchSelected').addClass('selected'); 2588 2615 this.ksearch_selected = 0; 2589 2616 2590 2617 // move the results pane right under the input box and make it visible 2591 var pos = rcube_get_object_pos(this.ksearch_input); 2592 this.ksearch_pane.move(pos.x, pos.y+this.ksearch_input.offsetHeight); 2593 this.ksearch_pane.show(1); 2618 var pos = $(this.ksearch_input).offset(); 2619 this.ksearch_pane.css({ left:pos.left+'px', top:(pos.top + this.ksearch_input.offsetHeight)+'px' }).show(); 2594 2620 } 2595 2621 // hide results pane … … 2624 2650 2625 2651 if (this.ksearch_pane) 2626 this.ksearch_pane. show(0);2652 this.ksearch_pane.hide(); 2627 2653 }; 2628 2654 … … 2789 2815 // update a contact record in the list 2790 2816 this.update_contact_row = function(cid, cols_arr) 2791 {2817 { 2792 2818 var row; 2793 if (this.contact_list.rows[cid] && (row = this.contact_list.rows[cid].obj)) 2794 { 2819 if (this.contact_list.rows[cid] && (row = this.contact_list.rows[cid].obj)) { 2795 2820 for (var c=0; c<cols_arr.length; c++) 2796 2821 if (row.cells[c]) 2797 row.cells[c].innerHTML = cols_arr[c];2822 $(row.cells[c]).html(cols_arr[c]); 2798 2823 2799 2824 return true; 2800 }2825 } 2801 2826 2802 2827 return false; 2803 };2828 }; 2804 2829 2805 2830 … … 2883 2908 { 2884 2909 if (this.check_droptarget(folder) && 2885 !this.env.subscriptionrows[this.get_folder_row_id(this.env.folder)][2] &&2886 (folder != this.env.folder.replace(reg, '')) &&2910 !this.env.subscriptionrows[this.get_folder_row_id(this.env.folder)][2] && 2911 (folder != this.env.folder.replace(reg, '')) && 2887 2912 (!folder.match(new RegExp('^'+RegExp.escape(this.env.folder+this.env.delimiter))))) 2888 2913 { 2889 2914 this.set_env('dstfolder', folder); 2890 this.set_classname(row, 'droptarget', true);2915 $(row).addClass('droptarget'); 2891 2916 } 2892 2917 } … … 2894 2919 { 2895 2920 this.set_env('dstfolder', this.env.delimiter); 2896 this.set_classname(this.subscription_list.frame, 'droptarget', true);2921 $(this.subscription_list.frame).addClass('droptarget'); 2897 2922 } 2898 2923 } … … 2900 2925 this.unfocus_subscription = function(id) 2901 2926 { 2902 var row ;2927 var row = $('#'+id); 2903 2928 this.set_env('dstfolder', null); 2904 if (this.env.subscriptionrows[id] && 2905 (row = document.getElementById(id))) 2906 this.set_classname(row, 'droptarget', false); 2929 if (this.env.subscriptionrows[id] && row[0]) 2930 row.removeClass('droptarget'); 2907 2931 else 2908 this.set_classname(this.subscription_list.frame, 'droptarget', false);2932 $(this.subscription_list.frame).removeClass('droptarget'); 2909 2933 } 2910 2934 … … 2920 2944 2921 2945 if (this.gui_objects.createfolderhint) 2922 this.gui_objects.createfolderhint.innerHTML = this.env.folder ? this.get_label('addsubfolderhint') : '';2946 $(this.gui_objects.createfolderhint).html(this.env.folder ? this.get_label('addsubfolderhint') : ''); 2923 2947 }; 2924 2948 … … 3007 3031 3008 3032 if (cell && this.edit_folder && this.env.subscriptionrows[this.edit_folder]) 3009 cell.innerHTML = this.env.subscriptionrows[this.edit_folder][1];3033 $(cell).html(this.env.subscriptionrows[this.edit_folder][1]); 3010 3034 3011 3035 this.edit_folder = null; … … 3055 3079 this.set_env('folder', null); 3056 3080 3057 if (this.gui_objects.createfolderhint) 3058 this.gui_objects.createfolderhint.innerHTML = ''; 3081 $(this.gui_objects.createfolderhint).html(''); 3059 3082 } 3060 3083 }; … … 3379 3402 }; 3380 3403 3381 // set/unset a specific class name3382 this.set_classname = function(obj, classname, set)3383 {3384 var reg = new RegExp('\s*'+classname, 'i');3385 if (!set && obj.className.match(reg))3386 obj.className = obj.className.replace(reg, '');3387 else if (set && !obj.className.match(reg))3388 obj.className += ' '+classname;3389 };3390 3391 3404 // write to the document/window title 3392 3405 this.set_pagetitle = function(title) … … 3419 3432 cont = '<div class="'+type+'">'+cont+'</div>'; 3420 3433 3421 var _rcube = this; 3422 this.gui_objects.message.innerHTML = cont; 3423 this.gui_objects.message.style.display = 'block'; 3434 var obj = $(this.gui_objects.message).html(cont).show(); 3424 3435 3425 3436 if (type!='loading') 3426 this.gui_objects.message.onmousedown = function(){ _rcube.hide_message(); return true; };3437 obj.bind('mousedown', function(){ ref.hide_message(); return true; }); 3427 3438 3428 3439 if (!hold) 3429 this.message_timer = window.setTimeout(function(){ ref.hide_message( ); }, this.message_time);3440 this.message_timer = window.setTimeout(function(){ ref.hide_message(true); }, this.message_time); 3430 3441 }; 3431 3442 3432 3443 // make a message row disapear 3433 this.hide_message = function( )3444 this.hide_message = function(fade) 3434 3445 { 3435 3446 if (this.gui_objects.message) 3436 { 3437 this.gui_objects.message.style.display = 'none'; 3438 this.gui_objects.message.onmousedown = null; 3439 } 3447 $(this.gui_objects.message).unbind()[(fade?'fadeOut':'hide')](); 3440 3448 }; 3441 3449 … … 3447 3455 var current_li, target_li; 3448 3456 3449 if ((current_li = this.get_folder_li(old))) 3450 { 3451 this.set_classname(current_li, 'selected', false); 3452 this.set_classname(current_li, 'unfocused', false); 3453 } 3454 3455 if ((target_li = this.get_folder_li(name))) 3456 { 3457 this.set_classname(target_li, 'unfocused', false); 3458 this.set_classname(target_li, 'selected', true); 3457 if ((current_li = this.get_folder_li(old))) { 3458 $(current_li).removeClass('selected').removeClass('unfocused'); 3459 } 3460 3461 if ((target_li = this.get_folder_li(name))) { 3462 $(target_li).removeClass('unfocused').addClass('selected'); 3459 3463 } 3460 3464 } … … 3513 3517 var even = rowcount%2; 3514 3518 3515 this.env.messages[uid] = { deleted:flags.deleted?1:0,3516 replied:flags.replied?1:0,3517 unread:flags.unread?1:0,3518 forwarded:flags.forwarded?1:0,3519 flagged:flags.flagged?1:0};3520 3521 var row = document.createElement('TR');3522 row.id = 'rcmrow'+uid; 3523 row.className= 'message'3524 + (even ? ' even' : ' odd')3519 this.env.messages[uid] = { 3520 deleted: flags.deleted?1:0, 3521 replied: flags.replied?1:0, 3522 unread: flags.unread?1:0, 3523 forwarded: flags.forwarded?1:0, 3524 flagged:flags.flagged?1:0 3525 }; 3526 3527 var css_class = 'message' 3528 + (even ? ' even' : ' odd') 3525 3529 + (flags.unread ? ' unread' : '') 3526 + (flags.deleted ? ' deleted' : '') 3527 + (flags.flagged ? ' flagged' : ''); 3530 + (flags.deleted ? ' deleted' : '') 3531 + (flags.flagged ? ' flagged' : ''); 3532 3533 var row = $('<tr>').attr('id', 'rcmrow'+uid).attr('class', css_class); 3528 3534 3529 3535 if (this.message_list.in_selection(uid)) 3530 row. className += ' selected';3536 row.addClass('selected'); 3531 3537 3532 3538 var icon = this.env.messageicon; … … 3545 3551 icon = this.env.unreadicon; 3546 3552 3547 var col = document.createElement('TD'); 3548 col.className = 'icon'; 3549 col.innerHTML = icon ? '<img src="'+icon+'" alt="" />' : ''; 3550 row.appendChild(col); 3553 // add icon col 3554 $('<td>').addClass('icon').html(icon ? '<img src="'+icon+'" alt="" />' : '').appendTo(row); 3551 3555 3552 3556 // add each submitted col 3553 for (var n = 0; n < this.coltypes.length; n++) 3554 { 3557 for (var n = 0; n < this.coltypes.length; n++) { 3555 3558 var c = this.coltypes[n]; 3556 col = document.createElement('TD'); 3557 col.className = String(c).toLowerCase(); 3558 3559 if (c=='flag') 3560 { 3559 col = $('<td>').addClass(String(c).toLowerCase()); 3560 3561 if (c=='flag') { 3561 3562 if (flags.flagged && this.env.flaggedicon) 3562 col. innerHTML = '<img src="'+this.env.flaggedicon+'" alt="" />';3563 col.html('<img src="'+this.env.flaggedicon+'" alt="" />'); 3563 3564 else if(!flags.flagged && this.env.unflaggedicon) 3564 col. innerHTML = '<img src="'+this.env.unflaggedicon+'" alt="" />';3565 col.html('<img src="'+this.env.unflaggedicon+'" alt="" />'); 3565 3566 } 3566 3567 else if (c=='attachment') 3567 col. innerHTML = attachment && this.env.attachmenticon ? '<img src="'+this.env.attachmenticon+'" alt="" />' : ' ';3568 col.html(attachment && this.env.attachmenticon ? '<img src="'+this.env.attachmenticon+'" alt="" />' : ' '); 3568 3569 else 3569 col. innerHTML = cols[c];3570 3571 row.appendChild(col);3570 col.html(cols[c]); 3571 3572 col.appendTo(row); 3572 3573 } 3573 3574 … … 3575 3576 3576 3577 // remove 'old' row 3577 if (attop && this.env.pagesize && this.message_list.rowcount > this.env.pagesize) 3578 { 3579 var uid = this.message_list.get_last_row(); 3580 this.message_list.remove_row(uid); 3581 this.message_list.clear_selection(uid); 3582 } 3583 }; 3578 if (attop && this.env.pagesize && this.message_list.rowcount > this.env.pagesize) { 3579 var uid = this.message_list.get_last_row(); 3580 this.message_list.remove_row(uid); 3581 this.message_list.clear_selection(uid); 3582 } 3583 }; 3584 3584 3585 3585 // replace content of row count display 3586 3586 this.set_rowcount = function(text) 3587 3587 { 3588 if (this.gui_objects.countdisplay) 3589 this.gui_objects.countdisplay.innerHTML = text; 3588 $(this.gui_objects.countdisplay).html(text); 3590 3589 3591 3590 // update page navigation buttons … … 3603 3602 this.set_quota = function(content) 3604 3603 { 3605 if ( this.gui_objects.quotadisplay && content)3606 this.gui_objects.quotadisplay.innerHTML = content;3604 if (content && this.gui_objects.quotadisplay) 3605 $(this.gui_objects.quotadisplay).html(content); 3607 3606 }; 3608 3607 … … 3633 3632 // add children's counters 3634 3633 for (var k in this.env.unread_counts) 3635 if (k.indexOf(mbox + this.env.delimiter) == 0) {3634 if (k.indexOf(mbox + this.env.delimiter) == 0) 3636 3635 childcount += this.env.unread_counts[k]; 3637 }3638 3636 } 3639 3637 … … 3651 3649 3652 3650 // set the right classes 3653 this.set_classname(item, 'unread', (mycount+childcount)>0 ? true : false); 3651 if ((mycount+childcount)>0) 3652 $(item).addClass('unread'); 3653 else 3654 $(item).removeClass('unread'); 3654 3655 } 3655 3656 … … 3692 3693 var even = rowcount%2; 3693 3694 3694 var row = document.createElement('TR'); 3695 row.id = 'rcmrow'+cid; 3696 row.className = 'contact '+(even ? 'even' : 'odd'); 3695 var row = $('<tr>').attr('id', 'rcmrow'+cid).addClass('class').addClass(even ? 'even' : 'odd'); 3697 3696 3698 3697 if (this.contact_list.in_selection(cid)) 3699 row. className += ' selected';3698 row.addClass('selected'); 3700 3699 3701 3700 // add each submitted col 3702 for (var c in cols) 3703 { 3704 col = document.createElement('TD'); 3705 col.className = String(c).toLowerCase(); 3706 col.innerHTML = cols[c]; 3707 row.appendChild(col); 3708 } 3701 for (var c in cols) { 3702 col = $('<td>').addClass(String(c).toLowerCase()).html(cols[c]).appendTo(row); 3703 } 3709 3704 3710 3705 this.contact_list.insert_row(row); … … 3721 3716 // display fetched raw headers 3722 3717 this.set_headers = function(content) 3723 { 3724 if (this.gui_objects.all_headers_row && this.gui_objects.all_headers_box && content) 3725 { 3726 var box = this.gui_objects.all_headers_box; 3727 box.innerHTML = content; 3728 box.style.display = 'block'; 3718 { 3719 if (this.gui_objects.all_headers_row && this.gui_objects.all_headers_box && content) { 3720 $(this.gui_objects.all_headers_box).html(content).show(); 3729 3721 3730 3722 if (this.env.framed && parent.rcmail) 3731 parent.rcmail.set_busy(false);3723 parent.rcmail.set_busy(false); 3732 3724 else 3733 3725 this.set_busy(false); 3734 }3735 };3726 } 3727 }; 3736 3728 3737 3729 // display all-headers row and fetch raw message headers … … 3741 3733 return; 3742 3734 3743 this.set_classname(elem, 'show-headers', false); 3744 this.set_classname(elem, 'hide-headers', true); 3745 this.gui_objects.all_headers_row.style.display = bw.ie ? 'block' : 'table-row'; 3735 $(elem).removeClass('show-headers').addClass('hide-headers'); 3736 $(this.gui_objects.all_headers_row).show(); 3746 3737 elem.onclick = function() { rcmail.hide_headers(elem); } 3747 3738 … … 3749 3740 if (!this.gui_objects.all_headers_box.innerHTML) 3750 3741 { 3751 this.display_message(this.get_label('loading'), 'loading', true); 3742 this.display_message(this.get_label('loading'), 'loading', true); 3752 3743 this.http_post('headers', '_uid='+this.env.uid); 3753 3744 } … … 3760 3751 return; 3761 3752 3762 this.set_classname(elem, 'hide-headers', false); 3763 this.set_classname(elem, 'show-headers', true); 3764 this.gui_objects.all_headers_row.style.display = 'none'; 3753 $(elem).removeClass('hide-headers').addClass('show-headers'); 3754 $(this.gui_objects.all_headers_row).hide(); 3765 3755 elem.onclick = function() { rcmail.load_headers(elem); } 3766 3756 } … … 3773 3763 this.html2plain = function(htmlText, id) 3774 3764 { 3775 var http_request = new rcube_http_request();3776 3765 var url = this.env.bin_path+'html2text.php'; 3777 3766 var rcmail = this; … … 3780 3769 console.log('HTTP POST: '+url); 3781 3770 3782 http_request.onerror = function(o) { rcmail.http_error(o); }; 3783 http_request.oncomplete = function(o) { rcmail.set_text_value(o, id); }; 3784 http_request.POST(url, htmlText, 'application/octet-stream'); 3785 } 3786 3787 this.set_text_value = function(httpRequest, id) 3788 { 3789 this.set_busy(false); 3790 document.getElementById(id).value = httpRequest.get_text(); 3791 console.log(httpRequest.get_text()); 3771 $.ajax({ type: 'POST', url: url, data: htmlText, contentType: 'application/octet-stream', 3772 error: function(o) { rcmail.http_error(o); }, 3773 success: function(data) { rcmail.set_busy(false); $(document.getElementById(id)).val(data); console.log(data); } 3774 }); 3792 3775 } 3793 3776 … … 3814 3797 }; 3815 3798 3816 this.http_sockets = new Array();3817 3818 // find a non-busy socket or create a new one3819 this.get_request_obj = function()3820 {3821 for (var n=0; n<this.http_sockets.length; n++)3822 {3823 if (!this.http_sockets[n].busy)3824 return this.http_sockets[n];3825 }3826 3827 // create a new XMLHTTP object3828 var i = this.http_sockets.length;3829 this.http_sockets[i] = new rcube_http_request();3830 3831 return this.http_sockets[i];3832 };3833 3834 3799 // send a http request to the server 3835 3800 this.http_request = function(action, querystring, lock) 3836 { 3837 var request_obj = this.get_request_obj(); 3801 { 3838 3802 querystring += (querystring ? '&' : '') + '_remote=1'; 3839 3840 // add timestamp to request url to avoid cacheing problems in Safari 3841 if (bw.safari) 3842 querystring += '&_ts='+(new Date().getTime()); 3843 3803 var url = this.env.comm_path + '&_action=' + action + '&' + querystring 3804 3844 3805 // send request 3845 if (request_obj) 3846 { 3847 console.log('HTTP request: '+this.env.comm_path+'&_action='+action+'&'+querystring); 3848 3849 if (lock) 3850 this.set_busy(true); 3851 3852 var rcm = this; 3853 request_obj.__lock = lock ? true : false; 3854 request_obj.__action = action; 3855 request_obj.onerror = function(o){ ref.http_error(o); }; 3856 request_obj.oncomplete = function(o){ ref.http_response(o); }; 3857 request_obj.GET(this.env.comm_path+'&_action='+action+'&'+querystring); 3858 } 3859 }; 3860 3861 // send a http POST request to the server 3862 this.http_post = function(action, postdata, lock) 3863 { 3864 var request_obj; 3865 if (postdata && typeof(postdata) == 'object') 3866 postdata._remote = 1; 3867 else 3868 postdata += (postdata ? '&' : '') + '_remote=1'; 3869 3870 // send request 3871 if (request_obj = this.get_request_obj()) 3872 { 3873 console.log('HTTP POST: '+this.env.comm_path+'&_action='+action); 3874 3875 if (lock) 3876 this.set_busy(true); 3877 3878 var rcm = this; 3879 request_obj.__lock = lock ? true : false; 3880 request_obj.__action = action; 3881 request_obj.onerror = function(o){ rcm.http_error(o); }; 3882 request_obj.oncomplete = function(o){ rcm.http_response(o); }; 3883 request_obj.POST(this.env.comm_path+'&_action='+action, postdata); 3884 } 3885 }; 3806 console.log('HTTP POST: ' + url); 3807 jQuery.get(url, { _unlock:(lock?1:0) }, function(data){ ref.http_response(data); }, 'json'); 3808 }; 3809 3810 // send a http POST request to the server 3811 this.http_post = function(action, postdata, lock) 3812 { 3813 var url = this.env.comm_path+'&_action=' + action; 3814 3815 if (postdata && typeof(postdata) == 'object') { 3816 postdata._remote = 1; 3817 postdata._unlock = (lock ? 1 : 0); 3818 } 3819 else 3820 postdata += (postdata ? '&' : '') + '_remote=1' + (lock ? '&_unlock=1' : ''); 3821 3822 // send request 3823 console.log('HTTP POST: ' + url); 3824 jQuery.post(url, postdata, function(data){ ref.http_response(data); }, 'json'); 3825 }; 3886 3826 3887 3827 // handle HTTP response 3888 this.http_response = function(request_obj) 3889 { 3890 var ctype = request_obj.get_header('Content-Type'); 3891 if (ctype) 3892 { 3893 ctype = String(ctype).toLowerCase(); 3894 var ctype_array=ctype.split(";"); 3895 ctype = ctype_array[0]; 3896 } 3897 3898 if (request_obj.__lock) 3828 this.http_response = function(response) 3829 { 3830 var console_msg = ''; 3831 3832 if (response.unlock) 3899 3833 this.set_busy(false); 3900 3834 3901 console.log(request_obj.get_text()); 3835 // set env vars 3836 if (response.env) 3837 this.set_env(response.env); 3838 3839 // we have labels to add 3840 if (typeof response.texts == 'object') { 3841 for (var name in response.texts) 3842 if (typeof response.texts[name] == 'string') 3843 this.add_label(name, response.texts[name]); 3844 } 3902 3845 3903 3846 // if we get javascript code from server -> execute it 3904 if (request_obj.get_text() && (ctype=='text/javascript' || ctype=='application/x-javascript')) 3905 eval(request_obj.get_text()); 3906 3847 if (response.exec) { 3848 console.log(response.exec); 3849 eval(response.exec); 3850 } 3851 3907 3852 // process the response data according to the sent action 3908 switch (re quest_obj.__action) {3853 switch (response.action) { 3909 3854 case 'delete': 3910 3855 if (this.task == 'addressbook') { … … 3923 3868 3924 3869 case 'purge': 3925 case 'expunge': 3870 case 'expunge': 3926 3871 if (!this.env.messagecount && this.task == 'mail') { 3927 3872 // clear preview pane content … … 3938 3883 case 'list': 3939 3884 if (this.task == 'mail') { 3940 if (this.message_list && re quest_obj.__action == 'list')3885 if (this.message_list && response.action == 'list') 3941 3886 this.msglist_select(this.message_list); 3942 3887 this.enable_command('show', 'expunge', 'select-all', 'select-none', 'sort', (this.env.messagecount > 0)); … … 3945 3890 else if (this.task == 'addressbook') 3946 3891 this.enable_command('export', (this.contact_list && this.contact_list.rowcount > 0)); 3947 3948 break; 3949 } 3950 3951 request_obj.reset(); 3952 }; 3892 break; 3893 } 3894 }; 3953 3895 3954 3896 // handle HTTP request errors 3955 this.http_error = function(request_obj) 3956 { 3897 this.http_error = function(request, status, err) 3898 { 3899 alert(status+":"+err); 3900 /* 3957 3901 //alert('Error sending request: '+request_obj.url+' => HTTP '+request_obj.xmlhttp.status); 3958 3902 if (request_obj.__lock) … … 3962 3906 request_obj.__lock = false; 3963 3907 this.display_message('Unknown Server Error!', 'error'); 3908 */ 3964 3909 }; 3965 3910 … … 4067 4012 }; 4068 4013 4069 } // end object rcube_webmail 4070 4071 4072 /** 4073 * Class for sending HTTP requests 4074 * @constructor 4075 */ 4076 function rcube_http_request() 4077 { 4078 this.url = ''; 4079 this.busy = false; 4080 this.xmlhttp = null; 4081 4082 // reset object properties 4083 this.reset = function() 4084 { 4085 // set unassigned event handlers 4086 this.onloading = function(){ }; 4087 this.onloaded = function(){ }; 4088 this.oninteractive = function(){ }; 4089 this.oncomplete = function(){ }; 4090 this.onabort = function(){ }; 4091 this.onerror = function(){ }; 4092 4093 this.url = ''; 4094 this.busy = false; 4095 this.xmlhttp = null; 4096 } 4097 4098 // create HTMLHTTP object 4099 this.build = function() 4100 { 4101 if (window.XMLHttpRequest) 4102 this.xmlhttp = new XMLHttpRequest(); 4103 else if (window.ActiveXObject) 4104 { 4105 try { this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } 4106 catch(e) { this.xmlhttp = null; } 4107 } 4108 else 4109 { 4110 4111 } 4112 } 4113 4114 // send GET request 4115 this.GET = function(url) 4116 { 4117 this.build(); 4118 4119 if (!this.xmlhttp) 4120 { 4121 this.onerror(this); 4122 return false; 4123 } 4124 4125 var _ref = this; 4126 this.url = url; 4127 this.busy = true; 4128 4129 this.xmlhttp.onreadystatechange = function(){ _ref.xmlhttp_onreadystatechange(); }; 4130 this.xmlhttp.open('GET', url, true); 4131 this.xmlhttp.setRequestHeader('X-RoundCube-Referer', bw.get_cookie('roundcube_sessid')); 4132 this.xmlhttp.send(null); 4133 }; 4134 4135 this.POST = function(url, body, contentType) 4136 { 4137 // default value for contentType if not provided 4138 if (typeof(contentType) == 'undefined') 4139 contentType = 'application/x-www-form-urlencoded'; 4140 4141 this.build(); 4142 4143 if (!this.xmlhttp) 4144 { 4145 this.onerror(this); 4146 return false; 4147 } 4148 4149 var req_body = body; 4150 if (typeof(body) == 'object') 4151 { 4152 req_body = ''; 4153 for (var p in body) 4154 req_body += (req_body ? '&' : '') + p+'='+urlencode(body[p]); 4155 } 4156 4157 var ref = this; 4158 this.url = url; 4159 this.busy = true; 4160 4161 this.xmlhttp.onreadystatechange = function() { ref.xmlhttp_onreadystatechange(); }; 4162 this.xmlhttp.open('POST', url, true); 4163 this.xmlhttp.setRequestHeader('Content-Type', contentType); 4164 this.xmlhttp.setRequestHeader('X-RoundCube-Referer', bw.get_cookie('roundcube_sessid')); 4165 this.xmlhttp.send(req_body); 4166 }; 4167 4168 // handle onreadystatechange event 4169 this.xmlhttp_onreadystatechange = function() 4170 { 4171 if(this.xmlhttp.readyState == 1) 4172 this.onloading(this); 4173 4174 else if(this.xmlhttp.readyState == 2) 4175 this.onloaded(this); 4176 4177 else if(this.xmlhttp.readyState == 3) 4178 this.oninteractive(this); 4179 4180 else if(this.xmlhttp.readyState == 4) 4181 { 4182 try { 4183 if (this.xmlhttp.status == 0) 4184 this.onabort(this); 4185 else if(this.xmlhttp.status == 200) 4186 this.oncomplete(this); 4187 else 4188 this.onerror(this); 4189 4190 this.busy = false; 4191 } 4192 catch(err) 4193 { 4194 this.onerror(this); 4195 this.busy = false; 4196 } 4197 } 4198 } 4199 4200 // getter method for HTTP headers 4201 this.get_header = function(name) 4202 { 4203 return this.xmlhttp.getResponseHeader(name); 4204 }; 4205 4206 this.get_text = function() 4207 { 4208 return this.xmlhttp.responseText; 4209 }; 4210 4211 this.get_xml = function() 4212 { 4213 return this.xmlhttp.responseXML; 4214 }; 4215 4216 this.reset(); 4217 4218 } // end class rcube_http_request 4219 4220 // helper function to call the init method with a delay 4221 function call_init(o) 4222 { 4223 window.setTimeout('if (window[\''+o+'\'] && window[\''+o+'\'].init) { '+o+'.init(); }', 4224 bw.win ? 500 : 200); 4225 } 4226 4014 } // end object rcube_webmail 4015 4016 4017 // copy event engine prototype 4018 rcube_webmail.prototype.addEventListener = rcube_event_engine.prototype.addEventListener; 4019 rcube_webmail.prototype.removeEventListener = rcube_event_engine.prototype.removeEventListener; 4020 rcube_webmail.prototype.triggerEvent = rcube_event_engine.prototype.triggerEvent; 4021 -
trunk/roundcubemail/program/js/common.js
r2395 r2401 94 94 95 95 96 // static functions for event handling96 // static functions for DOM event handling 97 97 var rcube_event = { 98 98 … … 160 160 161 161 if (e._offset) { 162 mX += e._offset. x;163 mY += e._offset. y;162 mX += e._offset.left; 163 mY += e._offset.top; 164 164 } 165 165 … … 235 235 236 236 237 var rcube_layer_objects = new Array(); 237 /** 238 * rcmail objects event interface 239 */ 240 function rcube_event_engine() 241 { 242 this._events = {}; 243 } 244 245 rcube_event_engine.prototype = { 246 247 /** 248 * Setter for object event handlers 249 * 250 * @param {String} Event name 251 * @param {Function} Handler function 252 * @return Listener ID (used to remove this handler later on) 253 */ 254 addEventListener: function(evt, func, obj) 255 { 256 if (!this._events) 257 this._events = {}; 258 if (!this._events[evt]) 259 this._events[evt] = []; 260 261 var e = {func:func, obj:obj ? obj : window}; 262 this._events[evt][this._events[evt].length] = e; 263 }, 264 265 /** 266 * Removes a specific event listener 267 * 268 * @param {String} Event name 269 * @param {Int} Listener ID to remove 270 */ 271 removeEventListener: function(evt, func, obj) 272 { 273 if (typeof obj == 'undefined') 274 obj = window; 275 276 for (var h,i=0; this._events && this._events[evt] && i < this._events[evt].length; i++) 277 if ((h = this._events[evt][i]) && h.func == func && h.obj == obj) 278 this._events[evt][i] = null; 279 }, 280 281 /** 282 * This will execute all registered event handlers 283 * 284 * @param {String} Event to trigger 285 * @param {Object} Event object/arguments 286 */ 287 triggerEvent: function(evt, e) 288 { 289 var ret, h; 290 if (typeof e == 'undefined') 291 e = {}; 292 if (typeof e == 'object') 293 e.event = evt; 294 295 if (this._events && this._events[evt] && !this._event_exec) { 296 this._event_exec = true; 297 for (var i=0; i < this._events[evt].length; i++) { 298 if ((h = this._events[evt][i])) { 299 if (typeof h.func == 'function') 300 ret = h.func.call ? h.func.call(h.obj, this, e) : h.func(this, e); 301 else if (typeof h.obj[h.func] == 'function') 302 ret = h.obj[h.func](this, e); 303 304 // cancel event execution 305 if (typeof ret != 'undefined' && !ret) 306 break; 307 } 308 } 309 } 310 311 this._event_exec = false; 312 return ret; 313 } 314 315 } // end rcube_event_engine.prototype 316 238 317 239 318 … … 244 323 */ 245 324 function rcube_layer(id, attributes) 246 {325 { 247 326 this.name = id; 248 327 … … 311 390 this.visible = (this.css.visibility=='visible' || this.css.visibility=='show' || this.css.visibility=='inherit') ? true : false; 312 391 313 this.id = rcube_layer_objects.length;314 this.obj = 'rcube_layer_objects['+this.id+']';315 rcube_layer_objects[this.id] = this;316 317 392 318 393 // ********* layer object methods ********* … … 328 403 } 329 404 330 331 // move the layer for a specific step332 this.shift = function(x,y)333 {334 x = Math.round(x*100)/100;335 y = Math.round(y*100)/100;336 this.move(this.x+x, this.y+y);337 }338 339 340 405 // change the layers width and height 341 406 this.resize = function(w,h) … … 345 410 this.width = w; 346 411 this.height = h; 347 }348 349 350 // cut the layer (top,width,height,left)351 this.clip = function(t,w,h,l)352 {353 this.css.clip='rect('+t+' '+w+' '+h+' '+l+')';354 this.clip_height = h;355 this.clip_width = w;356 412 } 357 413 … … 384 440 } 385 441 386 387 // set the given color to the layer background 388 this.set_bgcolor = function(c) 389 { 390 if(!c || c=='#') 391 c = 'transparent'; 392 393 this.css.backgroundColor = c; 394 } 395 396 397 // set the opacity of a layer to the given ammount (in %) 398 this.set_opacity = function(v) 399 { 400 if(!bw.opacity) 401 return; 402 403 var op = v<=1 ? Math.round(v*100) : parseInt(v); 404 405 if(bw.ie) 406 this.css.filter = 'alpha(opacity:'+op+')'; 407 else if(bw.safari) 408 { 409 this.css.opacity = op/100; 410 this.css.KhtmlOpacity = op/100; 411 } 412 else if(bw.mz) 413 this.css.MozOpacity = op/100; 414 } 415 } 442 } 416 443 417 444 … … 473 500 // get any type of html objects by id/name 474 501 function rcube_find_object(id, d) 475 {502 { 476 503 var n, f, obj, e; 477 504 if(!d) d = document; … … 487 514 obj = d.images[id]; 488 515 489 if(!obj && d.forms.length) 490 for(f=0; f<d.forms.length; f++) 491 { 516 if (!obj && d.forms.length) { 517 for (f=0; f<d.forms.length; f++) { 492 518 if(d.forms[f].name == id) 493 519 obj = d.forms[f]; 494 520 else if(d.forms[f].elements[id]) 495 521 obj = d.forms[f].elements[id]; 496 }497 498 if(!obj && d.layers) 499 {500 if (d.layers[id]) obj = d.layers[id];501 for (n=0; !obj && n<d.layers.length; n++)522 } 523 } 524 525 if (!obj && d.layers) { 526 if (d.layers[id]) obj = d.layers[id]; 527 for (n=0; !obj && n<d.layers.length; n++) 502 528 obj = rcube_find_object(id, d.layers[n].document); 503 }529 } 504 530 505 531 return obj; 506 } 507 508 509 // return the absolute position of an object within the document 510 function rcube_get_object_pos(obj, relative) 511 { 512 if(typeof(obj)=='string') 513 obj = rcube_find_object(obj); 514 515 if(!obj) return {x:0, y:0}; 516 517 var iX = (bw.layers) ? obj.x : obj.offsetLeft; 518 var iY = (bw.layers) ? obj.y : obj.offsetTop; 519 520 if(!relative && (bw.ie || bw.mz)) 521 { 522 var elm = obj.offsetParent; 523 while(elm && elm!=null) 524 { 525 iX += elm.offsetLeft - (elm.parentNode && elm.parentNode.scrollLeft ? elm.parentNode.scrollLeft : 0); 526 iY += elm.offsetTop - (elm.parentNode && elm.parentNode.scrollTop ? elm.parentNode.scrollTop : 0); 527 elm = elm.offsetParent; 528 } 529 } 530 531 return {x:iX, y:iY}; 532 } 532 } 533 533 534 534 // determine whether the mouse is over the given object or not … … 536 536 { 537 537 var mouse = rcube_event.get_mouse_pos(ev); 538 var pos = rcube_get_object_pos(obj); 539 540 return ((mouse.x >= pos.x) && (mouse.x < (pos.x + obj.offsetWidth)) && 541 (mouse.y >= pos.y) && (mouse.y < (pos.y + obj.offsetHeight))); 542 } 543 544 545 /** 546 * Return the currently applied value of a css property 547 * 548 * @param {Object} html_element Node reference 549 * @param {String} css_property Property name to read in Javascript notation (eg. 'textAlign') 550 * @param {String} mozilla_equivalent Equivalent property name in CSS notation (eg. 'text-align') 551 * @return CSS property value 552 * @type String 553 */ 554 function get_elements_computed_style(html_element, css_property, mozilla_equivalent) 555 { 556 if (arguments.length==2) 557 mozilla_equivalent = css_property; 558 559 var el = html_element; 560 if (typeof(html_element)=='string') 561 el = rcube_find_object(html_element); 562 563 if (el && el.currentStyle) 564 return el.currentStyle[css_property]; 565 else if (el && document.defaultView && document.defaultView.getComputedStyle) 566 return document.defaultView.getComputedStyle(el, null).getPropertyValue(mozilla_equivalent); 567 else 568 return false; 569 } 570 538 var pos = $(obj).offset(); 539 540 return ((mouse.x >= pos.left) && (mouse.x < (pos.left + obj.offsetWidth)) && 541 (mouse.y >= pos.top) && (mouse.y < (pos.top + obj.offsetHeight))); 542 } 543 571 544 572 545 // cookie functions by GoogieSpell … … 612 585 if (box) { 613 586 if (msg.charAt(msg.length-1)=='\n') 614 msg += '--------------------------------------\n';587 msg += '--------------------------------------\n'; 615 588 else 616 589 msg += '\n--------------------------------------\n'; … … 634 607 635 608 var bw = new roundcube_browser(); 636 var console = new rcube_console(); 609 if (!window.console) 610 console = new rcube_console(); 637 611 638 612 -
trunk/roundcubemail/program/js/editor.js
r2250 r2401 53 53 gecko_spellcheck : true, 54 54 relative_urls : false, 55 remove_script_host : false ,56 rc_client: rc ube_webmail_client,55 remove_script_host : false, 56 rc_client: rcmail, 57 57 oninit : 'rcmail_editor_callback' 58 58 }); -
trunk/roundcubemail/program/js/list.js
r2396 r2401 52 52 this.dblclick_time = 600; 53 53 this.row_init = function(){}; 54 this.events = { click:[], dblclick:[], select:[], keypress:[], dragstart:[], dragmove:[], dragend:[] };55 54 56 55 // overwrite default paramaters … … 161 160 { 162 161 var tbody = this.list.tBodies[0]; 162 if (!row.jquery) 163 row = $(row); 163 164 164 165 if (attop && tbody.rows.length) 165 tbody.insertBefore(row, tbody.firstChild);166 row.prependTo(tbody) 166 167 else 167 tbody.appendChild(row);168 169 this.init_row(row );168 row.appendTo(tbody); 169 170 this.init_row(row[0]); 170 171 this.rowcount++; 171 172 }, … … 182 183 { 183 184 id = this.selection[n]; 184 if (this.rows[id] && this.rows[id].obj) 185 { 186 this.set_classname(this.rows[id].obj, 'selected', true); 187 this.set_classname(this.rows[id].obj, 'unfocused', false); 185 if (this.rows[id] && this.rows[id].obj) { 186 $(this.rows[id].obj).addClass('selected').removeClass('unfocused'); 188 187 } 189 188 } … … 204 203 { 205 204 id = this.selection[n]; 206 if (this.rows[id] && this.rows[id].obj) 207 { 208 this.set_classname(this.rows[id].obj, 'selected', false); 209 this.set_classname(this.rows[id].obj, 'unfocused', true); 205 if (this.rows[id] && this.rows[id].obj) { 206 $(this.rows[id].obj).removeClass('selected').addClass('unfocused'); 210 207 } 211 208 } … … 252 249 iframedoc = iframes[n].contentDocument; 253 250 else if (iframes[n].contentWindow) 254 iframedoc = iframes[n].contentWindow.document;251 iframedoc = iframes[n].contentWindow.document; 255 252 else if (iframes[n].document) 256 253 iframedoc = iframes[n].document; … … 258 255 if (iframedoc) 259 256 { 260 var list = this;261 var pos = rcube_get_object_pos(document.getElementById(iframes[n].id));262 this.iframe_events[n] = function(e) { e._offset = pos; return list.drag_mouse_move(e); }263 264 if (iframedoc.addEventListener)265 iframedoc.addEventListener('mousemove', this.iframe_events[n], false);266 else if (iframes[n].attachEvent)267 iframedoc.attachEvent('onmousemove', this.iframe_events[n]);268 else269 iframedoc['onmousemove'] = this.iframe_events[n];257 var list = this; 258 var pos = $('#'+iframes[n].id).offset(); 259 this.iframe_events[n] = function(e) { e._offset = pos; return list.drag_mouse_move(e); } 260 261 if (iframedoc.addEventListener) 262 iframedoc.addEventListener('mousemove', this.iframe_events[n], false); 263 else if (iframes[n].attachEvent) 264 iframedoc.attachEvent('onmousemove', this.iframe_events[n]); 265 else 266 iframedoc['onmousemove'] = this.iframe_events[n]; 270 267 271 268 rcube_event.add_listener({element:iframedoc, event:'mouseup', object:this, method:'drag_mouse_up'}); 272 269 } 273 } 270 } 274 271 } 275 272 … … 308 305 // row was double clicked 309 306 if (this.rows && dblclicked && this.in_selection(id)) 310 this.trigger _event('dblclick');307 this.triggerEvent('dblclick'); 311 308 else 312 this.trigger _event('click');309 this.triggerEvent('click'); 313 310 314 311 if (!this.drag_active) … … 408 405 // trigger event if selection changed 409 406 if (this.selection.join(',') != select_before) 410 this.trigger _event('select');407 this.triggerEvent('select'); 411 408 412 409 if (this.last_selected != 0 && this.rows[this.last_selected]) 413 this.set_classname(this.rows[this.last_selected].obj, 'focused', false);410 $(this.rows[this.last_selected].obj).removeClass('focused'); 414 411 415 412 // unselect if toggleselect is active and the same row was clicked again … … 420 417 } 421 418 else 422 this.set_classname(this.rows[id].obj, 'focused', true);419 $(this.rows[id].obj).addClass('focused'); 423 420 424 421 if (!this.selection.length) … … 525 522 // trigger event if selection changed 526 523 if (this.selection.join(',') != select_before) 527 this.trigger _event('select');524 this.triggerEvent('select'); 528 525 529 526 this.focus(); … … 544 541 { 545 542 for (var n=0; n<this.selection.length; n++) 546 if (this.selection[n] == id) 547 { 548 this.selection.splice(n,1); 549 break; 550 } 543 if (this.selection[n] == id) { 544 this.selection.splice(n,1); 545 break; 546 } 551 547 } 552 548 // all rows … … 554 550 { 555 551 for (var n=0; n<this.selection.length; n++) 556 if (this.rows[this.selection[n]]) 557 { 558 this.set_classname(this.rows[this.selection[n]].obj, 'selected', false); 559 this.set_classname(this.rows[this.selection[n]].obj, 'unfocused', false); 552 if (this.rows[this.selection[n]]) { 553 $(this.rows[this.selection[n]].obj).removeClass('selected').removeClass('unfocused'); 560 554 } 561 555 … … 564 558 565 559 if (num_select && !this.selection.length) 566 this.trigger _event('select');560 this.triggerEvent('select'); 567 561 }, 568 562 … … 600 594 this.clear_selection(); 601 595 this.selection[0] = id; 602 this.set_classname(this.rows[id].obj, 'selected', true);596 $(this.rows[id].obj).addClass('selected'); 603 597 } 604 598 } … … 608 602 { 609 603 this.selection[this.selection.length] = id; 610 this.set_classname(this.rows[id].obj, 'selected', true);604 $(this.rows[id].obj).addClass('selected'); 611 605 } 612 606 else // unselect row … … 616 610 var a_post = this.selection.slice(p+1, this.selection.length); 617 611 this.selection = a_pre.concat(a_post); 618 this.set_classname(this.rows[id].obj, 'selected', false); 619 this.set_classname(this.rows[id].obj, 'unfocused', false); 612 $(this.rows[id].obj).removeClass('selected').removeClass('unfocused'); 620 613 } 621 614 } … … 645 638 this.shiftkey = e.shiftKey; 646 639 this.key_pressed = keyCode; 647 this.trigger _event('keypress');640 this.triggerEvent('keypress'); 648 641 649 642 if (this.key_pressed == this.BACKSPACE_KEY) … … 730 723 731 724 if (!this.draglayer) 732 this.draglayer = new rcube_layer('rcmdraglayer', {x:0, y:0, vis:0, zindex:2000});725 this.draglayer = $('<div>').attr('id', 'rcmdraglayer').css({ position:'absolute', display:'none', 'z-index':2000 }).appendTo(document.body); 733 726 734 727 // get subjects of selectedd messages … … 755 748 (this.subject_col < 0 || (this.subject_col >= 0 && this.subject_col == c))) 756 749 { 750 if (n == 0) 751 this.drag_start_pos = $(node).offset(); 752 757 753 subject = node.nodeType==3 ? node.data : node.innerHTML; 758 754 // remove leading spaces … … 768 764 } 769 765 770 this.draglayer. write(names);771 this.draglayer.show( 1);766 this.draglayer.html(names); 767 this.draglayer.show(); 772 768 773 769 this.drag_active = true; 774 this.trigger _event('dragstart');770 this.triggerEvent('dragstart'); 775 771 } 776 772 … … 778 774 { 779 775 var pos = rcube_event.get_mouse_pos(e); 780 this.draglayer. move(pos.x+20, bw.ie ? pos.y-5+document.documentElement.scrollTop : pos.y-5);781 this.trigger _event('dragmove', e);776 this.draglayer.css({ left:(pos.x+20)+'px', top:(pos.y-5 + (bw.ie ? document.documentElement.scrollTop : 0))+'px' }); 777 this.triggerEvent('dragmove', e); 782 778 } 783 779 … … 795 791 document.onmousemove = null; 796 792 797 if (this.draglayer && this.draglayer.visible) 798 this.draglayer.show(0); 793 if (this.draglayer && this.draglayer.is(':visible')) { 794 if (this.drag_start_pos) 795 this.draglayer.animate(this.drag_start_pos, 300, 'swing').hide(20); 796 else 797 this.draglayer.hide(); 798 } 799 799 800 800 this.drag_active = false; 801 this.trigger _event('dragend');801 this.triggerEvent('dragend'); 802 802 803 803 rcube_event.remove_listener({element:document, event:'mousemove', object:this, method:'drag_mouse_move'}); … … 829 829 830 830 return rcube_event.cancel(e); 831 },832 833 834 835 /**836 * set/unset a specific class name837 */838 set_classname: function(obj, classname, set)839 {840 var reg = new RegExp('\s*'+classname, 'i');841 if (!set && obj.className.match(reg))842 obj.className = obj.className.replace(reg, '');843 else if (set && !obj.className.match(reg))844 obj.className += ' '+classname;845 },846 847 848 /**849 * Setter for object event handlers850 *851 * @param {String} Event name852 * @param {Function} Handler function853 * @return Listener ID (used to remove this handler later on)854 */855 addEventListener: function(evt, handler)856 {857 if (this.events[evt]) {858 var handle = this.events[evt].length;859 this.events[evt][handle] = handler;860 return handle;861 }862 else863 return false;864 },865 866 867 /**868 * Removes a specific event listener869 *870 * @param {String} Event name871 * @param {Int} Listener ID to remove872 */873 removeEventListener: function(evt, handle)874 {875 if (this.events[evt] && this.events[evt][handle])876 this.events[evt][handle] = null;877 },878 879 880 /**881 * This will execute all registered event handlers882 * @private883 */884 trigger_event: function(evt, p)885 {886 if (this.events[evt] && this.events[evt].length) {887 for (var i=0; i<this.events[evt].length; i++)888 if (typeof(this.events[evt][i]) == 'function')889 this.events[evt][i](this, p);890 }891 831 } 892 832 893 894 833 }; 895 834 835 rcube_list_widget.prototype.addEventListener = rcube_event_engine.prototype.addEventListener; 836 rcube_list_widget.prototype.removeEventListener = rcube_event_engine.prototype.removeEventListener; 837 rcube_list_widget.prototype.triggerEvent = rcube_event_engine.prototype.triggerEvent; -
trunk/roundcubemail/program/lib/imap.inc
r2388 r2401 183 183 var $junk = false; 184 184 var $flagged = false; 185 var $others = array(); 185 186 } 186 187 … … 1662 1663 } 1663 1664 1664 function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bodystr=false )1665 function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bodystr=false, $add='') 1665 1666 { 1666 1667 global $IMAP_USE_INTERNAL_DATE; … … 1702 1703 } 1703 1704 } 1705 1706 if ($add) 1707 $add = ' '.strtoupper(trim($add)); 1704 1708 1705 1709 /* FETCH uid, size, flags and headers */ … … 1712 1716 $request .= "(DATE FROM TO SUBJECT REPLY-TO IN-REPLY-TO CC BCC "; 1713 1717 $request .= "CONTENT-TRANSFER-ENCODING CONTENT-TYPE MESSAGE-ID "; 1714 $request .= "REFERENCES DISPOSITION-NOTIFICATION-TO X-PRIORITY )])";1718 $request .= "REFERENCES DISPOSITION-NOTIFICATION-TO X-PRIORITY".$add.")])"; 1715 1719 1716 1720 if (!iil_PutLine($fp, $request)) { … … 1860 1864 1861 1865 $field = strtolower($field); 1862 $string = ereg_replace("\n[[:space:]]*"," ",$string); 1866 $string = ereg_replace("\n[[:space:]]*"," ",$string); 1863 1867 1864 1868 switch ($field) { … … 1918 1922 $result[$id]->priority = intval($matches[1]); 1919 1923 break; 1924 default: 1925 if (strlen($field) > 2) 1926 $result[$id]->others[$field] = $string; 1927 break; 1920 1928 } // end switch () 1921 1929 } // end while () … … 1965 1973 } 1966 1974 1967 function iil_C_FetchHeader(&$conn, $mailbox, $id, $uidfetch=false, $bodystr=false ) {1968 1969 $a = iil_C_FetchHeaders($conn, $mailbox, $id, $uidfetch, $bodystr );1975 function iil_C_FetchHeader(&$conn, $mailbox, $id, $uidfetch=false, $bodystr=false, $add='') { 1976 1977 $a = iil_C_FetchHeaders($conn, $mailbox, $id, $uidfetch, $bodystr, $add); 1970 1978 if (is_array($a)) { 1971 1979 return array_shift($a); -
trunk/roundcubemail/program/steps/addressbook/func.inc
r1939 r2401 43 43 if (strtolower($CONFIG['address_book_type']) != 'ldap') { 44 44 // We are using the DB address book, add it. 45 $js_list = array("0" => array('id' => 0, 'readonly' => false));45 $js_list['0'] = array('id' => 0, 'name' => rcube_label('personaladrbook'), 'readonly' => false); 46 46 } 47 47 if (is_array($CONFIG['ldap_public'])) { 48 48 foreach ($CONFIG['ldap_public'] as $id => $prop) 49 $js_list[$id] = array('id' => $id, ' readonly' => !$prop['writable']);49 $js_list[$id] = array('id' => $id, 'name' => $prop['name'], 'readonly' => !$prop['writable']); 50 50 } 51 $OUTPUT->set_env('address_sources', $js_list); 51 52 $plugin = $RCMAIL->plugins->exec_hook('address_sources', array('sources' => $js_list)); 53 $OUTPUT->set_env('address_sources', $plugin['sources']); 52 54 53 55 54 56 function rcmail_directory_list($attrib) 55 57 { 56 global $ CONFIG, $OUTPUT;58 global $RCMAIL, $OUTPUT; 57 59 58 60 if (!$attrib['id']) … … 64 66 $line_templ = html::tag('li', array('id' => 'rcmli%s', 'class' => '%s'), 65 67 html::a(array('href' => '%s', 'onclick' => "return ".JS_OBJECT_NAME.".command('list','%s',this)"), '%s')); 66 67 if (strtolower($CONFIG['address_book_type']) != 'ldap') { 68 $out .= sprintf($line_templ, $local_id, (!$current ? 'selected' : ''), 69 Q(rcmail_url(null, array('_source' => $local_id))), $local_id, rcube_label('personaladrbook')); 70 } // end if 71 else { 68 69 if (!$current && strtolower($RCMAIL->config->get('address_book_type', 'sql')) != 'ldap') { 70 $current = '0'; 71 } 72 else if (!$current) { 72 73 // DB address book not used, see if a source is set, if not use the 73 74 // first LDAP directory. 74 if (!$current) { 75 $current = key((array)$CONFIG['ldap_public']); 76 } // end if 77 } // end else 78 79 foreach ((array)$CONFIG['ldap_public'] as $id => $prop) { 75 $current = key((array)$RCMAIL->config->get('ldap_public', array())); 76 } 77 78 foreach ((array)$OUTPUT->env['address_sources'] as $j => $source) { 79 $id = $source['id'] ? $source['id'] : $j; 80 80 $js_id = JQ($id); 81 81 $dom_id = preg_replace('/[^a-z0-9\-_]/i', '', $id); 82 82 $out .= sprintf($line_templ, $dom_id, ($current == $id ? 'selected' : ''), 83 Q(rcmail_url(null, array('_source' => $id))), $js_id, (!empty($ prop['name']) ? Q($prop['name']) : Q($id)));84 } 85 83 Q(rcmail_url(null, array('_source' => $id))), $js_id, (!empty($source['name']) ? Q($source['name']) : Q($id))); 84 } 85 86 86 $OUTPUT->add_gui_object('folderlist', $attrib['id']); 87 87 -
trunk/roundcubemail/program/steps/mail/attachments.inc
r2376 r2401 29 29 if ($RCMAIL->action=='remove-attachment') 30 30 { 31 if (preg_match('/^rcmfile([0-9]+)$/', $_POST['_file'], $regs))32 {31 $id = 'undefined'; 32 if (preg_match('/^rcmfile(\w+)$/', $_POST['_file'], $regs)) 33 33 $id = $regs[1]; 34 if (is_array($_SESSION['compose']['attachments'][$id])) 35 { 36 @unlink($_SESSION['compose']['attachments'][$id]['path']); 34 if ($attachment = $_SESSION['compose']['attachments'][$id]) 35 $attachment = $RCMAIL->plugins->exec_hook('remove_attachment', $attachment); 36 if ($attachment['status']) { 37 if (is_array($_SESSION['compose']['attachments'][$id])) { 37 38 unset($_SESSION['compose']['attachments'][$id]); 38 39 $OUTPUT->command('remove_from_attachment_list', "rcmfile$id"); 39 $OUTPUT->send();40 40 } 41 41 } 42 43 $OUTPUT->send(); 42 44 exit; 43 45 } … … 45 47 if ($RCMAIL->action=='display-attachment') 46 48 { 47 if (preg_match('/^rcmfile([0-9]+)$/', $_GET['_file'], $regs))48 {49 $id = 'undefined'; 50 if (preg_match('/^rcmfile(\w+)$/', $_GET['_file'], $regs)) 49 51 $id = $regs[1]; 50 if (is_array($_SESSION['compose']['attachments'][$id])) 51 { 52 $apath = $_SESSION['compose']['attachments'][$id]['path']; 53 header('Content-Type: ' . $_SESSION['compose']['attachments'][$id]['mimetype']); 54 header('Content-Length: ' . filesize($apath)); 55 readfile($apath); 56 } 52 if ($attachment = $_SESSION['compose']['attachments'][$id]) 53 $attachment = $RCMAIL->plugins->exec_hook('display_attachment', $attachment); 54 55 if ($attachment['status']) { 56 $size = $attachment['data'] ? strlen($attachment['data']) : @filesize($attachment['path']); 57 header('Content-Type: ' . $attachment['mimetype']); 58 header('Content-Length: ' . $size); 59 60 if ($attachment['data']) 61 echo $attachment['data']; 62 else if ($attachment['path']) 63 readfile($attachment['path']); 57 64 } 58 65 exit; … … 60 67 61 68 // attachment upload action 62 63 // use common temp dir for file uploads64 $temp_dir = unslashify($CONFIG['temp_dir']);65 66 // #1484529: we need absolute path on Windows for move_uploaded_file()67 if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {68 $temp_dir = realpath($temp_dir);69 }70 69 71 70 if (!is_array($_SESSION['compose']['attachments'])) { … … 78 77 if (is_array($_FILES['_attachments']['tmp_name'])) { 79 78 foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) { 80 $tmpfname = tempnam($temp_dir, 'rcmAttmnt'); 81 if (move_uploaded_file($filepath, $tmpfname) && file_exists($tmpfname)) { 82 $id = count($_SESSION['compose']['attachments']); 83 $_SESSION['compose']['attachments'][] = array( 84 'name' => $_FILES['_attachments']['name'][$i], 85 'mimetype' => rc_mime_content_type($tmpfname, $_FILES['_attachments']['name'][$i], $_FILES['_attachments']['type'][$i]), 86 'path' => $tmpfname, 87 ); 79 $attachment = array( 80 'path' => $filepath, 81 'name' => $_FILES['_attachments']['name'][$i], 82 'mimetype' => rc_mime_content_type($tmpfname, $_FILES['_attachments']['type'][$i]) 83 ); 88 84 85 $attachment = $RCMAIL->plugins->exec_hook('upload_attachment', $attachment); 86 if ($attachment['status']) { 87 $id = $attachment['id']; 88 89 // store new attachment in session 90 unset($attachment['status']); 91 $_SESSION['compose']['attachments'][$id] = $attachment; 92 89 93 if (is_file($icon = $CONFIG['skin_path'] . '/images/icons/remove-attachment.png')) { 90 94 $button = html::img(array( … … 100 104 $content = html::a(array( 101 105 'href' => "#delete", 102 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile% d', this)", JS_OBJECT_NAME, $id),106 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", JS_OBJECT_NAME, $id), 103 107 'title' => rcube_label('delete'), 104 108 ), $button); 105 106 $content .= Q($ _FILES['_attachments']['name'][$i]);109 110 $content .= Q($attachment['name']); 107 111 108 112 $OUTPUT->command('add2attachment_list', "rcmfile$id", $content); -
trunk/roundcubemail/program/steps/mail/compose.inc
r2368 r2401 595 595 596 596 $cid_map = array(); 597 $id = 0;598 599 597 foreach ((array)$message->mime_parts as $pid => $part) 600 598 { … … 604 602 { 605 603 if ($attachment = rcmail_save_attachment($message, $pid)) { 606 $_SESSION['compose']['attachments'][$id] = $attachment; 607 if ($bodyIsHtml && $part->filename && $part->content_id) { 608 $cid_map['cid:'.$part->content_id] = 609 $OUTPUT->app->comm_path.'&_action=display-attachment&_file=rcmfile'.$id; 604 $_SESSION['compose']['attachments'][$attachment['id']] = $attachment; 605 if ($bodyIsHtml && $part->filename && $part->content_id) { 606 $cid_map['cid:'.$part->content_id] = $OUTPUT->app->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id']; 610 607 } 611 $id++; 612 } 613 } 614 } 615 608 } 609 } 610 } 611 616 612 $_SESSION['compose']['forward_attachments'] = true; 617 613 … … 625 621 626 622 $cid_map = array(); 627 $id = 0;628 629 623 foreach ((array)$message->mime_parts as $pid => $part) { 630 624 if ($part->content_id && $part->filename) { 631 625 if ($attachment = rcmail_save_attachment($message, $pid)) { 632 $_SESSION['compose']['attachments'][$id] = $attachment; 633 $cid_map['cid:'.$part->content_id] = 634 $OUTPUT->app->comm_path.'&_action=display-attachment&_file=rcmfile'.$id; 635 $id++; 626 $_SESSION['compose']['attachments'][$attachment['id']] = $attachment; 627 $cid_map['cid:'.$part->content_id] = $OUTPUT->app->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id']; 636 628 } 637 629 } … … 643 635 function rcmail_save_attachment(&$message, $pid) 644 636 { 645 global $RCMAIL;646 647 $temp_dir = unslashify($RCMAIL->config->get('temp_dir'));648 $tmp_path = tempnam($temp_dir, 'rcmAttmnt');649 637 $part = $message->mime_parts[$pid]; 650 638 651 if ($fp = fopen($tmp_path, 'w')) 652 { 653 $message->get_part_content($pid, $fp); 654 fclose($fp); 655 656 return array( 657 'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary, 658 'name' => $part->filename, 659 'path' => $tmp_path, 660 'content_id' => $part->content_id 661 ); 662 } 639 $attachment = array( 640 'name' => $part->filename, 641 'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary, 642 'content_id' => $part->content_id, 643 'data' => $message->get_part_content($pid), 644 ); 645 646 $attachment = rcmail::get_instance()->plugins->exec_hook('save_attachment', $attachment); 647 if ($attachment['status']) { 648 unset($attachment['data'], $attachment['status']); 649 return $attachment; 650 } 651 652 return false; 663 653 } 664 654 … … 740 730 'href' => "#delete", 741 731 'title' => rcube_label('delete'), 742 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile% d', this)", JS_OBJECT_NAME, $id)),732 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", JS_OBJECT_NAME, $id)), 743 733 $button) . Q($a_prop['name'])); 744 734 } -
trunk/roundcubemail/program/steps/mail/func.inc
r2397 r2401 731 731 function rcmail_print_body($part, $p = array()) 732 732 { 733 $p += array('safe' => false, 'plain' => false, 'inline_html' => true); 733 global $RCMAIL; 734 735 // trigger plugin hook 736 $data = $RCMAIL->plugins->exec_hook('message_part_before', 737 array('type' => $part->ctype_secondary, 'body' => $part->body) + $p + array('safe' => false, 'plain' => false, 'inline_html' => true)); 734 738 735 739 // convert html to text/plain 736 if ($ part->ctype_secondary == 'html' && $p['plain']) {737 $txt = new html2text($ part->body, false, true);740 if ($data['type'] == 'html' && $data['plain']) { 741 $txt = new html2text($data['body'], false, true); 738 742 $body = $txt->get_text(); 739 743 $part->ctype_secondary = 'plain'; 740 744 } 741 745 // text/html 742 else if ($part->ctype_secondary == 'html') { 743 return rcmail_wash_html($part->body, $p, $part->replaces); 746 else if ($data['type'] == 'html') { 747 $body = rcmail_wash_html($data['body'], $data, $part->replaces); 748 $part->ctype_secondary = $data['type']; 744 749 } 745 750 // text/enriched 746 else if ($ part->ctype_secondary=='enriched') {751 else if ($data['type'] == 'enriched') { 747 752 $part->ctype_secondary = 'html'; 748 753 require_once('lib/enriched.inc'); 749 return Q(enriched_to_html($part->body), 'show'); 750 } 751 else 754 $body = Q(enriched_to_html($data['body']), 'show'); 755 } 756 else { 757 // assert plaintext 752 758 $body = $part->body; 753 754 755 /**** assert plaintext ****/ 756 757 // make links and email-addresses clickable 758 $replacements = new rcube_string_replacer; 759 760 $url_chars = 'a-z0-9_\-\+\*\$\/&%=@#:;'; 761 $url_chars_within = '\?\.~,!'; 762 763 // search for patterns like links and e-mail addresses 764 $body = preg_replace_callback("/([\w]+):\/\/([a-z0-9\-\.]+[a-z]{2,4}([$url_chars$url_chars_within]*[$url_chars])?)/i", array($replacements, 'link_callback'), $body); 765 $body = preg_replace_callback("/([^\/:]|\s)(www\.)([a-z0-9\-]{2,}[a-z]{2,4}([$url_chars$url_chars_within]*[$url_chars])?)/i", array($replacements, 'link_callback'), $body); 766 $body = preg_replace_callback('/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/i', array($replacements, 'mailto_callback'), $body); 767 768 // split body into single lines 769 $a_lines = preg_split('/\r?\n/', $body); 770 $quote_level = 0; 771 772 // colorize quoted parts 773 for ($n=0; $n < sizeof($a_lines); $n++) { 774 $line = $a_lines[$n]; 775 $quotation = ''; 776 $q = 0; 777 778 if (preg_match('/^(>+\s*)+/', $line, $regs)) { 779 $q = strlen(preg_replace('/\s/', '', $regs[0])); 780 $line = substr($line, strlen($regs[0])); 781 782 if ($q > $quote_level) 783 $quotation = str_repeat('<blockquote>', $q - $quote_level); 784 else if ($q < $quote_level) 785 $quotation = str_repeat("</blockquote>", $quote_level - $q); 786 } 787 else if ($quote_level > 0) 788 $quotation = str_repeat("</blockquote>", $quote_level); 789 790 $quote_level = $q; 791 $a_lines[$n] = $quotation . Q($line, 'replace', false); // htmlquote plaintext 792 } 793 794 // insert the links for urls and mailtos 795 $body = $replacements->resolve(join("\n", $a_lines)); 796 797 return html::tag('pre', array(), $body); 759 $part->ctype_secondary = $data['type'] = 'plain'; 760 } 761 762 // free some memory (hopefully) 763 unset($data['body']); 764 765 766 // plaintext postprocessing 767 if ($part->ctype_secondary == 'plain') { 768 // make links and email-addresses clickable 769 $replacements = new rcube_string_replacer; 770 771 $url_chars = 'a-z0-9_\-\+\*\$\/&%=@#:;'; 772 $url_chars_within = '\?\.~,!'; 773 774 // search for patterns like links and e-mail addresses 775 $body = preg_replace_callback("/([\w]+):\/\/([a-z0-9\-\.]+[a-z]{2,4}([$url_chars$url_chars_within]*[$url_chars])?)/i", array($replacements, 'link_callback'), $body); 776 $body = preg_replace_callback("/([^\/:]|\s)(www\.)([a-z0-9\-]{2,}[a-z]{2,4}([$url_chars$url_chars_within]*[$url_chars])?)/i", array($replacements, 'link_callback'), $body); 777 $body = preg_replace_callback('/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/i', array($replacements, 'mailto_callback'), $body); 778 779 // split body into single lines 780 $a_lines = preg_split('/\r?\n/', $body); 781 $quote_level = 0; 782 783 // colorize quoted parts 784 for ($n=0; $n < count($a_lines); $n++) { 785 $line = $a_lines[$n]; 786 $quotation = ''; 787 $q = 0; 788 789 if (preg_match('/^(>+\s*)+/', $line, $regs)) { 790 $q = strlen(preg_replace('/\s/', '', $regs[0])); 791 $line = substr($line, strlen($regs[0])); 792 793 if ($q > $quote_level) 794 $quotation = str_repeat('<blockquote>', $q - $quote_level); 795 else if ($q < $quote_level) 796 $quotation = str_repeat("</blockquote>", $quote_level - $q); 797 } 798 else if ($quote_level > 0) 799 $quotation = str_repeat("</blockquote>", $quote_level); 800 801 $quote_level = $q; 802 $a_lines[$n] = $quotation . Q($line, 'replace', false); // htmlquote plaintext 803 } 804 805 // insert the links for urls and mailtos 806 $body = $replacements->resolve(join("\n", $a_lines)); 807 } 808 809 // allow post-processing of the message body 810 $data = $RCMAIL->plugins->exec_hook('message_part_after', array('type' => $part->ctype_secondary, 'body' => $body) + $data); 811 812 return $data['type'] == 'html' ? $data['body'] : html::tag('pre', array(), $data['body']); 798 813 } 799 814 … … 843 858 function rcmail_message_headers($attrib, $headers=NULL) 844 859 { 845 global $IMAP, $OUTPUT, $MESSAGE, $PRINT_MODE, $ CONFIG;860 global $IMAP, $OUTPUT, $MESSAGE, $PRINT_MODE, $RCMAIL; 846 861 static $sa_attrib; 847 862 … … 852 867 $attrib = $sa_attrib; 853 868 854 855 869 if (!isset($MESSAGE)) 856 870 return FALSE; … … 860 874 $headers = is_object($MESSAGE->headers) ? get_object_vars($MESSAGE->headers) : $MESSAGE->headers; 861 875 862 $header_count = 0;863 864 // allow the following attributes to be added to the <table> tag865 $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));866 $out = '<table' . $attrib_str . ">\n";867 868 876 // show these headers 869 877 $standard_headers = array('subject', 'from', 'to', 'cc', 'bcc', 'replyto', 'date'); 870 871 foreach ($standard_headers as $hkey) 872 {878 $output_headers = array(); 879 880 foreach ($standard_headers as $hkey) { 873 881 if (!$headers[$hkey]) 874 882 continue; 875 883 876 if ($hkey == 'date') 877 { 884 if ($hkey == 'date') { 878 885 if ($PRINT_MODE) 879 $header_value = format_date($headers[$hkey], $ CONFIG['date_long'] ? $CONFIG['date_long'] : 'x');886 $header_value = format_date($headers[$hkey], $RCMAIL->config->get('date_long', 'x')); 880 887 else 881 888 $header_value = format_date($headers[$hkey]); 882 } 883 else if ($hkey == 'replyto') 884 { 889 } 890 else if ($hkey == 'replyto') { 885 891 if ($headers['replyto'] != $headers['from']) 886 $header_value = Q(rcmail_address_string($headers['replyto'], null, true, $attrib['addicon']), 'show');892 $header_value = rcmail_address_string($headers['replyto'], null, true, $attrib['addicon']); 887 893 else 888 894 continue; 889 }895 } 890 896 else if (in_array($hkey, array('from', 'to', 'cc', 'bcc'))) 891 $header_value = Q(rcmail_address_string($headers[$hkey], null, true, $attrib['addicon']), 'show');897 $header_value = rcmail_address_string($headers[$hkey], null, true, $attrib['addicon']); 892 898 else if ($hkey == 'subject' && empty($headers[$hkey])) 893 $header_value = Q(rcube_label('nosubject'));899 $header_value = rcube_label('nosubject'); 894 900 else 895 $header_value = Q(trim($IMAP->decode_header($headers[$hkey]))); 896 897 $out .= "\n<tr>\n"; 898 $out .= '<td class="header-title">'.Q(rcube_label($hkey)).": </td>\n"; 899 $out .= '<td class="'.$hkey.'" width="90%">'.$header_value."</td>\n</tr>"; 900 $header_count++; 901 } 901 $header_value = trim($IMAP->decode_header($headers[$hkey])); 902 903 $output_headers[$hkey] = array('title' => rcube_label($hkey), 'value' => $header_value, 'raw' => $headers[$hkey]); 904 } 905 906 $plugin = $RCMAIL->plugins->exec_hook('message_headers_output', array('output' => $output_headers, 'headers' => $MESSAGE->headers)); 907 908 // compose html table 909 $table = new html_table(array('cols' => 2)); 910 911 foreach ($plugin['output'] as $hkey => $row) { 912 $table->add(array('class' => 'header-title'), Q($row['title'])); 913 $table->add(array('class' => $hkey, 'width' => "90%"), Q($row['value'], ($hkey == 'subject' ? 'strict' : 'show'))); 914 } 902 915 903 916 // all headers division 904 $ out .= "\n".'<tr><td colspan="2" class="more-headers show-headers"905 onclick="return '.JS_OBJECT_NAME.'.command(\'load-headers\', \'\', this)"></td></tr>';906 $ out .= "\n".'<tr id="all-headers"><td colspan="2" class="all"><div id="headers-source"></div></td></tr>';907 917 $table->add(array('colspan' => 2, 'class' => "more-headers show-headers", 'onclick' => "return ".JS_OBJECT_NAME.".command('load-headers','',this)"), ''); 918 $table->add_row(array('id' => "all-headers")); 919 $table->add(array('colspan' => 2, 'class' => "all"), html::div(array('id' => 'headers-source'), '')); 920 908 921 $OUTPUT->add_gui_object('all_headers_row', 'all-headers'); 909 922 $OUTPUT->add_gui_object('all_headers_box', 'headers-source'); 910 923 911 $out .= "\n</table>\n\n"; 912 913 return $header_count ? $out : ''; 924 return $table->show($attrib); 914 925 } 915 926 … … 1252 1263 return; 1253 1264 1254 // remove attachment files from temp dir 1255 if (is_array($_SESSION['compose']['attachments'])) 1256 foreach ($_SESSION['compose']['attachments'] as $attachment) 1257 @unlink($attachment['path']); 1265 rcmail::get_instance()->plugins->exec_hook('cleanup_attachments',array()); 1258 1266 1259 1267 unset($_SESSION['compose']); -
trunk/roundcubemail/program/steps/mail/sendmail.inc
r2368 r2401 298 298 // the HTML part and the plain-text part 299 299 300 if ($isHtml) 301 {302 $MAIL_MIME->setHTMLBody($ message_body. ($footer ? "\r\n<pre>".$footer.'</pre>' : ''));300 if ($isHtml) { 301 $plugin = $RCMAIL->plugins->exec_hook('outgoing_message_body', array('body' => $message_body, 'type' => 'html', 'message' => $MAIL_MIME)); 302 $MAIL_MIME->setHTMLBody($plugin['body'] . ($footer ? "\r\n<pre>".$footer.'</pre>' : '')); 303 303 304 304 // add a plain text version of the e-mail as an alternative part. 305 $h2t = new html2text($ message_body, false, true, 0);306 $plainTextPart = rc_wordwrap($h2t->get_text(), 75, "\r\n") . ($footer ? "\r\n".$footer : '');305 $h2t = new html2text($plugin['body'], false, true, 0); 306 $plainTextPart = rc_wordwrap($h2t->get_text(), 75, "\r\n") . ($footer ? "\r\n".$footer : ''); 307 307 $plainTextPart = wordwrap($plainTextPart, 998, "\r\n", true); 308 if (!strlen($plainTextPart)) 309 { 308 if (!strlen($plainTextPart)) { 310 309 // empty message body breaks attachment handling in drafts 311 310 $plainTextPart = "\r\n"; 312 } 313 $MAIL_MIME->setTXTBody($plainTextPart); 311 } 312 $plugin = $RCMAIL->plugins->exec_hook('outgoing_message_body', array('body' => $plainTextPart, 'type' => 'alternative', 'message' => $MAIL_MIME)); 313 $MAIL_MIME->setTXTBody($plugin['body']); 314 314 315 315 // look for "emoticon" images from TinyMCE and copy into message as attachments 316 316 $message_body = rcmail_attach_emoticons($MAIL_MIME); 317 }317 } 318 318 else 319 319 { … … 322 322 $message_body .= "\r\n" . $footer; 323 323 $message_body = wordwrap($message_body, 998, "\r\n", true); 324 if (!strlen($message_body)) 325 { 324 if (!strlen($message_body)) { 326 325 // empty message body breaks attachment handling in drafts 327 326 $message_body = "\r\n"; 328 } 329 $MAIL_MIME->setTXTBody($message_body, FALSE, TRUE); 330 } 327 } 328 $plugin = $RCMAIL->plugins->exec_hook('outgoing_message_body', array('body' => $message_body, 'type' => 'plain', 'message' => $MAIL_MIME)); 329 $MAIL_MIME->setTXTBody($plugin['body'], false, true); 330 } 331 331 332 332 // chose transfer encoding … … 335 335 336 336 // add stored attachments, if any 337 if (is_array($_SESSION['compose']['attachments'])) 338 foreach ($_SESSION['compose']['attachments'] as $id => $attachment) 339 { 340 $dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' . $id . '[\s\'"]\s*/'; 341 $match = preg_match($dispurl, $message_body, $matches); 342 if ($isHtml && ($match > 0)) 343 { 337 if (is_array($_SESSION['compose']['attachments'])) { 338 foreach ($_SESSION['compose']['attachments'] as $id => $attachment) { 339 // This hook retrieves the attachment contents from the file storage backend 340 $attachment = $RCMAIL->plugins->exec_hook('get_attachment', $attachment); 341 342 $dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' . preg_quote($attachment['id']) . '[\s\'"]\s*/'; 343 $message_body = $MAIL_MIME->getHTMLBody(); 344 if ($isHtml && (preg_match($dispurl, $message_body) > 0)) { 344 345 $message_body = preg_replace($dispurl, ' src="'.$attachment['name'].'" ', $message_body); 345 346 $MAIL_MIME->setHTMLBody($message_body); 346 $MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name']); 347 } 348 else 349 { 347 348 if ($attachment['data']) 349 $MAIL_MIME->addHTMLImage($attachment['data'], $attachment['mimetype'], $attachment['name'], false); 350 else 351 $MAIL_MIME->addHTMLImage($attachment['path'], $attachment['mimetype'], $attachment['name'], true); 352 } 353 else { 350 354 $ctype = str_replace('image/pjpeg', 'image/jpeg', $attachment['mimetype']); // #1484914 355 $file = $attachment['data'] ? $attachment['data'] : $attachment['path']; 351 356 352 357 // .eml attachments send inline 353 $MAIL_MIME->addAttachment($ attachment['path'],358 $MAIL_MIME->addAttachment($file, 354 359 $ctype, 355 $attachment['name'], true, 360 $attachment['name'], 361 ($attachment['data'] ? false : true), 356 362 ($ctype == 'message/rfc822' ? $transfer_encoding : 'base64'), 357 363 ($ctype == 'message/rfc822' ? 'inline' : 'attachment'), 358 364 $message_charset, '', '', 359 $CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL, 360 $CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL 361 ); 362 } 363 } 365 $CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL, 366 $CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL 367 ); 368 } 369 } 370 } 364 371 365 372 // add submitted attachments 366 if (is_array($_FILES['_attachments']['tmp_name'])) 367 foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) 368 { 373 if (is_array($_FILES['_attachments']['tmp_name'])) { 374 foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) { 369 375 $ctype = $files['type'][$i]; 370 376 $ctype = str_replace('image/pjpeg', 'image/jpeg', $ctype); // #1484914 371 377 372 378 $MAIL_MIME->addAttachment($filepath, $ctype, $files['name'][$i], true, 373 $ctype == 'message/rfc822' ? $transfer_encoding : 'base64',374 'attachment', $message_charset, '', '',375 $CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL,376 $CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL377 );378 }379 379 $ctype == 'message/rfc822' ? $transfer_encoding : 'base64', 380 'attachment', $message_charset, '', '', 381 $CONFIG['mime_param_folding'] ? 'quoted-printable' : NULL, 382 $CONFIG['mime_param_folding'] == 2 ? 'quoted-printable' : NULL 383 ); 384 } 385 } 380 386 381 387 // encoding settings for mail composing … … 388 394 'text_charset' => $message_charset, 389 395 )); 396 397 $data = $RCMAIL->plugins->exec_hook('outgoing_message_headers', array('headers' => $headers)); 398 $headers = $data['headers']; 390 399 391 400 // encoding subject header with mb_encode provides better results with asian characters -
trunk/roundcubemail/program/steps/mail/show.inc
r2301 r2401 136 136 137 137 // mark message as read 138 if (!$MESSAGE->headers->seen) 138 if (!$MESSAGE->headers->seen) { 139 139 $IMAP->set_flag($MESSAGE->uid, 'SEEN'); 140 } 140 $RCMAIL->plugins->exec_hook('message_read', array('uid' => $MESSAGE->uid, 'mailbox' => $IMAP->mailbox, 'message' => $MESSAGE)); 141 } 142 } 141 143 142 144 -
trunk/roundcubemail/program/steps/settings/func.inc
r2383 r2401 160 160 } 161 161 162 $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table)); 163 162 164 if ($table->size()) 163 165 $out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('uisettings'))) . $table->show($attrib)); … … 217 219 } 218 220 221 $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table)); 222 219 223 if ($table->size()) 220 224 $out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('mailboxview'))) . $table->show($attrib)); … … 255 259 } 256 260 261 $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table)); 262 257 263 if ($table->size()) 258 264 $out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('messagesdisplaying'))) . $table->show($attrib)); … … 296 302 } 297 303 304 $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table)); 305 298 306 if ($table->size()) 299 307 $out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('messagescomposition'))) . $table->show($attrib)); … … 330 338 } 331 339 340 $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table)); 341 332 342 $out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('specialfolders'))) . $table->show($attrib)); 333 343 } … … 381 391 $table->add(null, $input_expunge->show($config['logout_expunge']?1:0)); 382 392 } 393 394 $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table)); 383 395 384 396 if ($table->size()) -
trunk/roundcubemail/program/steps/settings/manage_folders.inc
r2256 r2401 257 257 } 258 258 259 rcmail::get_instance()->plugins->exec_hook('manage_folders', array('table'=>$table)); 259 260 260 261 $OUTPUT->add_gui_object('subscriptionlist', $attrib['id']); -
trunk/roundcubemail/program/steps/settings/save_prefs.inc
r2115 r2401 49 49 ); 50 50 51 $data = rcmail::get_instance()->plugins->exec_hook('save_preferences', array('prefs' => $a_user_prefs)); 52 $a_user_prefs = $data['prefs']; 53 51 54 // don't override these parameters 52 55 foreach ((array)$CONFIG['dont_override'] as $p) -
trunk/roundcubemail/skins/default/common.css
r2398 r2401 247 247 } 248 248 249 #pagecontent 250 { 251 position: absolute; 252 top: 95px; 253 left: 20px; 254 } 255 249 256 .splitter 250 257 { -
trunk/roundcubemail/skins/default/functions.js
r2196 r2401 9 9 function rcube_init_settings_tabs() 10 10 { 11 var tab = '#settingstabdefault'; 11 12 if (window.rcmail && rcmail.env.action) 12 { 13 var action = rcmail.env.action=='preferences' ? 'default' : (rcmail.env.action.indexOf('identity')>0 ? 'identities' : rcmail.env.action); 14 var tab = document.getElementById('settingstab'+action); 15 } 16 else 17 var tab = document.getElementById('settingstabdefault'); 18 19 if (tab) 20 tab.className = 'tablink-selected'; 13 tab = '#settingstab' + (rcmail.env.action=='preferences' ? 'default' : (rcmail.env.action.indexOf('identity')>0 ? 'identities' : rcmail.env.action.replace(/\./g, ''))); 14 15 $(tab).addClass('tablink-selected'); 21 16 } 22 17 23 18 function rcube_show_advanced(visible) 24 19 { 25 var rows = document.getElementsByTagName('TR'); 26 for(var i=0; i<rows.length; i++) 27 if(rows[i].className && rows[i].className.match(/advanced/)) 28 rows[i].style.display = visible ? (bw.ie ? 'block' : 'table-row') : 'none'; 20 $('tr.advanced').css('display', (visible ? (bw.ie ? 'block' : 'table-row') : 'none')); 29 21 } 30 22 … … 129 121 function rcube_mail_ui() 130 122 { 131 this.markmenu = new rcube_layer('markmessagemenu');123 this.markmenu = $('#markmessagemenu'); 132 124 } 133 125 … … 137 129 { 138 130 if (typeof show == 'undefined') 139 show = this.markmenu. visible? false : true;131 show = this.markmenu.is(':visible') ? false : true; 140 132 141 133 var ref = rcube_find_object('markreadbutton'); 142 134 if (show && ref) 143 this.markmenu. move(ref.offsetLeft, ref.offsetTop + ref.offsetHeight);135 this.markmenu.css({ left:ref.offsetLeft, top:(ref.offsetTop + ref.offsetHeight) }); 144 136 145 this.markmenu .show(show);137 this.markmenu[show?'show':'hide'](); 146 138 }, 147 139 148 140 body_mouseup: function(evt, p) 149 141 { 150 if (this.markmenu && this.markmenu. visible&& rcube_event.get_target(evt) != rcube_find_object('markreadbutton'))142 if (this.markmenu && this.markmenu.is(':visible') && rcube_event.get_target(evt) != rcube_find_object('markreadbutton')) 151 143 this.show_markmenu(false); 152 144 }, … … 154 146 body_keypress: function(evt, p) 155 147 { 156 if (rcube_event.get_keycode(evt) == 27 && this.markmenu && this.markmenu. visible)148 if (rcube_event.get_keycode(evt) == 27 && this.markmenu && this.markmenu.is(':visible')) 157 149 this.show_markmenu(false); 158 150 } -
trunk/roundcubemail/skins/default/includes/settingstabs.html
r1409 r2401 3 3 <span id="settingstabfolders" class="tablink"><roundcube:button command="folders" type="link" label="folders" title="managefolders" class="tablink" /></span> 4 4 <span id="settingstabidentities" class="tablink"><roundcube:button command="identities" type="link" label="identities" title="manageidentities" class="tablink" /></span> 5 <roundcube:container name="tabs" id="tabsbar" /> 6 <script type="text/javascript"> if (window.rcmail) rcmail.add_onload(rcube_init_settings_tabs); </script> 5 7 </div> -
trunk/roundcubemail/skins/default/includes/taskbar.html
r62 r2401 1 1 <div id="taskbar"> 2 <roundcube:container name="taskbar" id="taskbar" /> 2 3 <roundcube:button command="mail" label="mail" class="button-mail" /> 3 4 <roundcube:button command="addressbook" label="addressbook" class="button-addressbook" /> -
trunk/roundcubemail/skins/default/mail.css
r2374 r2401 50 50 left: 90px; 51 51 width: auto; 52 visibility: hidden;52 display: none; 53 53 background-color: #F9F9F9; 54 54 border: 1px solid #CCC; -
trunk/roundcubemail/skins/default/splitter.js
r2169 r2401 23 23 24 24 // create and position the handle for this splitter 25 this.p1pos = rcube_get_object_pos(this.p1, this.relative);26 this.p2pos = rcube_get_object_pos(this.p2, this.relative);25 this.p1pos = this.relative ? $(this.p1).position() : $(this.p1).offset(); 26 this.p2pos = this.relative ? $(this.p2).position() : $(this.p2).offset(); 27 27 28 28 if (this.horizontal) 29 29 { 30 var top = this.p1pos. y+ this.p1.offsetHeight;30 var top = this.p1pos.top + this.p1.offsetHeight; 31 31 this.layer = new rcube_layer(this.id, {x: 0, y: top, height: 10, 32 32 width: '100%', vis: 1, parent: this.p1.parentNode}); … … 34 34 else 35 35 { 36 var left = this.p1pos. x+ this.p1.offsetWidth;36 var left = this.p1pos.left + this.p1.offsetWidth; 37 37 this.layer = new rcube_layer(this.id, {x: left, y: 0, width: 10, 38 38 height: '100%', vis: 1, parent: this.p1.parentNode}); … … 71 71 { 72 72 var lh = this.layer.height - this.offset * 2; 73 this.p1.style.height = Math.floor(this.pos - this.p1pos. y- lh / 2) + 'px';73 this.p1.style.height = Math.floor(this.pos - this.p1pos.top - lh / 2) + 'px'; 74 74 this.p2.style.top = Math.ceil(this.pos + lh / 2) + 'px'; 75 this.layer.move(this.layer.x, Math.round(this.pos - lh / 2 + 1)); 75 this.layer.move(this.layer.x, Math.round(this.pos - lh / 2 + 1)); 76 76 if (bw.ie) 77 {77 { 78 78 var new_height = (parseInt(this.p2.parentNode.offsetHeight) - parseInt(this.p2.style.top)); 79 79 this.p2.style.height = (new_height > 0 ? new_height : 0) +'px'; … … 82 82 else 83 83 { 84 this.p1.style.width = Math.floor(this.pos - this.p1pos. x- this.layer.width / 2) + 'px';84 this.p1.style.width = Math.floor(this.pos - this.p1pos.left - this.layer.width / 2) + 'px'; 85 85 this.p2.style.left = Math.ceil(this.pos + this.layer.width / 2) + 'px'; 86 86 this.layer.move(Math.round(this.pos - this.layer.width / 2 + 1), this.layer.y); … … 95 95 this.onDragStart = function(e) 96 96 { 97 this.p1pos = rcube_get_object_pos(this.p1, this.relative);98 this.p2pos = rcube_get_object_pos(this.p2, this.relative);97 this.p1pos = this.relative ? $(this.p1).position() : $(this.p1).offset(); 98 this.p2pos = this.relative ? $(this.p2).position() : $(this.p2).offset(); 99 99 this.drag_active = true; 100 100 … … 120 120 // the position of each iframe when the event is received 121 121 var s = this; 122 var id = iframes[n].id;123 this.iframe_events[n] = function(e){ e._offset = rcube_get_object_pos(document.getElementById(id)); return s.onDrag(e); }122 var id = '#'+iframes[n].id; 123 this.iframe_events[n] = function(e){ e._offset = $(id).offset(); return s.onDrag(e); } 124 124 125 125 if (iframedoc.addEventListener) … … 146 146 if (this.relative) 147 147 { 148 var parent = rcube_get_object_pos(this.p1.parentNode);149 pos.x -= parent. x;150 pos.y -= parent. y;151 } 152 153 if (this.horizontal) 154 { 155 if (((pos.y - this.layer.height * 1.5) > this.p1pos. y) && ((pos.y + this.layer.height * 1.5) < (this.p2pos.y+ this.p2.offsetHeight)))148 var parent = $(this.p1.parentNode).offset(); 149 pos.x -= parent.left; 150 pos.y -= parent.top; 151 } 152 153 if (this.horizontal) 154 { 155 if (((pos.y - this.layer.height * 1.5) > this.p1pos.top) && ((pos.y + this.layer.height * 1.5) < (this.p2pos.top + this.p2.offsetHeight))) 156 156 { 157 157 this.pos = pos.y; … … 161 161 else 162 162 { 163 if (((pos.x - this.layer.width * 1.5) > this.p1pos. x) && ((pos.x + this.layer.width * 1.5) < (this.p2pos.x+ this.p2.offsetWidth)))163 if (((pos.x - this.layer.width * 1.5) > this.p1pos.left) && ((pos.x + this.layer.width * 1.5) < (this.p2pos.left + this.p2.offsetWidth))) 164 164 { 165 165 this.pos = pos.x; … … 168 168 } 169 169 170 this.p1pos = rcube_get_object_pos(this.p1, this.relative);171 this.p2pos = rcube_get_object_pos(this.p2, this.relative);170 this.p1pos = this.relative ? $(this.p1).position() : $(this.p1).offset(); 171 this.p2pos = this.relative ? $(this.p2).position() : $(this.p2).offset(); 172 172 return false; 173 173 }; … … 199 199 if (iframedoc.removeEventListener) 200 200 iframedoc.removeEventListener('mousemove', this.iframe_events[n], false); 201 else if (iframedoc.detachEvent)201 else if (iframedoc.detachEvent) 202 202 iframedoc.detachEvent('onmousemove', this.iframe_events[n]); 203 203 else -
trunk/roundcubemail/skins/default/templates/addressbook.html
r2398 r2401 8 8 9 9 <style type="text/css"> 10 <roundcube:if condition="co nfig:ldap_public == false" />10 <roundcube:if condition="count(env:address_sources) <= 1" /> 11 11 #abookcountbar { left: 20px;} 12 12 #mainscreen { left:20px; /* IE hack */ width:expression((parseInt(document.documentElement.clientWidth)-40)+'px') } … … 45 45 </div> 46 46 47 <roundcube:if condition="co nfig:ldap_public" />47 <roundcube:if condition="count(env:address_sources) > 1" /> 48 48 <div id="directorylist"> 49 49 <div id="groups-title"><roundcube:label name="groups" /></div> -
trunk/roundcubemail/skins/default/templates/identities.html
r2167 r2401 7 7 <script type="text/javascript" src="/functions.js"></script> 8 8 </head> 9 <body onload="rcube_init_settings_tabs()">9 <body> 10 10 11 11 <roundcube:include file="/includes/taskbar.html" /> -
trunk/roundcubemail/skins/default/templates/mail.html
r2398 r2401 120 120 <roundcube:button command="delete" imageSel="/images/buttons/delete_sel.png" imageAct="/images/buttons/delete_act.png" imagePas="/images/buttons/delete_pas.png" width="32" height="32" title="deletemessage" /> 121 121 <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="printmessage" /> 122 <roundcube:container name="toolbar" id="messagetoolbar" /> 122 123 123 124 <div id="markmessagemenu"> -
trunk/roundcubemail/skins/default/templates/managefolders.html
r2380 r2401 7 7 <script type="text/javascript" src="/functions.js"></script> 8 8 </head> 9 <body onload="rcube_init_settings_tabs()">9 <body> 10 10 11 11 <roundcube:include file="/includes/taskbar.html" /> -
trunk/roundcubemail/skins/default/templates/message.html
r2131 r2401 37 37 <roundcube:button command="viewsource" imageSel="/images/buttons/source_sel.png" imageAct="/images/buttons/source_act.png" imagePas="/images/buttons/source_pas.png" width="32" height="32" title="viewsource" /> 38 38 <roundcube:object name="mailboxlist" type="select" noSelection="moveto" maxlength="25" onchange="rcmail.command('moveto', this.options[this.selectedIndex].value)" class="mboxlist" /> 39 <roundcube:container name="toolbar" id="messagetoolbar" /> 39 40 </div> 40 41 -
trunk/roundcubemail/skins/default/templates/settings.html
r2164 r2401 7 7 <script type="text/javascript" src="/functions.js"></script> 8 8 </head> 9 <body onload="rcube_init_settings_tabs()">9 <body> 10 10 11 11 <roundcube:include file="/includes/taskbar.html" /> … … 18 18 <div id="userprefs-title"><roundcube:label name="userpreferences" /></div> 19 19 20 <div style="padding:15px 0 15px 15px">20 <div id="userprefscontainer" style="padding:15px 0 15px 15px"> 21 21 <div class="userprefs-block"> 22 22 <roundcube:object name="userprefs" form="form" parts="general,mailbox,mailview" /> … … 26 26 </div> 27 27 <div style="clear:left"></div> 28 29 <roundcube:container name="userprefs" id="userprefscontainer" /> 28 30 </div> 29 31 </div>
Note: See TracChangeset
for help on using the changeset viewer.
