Changeset 2401 in subversion


Ignore:
Timestamp:
Apr 19, 2009 1:44:29 PM (4 years ago)
Author:
thomasb
Message:

Merged branch devel-api (from r2208 to r2387) back into trunk (omitting some sample plugins)

Location:
trunk/roundcubemail
Files:
42 edited
37 copied

Legend:

Unmodified
Added
Removed
  • trunk/roundcubemail/config/main.inc.php.dist

    r2388 r2401  
    3636$rcmail_config['temp_dir'] = 'temp/'; 
    3737 
     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 
    3844// enable caching of messages and mailbox data in the local database. 
    3945// this is recommended if the IMAP server does not run on the same machine 
     
    153159 
    154160// 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'; 
    156162 
    157163// use this name to compose page titles 
  • trunk/roundcubemail/index.php

    r2347 r2401  
    33 +-------------------------------------------------------------------------+ 
    44 | RoundCube Webmail IMAP Client                                           | 
    5  | Version 0.2-20080829                                                    | 
     5 | Version 0.3-20090419                                                    | 
    66 |                                                                         | 
    77 | Copyright (C) 2005-2009, RoundCube Dev. - Switzerland                   | 
     
    3636// init output class 
    3737$OUTPUT = !empty($_REQUEST['_remote']) ? $RCMAIL->init_json() : $RCMAIL->load_gui(!empty($_REQUEST['_framed'])); 
     38 
     39// init plugin API 
     40$RCMAIL->plugins->init(); 
    3841 
    3942// set output buffering 
     
    7174} 
    7275 
     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 
    7383// try to log in 
    7484if ($RCMAIL->action=='login' && $RCMAIL->task=='mail') { 
    7585  // 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 
    8193  // check if client supports cookies 
    8294  if (empty($_COOKIE)) { 
    8395    $OUTPUT->show_message("cookiesdisabled", 'warning'); 
    8496  } 
    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'])) { 
    8899    // create new session ID 
    89100    unset($_SESSION['temp']); 
     
    100111        $_SERVER['REMOTE_ADDR'])); 
    101112    } 
     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']); 
    102122 
    103123    // send redirect 
    104     $OUTPUT->redirect(); 
     124    $OUTPUT->redirect($redir); 
    105125  } 
    106126  else { 
    107127    $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'])); 
    108129    $RCMAIL->kill_session(); 
    109130  } 
     
    209230  $stepfile = !empty($action_map[$RCMAIL->task][$RCMAIL->action]) ? 
    210231    $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  } 
    212238  // 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))) { 
    214240    include($incfile); 
    215241    $redirects++; 
  • trunk/roundcubemail/plugins/filesystem_attachments/filesystem_attachments.php

    r2400 r2401  
    5050        $args['status'] = false; 
    5151        $rcmail = rcmail::get_instance(); 
    52          
     52 
    5353        // 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')); 
    5556        $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)) { 
    5859            $args['id'] = count($_SESSION['plugins']['filesystem_attachments']['tmp_files'])+1; 
    5960            $args['path'] = $tmpfname; 
  • trunk/roundcubemail/plugins/show_additional_headers/show_additional_headers.php

    r2400 r2401  
    3838  function message_headers($p) 
    3939  { 
    40 console($p['headers']); 
    4140    $rcmail = rcmail::get_instance(); 
    4241    foreach ($rcmail->config->get('show_additional_headers', array()) as $header) { 
  • trunk/roundcubemail/program/include/html.php

    r2237 r2401  
    3434 
    3535    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'); 
    3737    public static $lc_tags = true; 
    3838 
     
    600600    } 
    601601 
     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 
    602630    /** 
    603631     * Jump to next row 
  • trunk/roundcubemail/program/include/iniset.php

    r2345 r2401  
    2323 
    2424// application constants 
    25 define('RCMAIL_VERSION', '0.2-trunk'); 
     25define('RCMAIL_VERSION', '0.3-trunk'); 
    2626define('RCMAIL_CHARSET', 'UTF-8'); 
    2727define('JS_OBJECT_NAME', 'rcmail'); 
  • trunk/roundcubemail/program/include/main.inc

    r2352 r2401  
    8989 * @see rcmail::gettext() 
    9090 */ 
    91 function rcube_label($p) 
    92 { 
    93   return rcmail::get_instance()->gettext($p); 
     91function rcube_label($p, $domain=null) 
     92{ 
     93  return rcmail::get_instance()->gettext($p, $domain); 
    9494} 
    9595 
     
    303303function rep_specialchars_output($str, $enctype='', $mode='', $newlines=TRUE) 
    304304  { 
    305   global $OUTPUT; 
    306305  static $html_encode_arr = false; 
    307306  static $js_rep_table = false; 
    308307  static $xml_rep_table = false; 
    309308 
    310   $charset = $OUTPUT->get_charset(); 
     309  $charset = rcmail::get_instance()->config->get('charset', RCMAIL_CHARSET); 
    311310  $is_iso_8859_1 = false; 
    312311  if ($charset == 'ISO-8859-1') { 
     
    693692 
    694693  // 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  } 
    700699 
    701700  return $attrib; 
     
    830829function console() 
    831830  { 
     831  $args = func_get_args(); 
     832  if (class_exists('rcmail', false)) 
     833      rcmail::get_instance()->plugins->exec_hook('console', $args); 
     834 
    832835  $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; 
    835838 
    836839  if (!($GLOBALS['CONFIG']['debug_level'] & 4)) 
  • trunk/roundcubemail/program/include/rcmail.php

    r2388 r2401  
    3838  public $imap; 
    3939  public $output; 
     40  public $plugins; 
    4041  public $task = 'mail'; 
    4142  public $action = ''; 
     
    8990      openlog($syslog_id, LOG_ODELAY, $syslog_facility); 
    9091    } 
    91                                  
     92 
    9293    // set task and action properties 
    9394    $this->set_task(strip_quotes(get_input_value('_task', RCUBE_INPUT_GPC))); 
     
    132133    if ($this->task == 'mail') 
    133134      $this->imap_init(); 
     135       
     136    // create plugin API and load plugins 
     137    $this->plugins = rcube_plugin_api::get_instance(); 
    134138  } 
    135139   
     
    256260    $ldap_config = (array)$this->config->get('ldap_public'); 
    257261    $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]) { 
    260270      $contacts = new rcube_ldap($ldap_config[$id]); 
     271    } 
     272    else if ($id === '0') { 
     273      $contacts = new rcube_contacts($this->db, $this->user->ID); 
    261274    } 
    262275    else if ($abook_type == 'ldap') { 
     
    599612   * @return string Localized text 
    600613   */ 
    601   public function gettext($attrib) 
     614  public function gettext($attrib, $domain=null) 
    602615  { 
    603616    // load localization files if not done yet 
     
    614627    $command_name = !empty($attrib['command']) ? $attrib['command'] : NULL; 
    615628    $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      ; 
    617633    // text does not exist 
    618     if (!($text_item = $this->texts[$alias])) { 
     634    else if (!($text_item = $this->texts[$alias])) { 
    619635      /* 
    620636      raise_error(array( 
     
    678694   * @param string Language ID 
    679695   */ 
    680   public function load_language($lang = null) 
     696  public function load_language($lang = null, $add = array()) 
    681697  { 
    682698    $lang = $this->language_prop(($lang ? $lang : $_SESSION['language'])); 
     
    708724      $_SESSION['language'] = $lang; 
    709725    } 
     726 
     727    // append additional texts (from plugin) 
     728    if (is_array($add) && !empty($add)) 
     729      $this->texts += $add; 
    710730  } 
    711731 
     
    921941    if (!is_array($p)) 
    922942      $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; 
    928949    unset($p['task']); 
    929950 
    930951    $url = './'; 
    931952    $delm = '?'; 
    932     foreach (array_reverse($p) as $par => $val) 
     953    foreach (array_reverse($p) as $key => $val) 
    933954    { 
    934955      if (!empty($val)) { 
     956        $par = $key[0] == '_' ? $key : '_'.$key; 
    935957        $url .= $delm.urlencode($par).'='.urlencode($val); 
    936958        $delm = '&'; 
  • trunk/roundcubemail/program/include/rcube_config.php

    r2237 r2401  
    7575    $this->prop['log_dir'] = $this->prop['log_dir'] ? unslashify($this->prop['log_dir']) : INSTALL_PATH . 'logs'; 
    7676    $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'; 
    7778 
    7879    // fix default imap folders encoding 
  • trunk/roundcubemail/program/include/rcube_contacts.php

    r2237 r2401  
    2626 * @package Addressbook 
    2727 */ 
    28 class rcube_contacts 
     28class rcube_contacts extends rcube_addressbook 
    2929{ 
    3030  var $db = null; 
     
    6161 
    6262  /** 
    63    * Set internal list page 
    64    * 
    65    * @param  number  Page number to list 
    66    * @access public 
    67    */ 
    68   function set_page($page) 
    69   { 
    70     $this->list_page = (int)$page; 
    71   } 
    72  
    73  
    74   /** 
    75    * Set internal page size 
    76    * 
    77    * @param  number  Number of messages to display on one page 
    78    * @access public 
    79    */ 
    80   function set_pagesize($size) 
    81   { 
    82     $this->page_size = (int)$size; 
    83   } 
    84  
    85  
    86   /** 
    8763   * Save a search string for future listings 
    8864   * 
     
    11692    $this->search_string = null; 
    11793  } 
    118    
    119    
    120   /** 
    121    * Close connection to source 
    122    * Called on script shutdown 
    123    */ 
    124   function close(){} 
    12594   
    12695   
     
    234203   * @return Result array or NULL if nothing selected yet 
    235204   */ 
    236   function get_result($as_res=true) 
     205  function get_result() 
    237206  { 
    238207    return $this->result; 
  • trunk/roundcubemail/program/include/rcube_html_page.php

    r2237 r2401  
    3232    protected $charset = 'UTF-8'; 
    3333 
    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>"; 
    3636    protected $default_template = "<html>\n<head><title></title></head>\n<body></body>\n</html>"; 
    3737 
     
    5454    { 
    5555        static $sa_files = array(); 
     56         
     57        if (!ereg('^https?://', $file) && $file[0] != '/') 
     58          $file = $this->scripts_path . $file; 
    5659 
    5760        if (in_array($file, $sa_files)) { 
     
    166169        if (is_array($this->script_files['head'])) { 
    167170            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); 
    169172            } 
    170173        } 
     
    181184        if (is_array($this->script_files['foot'])) { 
    182185            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); 
    184187            } 
    185188        } 
  • trunk/roundcubemail/program/include/rcube_imap.php

    r2389 r2401  
    5656  var $default_folders = array('INBOX'); 
    5757  var $default_folders_lc = array('inbox'); 
     58  var $fetch_add_headers = ''; 
    5859  var $cache = array(); 
    5960  var $cache_keys = array();   
     
    429430      return $a_mboxes; 
    430431 
    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 
    433442     
    434443    if (!is_array($a_folders) || !sizeof($a_folders)) 
     
    776785     
    777786    // 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); 
    779788    $deleted_count = 0; 
    780789     
     
    830839          $this->search('', $this->search_string, $this->search_charset, $this->sort_field); 
    831840 
    832         if ($this->sort_order == 'DESC') 
     841        if ($this->sort_order == 'DESC') 
    833842          $this->cache[$key] = array_reverse($this->search_set); 
    834         else 
    835           $this->cache[$key] = $this->search_set; 
     843        else 
     844          $this->cache[$key] = $this->search_set; 
    836845        } 
    837846      else 
    838847        { 
    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); 
    840849 
    841850        if ($this->sort_order=="ASC") 
     
    924933 
    925934      // 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); 
    927936      $this->add_message_cache($cache_key, $headers->id, $headers); 
    928937      } 
     
    10631072      return $headers; 
    10641073 
    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); 
    10661075 
    10671076    // write headers cache 
     
    22282237      { 
    22292238      // 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); 
    22312240      $cache_uid = array_pop($cache_index); 
    22322241       
     
    22782287        // featch headers if unserialize failed 
    22792288        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); 
    22812290        } 
    22822291      } 
  • trunk/roundcubemail/program/include/rcube_json_output.php

    r2237 r2401  
    197197     * @deprecated 
    198198     */ 
    199     public function remote_response($add='', $flush=false) 
     199    public function remote_response($add='') 
    200200    { 
    201201        static $s_header_sent = false; 
     
    204204            $s_header_sent = true; 
    205205            send_nocacheing_headers(); 
    206             header('Content-Type: application/x-javascript; charset=' . $this->get_charset()); 
     206            header('Content-Type: text/plain; charset=' . $this->get_charset()); 
    207207            print '/** ajax response ['.date('d/M/Y h:i:s O')."] **/\n"; 
    208208        } 
     
    211211        unset($this->env['task'], $this->env['action'], $this->env['comm_path']); 
    212212 
     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 
    213222        // 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); 
    219226    } 
    220227     
     
    228235    { 
    229236        $out = ''; 
    230          
    231         if (sizeof($this->env)) 
    232             $out .= 'this.set_env('.json_serialize($this->env).");\n"; 
    233237         
    234         foreach($this->texts as $name => $text) { 
    235             $out .= sprintf("this.add_label('%s', '%s');\n", $name, JQ($text)); 
    236         } 
    237  
    238238        foreach ($this->commands as $i => $args) { 
    239239            $method = array_shift($args); 
  • trunk/roundcubemail/program/include/rcube_ldap.php

    r2237 r2401  
    2525 * @package Addressbook 
    2626 */ 
    27 class rcube_ldap 
     27class rcube_ldap extends rcube_addressbook 
    2828{ 
    2929  var $conn; 
  • trunk/roundcubemail/program/include/rcube_message.php

    r2294 r2401  
    8585      $this->body = $this->imap->get_body($uid); 
    8686    } 
     87     
     88    // notify plugins and let them analyze this structured message object 
     89    $this->app->plugins->exec_hook('message_load', array('object' => $this)); 
    8790  } 
    8891   
  • trunk/roundcubemail/program/include/rcube_template.php

    r2237 r2401  
    6767 
    6868        // 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(); });'; 
    7070 
    7171        $this->add_script($javascript, 'head_top'); 
    7272        $this->add_script($javascript_foot, 'foot'); 
    7373        $this->scripts_path = 'program/js/'; 
     74        $this->include_script('http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js'); 
    7475        $this->include_script('common.js'); 
    7576        $this->include_script('app.js'); 
     
    209210    public function add_label() 
    210211    { 
    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) { 
    213217            $this->command('add_label', $name, rcube_label($name)); 
    214218        } 
     
    376380            $out .= sprintf( 
    377381                "%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) 
    381385            ); 
    382386        } 
     
    512516    private function parse_xml($input) 
    513517    { 
    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 
    539527     * @return string Tag/Object content 
    540528     */ 
    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]); 
    545533 
    546534        // empty output if required condition is not met 
     
    573561                    } 
    574562                    else { 
    575                         $incl = file_get_contents($path); 
    576                     } 
     563                      $incl = file_get_contents($path); 
     564                    } 
    577565                    return $this->parse_xml($incl); 
    578566                } 
     
    580568 
    581569            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']; 
    593581                } 
    594582                break; 
     
    597585            case 'object': 
    598586                $object = strtolower($attrib['name']); 
     587                $content = ''; 
    599588 
    600589                // we are calling a class/method 
     
    602591                    if ((is_object($handler[0]) && method_exists($handler[0], $handler[1])) || 
    603592                    (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 
    606596                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') { 
    612600                    $name = !empty($this->config['product_name']) ? $this->config['product_name'] : 'RoundCube Webmail'; 
    613                     return Q($name); 
    614                 } 
    615                 if ($object=='version') { 
     601                    $content = Q($name); 
     602                } 
     603                else if ($object == 'version') { 
    616604                    $ver = (string)RCMAIL_VERSION; 
    617605                    if (is_file(INSTALL_PATH . '.svn/entries')) { 
     
    619607                          $ver .= ' [SVN r'.$regs[1].']'; 
    620608                    } 
    621                     return $ver; 
    622                 } 
    623                 if ($object=='steptitle') { 
    624                   return Q($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') { 
    627615                    $title = !empty($this->config['product_name']) ? $this->config['product_name'].' :: ' : ''; 
    628616                    $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']; 
    632623 
    633624            // return code for a specified eval expression 
    634625            case 'exp': 
    635                 $value = $this->parse_expression($attrib['expression']); 
     626                $value = $this->parse_expression($attrib['expression']); 
    636627                return eval("return Q($value);"); 
    637628             
     
    703694 
    704695        // 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'); 
    706697 
    707698        if (!($attrib['command'] || $attrib['name'])) { 
     
    942933 
    943934        $_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']; 
    944940 
    945941        $input_user   = new html_inputfield(array('name' => '_user', 'id' => 'rcmloginuser', 'size' => 30) + $attrib); 
     
    947943        $input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'login')); 
    948944        $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)); 
    949946        $input_host   = null; 
    950947 
     
    986983        $out = $input_action->show(); 
    987984        $out .= $input_tzone->show(); 
     985        $out .= $input_url->show(); 
    988986        $out .= $table->show(); 
    989987 
  • trunk/roundcubemail/program/include/rcube_user.php

    r2384 r2401  
    347347  static function create($user, $host) 
    348348  { 
     349    $user_name  = ''; 
    349350    $user_email = ''; 
    350351    $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 
    351357    $dbh = $rcmail->get_dbh(); 
    352358 
    353359    // try to resolve user in virtuser table and file 
    354     if (!strpos($user, '@')) { 
     360    if ($user_email != '' && !strpos($user, '@')) { 
    355361      if ($email_list = self::user2email($user, false)) 
    356362        $user_email = $email_list[0]; 
    357363    } 
    358      
     364 
    359365    $dbh->query( 
    360366      "INSERT INTO ".get_table_name('users')." 
     
    373379        $user_email = strpos($user, '@') ? $user : sprintf('%s@%s', $user, $mail_domain); 
    374380 
    375       $user_name = $user != $user_email ? $user : ''; 
     381      if ($user_name == '') { 
     382        $user_name = $user != $user_email ? $user : ''; 
     383      } 
    376384 
    377385      if (empty($email_list)) 
     
    386394             VALUES (?, 0, ?, ?, ?)", 
    387395            $user_id, 
    388             $standard, 
     396            $standard, 
    389397            strip_newlines($user_name), 
    390398            preg_replace('/^@/', $user . '@', $email)); 
    391         $standard = 0; 
     399        $standard = 0; 
    392400      } 
    393401    } 
     
    447455        if (strpos($sql_arr[0], '@')) { 
    448456          $result[] = $sql_arr[0]; 
    449           if ($first) 
    450             return $result[0]; 
    451         } 
     457          if ($first) 
     458            return $result[0]; 
     459        } 
    452460    } 
    453461    // File lookup 
     
    461469        $result[] = trim(str_replace('\\@', '@', $arr[0])); 
    462470 
    463         if ($first) 
     471        if ($first) 
    464472          return $result[0]; 
    465473      } 
  • trunk/roundcubemail/program/include/rcube_vcard.php

    r2283 r2401  
    264264      } 
    265265 
    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)) { 
    267267        $entry = array(''); 
    268         $field = $regs2[1][0]; 
     268        $field = strtoupper($regs2[1][0]); 
    269269 
    270270        foreach($regs2[1] as $attrid => $attr) { 
  • trunk/roundcubemail/program/js/app.js

    r2394 r2401  
    1111 |          Charles McNulty <charles@charlesmcnulty.com>                 | 
    1212 +-----------------------------------------------------------------------+ 
    13  | Requires: common.js, list.js                                          | 
     13 | Requires: jquery.js, common.js, list.js                               | 
    1414 +-----------------------------------------------------------------------+ 
    1515 
     
    1818 
    1919 
    20 var rcube_webmail_client; 
    21  
    2220function rcube_webmail() 
    23   { 
     21{ 
    2422  this.env = new Object(); 
    2523  this.labels = new Object(); 
    2624  this.buttons = new Object(); 
    2725  this.gui_objects = new Object(); 
     26  this.gui_containers = new Object(); 
    2827  this.commands = new Object(); 
     28  this.command_handlers = new Object(); 
    2929  this.onloads = new Array(); 
    3030 
    3131  // create protected reference to myself 
    32   rcube_webmail_client = this; 
    33   this.ref = 'rcube_webmail_client'; 
     32  this.ref = 'rcmail'; 
    3433  var ref = this; 
    3534  
     
    5453  this.env.blankpage = 'program/blank.gif'; 
    5554 
     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 
    5661  // set environment variable(s) 
    5762  this.set_env = function(p, value) 
     
    9095    }; 
    9196   
     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   
    92119  // execute the given script on load 
    93120  this.add_onload = function(f) 
    94     { 
    95       this.onloads[this.onloads.length] = f; 
    96     }; 
     121  { 
     122    this.onloads[this.onloads.length] = f; 
     123  }; 
    97124 
    98125  // initialize webmail client 
     
    109136      } 
    110137     
     138    // find all registered gui containers 
     139    for (var n in this.gui_containers) 
     140      this.gui_containers[n] = $('#'+this.gui_containers[n]); 
     141 
    111142    // find all registered gui objects 
    112143    for (var n in this.gui_objects) 
     
    136167          this.message_list.addEventListener('dragmove', function(o, e){ p.drag_move(e); }); 
    137168          this.message_list.addEventListener('dragend', function(o){ p.drag_active = false; }); 
     169          document.onmouseup = function(e){ return p.doc_mouse_up(e); }; 
    138170 
    139171          this.message_list.init(); 
     
    141173           
    142174          if (this.gui_objects.mailcontframe) 
    143             { 
    144175            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             } 
    147176          else 
    148177            this.message_list.focus(); 
     
    197226            this.env.spellcheck.spelling_state_observer = function(s){ ref.set_spellcheck_state(s); }; 
    198227            this.set_spellcheck_state('ready'); 
    199             if (rcube_find_object('_is_html').value == '1') 
     228            if ($("input[name='_is_html']").val() == '1') 
    200229              this.display_spellcheck_controls(false); 
    201230            } 
     
    264293          else 
    265294            this.contact_list.focus(); 
     295             
     296          this.gui_objects.folderlist = this.gui_objects.contactslist; 
    266297          } 
    267298 
     
    317348 
    318349      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() == '') 
    326354          input_user.focus(); 
    327         else if (input_pass) 
    328           input_pass.focus(); 
     355        else 
     356          $('#rcmloginpwd').focus(); 
    329357 
    330358        // detect client timezone 
    331         if (input_tz) 
    332           input_tz.value = new Date().getTimezoneOffset() / -60; 
     359        $('#rcmlogintz').val(new Date().getTimezoneOffset() / -60); 
    333360 
    334361        this.enable_command('login', true); 
     
    348375    if (this.pending_message) 
    349376      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 }); 
    353384     
    354385    // execute all foreign onload scripts 
     386    // @deprecated 
    355387    for (var i=0; i<this.onloads.length; i++) 
    356388      { 
     
    360392        this.onloads[i](); 
    361393      } 
    362     }; 
     394 
     395    // start keep-alive interval 
     396    this.start_keepalive(); 
     397  }; 
    363398 
    364399  // start interval for keep-alive/recent_check signal 
     
    418453     
    419454    //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); 
    428459 
    429460    // 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']")); 
    436464 
    437465    // 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() == '') 
    446472      input_to.focus(); 
    447     else if (input_subject && input_subject.value=='') 
     473    else if (input_subject.val() == '') 
    448474      input_subject.focus(); 
    449475    else if (input_message) 
     
    460486    { 
    461487    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'); 
    469490    }; 
    470491 
     
    500521     } 
    501522 
    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 
    503546    switch (command) 
    504547      { 
     
    510553      case 'logout': 
    511554        this.goto_url('logout', '', true); 
    512         break;       
     555        break; 
    513556 
    514557      // commands to switch task 
     
    559602        var sort_col = a_sort[0]; 
    560603        var sort_order = a_sort[1] ? a_sort[1].toUpperCase() : null; 
    561         var header; 
    562604 
    563605        // no sort order specified: toggle 
     
    574616 
    575617        // 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); 
    580620 
    581621        // save new sort properties 
     
    658698        if (this.gui_objects.editform) 
    659699          { 
    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']"); 
    663703 
    664704          // user prefs 
    665           if (input_pagesize && isNaN(parseInt(input_pagesize.value))) 
     705          if (input_pagesize.length && isNaN(parseInt(input_pagesize.val()))) 
    666706            { 
    667707            alert(this.get_label('nopagesizewarning')); 
     
    672712          else 
    673713            { 
    674             if (input_name && input_name.value == '') 
     714            if (input_name.length && input_name.val() == '') 
    675715              { 
    676716              alert(this.get_label('nonamewarning')); 
     
    678718              break; 
    679719              } 
    680             else if (input_email && !rcube_check_email(input_email.value)) 
     720            else if (input_email.length && !rcube_check_email(input_email.val())) 
    681721              { 
    682722              alert(this.get_label('noemailwarning')); 
     
    10631103 
    10641104      } 
     1105       
     1106    this.triggerEvent('after'+command, props); 
    10651107 
    10661108    return obj ? false : true; 
     
    11151157 
    11161158  // 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]) 
    11201164      return this.labels[name]; 
    11211165    else 
    11221166      return name; 
    11231167    }; 
     1168   
     1169  // alias for convenience reasons 
     1170  this.gettext = this.get_label; 
    11241171 
    11251172  // switch to another application task 
     
    11581205  this.doc_mouse_up = function(e) 
    11591206  { 
    1160     var model, li; 
     1207    var model, list, li; 
    11611208 
    11621209    if (this.message_list) { 
    11631210      if (!rcube_mouse_is_over(e, this.message_list.list)) 
    11641211        this.message_list.blur(); 
     1212      list = this.message_list; 
    11651213      model = this.env.mailboxes; 
    11661214    } 
     
    11681216      if (!rcube_mouse_is_over(e, this.contact_list.list)) 
    11691217        this.contact_list.blur(); 
     1218      list = this.contact_list; 
    11701219      model = this.env.address_sources; 
    11711220    } 
     
    11761225    // handle mouse release when dragging 
    11771226    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'); 
    11791228      this.command('moveto', model[this.env.last_folder_target].id); 
    11801229      this.env.last_folder_target = null; 
     1230      list.draglayer.hide(); 
    11811231    } 
    11821232  }; 
     
    11971247      { 
    11981248      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() }; 
    12021252 
    12031253      this.env.folder_coords = new Array(); 
    12041254      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    } 
    12141263  }; 
    12151264 
    12161265  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) { 
    12201268      // offsets to compensate for scrolling while dragging a message 
    12211269      var boffset = bw.ie ? -document.documentElement.scrollTop : this.initialBodyScrollTop; 
     
    12301278 
    12311279      // 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'); 
    12371283          this.env.last_folder_target = null; 
    1238           } 
    1239         return; 
    1240         } 
     1284        } 
     1285        return; 
     1286      } 
    12411287 
    12421288      // 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  }; 
    12571304   
    12581305  this.collapse_folder = function(id) 
     
    12601307    var div; 
    12611308    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'); 
    12711317        var reg = new RegExp('&'+urlencode(id)+'&'); 
    12721318        this.set_env('collapsed_folders', this.env.collapsed_folders.replace(reg, '')); 
     
    12741320      else 
    12751321        { 
    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'); 
    12791324        this.set_env('collapsed_folders', this.env.collapsed_folders+'&'+urlencode(id)+'&'); 
    12801325 
     
    13091354    else if (this.contact_list) 
    13101355      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); 
    13151356 
    13161357    return rcube_event.get_button(e) == 2 ? true : rcube_event.cancel(e); 
     
    14131454    if (this.env.search_request) 
    14141455      add_url += '&_search='+this.env.search_request; 
     1456 
    14151457    var url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.env.mailbox)+add_url; 
    14161458    if (action == 'preview' && String(target.location.href).indexOf(url) >= 0) 
     
    14251467        { 
    14261468        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        } 
    14331475      } 
    14341476    }; 
     
    14371479    { 
    14381480    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) 
    14401482      { 
    14411483      if (!show && window.frames[this.env.contentframe]) 
     
    14451487        } 
    14461488      else if (!bw.safari && !bw.konq) 
    1447         frm.style.display = show ? 'block' : 'none'; 
     1489        frm[show ? 'show' : 'hide'](); 
    14481490      } 
    14491491 
     
    16781720      this.set_message_status(uid, flag, status); 
    16791721     
     1722    var rowobj = $(rows[uid].obj); 
    16801723    if (rows[uid].unread && rows[uid].classname.indexOf('unread')<0) 
    16811724      { 
    16821725      rows[uid].classname += ' unread'; 
    1683       this.set_classname(rows[uid].obj, 'unread', true); 
     1726      rowobj.addClass('unread'); 
    16841727      } 
    16851728    else if (!rows[uid].unread && rows[uid].classname.indexOf('unread')>=0) 
    16861729      { 
    16871730      rows[uid].classname = rows[uid].classname.replace(/\s*unread/, ''); 
    1688       this.set_classname(rows[uid].obj, 'unread', false); 
     1731      rowobj.removeClass('unread'); 
    16891732      } 
    16901733     
     
    16921735      { 
    16931736      rows[uid].classname += ' deleted'; 
    1694       this.set_classname(rows[uid].obj, 'deleted', true); 
     1737      rowobj.addClass('deleted'); 
    16951738      } 
    16961739    else if (!rows[uid].deleted && rows[uid].classname.indexOf('deleted')>=0) 
    16971740      { 
    16981741      rows[uid].classname = rows[uid].classname.replace(/\s*deleted/, ''); 
    1699       this.set_classname(rows[uid].obj, 'deleted', false); 
     1742      rowobj.removeClass('deleted'); 
    17001743      } 
    17011744 
     
    17031746      { 
    17041747      rows[uid].classname += ' flagged'; 
    1705       this.set_classname(rows[uid].obj, 'flagged', true); 
     1748      rowobj.addClass('flagged'); 
    17061749      } 
    17071750    else if (!rows[uid].flagged && rows[uid].classname.indexOf('flagged')>=0) 
    17081751      { 
    17091752      rows[uid].classname = rows[uid].classname.replace(/\s*flagged/, ''); 
    1710       this.set_classname(rows[uid].obj, 'flagged', false); 
     1753      rowobj.removeClass('flagged'); 
    17111754      } 
    17121755 
     
    18121855          this.set_message_status(id, 'deleted', true); 
    18131856          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); 
    18161859        } 
    18171860      } 
     
    20002043  { 
    20012044    var key = rcube_event.get_keycode(e); 
    2002     var elm; 
     2045    var passwd = $('#rcmloginpwd'); 
    20032046 
    20042047    // 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; 
    20102054  }; 
    20112055 
     
    20192063    { 
    20202064    // 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']"); 
    20272071 
    20282072    // 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)) 
    20302074      { 
    20312075      alert(this.get_label('nosenderwarning')); 
     
    20352079 
    20362080    // check for empty recipient 
    2037     var recipients = input_to.value ? 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()); 
    20382082    if (!rcube_check_email(recipients.replace(/^\s+/, '').replace(/[\s,;]+$/, ''), true)) 
    20392083      { 
     
    20442088 
    20452089    // display localized warning for missing subject 
    2046     if (input_subject && input_subject.value == '') 
     2090    if (input_subject.val() == '') 
    20472091      { 
    20482092      var subject = prompt(this.get_label('nosubjectwarning'), this.get_label('nosubject')); 
     
    20562100      else 
    20572101        { 
    2058         input_subject.value = subject ? subject : this.get_label('nosubject');             
     2102        input_subject.val((subject ? subject : this.get_label('nosubject'))); 
    20592103        } 
    20602104      } 
    20612105 
    20622106    // check for empty body 
    2063     if ((!window.tinyMCE || !tinyMCE.get('compose-body')) && input_message.value == '' && !confirm(this.get_label('nobodywarning'))) 
     2107    if ((!window.tinyMCE || !tinyMCE.get('compose-body')) && input_message.val() == '' && !confirm(this.get_label('nobodywarning'))) 
    20642108      { 
    20652109      input_message.focus(); 
     
    21062150  this.set_draft_id = function(id) 
    21072151    { 
    2108     var f; 
    2109     if (f = rcube_find_object('_draft_saveid')) 
    2110       f.value = id; 
     2152    $("input[name='_draft_saveid']").val(id); 
    21112153    }; 
    21122154 
     
    21232165    { 
    21242166    // 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(); 
    21302171    var str = ''; 
    21312172     
    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) 
    21422184      str += editor.getContent(); 
    21432185    else 
    2144       { 
    2145       input_message = rcube_find_object('_message'); 
    2146       str += input_message.value; 
    2147       } 
     2186      str += $("[name='_message']").val(); 
    21482187     
    21492188    if (save) 
     
    21592198 
    21602199    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'); 
    21642203    var sig, p; 
    21652204 
     
    21752214          sig = this.env.signatures[this.env.identity]['plain_text']; 
    21762215        else 
    2177           sig = this.env.signatures[this.env.identity]['text']; 
     2216          sig = this.env.signatures[this.env.identity]['text']; 
    21782217         
    2179         if (sig.indexOf('-- ')!=0) 
     2218        if (sig.indexOf('-- ')!=0) 
    21802219          sig = '-- \n'+sig; 
    21812220 
     
    22082247        // Append the signature as a div within the body 
    22092248        var sigElem = editor.dom.get('_rc_sig'); 
    2210         var newsig = ''; 
    2211         var htmlsig = true; 
     2249        var newsig = ''; 
     2250        var htmlsig = true; 
    22122251 
    22132252        if (!sigElem) 
    22142253          { 
    2215           // add empty line before signature on IE 
    2216           if (bw.ie) 
     2254          // add empty line before signature on IE 
     2255          if (bw.ie) 
    22172256            editor.getBody().appendChild(editor.getDoc().createElement('br')); 
    22182257 
    2219           sigElem = editor.getDoc().createElement('div'); 
     2258          sigElem = editor.getDoc().createElement('div'); 
    22202259          sigElem.setAttribute('id', '_rc_sig'); 
    22212260          editor.getBody().appendChild(sigElem); 
    22222261          } 
    22232262 
    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) 
    22312270              newsig = '<p>-- </p>' + newsig; 
    2232             else if (!htmlsig && newsig.indexOf('-- ')!=0) 
     2271            else if (!htmlsig && newsig.indexOf('-- ')!=0) 
    22332272              newsig = '-- \n' + newsig; 
    2234             } 
    2235           } 
     2273          } 
     2274        } 
    22362275 
    22372276        if (htmlsig) 
     
    22422281      } 
    22432282 
    2244     if (input_message) 
    2245       input_message.value = message; 
     2283    input_message.val(message); 
    22462284 
    22472285    this.env.identity = id; 
     
    22572295    if (elm = this.gui_objects.uploadbox) 
    22582296      { 
    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'; 
    22672302        } 
    22682303       
     
    22712306       
    22722307    // clear upload form 
    2273         try { 
     2308    try { 
    22742309      if (!a && this.gui_objects.attachmentform != this.gui_objects.messageform) 
    2275         this.gui_objects.attachmentform.reset(); 
    2276         } 
    2277         catch(e){}  // ignore errors 
    2278      
    2279     return true;   
     2310        this.gui_objects.attachmentform.reset(); 
     2311    } 
     2312    catch(e){}  // ignore errors 
     2313     
     2314    return true; 
    22802315    }; 
    22812316 
     
    23372372      return false; 
    23382373       
    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); 
    23432375    return true; 
    23442376    }; 
     
    24402472        highlight = document.getElementById('rcmksearchSelected'); 
    24412473        if (!highlight) 
    2442           highlight = this.ksearch_pane.ul.firstChild; 
     2474          highlight = this.ksearch_pane.__ul.firstChild; 
    24432475         
    24442476        if (highlight) 
     
    24802512  this.ksearch_select = function(node) 
    24812513  { 
    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'); 
    24862517    } 
    24872518 
    24882519    if (node) { 
    2489       node.setAttribute('id', 'rcmksearchSelected'); 
    2490       this.set_classname(node, 'selected', true); 
     2520      $(node).attr('id', 'rcmksearchSelected').addClass('selected'); 
    24912521      this.ksearch_selected = node._rcm_id; 
    24922522    } 
     
    25222552      return; 
    25232553       
    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(); 
    25262556 
    25272557    // get string from current cursor pos to last comma 
     
    25622592      // create results pane if not present 
    25632593      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      } 
    25712598 
    25722599      // remove all search results 
     2600      ul = this.ksearch_pane.__ul; 
    25732601      ul.innerHTML = ''; 
    25742602             
     
    25842612 
    25852613      // 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'); 
    25882615      this.ksearch_selected = 0; 
    25892616 
    25902617      // 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(); 
    25942620    } 
    25952621    // hide results pane 
     
    26242650     
    26252651    if (this.ksearch_pane) 
    2626       this.ksearch_pane.show(0); 
     2652      this.ksearch_pane.hide(); 
    26272653    }; 
    26282654 
     
    27892815  // update a contact record in the list 
    27902816  this.update_contact_row = function(cid, cols_arr) 
    2791     { 
     2817  { 
    27922818    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)) { 
    27952820      for (var c=0; c<cols_arr.length; c++) 
    27962821        if (row.cells[c]) 
    2797           row.cells[c].innerHTML = cols_arr[c]; 
     2822          $(row.cells[c]).html(cols_arr[c]); 
    27982823 
    27992824      return true; 
    2800       } 
     2825    } 
    28012826 
    28022827    return false; 
    2803     }; 
     2828  }; 
    28042829 
    28052830 
     
    28832908        { 
    28842909        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, '')) && 
    28872912            (!folder.match(new RegExp('^'+RegExp.escape(this.env.folder+this.env.delimiter))))) 
    28882913          { 
    28892914          this.set_env('dstfolder', folder); 
    2890           this.set_classname(row, 'droptarget', true); 
     2915          $(row).addClass('droptarget'); 
    28912916          } 
    28922917        } 
     
    28942919        { 
    28952920        this.set_env('dstfolder', this.env.delimiter); 
    2896         this.set_classname(this.subscription_list.frame, 'droptarget', true); 
     2921        $(this.subscription_list.frame).addClass('droptarget'); 
    28972922        } 
    28982923    } 
     
    29002925  this.unfocus_subscription = function(id) 
    29012926    { 
    2902       var row; 
     2927      var row = $('#'+id); 
    29032928      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'); 
    29072931      else 
    2908         this.set_classname(this.subscription_list.frame, 'droptarget', false); 
     2932        $(this.subscription_list.frame).removeClass('droptarget'); 
    29092933    } 
    29102934 
     
    29202944       
    29212945    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') : ''); 
    29232947    }; 
    29242948 
     
    30073031 
    30083032    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]); 
    30103034       
    30113035    this.edit_folder = null; 
     
    30553079      this.set_env('folder', null); 
    30563080 
    3057       if (this.gui_objects.createfolderhint) 
    3058         this.gui_objects.createfolderhint.innerHTML = ''; 
     3081      $(this.gui_objects.createfolderhint).html(''); 
    30593082      } 
    30603083    }; 
     
    33793402    }; 
    33803403 
    3381   // set/unset a specific class name 
    3382   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  
    33913404  // write to the document/window title 
    33923405  this.set_pagetitle = function(title) 
     
    34193432      cont = '<div class="'+type+'">'+cont+'</div>'; 
    34203433 
    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(); 
    34243435     
    34253436    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; }); 
    34273438     
    34283439    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); 
    34303441    }; 
    34313442 
    34323443  // make a message row disapear 
    3433   this.hide_message = function() 
     3444  this.hide_message = function(fade) 
    34343445    { 
    34353446    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')](); 
    34403448    }; 
    34413449 
     
    34473455      var current_li, target_li; 
    34483456       
    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'); 
    34593463      } 
    34603464    } 
     
    35133517    var even = rowcount%2; 
    35143518     
    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') 
    35253529        + (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); 
    35283534 
    35293535    if (this.message_list.in_selection(uid)) 
    3530       row.className += ' selected'; 
     3536      row.addClass('selected'); 
    35313537 
    35323538    var icon = this.env.messageicon; 
     
    35453551      icon = this.env.unreadicon; 
    35463552     
    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); 
    35513555 
    35523556    // 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++) { 
    35553558      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') { 
    35613562        if (flags.flagged && this.env.flaggedicon) 
    3562           col.innerHTML = '<img src="'+this.env.flaggedicon+'" alt="" />'; 
     3563          col.html('<img src="'+this.env.flaggedicon+'" alt="" />'); 
    35633564        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="" />'); 
    35653566      } 
    35663567      else if (c=='attachment') 
    3567         col.innerHTML = attachment && this.env.attachmenticon ? '<img src="'+this.env.attachmenticon+'" alt="" />' : '&nbsp;'; 
     3568        col.html(attachment && this.env.attachmenticon ? '<img src="'+this.env.attachmenticon+'" alt="" />' : '&nbsp;'); 
    35683569      else 
    3569         col.innerHTML = cols[c]; 
    3570  
    3571       row.appendChild(col); 
     3570        col.html(cols[c]); 
     3571 
     3572      col.appendTo(row); 
    35723573      } 
    35733574 
     
    35753576 
    35763577    // 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  }; 
    35843584 
    35853585  // replace content of row count display 
    35863586  this.set_rowcount = function(text) 
    35873587    { 
    3588     if (this.gui_objects.countdisplay) 
    3589       this.gui_objects.countdisplay.innerHTML = text; 
     3588    $(this.gui_objects.countdisplay).html(text); 
    35903589 
    35913590    // update page navigation buttons 
     
    36033602  this.set_quota = function(content) 
    36043603    { 
    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); 
    36073606    }; 
    36083607 
     
    36333632        // add children's counters 
    36343633        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) 
    36363635            childcount += this.env.unread_counts[k]; 
    3637           } 
    36383636        } 
    36393637 
     
    36513649 
    36523650      // 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'); 
    36543655      } 
    36553656 
     
    36923693    var even = rowcount%2; 
    36933694     
    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'); 
    36973696     
    36983697    if (this.contact_list.in_selection(cid)) 
    3699       row.className += ' selected'; 
     3698      row.addClass('selected'); 
    37003699 
    37013700    // 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    } 
    37093704     
    37103705    this.contact_list.insert_row(row); 
     
    37213716  // display fetched raw headers 
    37223717  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(); 
    37293721 
    37303722      if (this.env.framed && parent.rcmail) 
    3731         parent.rcmail.set_busy(false); 
     3723        parent.rcmail.set_busy(false); 
    37323724      else 
    37333725        this.set_busy(false); 
    3734       } 
    3735     }; 
     3726    } 
     3727  }; 
    37363728 
    37373729  // display all-headers row and fetch raw message headers 
     
    37413733      return; 
    37423734     
    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(); 
    37463737    elem.onclick = function() { rcmail.hide_headers(elem); } 
    37473738 
     
    37493740    if (!this.gui_objects.all_headers_box.innerHTML) 
    37503741      { 
    3751       this.display_message(this.get_label('loading'), 'loading', true);  
     3742      this.display_message(this.get_label('loading'), 'loading', true); 
    37523743      this.http_post('headers', '_uid='+this.env.uid); 
    37533744      } 
     
    37603751      return; 
    37613752 
    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(); 
    37653755    elem.onclick = function() { rcmail.load_headers(elem); } 
    37663756    } 
     
    37733763  this.html2plain = function(htmlText, id) 
    37743764    { 
    3775     var http_request = new rcube_http_request(); 
    37763765    var url = this.env.bin_path+'html2text.php'; 
    37773766    var rcmail = this; 
     
    37803769    console.log('HTTP POST: '+url); 
    37813770 
    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      }); 
    37923775    } 
    37933776 
     
    38143797    }; 
    38153798 
    3816   this.http_sockets = new Array(); 
    3817    
    3818   // find a non-busy socket or create a new one 
    3819   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 object 
    3828     var i = this.http_sockets.length; 
    3829     this.http_sockets[i] = new rcube_http_request(); 
    3830  
    3831     return this.http_sockets[i]; 
    3832     }; 
    3833    
    38343799  // send a http request to the server 
    38353800  this.http_request = function(action, querystring, lock) 
    3836     { 
    3837     var request_obj = this.get_request_obj(); 
     3801  { 
    38383802    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     
    38443805    // 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  }; 
    38863826 
    38873827  // 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) 
    38993833      this.set_busy(false); 
    39003834 
    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    } 
    39023845 
    39033846    // 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     
    39073852    // process the response data according to the sent action 
    3908     switch (request_obj.__action) { 
     3853    switch (response.action) { 
    39093854      case 'delete': 
    39103855        if (this.task == 'addressbook') { 
     
    39233868         
    39243869      case 'purge': 
    3925       case 'expunge':       
     3870      case 'expunge': 
    39263871        if (!this.env.messagecount && this.task == 'mail') { 
    39273872          // clear preview pane content 
     
    39383883      case 'list': 
    39393884        if (this.task == 'mail') { 
    3940           if (this.message_list && request_obj.__action == 'list') 
     3885          if (this.message_list && response.action == 'list') 
    39413886            this.msglist_select(this.message_list); 
    39423887          this.enable_command('show', 'expunge', 'select-all', 'select-none', 'sort', (this.env.messagecount > 0)); 
     
    39453890        else if (this.task == 'addressbook') 
    39463891          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  }; 
    39533895 
    39543896  // 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/* 
    39573901    //alert('Error sending request: '+request_obj.url+' => HTTP '+request_obj.xmlhttp.status); 
    39583902    if (request_obj.__lock) 
     
    39623906    request_obj.__lock = false; 
    39633907    this.display_message('Unknown Server Error!', 'error'); 
     3908*/ 
    39643909    }; 
    39653910 
     
    40674012    }; 
    40684013     
    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 
     4018rcube_webmail.prototype.addEventListener = rcube_event_engine.prototype.addEventListener; 
     4019rcube_webmail.prototype.removeEventListener = rcube_event_engine.prototype.removeEventListener; 
     4020rcube_webmail.prototype.triggerEvent = rcube_event_engine.prototype.triggerEvent; 
     4021 
  • trunk/roundcubemail/program/js/common.js

    r2395 r2401  
    9494 
    9595 
    96 // static functions for event handling 
     96// static functions for DOM event handling 
    9797var rcube_event = { 
    9898 
     
    160160 
    161161  if (e._offset) { 
    162     mX += e._offset.x; 
    163     mY += e._offset.y; 
     162    mX += e._offset.left; 
     163    mY += e._offset.top; 
    164164  } 
    165165 
     
    235235 
    236236 
    237 var rcube_layer_objects = new Array(); 
     237/** 
     238 * rcmail objects event interface 
     239 */ 
     240function rcube_event_engine() 
     241{ 
     242  this._events = {}; 
     243} 
     244 
     245rcube_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 */ 
     254addEventListener: 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 */ 
     271removeEventListener: 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 */ 
     287triggerEvent: 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 
    238317 
    239318 
     
    244323 */ 
    245324function rcube_layer(id, attributes) 
    246   { 
     325{ 
    247326  this.name = id; 
    248327   
     
    311390  this.visible = (this.css.visibility=='visible' || this.css.visibility=='show' || this.css.visibility=='inherit') ? true : false; 
    312391 
    313   this.id = rcube_layer_objects.length; 
    314   this.obj = 'rcube_layer_objects['+this.id+']'; 
    315   rcube_layer_objects[this.id] = this; 
    316  
    317392 
    318393  // ********* layer object methods ********* 
     
    328403    } 
    329404 
    330  
    331   // move the layer for a specific step 
    332   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  
    340405  // change the layers width and height 
    341406  this.resize = function(w,h) 
     
    345410    this.width = w; 
    346411    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; 
    356412    } 
    357413 
     
    384440    } 
    385441 
    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} 
    416443 
    417444 
     
    473500// get any type of html objects by id/name 
    474501function rcube_find_object(id, d) 
    475   { 
     502{ 
    476503  var n, f, obj, e; 
    477504  if(!d) d = document; 
     
    487514    obj = d.images[id]; 
    488515 
    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++) { 
    492518      if(d.forms[f].name == id) 
    493519        obj = d.forms[f]; 
    494520      else if(d.forms[f].elements[id]) 
    495521        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++) 
    502528      obj = rcube_find_object(id, d.layers[n].document); 
    503     } 
     529  } 
    504530 
    505531  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} 
    533533 
    534534// determine whether the mouse is over the given object or not 
     
    536536{ 
    537537  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 
    571544 
    572545// cookie functions by GoogieSpell 
     
    612585    if (box) { 
    613586      if (msg.charAt(msg.length-1)=='\n') 
    614         msg += '--------------------------------------\n'; 
     587        msg += '--------------------------------------\n'; 
    615588      else 
    616589        msg += '\n--------------------------------------\n'; 
     
    634607 
    635608var bw = new roundcube_browser(); 
    636 var console = new rcube_console(); 
     609if (!window.console)  
     610  console = new rcube_console(); 
    637611 
    638612 
  • trunk/roundcubemail/program/js/editor.js

    r2250 r2401  
    5353      gecko_spellcheck : true, 
    5454      relative_urls : false, 
    55       remove_script_host : false , 
    56       rc_client: rcube_webmail_client, 
     55      remove_script_host : false, 
     56      rc_client: rcmail, 
    5757      oninit : 'rcmail_editor_callback' 
    5858    }); 
  • trunk/roundcubemail/program/js/list.js

    r2396 r2401  
    5252  this.dblclick_time = 600; 
    5353  this.row_init = function(){}; 
    54   this.events = { click:[], dblclick:[], select:[], keypress:[], dragstart:[], dragmove:[], dragend:[] }; 
    5554   
    5655  // overwrite default paramaters 
     
    161160{ 
    162161  var tbody = this.list.tBodies[0]; 
     162  if (!row.jquery) 
     163    row = $(row); 
    163164 
    164165  if (attop && tbody.rows.length) 
    165     tbody.insertBefore(row, tbody.firstChild); 
     166    row.prependTo(tbody) 
    166167  else 
    167     tbody.appendChild(row); 
    168  
    169   this.init_row(row); 
     168    row.appendTo(tbody); 
     169 
     170  this.init_row(row[0]); 
    170171  this.rowcount++; 
    171172}, 
     
    182183  { 
    183184    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'); 
    188187    } 
    189188  } 
     
    204203  { 
    205204    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'); 
    210207    } 
    211208  } 
     
    252249        iframedoc = iframes[n].contentDocument; 
    253250      else if (iframes[n].contentWindow) 
    254         iframedoc = iframes[n].contentWindow.document; 
     251        iframedoc = iframes[n].contentWindow.document; 
    255252      else if (iframes[n].document) 
    256253        iframedoc = iframes[n].document; 
     
    258255      if (iframedoc) 
    259256      { 
    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         else 
    269           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]; 
    270267 
    271268        rcube_event.add_listener({element:iframedoc, event:'mouseup', object:this, method:'drag_mouse_up'}); 
    272269      } 
    273     }                                                              
     270    } 
    274271  } 
    275272 
     
    308305  // row was double clicked 
    309306  if (this.rows && dblclicked && this.in_selection(id)) 
    310     this.trigger_event('dblclick'); 
     307    this.triggerEvent('dblclick'); 
    311308  else 
    312     this.trigger_event('click'); 
     309    this.triggerEvent('click'); 
    313310 
    314311  if (!this.drag_active) 
     
    408405  // trigger event if selection changed 
    409406  if (this.selection.join(',') != select_before) 
    410     this.trigger_event('select'); 
     407    this.triggerEvent('select'); 
    411408 
    412409  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'); 
    414411 
    415412  // unselect if toggleselect is active and the same row was clicked again 
     
    420417  } 
    421418  else 
    422     this.set_classname(this.rows[id].obj, 'focused', true); 
     419    $(this.rows[id].obj).addClass('focused'); 
    423420 
    424421  if (!this.selection.length) 
     
    525522  // trigger event if selection changed 
    526523  if (this.selection.join(',') != select_before) 
    527     this.trigger_event('select'); 
     524    this.triggerEvent('select'); 
    528525 
    529526  this.focus(); 
     
    544541    { 
    545542    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      } 
    551547    } 
    552548  // all rows 
     
    554550    { 
    555551    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'); 
    560554        } 
    561555     
     
    564558 
    565559  if (num_select && !this.selection.length) 
    566     this.trigger_event('select'); 
     560    this.triggerEvent('select'); 
    567561}, 
    568562 
     
    600594      this.clear_selection(); 
    601595      this.selection[0] = id; 
    602       this.set_classname(this.rows[id].obj, 'selected', true); 
     596      $(this.rows[id].obj).addClass('selected'); 
    603597    } 
    604598  } 
     
    608602    { 
    609603      this.selection[this.selection.length] = id; 
    610       this.set_classname(this.rows[id].obj, 'selected', true); 
     604      $(this.rows[id].obj).addClass('selected'); 
    611605    } 
    612606    else  // unselect row 
     
    616610      var a_post = this.selection.slice(p+1, this.selection.length); 
    617611      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'); 
    620613    } 
    621614  } 
     
    645638      this.shiftkey = e.shiftKey; 
    646639      this.key_pressed = keyCode; 
    647       this.trigger_event('keypress'); 
     640      this.triggerEvent('keypress'); 
    648641       
    649642      if (this.key_pressed == this.BACKSPACE_KEY) 
     
    730723   
    731724    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); 
    733726   
    734727    // get subjects of selectedd messages 
     
    755748              (this.subject_col < 0 || (this.subject_col >= 0 && this.subject_col == c))) 
    756749            { 
     750              if (n == 0) 
     751                this.drag_start_pos = $(node).offset(); 
     752               
    757753              subject = node.nodeType==3 ? node.data : node.innerHTML; 
    758754              // remove leading spaces 
     
    768764    } 
    769765 
    770     this.draglayer.write(names); 
    771     this.draglayer.show(1); 
     766    this.draglayer.html(names); 
     767    this.draglayer.show(); 
    772768 
    773769    this.drag_active = true; 
    774     this.trigger_event('dragstart'); 
     770    this.triggerEvent('dragstart'); 
    775771  } 
    776772 
     
    778774  { 
    779775    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); 
    782778  } 
    783779 
     
    795791  document.onmousemove = null; 
    796792 
    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  } 
    799799 
    800800  this.drag_active = false; 
    801   this.trigger_event('dragend'); 
     801  this.triggerEvent('dragend'); 
    802802 
    803803  rcube_event.remove_listener({element:document, event:'mousemove', object:this, method:'drag_mouse_move'}); 
     
    829829 
    830830  return rcube_event.cancel(e); 
    831 }, 
    832  
    833  
    834  
    835 /** 
    836  * set/unset a specific class name 
    837  */ 
    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 handlers 
    850  * 
    851  * @param {String}   Event name 
    852  * @param {Function} Handler function 
    853  * @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   else 
    863     return false; 
    864 }, 
    865  
    866  
    867 /** 
    868  * Removes a specific event listener 
    869  * 
    870  * @param {String} Event name 
    871  * @param {Int}    Listener ID to remove 
    872  */ 
    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 handlers 
    882  * @private 
    883  */ 
    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   } 
    891831} 
    892832 
    893  
    894833}; 
    895834 
     835rcube_list_widget.prototype.addEventListener = rcube_event_engine.prototype.addEventListener; 
     836rcube_list_widget.prototype.removeEventListener = rcube_event_engine.prototype.removeEventListener; 
     837rcube_list_widget.prototype.triggerEvent = rcube_event_engine.prototype.triggerEvent; 
  • trunk/roundcubemail/program/lib/imap.inc

    r2388 r2401  
    183183        var $junk = false; 
    184184        var $flagged = false; 
     185        var $others = array(); 
    185186} 
    186187 
     
    16621663} 
    16631664 
    1664 function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bodystr=false) 
     1665function iil_C_FetchHeaders(&$conn, $mailbox, $message_set, $uidfetch=false, $bodystr=false, $add='') 
    16651666{ 
    16661667        global $IMAP_USE_INTERNAL_DATE; 
     
    17021703                } 
    17031704        } 
     1705         
     1706        if ($add) 
     1707          $add = ' '.strtoupper(trim($add)); 
    17041708 
    17051709        /* FETCH uid, size, flags and headers */ 
     
    17121716        $request .= "(DATE FROM TO SUBJECT REPLY-TO IN-REPLY-TO CC BCC "; 
    17131717        $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.")])"; 
    17151719 
    17161720        if (!iil_PutLine($fp, $request)) { 
     
    18601864                                         
    18611865                                        $field  = strtolower($field); 
    1862                                         $string = ereg_replace("\n[[:space:]]*"," ",$string);  
     1866                                        $string = ereg_replace("\n[[:space:]]*"," ",$string); 
    18631867                                         
    18641868                                        switch ($field) { 
     
    19181922                                                        $result[$id]->priority = intval($matches[1]); 
    19191923                                                break; 
     1924                                        default: 
     1925                                                if (strlen($field) > 2) 
     1926                                                        $result[$id]->others[$field] = $string; 
     1927                                                break; 
    19201928                                        } // end switch () 
    19211929                                } // end while () 
     
    19651973} 
    19661974 
    1967 function iil_C_FetchHeader(&$conn, $mailbox, $id, $uidfetch=false, $bodystr=false) { 
    1968  
    1969         $a  = iil_C_FetchHeaders($conn, $mailbox, $id, $uidfetch, $bodystr); 
     1975function iil_C_FetchHeader(&$conn, $mailbox, $id, $uidfetch=false, $bodystr=false, $add='') { 
     1976 
     1977        $a  = iil_C_FetchHeaders($conn, $mailbox, $id, $uidfetch, $bodystr, $add); 
    19701978        if (is_array($a)) { 
    19711979                return array_shift($a); 
  • trunk/roundcubemail/program/steps/addressbook/func.inc

    r1939 r2401  
    4343if (strtolower($CONFIG['address_book_type']) != 'ldap') { 
    4444  // 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); 
    4646} 
    4747if (is_array($CONFIG['ldap_public'])) { 
    4848  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']); 
    5050} 
    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']); 
    5254 
    5355 
    5456function rcmail_directory_list($attrib) 
    5557{ 
    56   global $CONFIG, $OUTPUT; 
     58  global $RCMAIL, $OUTPUT; 
    5759   
    5860  if (!$attrib['id']) 
     
    6466  $line_templ = html::tag('li', array('id' => 'rcmli%s', 'class' => '%s'), 
    6567    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) { 
    7273    // DB address book not used, see if a source is set, if not use the 
    7374    // 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; 
    8080    $js_id = JQ($id); 
    8181    $dom_id = preg_replace('/[^a-z0-9\-_]/i', '', $id); 
    8282    $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 
    8686  $OUTPUT->add_gui_object('folderlist', $attrib['id']); 
    8787   
  • trunk/roundcubemail/program/steps/mail/attachments.inc

    r2376 r2401  
    2929if ($RCMAIL->action=='remove-attachment') 
    3030{ 
    31   if (preg_match('/^rcmfile([0-9]+)$/', $_POST['_file'], $regs)) 
    32   { 
     31  $id = 'undefined'; 
     32  if (preg_match('/^rcmfile(\w+)$/', $_POST['_file'], $regs)) 
    3333    $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])) { 
    3738      unset($_SESSION['compose']['attachments'][$id]); 
    3839      $OUTPUT->command('remove_from_attachment_list', "rcmfile$id"); 
    39       $OUTPUT->send(); 
    4040    } 
    4141  } 
     42   
     43  $OUTPUT->send(); 
    4244  exit; 
    4345} 
     
    4547if ($RCMAIL->action=='display-attachment') 
    4648{ 
    47   if (preg_match('/^rcmfile([0-9]+)$/', $_GET['_file'], $regs)) 
    48   { 
     49  $id = 'undefined'; 
     50  if (preg_match('/^rcmfile(\w+)$/', $_GET['_file'], $regs)) 
    4951    $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']); 
    5764  } 
    5865  exit; 
     
    6067 
    6168// attachment upload action 
    62  
    63 // use common temp dir for file uploads 
    64 $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 } 
    7069 
    7170if (!is_array($_SESSION['compose']['attachments'])) { 
     
    7877if (is_array($_FILES['_attachments']['tmp_name'])) { 
    7978  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    ); 
    8884 
     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       
    8993      if (is_file($icon = $CONFIG['skin_path'] . '/images/icons/remove-attachment.png')) { 
    9094        $button = html::img(array( 
     
    100104      $content = html::a(array( 
    101105        '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), 
    103107        'title' => rcube_label('delete'), 
    104108      ), $button); 
    105        
    106       $content .= Q($_FILES['_attachments']['name'][$i]); 
     109 
     110      $content .= Q($attachment['name']); 
    107111       
    108112      $OUTPUT->command('add2attachment_list', "rcmfile$id", $content); 
  • trunk/roundcubemail/program/steps/mail/compose.inc

    r2368 r2401  
    595595   
    596596  $cid_map = array(); 
    597   $id = 0; 
    598    
    599597  foreach ((array)$message->mime_parts as $pid => $part) 
    600598  { 
     
    604602    { 
    605603      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']; 
    610607        } 
    611         $id++; 
    612       } 
    613     } 
    614   } 
    615          
     608      } 
     609    } 
     610  } 
     611 
    616612  $_SESSION['compose']['forward_attachments'] = true; 
    617613 
     
    625621 
    626622  $cid_map = array(); 
    627   $id = 0; 
    628    
    629623  foreach ((array)$message->mime_parts as $pid => $part) { 
    630624    if ($part->content_id && $part->filename) { 
    631625      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']; 
    636628      } 
    637629    } 
     
    643635function rcmail_save_attachment(&$message, $pid) 
    644636{ 
    645   global $RCMAIL; 
    646  
    647   $temp_dir = unslashify($RCMAIL->config->get('temp_dir')); 
    648   $tmp_path = tempnam($temp_dir, 'rcmAttmnt'); 
    649637  $part = $message->mime_parts[$pid]; 
    650638   
    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; 
    663653} 
    664654 
     
    740730            'href' => "#delete", 
    741731            '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)), 
    743733          $button) . Q($a_prop['name'])); 
    744734    } 
  • trunk/roundcubemail/program/steps/mail/func.inc

    r2397 r2401  
    731731function rcmail_print_body($part, $p = array()) 
    732732{ 
    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)); 
    734738 
    735739  // 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); 
    738742    $body = $txt->get_text(); 
    739743    $part->ctype_secondary = 'plain'; 
    740744  } 
    741745  // 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']; 
    744749  } 
    745750  // text/enriched 
    746   else if ($part->ctype_secondary=='enriched') { 
     751  else if ($data['type'] == 'enriched') { 
    747752    $part->ctype_secondary = 'html'; 
    748753    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 
    752758    $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']); 
    798813} 
    799814 
     
    843858function rcmail_message_headers($attrib, $headers=NULL) 
    844859  { 
    845   global $IMAP, $OUTPUT, $MESSAGE, $PRINT_MODE, $CONFIG; 
     860  global $IMAP, $OUTPUT, $MESSAGE, $PRINT_MODE, $RCMAIL; 
    846861  static $sa_attrib; 
    847862   
     
    852867    $attrib = $sa_attrib; 
    853868   
    854    
    855869  if (!isset($MESSAGE)) 
    856870    return FALSE; 
     
    860874    $headers = is_object($MESSAGE->headers) ? get_object_vars($MESSAGE->headers) : $MESSAGE->headers; 
    861875     
    862   $header_count = 0; 
    863    
    864   // allow the following attributes to be added to the <table> tag 
    865   $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary')); 
    866   $out = '<table' . $attrib_str . ">\n"; 
    867  
    868876  // show these headers 
    869877  $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) { 
    873881    if (!$headers[$hkey]) 
    874882      continue; 
    875883 
    876     if ($hkey == 'date') 
    877       { 
     884    if ($hkey == 'date') { 
    878885      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')); 
    880887      else 
    881888        $header_value = format_date($headers[$hkey]); 
    882       } 
    883     else if ($hkey == 'replyto') 
    884       { 
     889    } 
     890    else if ($hkey == 'replyto') { 
    885891      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']); 
    887893      else 
    888894        continue; 
    889       } 
     895    } 
    890896    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']); 
    892898    else if ($hkey == 'subject' && empty($headers[$hkey])) 
    893       $header_value = Q(rcube_label('nosubject')); 
     899      $header_value = rcube_label('nosubject'); 
    894900    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)).":&nbsp;</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  } 
    902915 
    903916  // 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   
    908921  $OUTPUT->add_gui_object('all_headers_row', 'all-headers'); 
    909922  $OUTPUT->add_gui_object('all_headers_box', 'headers-source'); 
    910923 
    911   $out .= "\n</table>\n\n"; 
    912  
    913   return $header_count ? $out : '';   
     924  return $table->show($attrib); 
    914925  } 
    915926 
     
    12521263    return; 
    12531264 
    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()); 
    12581266   
    12591267  unset($_SESSION['compose']); 
  • trunk/roundcubemail/program/steps/mail/sendmail.inc

    r2368 r2401  
    298298// the HTML part and the plain-text part 
    299299 
    300 if ($isHtml) 
    301   { 
    302   $MAIL_MIME->setHTMLBody($message_body . ($footer ? "\r\n<pre>".$footer.'</pre>' : '')); 
     300if ($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>' : '')); 
    303303 
    304304  // 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 : ''); 
    307307  $plainTextPart = wordwrap($plainTextPart, 998, "\r\n", true); 
    308   if (!strlen($plainTextPart)) 
    309     {  
     308  if (!strlen($plainTextPart)) { 
    310309    // empty message body breaks attachment handling in drafts  
    311310    $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']); 
    314314 
    315315  // look for "emoticon" images from TinyMCE and copy into message as attachments 
    316316  $message_body = rcmail_attach_emoticons($MAIL_MIME); 
    317   } 
     317} 
    318318else 
    319319  { 
     
    322322    $message_body .= "\r\n" . $footer; 
    323323  $message_body = wordwrap($message_body, 998, "\r\n", true); 
    324   if (!strlen($message_body))   
    325     {  
     324  if (!strlen($message_body)) {  
    326325    // empty message body breaks attachment handling in drafts  
    327326    $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} 
    331331 
    332332// chose transfer encoding 
     
    335335 
    336336// 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     { 
     337if (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)) { 
    344345      $message_body = preg_replace($dispurl, ' src="'.$attachment['name'].'" ', $message_body); 
    345346      $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 { 
    350354      $ctype = str_replace('image/pjpeg', 'image/jpeg', $attachment['mimetype']); // #1484914 
     355      $file = $attachment['data'] ? $attachment['data'] : $attachment['path']; 
    351356 
    352357      // .eml attachments send inline 
    353       $MAIL_MIME->addAttachment($attachment['path'], 
     358      $MAIL_MIME->addAttachment($file, 
    354359        $ctype,  
    355         $attachment['name'], true,  
     360        $attachment['name'], 
     361        ($attachment['data'] ? false : true), 
    356362        ($ctype == 'message/rfc822' ? $transfer_encoding : 'base64'), 
    357363        ($ctype == 'message/rfc822' ? 'inline' : 'attachment'), 
    358364        $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} 
    364371 
    365372// add submitted attachments 
    366 if (is_array($_FILES['_attachments']['tmp_name'])) 
    367   foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) 
    368     { 
     373if (is_array($_FILES['_attachments']['tmp_name'])) { 
     374  foreach ($_FILES['_attachments']['tmp_name'] as $i => $filepath) { 
    369375    $ctype = $files['type'][$i]; 
    370376    $ctype = str_replace('image/pjpeg', 'image/jpeg', $ctype); // #1484914 
    371377     
    372378    $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' : NULL 
    377         ); 
    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} 
    380386 
    381387// encoding settings for mail composing 
     
    388394  'text_charset'  => $message_charset, 
    389395)); 
     396 
     397$data = $RCMAIL->plugins->exec_hook('outgoing_message_headers', array('headers' => $headers)); 
     398$headers = $data['headers']; 
    390399 
    391400// encoding subject header with mb_encode provides better results with asian characters 
  • trunk/roundcubemail/program/steps/mail/show.inc

    r2301 r2401  
    136136 
    137137  // mark message as read 
    138   if (!$MESSAGE->headers->seen) 
     138  if (!$MESSAGE->headers->seen) { 
    139139    $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} 
    141143 
    142144 
  • trunk/roundcubemail/program/steps/settings/func.inc

    r2383 r2401  
    160160    } 
    161161     
     162    $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table)); 
     163     
    162164    if ($table->size()) 
    163165      $out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('uisettings'))) . $table->show($attrib)); 
     
    217219    } 
    218220 
     221    $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table)); 
     222 
    219223    if ($table->size()) 
    220224      $out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('mailboxview'))) . $table->show($attrib)); 
     
    255259    } 
    256260 
     261    $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table)); 
     262 
    257263    if ($table->size()) 
    258264      $out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('messagesdisplaying'))) . $table->show($attrib)); 
     
    296302    } 
    297303 
     304    $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table)); 
     305 
    298306    if ($table->size()) 
    299307      $out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('messagescomposition'))) . $table->show($attrib)); 
     
    330338      } 
    331339 
     340      $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table)); 
     341 
    332342      $out = html::tag('fieldset', null, html::tag('legend', null, Q(rcube_label('specialfolders'))) . $table->show($attrib)); 
    333343    } 
     
    381391      $table->add(null, $input_expunge->show($config['logout_expunge']?1:0)); 
    382392    } 
     393 
     394    $RCMAIL->plugins->exec_hook('user_preferences', array('section' => $part, 'table' => $table)); 
    383395 
    384396    if ($table->size()) 
  • trunk/roundcubemail/program/steps/settings/manage_folders.inc

    r2256 r2401  
    257257  } 
    258258 
     259  rcmail::get_instance()->plugins->exec_hook('manage_folders', array('table'=>$table)); 
    259260 
    260261  $OUTPUT->add_gui_object('subscriptionlist', $attrib['id']); 
  • trunk/roundcubemail/program/steps/settings/save_prefs.inc

    r2115 r2401  
    4949  ); 
    5050 
     51$data  =  rcmail::get_instance()->plugins->exec_hook('save_preferences', array('prefs' => $a_user_prefs)); 
     52$a_user_prefs = $data['prefs']; 
     53 
    5154// don't override these parameters 
    5255foreach ((array)$CONFIG['dont_override'] as $p) 
  • trunk/roundcubemail/skins/default/common.css

    r2398 r2401  
    247247} 
    248248 
     249#pagecontent 
     250{ 
     251  position: absolute; 
     252  top: 95px; 
     253  left: 20px; 
     254} 
     255 
    249256.splitter 
    250257{ 
  • trunk/roundcubemail/skins/default/functions.js

    r2196 r2401  
    99function rcube_init_settings_tabs() 
    1010{ 
     11  var tab = '#settingstabdefault'; 
    1112  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'); 
    2116} 
    2217 
    2318function rcube_show_advanced(visible) 
    2419{ 
    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')); 
    2921} 
    3022 
     
    129121function rcube_mail_ui() 
    130122{ 
    131   this.markmenu = new rcube_layer('markmessagemenu'); 
     123  this.markmenu = $('#markmessagemenu'); 
    132124} 
    133125 
     
    137129{ 
    138130  if (typeof show == 'undefined') 
    139     show = this.markmenu.visible ? false : true; 
     131    show = this.markmenu.is(':visible') ? false : true; 
    140132   
    141133  var ref = rcube_find_object('markreadbutton'); 
    142134  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) }); 
    144136   
    145   this.markmenu.show(show); 
     137  this.markmenu[show?'show':'hide'](); 
    146138}, 
    147139 
    148140body_mouseup: function(evt, p) 
    149141{ 
    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')) 
    151143    this.show_markmenu(false); 
    152144}, 
     
    154146body_keypress: function(evt, p) 
    155147{ 
    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')) 
    157149    this.show_markmenu(false); 
    158150} 
  • trunk/roundcubemail/skins/default/includes/settingstabs.html

    r1409 r2401  
    33<span id="settingstabfolders" class="tablink"><roundcube:button command="folders" type="link" label="folders" title="managefolders" class="tablink" /></span> 
    44<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> 
    57</div> 
  • trunk/roundcubemail/skins/default/includes/taskbar.html

    r62 r2401  
    11<div id="taskbar"> 
     2<roundcube:container name="taskbar" id="taskbar" /> 
    23<roundcube:button command="mail" label="mail" class="button-mail" /> 
    34<roundcube:button command="addressbook" label="addressbook" class="button-addressbook" /> 
  • trunk/roundcubemail/skins/default/mail.css

    r2374 r2401  
    5050  left: 90px; 
    5151  width: auto; 
    52   visibility: hidden; 
     52  display: none; 
    5353  background-color: #F9F9F9; 
    5454  border: 1px solid #CCC; 
  • trunk/roundcubemail/skins/default/splitter.js

    r2169 r2401  
    2323 
    2424    // 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(); 
    2727     
    2828    if (this.horizontal) 
    2929      { 
    30       var top = this.p1pos.y + this.p1.offsetHeight; 
     30      var top = this.p1pos.top + this.p1.offsetHeight; 
    3131      this.layer = new rcube_layer(this.id, {x: 0, y: top, height: 10,  
    3232            width: '100%', vis: 1, parent: this.p1.parentNode}); 
     
    3434    else 
    3535      { 
    36       var left = this.p1pos.x + this.p1.offsetWidth; 
     36      var left = this.p1pos.left + this.p1.offsetWidth; 
    3737      this.layer = new rcube_layer(this.id, {x: left, y: 0, width: 10,  
    3838            height: '100%', vis: 1,  parent: this.p1.parentNode}); 
     
    7171      { 
    7272      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'; 
    7474      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)); 
    7676      if (bw.ie) 
    77         { 
     77        { 
    7878        var new_height = (parseInt(this.p2.parentNode.offsetHeight) - parseInt(this.p2.style.top)); 
    7979        this.p2.style.height = (new_height > 0 ? new_height : 0) +'px'; 
     
    8282    else 
    8383      { 
    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'; 
    8585      this.p2.style.left = Math.ceil(this.pos + this.layer.width / 2) + 'px'; 
    8686      this.layer.move(Math.round(this.pos - this.layer.width / 2 + 1), this.layer.y); 
     
    9595  this.onDragStart = function(e) 
    9696    { 
    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(); 
    9999    this.drag_active = true; 
    100100     
     
    120120        // the position of each iframe when the event is received 
    121121        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); } 
    124124 
    125125        if (iframedoc.addEventListener) 
     
    146146    if (this.relative) 
    147147      { 
    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))) 
    156156        { 
    157157        this.pos = pos.y; 
     
    161161    else 
    162162      { 
    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))) 
    164164        { 
    165165        this.pos = pos.x; 
     
    168168      } 
    169169 
    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(); 
    172172    return false; 
    173173    }; 
     
    199199          if (iframedoc.removeEventListener) 
    200200            iframedoc.removeEventListener('mousemove', this.iframe_events[n], false); 
    201           else if (iframedoc.detachEvent) 
     201          else if (iframedoc.detachEvent) 
    202202            iframedoc.detachEvent('onmousemove', this.iframe_events[n]); 
    203203          else 
  • trunk/roundcubemail/skins/default/templates/addressbook.html

    r2398 r2401  
    88 
    99<style type="text/css"> 
    10 <roundcube:if condition="config:ldap_public == false" /> 
     10<roundcube:if condition="count(env:address_sources) &lt;= 1" /> 
    1111#abookcountbar { left: 20px;} 
    1212#mainscreen { left:20px; /* IE hack */ width:expression((parseInt(document.documentElement.clientWidth)-40)+'px') } 
     
    4545</div> 
    4646 
    47 <roundcube:if condition="config:ldap_public" /> 
     47<roundcube:if condition="count(env:address_sources) &gt; 1" /> 
    4848<div id="directorylist"> 
    4949<div id="groups-title"><roundcube:label name="groups" /></div> 
  • trunk/roundcubemail/skins/default/templates/identities.html

    r2167 r2401  
    77<script type="text/javascript" src="/functions.js"></script> 
    88</head> 
    9 <body onload="rcube_init_settings_tabs()"> 
     9<body> 
    1010 
    1111<roundcube:include file="/includes/taskbar.html" /> 
  • trunk/roundcubemail/skins/default/templates/mail.html

    r2398 r2401  
    120120<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" /> 
    121121<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" /> 
    122123 
    123124<div id="markmessagemenu"> 
  • trunk/roundcubemail/skins/default/templates/managefolders.html

    r2380 r2401  
    77<script type="text/javascript" src="/functions.js"></script> 
    88</head> 
    9 <body onload="rcube_init_settings_tabs()"> 
     9<body> 
    1010 
    1111<roundcube:include file="/includes/taskbar.html" /> 
  • trunk/roundcubemail/skins/default/templates/message.html

    r2131 r2401  
    3737<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" /> 
    3838<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" /> 
    3940</div> 
    4041 
  • trunk/roundcubemail/skins/default/templates/settings.html

    r2164 r2401  
    77<script type="text/javascript" src="/functions.js"></script> 
    88</head> 
    9 <body onload="rcube_init_settings_tabs()"> 
     9<body> 
    1010 
    1111<roundcube:include file="/includes/taskbar.html" /> 
     
    1818<div id="userprefs-title"><roundcube:label name="userpreferences" /></div> 
    1919 
    20 <div style="padding:15px 0 15px 15px"> 
     20<div id="userprefscontainer" style="padding:15px 0 15px 15px"> 
    2121<div class="userprefs-block"> 
    2222  <roundcube:object name="userprefs" form="form" parts="general,mailbox,mailview" /> 
     
    2626</div> 
    2727<div style="clear:left"></div> 
     28 
     29<roundcube:container name="userprefs" id="userprefscontainer" /> 
    2830</div> 
    2931</div> 
Note: See TracChangeset for help on using the changeset viewer.