alecpl
2008-04-02 fdccdb4afee82fe8ac4d2853ab806f4a7f90d13d
program/js/app.js
@@ -3,7 +3,7 @@
 | RoundCube Webmail Client Script                                       |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2005-2006, RoundCube Dev, - Switzerland                 |
 | Copyright (C) 2005-2008, RoundCube Dev, - Switzerland                 |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 +-----------------------------------------------------------------------+
@@ -28,15 +28,16 @@
  this.commands = new Object();
  this.onloads = new Array();
  // create public reference to myself
  // create protected reference to myself
  rcube_webmail_client = this;
  this.ref = 'rcube_webmail_client';
  var ref = this;
 
  // webmail client settings
  this.dblclick_time = 500;
  this.message_time = 5000;
  this.message_time = 3000;
  
  this.mbox_expression = new RegExp('[^0-9a-z\-_]', 'gi');
  this.identifier_expr = new RegExp('[^0-9a-z\-_]', 'gi');
  
  // mimetypes supported by the browser (default settings)
  this.mimetypes = new Array('text/plain', 'text/html', 'text/xml',
@@ -48,12 +49,19 @@
  this.env.keep_alive = 60;        // seconds
  this.env.request_timeout = 180;  // seconds
  this.env.draft_autosave = 0;     // seconds
  this.env.comm_path = './';
  this.env.bin_path = './bin/';
  this.env.blankpage = 'program/blank.gif';
  // set environment variable
  this.set_env = function(name, value)
  // set environment variable(s)
  this.set_env = function(p, value)
    {
    this.env[name] = value;
    if (p != null && typeof(p) == 'object' && !value)
      for (var n in p)
        this.env[n] = p[n];
    else
      this.env[p] = value;
    };
@@ -124,7 +132,7 @@
          this.message_list.addEventListener('dblclick', function(o){ p.msglist_dbl_click(o); });
          this.message_list.addEventListener('keypress', function(o){ p.msglist_keypress(o); });
          this.message_list.addEventListener('select', function(o){ p.msglist_select(o); });
          this.message_list.addEventListener('dragstart', function(o){ p.drag_active = true; });
          this.message_list.addEventListener('dragstart', function(o){ p.drag_active = true; if (p.preview_timer) clearTimeout(p.preview_timer); });
          this.message_list.addEventListener('dragend', function(o){ p.drag_active = false; });
          this.message_list.init();
@@ -138,13 +146,19 @@
          else
            this.message_list.focus();
          }
        if (this.env.coltypes)
          this.set_message_coltypes(this.env.coltypes);
        // enable mail commands
        this.enable_command('list', 'checkmail', 'compose', 'add-contact', 'search', 'reset-search', true);
        if (this.env.search_text != null && document.getElementById('quicksearchbox') != null)
          document.getElementById('quicksearchbox').value = this.env.search_text;
        
        if (this.env.action=='show' || this.env.action=='preview')
          {
          this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'viewsource', 'print', 'load-attachment', true);
          this.enable_command('show', 'reply', 'reply-all', 'forward', 'moveto', 'delete', 'mark', 'viewsource', 'print', 'load-attachment', true);
          if (this.env.next_uid)
            {
            this.enable_command('nextmessage', true);
@@ -156,13 +170,16 @@
            this.enable_command('firstmessage', true);
            }
          }
        if (this.env.trash_mailbox && this.env.mailbox != this.env.trash_mailbox)
          this.set_alttext('delete', 'movemessagetotrash');
        
        // make preview/message frame visible
        if (this.env.action == 'preview' && this.env.framed && parent.rcmail)
          {
          this.enable_command('compose', 'add-contact', false);
          parent.rcmail.show_messageframe(true);
          parent.rcmail.mark_message('read', this.uid);
          parent.rcmail.show_contentframe(true);
          parent.rcmail.mark_message('read', this.env.uid);
          }
        if ((this.env.action=='show' || this.env.action=='preview') && this.env.blockedobjects)
@@ -177,7 +194,7 @@
          this.enable_command('add-attachment', 'send-attachment', 'remove-attachment', 'send', true);
          if (this.env.spellcheck)
            {
            this.env.spellcheck.spelling_state_observer = function(s){ rcube_webmail_client.set_spellcheck_state(s); };
            this.env.spellcheck.spelling_state_observer = function(s){ ref.set_spellcheck_state(s); };
            this.set_spellcheck_state('ready');
            }
          if (this.env.drafts_mailbox)
@@ -185,15 +202,18 @@
          }
        if (this.env.messagecount)
          this.enable_command('select-all', 'select-none', 'sort', 'expunge', true);
          this.enable_command('select-all', 'select-none', 'expunge', true);
        if (this.env.messagecount && (this.env.mailbox==this.env.trash_mailbox || this.env.mailbox==this.env.junk_mailbox))
          this.enable_command('purge', true);
        this.set_page_buttons();
        // focus this window
        window.focus();
        // focus main window
        if (this.env.framed && window.parent)
          window.parent.focus();
        else
          window.focus();
        // init message compose form
        if (this.env.action=='compose')
@@ -205,7 +225,20 @@
        // get unread count for each mailbox
        if (this.gui_objects.mailboxlist)
        {
          this.gui_objects.folderlist = this.gui_objects.mailboxlist;
          this.http_request('getunread', '');
        }
        // ask user to send MDN
        if (this.env.mdn_request && this.env.uid)
        {
          var mdnurl = '_uid='+this.env.uid+'&_mbox='+urlencode(this.env.mailbox);
          if (confirm(this.get_label('mdnrequest')))
            this.http_post('sendmdn', mdnurl);
          else
            this.http_post('mark', mdnurl+'&_flag=mdnsent');
        }
        break;
@@ -213,9 +246,11 @@
      case 'addressbook':
        if (this.gui_objects.contactslist)
          {
          this.contact_list = new rcube_list_widget(this.gui_objects.contactslist, {multiselect:true, draggable:false, keyboard:true});
          this.contact_list = new rcube_list_widget(this.gui_objects.contactslist, {multiselect:true, draggable:true, keyboard:true});
          this.contact_list.addEventListener('keypress', function(o){ p.contactlist_keypress(o); });
          this.contact_list.addEventListener('select', function(o){ p.contactlist_select(o); });
          this.contact_list.addEventListener('dragstart', function(o){ p.drag_active = true; });
          this.contact_list.addEventListener('dragend', function(o){ p.drag_active = false; });
          this.contact_list.init();
          if (this.env.cid)
@@ -231,17 +266,19 @@
          }
        this.set_page_buttons();
        if (this.env.address_sources && !this.env.address_sources[this.env.source].readonly)
          this.enable_command('add', true);
        if (this.env.cid)
          this.enable_command('show', 'edit', true);
        if ((this.env.action=='add' || this.env.action=='edit') && this.gui_objects.editform)
          this.enable_command('save', true);
        else
          this.enable_command('search', 'reset-search', 'moveto', true);
        this.enable_command('list', 'add', true);
        // this.enable_command('ldappublicsearch', this.env.ldappublicsearch);
        this.enable_command('list', true);
        break;
@@ -268,11 +305,16 @@
            this.identity_list.highlight_row(this.env.iid);
          }
        if (this.gui_objects.subscriptionlist)
          this.init_subscription_list();
        break;
      case 'login':
        var input_user = rcube_find_object('_user');
        var input_pass = rcube_find_object('_pass');
        var input_user = rcube_find_object('rcmloginuser');
        var input_pass = rcube_find_object('rcmloginpwd');
        if (input_user)
          input_user.onkeyup = function(e){ return rcmail.login_user_keyup(e); };
        if (input_user && input_user.value=='')
          input_user.focus();
        else if (input_pass)
@@ -315,9 +357,9 @@
  this.start_keepalive = function()
    {
    if (this.env.keep_alive && !this.env.framed && this.task=='mail' && this.gui_objects.messagelist)
      this._int = setInterval(this.ref+'.check_for_recent()', this.env.keep_alive * 1000);
      this._int = setInterval(function(){ ref.check_for_recent(); }, this.env.keep_alive * 1000);
    else if (this.env.keep_alive && !this.env.framed && this.task!='login')
      this._int = setInterval(this.ref+'.send_keep_alive()', this.env.keep_alive * 1000);
      this._int = setInterval(function(){ ref.send_keep_alive(); }, this.env.keep_alive * 1000);
    }
@@ -326,9 +368,9 @@
    var uid = row.uid;
    if (uid && this.env.messages[uid])
      {
      row.deleted = this.env.messages[uid].deleted;
      row.unread = this.env.messages[uid].unread;
      row.replied = this.env.messages[uid].replied;
      row.deleted = this.env.messages[uid].deleted ? true : false;
      row.unread = this.env.messages[uid].unread ? true : false;
      row.replied = this.env.messages[uid].replied ? true : false;
      }
    // set eventhandler to message icon
@@ -377,7 +419,7 @@
      this.set_caret2start(input_message);
    // get summary of all field values
    this.cmp_hash = this.compose_field_hash();
    this.compose_field_hash(true);
 
    // start the auto-save timer
    this.auto_save_start();
@@ -385,18 +427,19 @@
  this.init_address_input_events = function(obj)
    {
    var handler = function(e){ return rcube_webmail_client.ksearch_keypress(e,this); };
    var handler2 = function(e){ return rcube_webmail_client.ksearch_blur(e,this); };
    if (bw.safari)
      obj.addEventListener('keydown', handler, false);
    else if (bw.mz)
      {
      obj.addEventListener('keypress', handler, false);
    var handler = function(e){ return ref.ksearch_keypress(e,this); };
    var handler2 = function(e){ return ref.ksearch_blur(e,this); };
    if (obj.addEventListener)
    {
      obj.addEventListener(bw.safari ? 'keydown' : 'keypress', handler, false);
      obj.addEventListener('blur', handler2, false);
      }
    else if (bw.ie)
    }
    else
    {
      obj.onkeydown = handler;
      obj.onblur = handler2;
    }
    obj.setAttribute('autocomplete', 'off');       
    };
@@ -445,7 +488,7 @@
        break;
      case 'logout':
        this.goto_url('logout');
        this.goto_url('logout', true);
        break;      
      // commands to switch task
@@ -460,13 +503,22 @@
      case 'list':
        if (this.task=='mail')
          {
          if (this.env.search_request<0 || (this.env.search_request && props != this.env.mailbox))
          if (this.env.search_request<0 || (props != '' && (this.env.search_request && props != this.env.mailbox)))
            this.reset_qsearch();
          this.list_mailbox(props);
          if (this.env.trash_mailbox)
            this.set_alttext('delete', this.env.mailbox != this.env.trash_mailbox ? 'movemessagetotrash' : 'deletemessage');
          }
        else if (this.task=='addressbook')
          this.list_contacts();
          {
          if (this.env.search_request<0 || (this.env.search_request && props != this.env.source))
            this.reset_qsearch();
          this.list_contacts(props);
          this.enable_command('add', (this.env.address_sources && !this.env.address_sources[props].readonly));
          }
        break;
@@ -555,18 +607,6 @@
      case 'add':
        if (this.task=='addressbook')
          this.load_contact(0, 'add');
        /* LDAP stuff, has to be re-written with new address book
          if (!window.frames[this.env.contentframe].rcmail)
            this.load_contact(0, 'add');
          else
            {
            if (window.frames[this.env.contentframe].rcmail.selection.length)
              this.add_ldap_contacts();
            else
              this.load_contact(0, 'add');
            }
        */
        else if (this.task=='settings')
          {
          this.identity_list.clear_selection();
@@ -634,9 +674,17 @@
      // mail task commands
      case 'move':
      case 'moveto':
        this.move_messages(props);
        if (this.task == 'mail')
          this.move_messages(props);
        else if (this.task == 'addressbook' && this.drag_active)
          this.copy_contact(null, props);
        break;
      case 'mark':
        if (props)
          this.mark_message(props);
        break;
      case 'toggle_status':
        if (props && !props._row)
          break;
@@ -647,7 +695,7 @@
        if (props._row.uid)
          {
          uid = props._row.uid;
          this.message_list.dont_select = true;
          // toggle read/unread
          if (this.message_list.rows[uid].deleted) {
            flag = 'undelete';
@@ -664,20 +712,22 @@
        break;
      case 'load-attachment':
        var qstring = '_mbox='+this.env.mailbox+'&_uid='+this.env.uid+'&_part='+props.part;
        var qstring = '_mbox='+urlencode(this.env.mailbox)+'&_uid='+this.env.uid+'&_part='+props.part;
        
        // open attachment in frame if it's of a supported mimetype
        if (this.env.uid && props.mimetype && find_in_array(props.mimetype, this.mimetypes)>=0)
          {
          if (props.mimetype == 'text/html')
            qstring += '&_safe=1';
          this.attachment_win = window.open(this.env.comm_path+'&_action=get&'+qstring+'&_frame=1', 'rcubemailattachment');
          if (this.attachment_win)
            {
            setTimeout(this.ref+'.attachment_win.focus()', 10);
            setTimeout(function(){ ref.attachment_win.focus(); }, 10);
            break;
            }
          }
        this.goto_url('get', qstring+'&_download=1');
        this.goto_url('get', qstring+'&_download=1', false);
        break;
        
      case 'select-all':
@@ -720,55 +770,42 @@
          var uid;
          if (uid = this.get_single_uid())
            url += '&_draft_uid='+uid+'&_mbox='+urlencode(this.env.mailbox);
          }
          }
        // modify url if we're in addressbook
        else if (this.task=='addressbook')
          {
          url = this.get_task_url('mail', url);
          var a_cids = new Array();
          // switch to mail compose step directly
          if (props && props.indexOf('@') > 0)
          {
            url = this.get_task_url('mail', url);
            this.redirect(url + '&_to='+urlencode(props));
            break;
          }
          
          // use contact_id passed as command parameter
          var a_cids = new Array();
          if (props)
            a_cids[a_cids.length] = props;
          // get selected contacts
          else
          else if (this.contact_list)
            {
            var selection = this.contact_list.get_selection();
            for (var n=0; n<selection.length; n++)
              a_cids[a_cids.length] = selection[n];
            /* LDAP stuff, has to be re-written with new address book
            if (!window.frames[this.env.contentframe].rcmail.selection.length)
              {
              for (var n=0; n<selection.length; n++)
                a_cids[a_cids.length] = selection[n];
              }
            else
              {
              var frameRcmail = window.frames[this.env.contentframe].rcmail;
              // get the email address(es)
              for (var n=0; n<frameRcmail.selection.length; n++)
                a_cids[a_cids.length] = frameRcmail.ldap_contact_rows[frameRcmail.selection[n]].obj.cells[1].innerHTML;
              }
            */
            }
          if (a_cids.length)
            url += '&_to='+a_cids.join(',');
          else
            break;
            this.http_request('mailto', '_cid='+urlencode(a_cids.join(','))+'&_source='+urlencode(this.env.source), true);
          break;
          }
        else if (props)
           url += '&_to='+urlencode(props);
        // don't know if this is necessary...
        url = url.replace(/&_framed=1/, "");
        this.set_busy(true);
        // need parent in case we are coming from the contact frame
        if (this.env.framed)
          parent.location.href = url;
        else
          location.href = url;
        this.redirect(url);
        break;
        
      case 'spellcheck':
@@ -794,6 +831,7 @@
        this.set_busy(true, 'savingmessage');
        var form = this.gui_objects.messageform;
        form.target = "savetarget";
        form._draft.value = '1';
        form.submit();
        break;
@@ -803,7 +841,7 @@
        if (!this.check_compose_input())
          break;
        // Reset the auto-save timer
        self.clearTimeout(this.save_timer);
@@ -848,20 +886,24 @@
      case 'print':
        var uid;
        if (uid = this.get_single_uid())
          {
          this.printwin = window.open(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : ''));
        {
          ref.printwin = window.open(this.env.comm_path+'&_action=print&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)+(this.env.safemode ? '&_safe=1' : ''));
          if (this.printwin)
            setTimeout(this.ref+'.printwin.focus()', 20);
          {
            setTimeout(function(){ ref.printwin.focus(); }, 20);
            if (this.env.action != 'show')
              this.toggle_read_status('read', [uid]);
          }
        }
        break;
      case 'viewsource':
        var uid;
        if (uid = this.get_single_uid())
          {
          this.sourcewin = window.open(this.env.comm_path+'&_action=viewsource&_uid='+this.env.uid+'&_mbox='+urlencode(this.env.mailbox));
          {
          ref.sourcewin = window.open(this.env.comm_path+'&_action=viewsource&_uid='+this.env.uid+'&_mbox='+urlencode(this.env.mailbox));
          if (this.sourcewin)
            setTimeout(this.ref+'.sourcewin.focus()', 20);
            setTimeout(function(){ ref.sourcewin.focus(); }, 20);
          }
        break;
@@ -869,30 +911,26 @@
        this.add_contact(props);
        break;
      
      // mail quicksearch
      // quicksearch
      case 'search':
        if (!props && this.gui_objects.qsearchbox)
          props = this.gui_objects.qsearchbox.value;
        if (props)
          this.qsearch(urlencode(props), this.env.mailbox);
        break;
        {
          this.qsearch(props);
          break;
        }
      // reset quicksearch        
      case 'reset-search':
        var s = this.env.search_request;
        this.reset_qsearch();
        
        if (s)
        if (s && this.env.mailbox)
          this.list_mailbox(this.env.mailbox);
        else if (s && this.task == 'addressbook')
          this.list_contacts(this.env.source);
        break;
      // ldap search
      case 'ldappublicsearch':
        if (this.gui_objects.ldappublicsearchform)
          this.gui_objects.ldappublicsearchform.submit();
        else
          this.ldappublicsearch(command);
        break;
      // user settings commands
@@ -928,8 +966,7 @@
        break;
      case 'delete-folder':
        if (confirm(this.get_label('deletefolderconfirm')))
          this.delete_folder(props);
        this.delete_folder(props);
        break;
      }
@@ -968,7 +1005,7 @@
      this.display_message(msg, 'loading', true);
      }
    else if (!a && this.busy)
    else if (!a)
      this.hide_message();
    this.busy = a;
@@ -983,7 +1020,7 @@
    // set timer for requests
    if (a && this.env.request_timeout)
      this.request_timer = setTimeout(this.ref+'.request_timed_out()', this.env.request_timeout * 1000);
      this.request_timer = setTimeout(function(){ ref.request_timed_out(); }, this.env.request_timeout * 1000);
    };
@@ -1007,8 +1044,7 @@
    if (task=='mail')
      url += '&_mbox=INBOX';
    this.set_busy(true);
    location.href = url;
    this.redirect(url);
    };
@@ -1042,21 +1078,29 @@
      this.contact_list.blur();
    };
  this.focus_folder = function(id)
    {
    var li;
    if (this.drag_active && this.check_droptarget(id) && (li = this.get_folder_li(id)))
      this.set_classname(li, 'droptarget', true);
    }
  // onmouseup handler for mailboxlist item
  this.mbox_mouse_up = function(mbox)
  this.unfocus_folder = function(id)
    {
    var li;
    if (this.drag_active && (li = this.get_folder_li(id)))
      this.set_classname(li, 'droptarget', false);
    }
  // onmouseup handler for folder list item
  this.folder_mouse_up = function(id)
    {
    if (this.drag_active)
      {
      this.unfocus_mailbox(mbox);
      this.command('moveto', mbox);
      this.unfocus_folder(id);
      this.command('moveto', id);
      }
    else
      this.command('list', mbox);
    return false;
    };
  this.click_on_list = function(e)
    {
@@ -1066,7 +1110,7 @@
        this.contact_list.focus();
    var mbox_li;
    if (mbox_li = this.get_mailbox_li())
    if (mbox_li = this.get_folder_li())
      this.set_classname(mbox_li, 'unfocused', true);
    rcube_event.cancel(e);
@@ -1079,22 +1123,25 @@
      clearTimeout(this.preview_timer);
    var selected = list.selection.length==1;
    // Hide certain command buttons when Drafts folder is selected
    if (this.env.mailbox == this.env.drafts_mailbox)
      {
      this.enable_command('reply', 'reply-all', 'forward', false);
      this.enable_command('show', selected);
      this.enable_command('delete', 'moveto', list.selection.length>0 ? true : false);
      this.enable_command('delete', 'moveto', 'mark', (list.selection.length > 0 ? true : false));
      }
    else
      {
      this.enable_command('show', 'reply', 'reply-all', 'forward', 'print', selected);
      this.enable_command('delete', 'moveto', list.selection.length>0 ? true : false);
      // start timer for message preview (wait for double click)
      if (selected && this.env.contentframe)
        this.preview_timer = setTimeout(this.ref+'.msglist_get_preview()', this.dblclick_time + 10);
      else if (this.env.contentframe)
        this.show_messageframe(false);
      this.enable_command('delete', 'moveto', 'mark', (list.selection.length > 0 ? true : false));
      }
    // start timer for message preview (wait for double click)
    if (selected && this.env.contentframe && !list.multi_selecting)
      this.preview_timer = setTimeout(function(){ ref.msglist_get_preview(); }, this.dblclick_time + 10);
    else if (this.env.contentframe)
      this.show_contentframe(false);
    };
@@ -1117,16 +1164,29 @@
      this.command('show');
    else if (list.key_pressed == list.DELETE_KEY)
      this.command('delete');
    else
      list.shiftkey = false;
    };
  this.msglist_get_preview = function()
  {
    var uid = this.get_single_uid();
    if (uid && this.env.contentframe)
    if (uid && this.env.contentframe && !this.drag_active)
      this.show_message(uid, false, true);
    else if (this.env.contentframe)
      this.show_messageframe(false);
      this.show_contentframe(false);
  };
  this.check_droptarget = function(id)
  {
    if (this.task == 'mail')
      return (id != this.env.mailbox);
    else if (this.task == 'addressbook')
      return (id != this.env.source && this.env.address_sources[id] && !this.env.address_sources[id].readonly);
    else if (this.task == 'settings')
      return (id != this.env.folder);
  };
@@ -1150,11 +1210,15 @@
    if (safe)
      add_url = '&_safe=1';
    // also send search request to get the right messages
    if (this.env.search_request)
      add_url += '&_search='+this.env.search_request;
    if (id)
      {
      var url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.env.mailbox)+add_url;
      if (action == 'preview' && String(target.location.href).indexOf(url) >= 0)
        this.show_messageframe(true);
        this.show_contentframe(true);
      else
        {
        this.set_busy(true, 'loading');
@@ -1164,14 +1228,15 @@
    };
  this.show_messageframe = function(show)
  this.show_contentframe = function(show)
    {
    var frm;
    if (this.env.contentframe && (frm = rcube_find_object(this.env.contentframe)))
      {
      if (window.frames[this.env.contentframe] && !show)
        window.frames[this.env.contentframe].location.href = 'program/blank.gif';
      frm.style.display = show ? 'block' : 'none';
      if (!show && window.frames[this.env.contentframe] && frames[this.env.contentframe].location.href.indexOf(this.env.blankpage)<0)
        frames[this.env.contentframe].location.href = this.env.blankpage;
      if (!bw.safari)
        frm.style.display = show ? 'block' : 'none';
      }
      
    if (!show && this.busy)
@@ -1198,7 +1263,7 @@
      if (this.task=='mail')
        this.list_mailbox(this.env.mailbox, page);
      else if (this.task=='addressbook')
        this.list_contacts(page);
        this.list_contacts(this.env.source, page);
      }
    };
@@ -1216,22 +1281,26 @@
    // add sort to url if set
    if (sort)
      add_url += '&_sort=' + sort;
    // also send search request to get the right messages
    if (this.env.search_request)
      add_url += '&_search='+this.env.search_request;
      
    // set page=1 if changeing to another mailbox
    if (!page && mbox != this.env.mailbox)
      {
      page = 1;
      add_url += '&_refresh=1';
      this.env.current_page = page;
      this.message_list.clear_selection();
      this.show_messageframe(false);
      if (this.message_list)
        this.message_list.clear_selection();
      this.show_contentframe(false);
      }
    
    // also send search request to get the right messages
    if (this.env.search_request)
      add_url += '&_search='+this.env.search_request;
    this.select_mailbox(mbox);
    if (mbox != this.env.mailbox || (mbox == this.env.mailbox && !page && !sort))
      add_url += '&_refresh=1';
    this.select_folder(mbox, this.env.mailbox);
    this.env.mailbox = mbox;
    // load message list remotely
    if (this.gui_objects.messagelist)
@@ -1283,7 +1352,7 @@
    // send request to server
    var url = '_mbox='+urlencode(mbox);
    this.http_request('expunge', url+add_url, lock);
    this.http_post('expunge', url+add_url, lock);
    };
@@ -1305,52 +1374,20 @@
    // send request to server
    var url = '_mbox='+urlencode(mbox);
    this.http_request('purge', url+add_url, lock);
    this.http_post('purge', url+add_url, lock);
    return true;
    };
  this.focus_mailbox = function(mbox)
    {
    var mbox_li;
    if (this.drag_active && mbox != this.env.mailbox && (mbox_li = this.get_mailbox_li(mbox)))
      this.set_classname(mbox_li, 'droptarget', true);
    }
  this.unfocus_mailbox = function(mbox)
    {
    var mbox_li;
    if (this.drag_active && (mbox_li = this.get_mailbox_li(mbox)))
      this.set_classname(mbox_li, 'droptarget', false);
    }
  
  // move selected messages to the specified mailbox
  this.move_messages = function(mbox)
    {
    // exit if current or no mailbox specified or if selection is empty
    if (!mbox || !this.env.uid || mbox==this.env.mailbox)
      {
      if (!this.message_list || !this.message_list.get_selection().length)
        return;
      }
    var a_uids = new Array();
    if (this.env.uid)
      a_uids[a_uids.length] = this.env.uid;
    else
      {
      var selection = this.message_list.get_selection();
      for (var n=0, id; n<selection.length; n++)
        {
        id = selection[n];
        a_uids[a_uids.length] = id;
        this.message_list.remove_row(id);
        }
        this.show_messageframe(false);
      }
    if (!mbox || mbox == this.env.mailbox || (!this.env.uid && (!this.message_list || !this.message_list.get_selection().length)))
      return;
    var lock = false;
    var add_url = '&_target_mbox='+urlencode(mbox)+'&_from='+(this.env.action ? this.env.action : '');
    // show wait message
    if (this.env.action=='show')
@@ -1358,22 +1395,70 @@
      lock = true;
      this.set_busy(true, 'movingmessage');
      }
    else
      this.show_contentframe(false);
    // send request to server
    this.http_request('moveto', '_uid='+a_uids.join(',')+'&_mbox='+urlencode(this.env.mailbox)+'&_target_mbox='+urlencode(mbox)+'&_from='+(this.env.action ? this.env.action : ''), lock);
    // Hide message command buttons until a message is selected
    this.enable_command('reply', 'reply-all', 'forward', 'delete', 'mark', 'print', false);
    this._with_selected_messages('moveto', lock, add_url);
    };
  // delete selected messages from the current mailbox
  this.delete_messages = function()
    {
    var selection = this.message_list ? this.message_list.get_selection() : new Array();
    // exit if no mailbox specified or if selection is empty
    if (!this.env.uid && !selection.length)
        return;
    // if there is a trash mailbox defined and we're not currently in it:
    if (this.env.trash_mailbox && String(this.env.mailbox).toLowerCase() != String(this.env.trash_mailbox).toLowerCase())
      {
      // if shift was pressed delete it immediately
      if (this.message_list && this.message_list.shiftkey)
        {
        if (confirm(this.get_label('deletemessagesconfirm')))
          this.permanently_remove_messages();
        }
      else
        this.move_messages(this.env.trash_mailbox);
      }
    // if there is a trash mailbox defined but we *are* in it:
    else if (this.env.trash_mailbox && String(this.env.mailbox).toLowerCase() == String(this.env.trash_mailbox).toLowerCase())
      this.permanently_remove_messages();
    // if there isn't a defined trash mailbox and the config is set to flag for deletion
    else if (!this.env.trash_mailbox && this.env.flag_for_deletion)
      {
      this.mark_message('delete');
      if(this.env.action=="show")
        this.command('nextmessage','',this);
      else if (selection.length == 1)
        this.message_list.select_next();
      }
    // if there isn't a defined trash mailbox and the config is set NOT to flag for deletion
    else if (!this.env.trash_mailbox)
      this.permanently_remove_messages();
  };
  // delete the selected messages permanently
  this.permanently_remove_messages = function()
    {
    // exit if no mailbox specified or if selection is empty
    if (!this.env.uid)
      {
      if (!this.message_list || !this.message_list.get_selection().length)
        return;
      }
    if (!this.env.uid && (!this.message_list || !this.message_list.get_selection().length))
      return;
    this.show_contentframe(false);
    this._with_selected_messages('delete', false, '&_from='+(this.env.action ? this.env.action : ''));
    };
  // Send a specifc request with UIDs of all selected messages
  // @private
  this._with_selected_messages = function(action, lock, add_url)
    {
    var a_uids = new Array();
    if (this.env.uid)
      a_uids[a_uids.length] = this.env.uid;
    else
@@ -1384,54 +1469,17 @@
        {
        id = selection[n];
        a_uids[a_uids.length] = id;
        this.message_list.remove_row(id);
        this.message_list.remove_row(id, (n == selection.length-1));
        }
      this.message_list.select_next();
      }
      
    // send request to server
    this.http_request('delete', '_uid='+a_uids.join(',')+'&_mbox='+urlencode(this.env.mailbox)+'&_from='+(this.env.action ? this.env.action : ''));
  }
  // delete selected messages from the current mailbox
  this.delete_messages = function()
    {
    // exit if no mailbox specified or if selection is empty
    if (!this.env.uid)
      {
      if (!this.message_list || !this.message_list.get_selection().length)
        return;
      }
    // also send search request to get the right messages
    if (this.env.search_request)
      add_url += '&_search='+this.env.search_request;
    // if there is a trash mailbox defined and we're not currently in it:
    if (this.env.trash_mailbox && String(this.env.mailbox).toLowerCase()!=String(this.env.trash_mailbox).toLowerCase())
      // if shift was pressed delete it immediately
      if (this.message_list && this.message_list.shiftkey)
        {
        if (confirm(this.get_label('deletemessagesconfirm')))
          this.permanently_remove_messages();
        }
      else
        this.move_messages(this.env.trash_mailbox);
    // if there is a trash mailbox defined but we *are* in it:
    else if (this.env.trash_mailbox && String(this.env.mailbox).toLowerCase() == String(this.env.trash_mailbox).toLowerCase())
      this.permanently_remove_messages();
    // if there isn't a defined trash mailbox and the config is set to flag for deletion
    else if (!this.env.trash_mailbox && this.env.flag_for_deletion)
      {
      flag = 'delete';
      this.mark_message(flag);
      if(this.env.action=="show")
        this.command('nextmessage','',this);
      else if (selection.length == 1)
        this.message_list.select_next();
      }
    // if there isn't a defined trash mailbox and the config is set NOT to flag for deletion
    else if (!this.env.trash_mailbox)
      this.permanently_remove_messages();
  };
    // send request to server
    this.http_post(action, '_uid='+a_uids.join(',')+'&_mbox='+urlencode(this.env.mailbox)+add_url, lock);
    };
  // set a specific flag to one or more messages
@@ -1444,13 +1492,13 @@
      a_uids[0] = uid;
    else if (this.env.uid)
      a_uids[0] = this.env.uid;
    else
    else if (this.message_list)
      {
      var id;
      for (var n=0; n<selection.length; n++)
      for (var id, n=0; n<selection.length; n++)
        {
        id = selection[n];
        if ((flag=='read' && this.message_list.rows[id].unread) || (flag=='unread' && !this.message_list.rows[id].unread))
        if ((flag=='read' && this.message_list.rows[id].unread) || (flag=='unread' && !this.message_list.rows[id].unread)
            || (flag=='delete' && !this.message_list.rows[id].deleted) || (flag=='undelete' && this.message_list.rows[id].deleted))
          a_uids[a_uids.length] = id;
        }
      }
@@ -1477,12 +1525,16 @@
  {
    // mark all message rows as read/unread
    var icn_src;
    var res_uids = new Array();
    var rows = this.message_list.rows;
    for (var i=0; i<a_uids.length; i++)
      {
      uid = a_uids[i];
      if (rows[uid])
      // check if flag isn't set yet
      if (rows[uid] && ((flag=='unread' && !rows[uid].unread) || (flag=='read' && rows[uid].unread)))
        {
        res_uids[res_uids.length] = uid;
        rows[uid].unread = (flag=='unread' ? true : false);
        
        if (rows[uid].classname.indexOf('unread')<0 && rows[uid].unread)
@@ -1508,8 +1560,9 @@
          rows[uid].icon.src = icn_src;
        }
      }
    this.http_request('mark', '_uid='+a_uids.join(',')+'&_flag='+flag);
    if (res_uids.length)
      this.http_post('mark', '_uid='+res_uids.join(',')+'&_flag='+flag);
  };
  
  // mark all message rows as deleted/undeleted
@@ -1523,7 +1576,8 @@
      return false;
    var rows = this.message_list.rows;
    if (a_uids.length==1) {
    if (a_uids.length==1)
    {
      if (rows[a_uids[0]] && rows[a_uids[0]].classname.indexOf('deleted') < 0)
        this.flag_as_deleted(a_uids);
      else
@@ -1533,10 +1587,12 @@
    }
    
    var all_deleted = true;
    for (var i=0; i<a_uids.length; i++) {
    for (var i=0; i<a_uids.length; i++)
    {
      uid = a_uids[i];
      if (rows[uid]) {
        if (rows[uid].classname.indexOf('deleted')<0) {
        if (rows[uid].classname.indexOf('deleted')<0)
        {
          all_deleted = false;
          break;
        }
@@ -1561,12 +1617,14 @@
    var icn_src;
    var rows = this.message_list.rows;
      
    for (var i=0; i<a_uids.length; i++) {
    for (var i=0; i<a_uids.length; i++)
    {
      uid = a_uids[i];
      if (rows[uid]) {
        rows[uid].deleted = false;
        
        if (rows[uid].classname.indexOf('deleted') > 0) {
        if (rows[uid].classname.indexOf('deleted') > 0)
        {
          rows[uid].classname = rows[uid].classname.replace(/\s*deleted/, '');
          this.set_classname(rows[uid].obj, 'deleted', false);
        }
@@ -1581,7 +1639,7 @@
      }
    }
    this.http_request('mark', '_uid='+a_uids.join(',')+'&_flag=undelete');
    this.http_post('mark', '_uid='+a_uids.join(',')+'&_flag=undelete');
    return true;
  };
@@ -1593,7 +1651,8 @@
      return false;
    var rows = this.message_list.rows;
    for (var i=0; i<a_uids.length; i++) {
    for (var i=0; i<a_uids.length; i++)
    {
      uid = a_uids[i];
      if (rows[uid]) {
        rows[uid].deleted = true;
@@ -1607,22 +1666,29 @@
      }
    }
    this.http_request('mark', '_uid='+a_uids.join(',')+'&_flag=delete');
    this.http_post('mark', '_uid='+a_uids.join(',')+'&_flag=delete');
    return true;  
  };
  this.get_mailbox_li = function(mbox)
  /*********************************************************/
  /*********           login form methods          *********/
  /*********************************************************/
  // handler for keyboard events on the _user field
  this.login_user_keyup = function(e)
  {
    var key = rcube_event.get_keycode(e);
    var elm;
    // enter
    if ((key==13) && (elm = rcube_find_object('_pass')))
    {
    if (this.gui_objects.mailboxlist)
      {
      mbox = String((mbox ? mbox : this.env.mailbox)).toLowerCase().replace(this.mbox_expression, '');
      return document.getElementById('rcmbx'+mbox);
      }
    return null;
    };
      elm.focus();
      return false;
    }
  };
  /*********************************************************/
  /*********        message compose methods        *********/
@@ -1634,11 +1700,14 @@
    {
    // check input fields
    var input_to = rcube_find_object('_to');
    var input_cc = rcube_find_object('_cc');
    var input_bcc = rcube_find_object('_bcc');
    var input_subject = rcube_find_object('_subject');
    var input_message = rcube_find_object('_message');
    // check for empty recipient
    if (input_to && !rcube_check_email(input_to.value, true))
    var recipients = input_to.value ? input_to.value : (input_cc.value ? input_cc.value : input_bcc.value);
    if (!rcube_check_email(recipients.replace(/^\s+/, '').replace(/[\s,;]+$/, ''), true))
      {
      alert(this.get_label('norecipientwarning'));
      input_to.focus();
@@ -1663,13 +1732,10 @@
      }
    // check for empty body
    if ((input_message.value=='')&&(tinyMCE.getContent()==''))
    if ((input_message.value == '' && (!window.tinyMCE || tinyMCE.getContent() == '')) && !confirm(this.get_label('nobodywarning')))
      {
      if (!confirm(this.get_label('nobodywarning')))
        {
        input_message.focus();
        return false;
        }
      input_message.focus();
      return false;
      }
    return true;
@@ -1678,19 +1744,29 @@
  this.set_spellcheck_state = function(s)
    {
  this.spellcheck_ready = (s=='check_spelling' || s=='ready');
    this.spellcheck_ready = (s=='check_spelling' || s=='ready');
    this.enable_command('spellcheck', this.spellcheck_ready);
  };
    };
  this.set_draft_id = function(id)
    {
    var f;
    if (f = rcube_find_object('_draft_saveid'))
      f.value = id;
    };
  this.auto_save_start = function()
    {
    if (this.env.draft_autosave)
      this.save_timer = self.setTimeout(this.ref+'.command("savedraft")', this.env.draft_autosave * 1000);
      this.save_timer = self.setTimeout(function(){ ref.command("savedraft"); }, this.env.draft_autosave * 1000);
    // Unlock interface now that saving is complete
    this.busy = false;
    };
  this.compose_field_hash = function()
  this.compose_field_hash = function(save)
    {
    // check input fields
    var input_to = rcube_find_object('_to');
@@ -1710,7 +1786,10 @@
      str += input_subject.value+':';
    if (input_message && input_message.value)
      str += input_message.value;
    if (save)
      this.cmp_hash = str;
    return str;
    };
    
@@ -1761,6 +1840,10 @@
      var eid = tinyMCE.getEditorId('_message');
      // editor is a TinyMCE_Control object
      var editor = tinyMCE.getInstanceById(eid);
      // if this is null, we should exit
      if (editor == null) {
        return false;
      }
      var msgDoc = editor.getDoc();
      var msgBody = msgDoc.body;
@@ -1815,8 +1898,11 @@
      }
      
    // clear upload form
    if (!a && this.gui_objects.attachmentform && this.gui_objects.attachmentform!=this.gui_objects.messageform)
      this.gui_objects.attachmentform.reset();
   try {
      if (!a && this.gui_objects.attachmentform != this.gui_objects.messageform)
         this.gui_objects.attachmentform.reset();
   }
   catch(e){}  // ignore errors
    
    return true;  
    };
@@ -1825,7 +1911,6 @@
  // upload attachment file
  this.upload_file = function(form)
    {
    if (!form)
      return false;
      
@@ -1901,7 +1986,7 @@
  this.remove_attachment = function(name)
    {
    if (name)
      this.http_request('remove-attachment', '_file='+urlencode(name));
      this.http_post('remove-attachment', '_file='+urlencode(name));
    return true;
    };
@@ -1910,19 +1995,27 @@
  this.add_contact = function(value)
    {
    if (value)
      this.http_request('addcontact', '_address='+value);
      this.http_post('addcontact', '_address='+value);
    
    return true;
    };
  // send remote request to search mail
  this.qsearch = function(value, mbox)
  // send remote request to search mail or contacts
  this.qsearch = function(value)
    {
    if (value && mbox)
    if (value != '')
      {
      this.message_list.clear();
      if (this.message_list)
        this.message_list.clear();
      else if (this.contact_list) {
        this.contact_list.clear(true);
        this.show_contentframe(false);
      }
      // reset vars
      this.env.current_page = 1;
      this.set_busy(true, 'searching');
      this.http_request('search', '_search='+value+'&_mbox='+mbox, true);
      this.http_request('search', '_q='+urlencode(value)+(this.env.mailbox ? '&_mbox='+urlencode(this.env.mailbox) : '')+(this.env.source ? '&_source='+urlencode(this.env.source) : ''), true);
      }
    return true;
    };
@@ -1959,11 +2052,9 @@
    if (this.ksearch_timer)
      clearTimeout(this.ksearch_timer);
    if (!e)
      e = window.event;
    var highlight;
    var key = e.keyCode ? e.keyCode : e.which;
    var key = rcube_event.get_keycode(e);
    var mod = rcube_event.get_modifier(e);
    switch (key)
      {
@@ -1982,7 +2073,6 @@
        if (highlight && (next = dir ? highlight.previousSibling : highlight.nextSibling))
          {
          highlight.removeAttribute('id');
          //highlight.removeAttribute('class');
          this.set_classname(highlight, 'selected', false);
          }
@@ -1993,42 +2083,21 @@
          this.ksearch_selected = next._rcm_id;
          }
        if (e.preventDefault)
          e.preventDefault();
        return false;
        return rcube_event.cancel(e);
      case 9:  // tab
        if(e.shiftKey)
        if(mod == SHIFT_KEY)
          break;
      case 13:  // enter     
        if (this.ksearch_selected===null || !this.ksearch_input || !this.ksearch_value)
          break;
        // get cursor pos
        var inp_value = this.ksearch_input.value.toLowerCase();
        var cpos = this.get_caret_pos(this.ksearch_input);
        var p = inp_value.lastIndexOf(this.ksearch_value, cpos);
        // replace search string with full address
        var pre = this.ksearch_input.value.substring(0, p);
        var end = this.ksearch_input.value.substring(p+this.ksearch_value.length, this.ksearch_input.value.length);
        var insert = this.env.contacts[this.ksearch_selected]+', ';
        this.ksearch_input.value = pre + insert + end;
        //this.ksearch_input.value = this.ksearch_input.value.substring(0, p)+insert;
        // set caret to insert pos
        cpos = p+insert.length;
        if (this.ksearch_input.setSelectionRange)
          this.ksearch_input.setSelectionRange(cpos, cpos);
        // hide ksearch pane
        // insert selected address and hide ksearch pane
        this.insert_recipient(this.ksearch_selected);
        this.ksearch_hide();
        if (e.preventDefault)
          e.preventDefault();
        return false;
        return rcube_event.cancel(e);
      case 27:  // escape
        this.ksearch_hide();
@@ -2037,11 +2106,35 @@
      }
    // start timer
    this.ksearch_timer = setTimeout(this.ref+'.ksearch_get_results()', 200);
    this.ksearch_timer = setTimeout(function(){ ref.ksearch_get_results(); }, 200);
    this.ksearch_input = obj;
    
    return true;
    };
  this.insert_recipient = function(id)
  {
    if (!this.env.contacts[id] || !this.ksearch_input)
      return;
    // get cursor pos
    var inp_value = this.ksearch_input.value.toLowerCase();
    var cpos = this.get_caret_pos(this.ksearch_input);
    var p = inp_value.lastIndexOf(this.ksearch_value, cpos);
    // replace search string with full address
    var pre = this.ksearch_input.value.substring(0, p);
    var end = this.ksearch_input.value.substring(p+this.ksearch_value.length, this.ksearch_input.value.length);
    var insert  = this.env.contacts[id]+', ';
    this.ksearch_input.value = pre + insert + end;
    // set caret to insert pos
    cpos = p+insert.length;
    if (this.ksearch_input.setSelectionRange)
      this.ksearch_input.setSelectionRange(cpos, cpos);
  };
  // address search processor
@@ -2109,6 +2202,8 @@
        {
        li = document.createElement('LI');
        li.innerHTML = a_results[i].replace(/</, '&lt;').replace(/>/, '&gt;');
        li.onmousedown = function(e){ ref.insert_recipient(this._rcm_id); ref.ksearch_pane.show(0); return rcube_event.cancel(e); };
        li.style.cursor = 'pointer';
        li._rcm_id = a_result_ids[i];
        ul.appendChild(li);
        }
@@ -2134,9 +2229,6 @@
        this.ksearch_selected = a_result_ids[0];
        }
      // resize the containing layer to fit the list
      //this.ksearch_pane.resize(ul.offsetWidth, ul.offsetHeight);
      // move the results pane right under the input box and make it visible
      var pos = rcube_get_object_pos(this.ksearch_input);
      this.ksearch_pane.move(pos.x, pos.y+this.ksearch_input.offsetHeight);
@@ -2184,33 +2276,48 @@
  this.contactlist_select = function(list)
    {
      var id, frame;
      if (this.preview_timer)
        clearTimeout(this.preview_timer);
      var id, frame, ref = this;
      if (id = list.get_single_selection())
        this.load_contact(id, 'show');
      else if (frame = document.getElementById(this.env.contentframe))
        frame.style.visibility = 'hidden';
        this.preview_timer = setTimeout(function(){ ref.load_contact(id, 'show'); }, this.dblclick_time + 10);
      else if (this.env.contentframe)
        this.show_contentframe(false);
      this.enable_command('edit', id?true:false);
      this.enable_command('compose', list.selection.length > 0);
      this.enable_command('delete', list.selection.length && this.env.address_sources && !this.env.address_sources[this.env.source].readonly);
      if (list.selection.length)
        this.enable_command('delete', 'compose', true);
      return false;
      return false;
    };
  this.list_contacts = function(page)
  this.list_contacts = function(src, page)
    {
    var add_url = '';
    var target = window;
    
    if (page && this.current_page==page)
    if (!src)
      src = this.env.source;
    if (page && this.current_page==page && src == this.env.source)
      return false;
    if (src != this.env.source)
      {
      page = 1;
      this.env.current_page = page;
      this.reset_qsearch();
      }
    this.select_folder(src, this.env.source);
    this.env.source = src;
    // load contacts remotely
    if (this.gui_objects.contactslist)
      {
      this.list_contacts_remote(page);
      this.list_contacts_remote(src, page);
      return;
      }
@@ -2220,19 +2327,31 @@
      add_url = '&_framed=1';
      }
    // also send search request to get the correct listing
    if (this.env.search_request)
      add_url += '&_search='+this.env.search_request;
    this.set_busy(true, 'loading');
    target.location.href = this.env.comm_path+(page ? '&_page='+page : '')+add_url;
    target.location.href = this.env.comm_path+(src ? '&_source='+urlencode(src) : '')+(page ? '&_page='+page : '')+add_url;
    };
  // send remote request to load contacts list
  this.list_contacts_remote = function(page)
  this.list_contacts_remote = function(src, page)
    {
    // clear message list first
    this.contact_list.clear();
    this.contact_list.clear(true);
    this.show_contentframe(false);
    this.enable_command('delete', 'compose', false);
    // send request to server
    var url = page ? '&_page='+page : '';
    var url = (src ? '_source='+urlencode(src) : '') + (page ? (src?'&':'') + '_page='+page : '');
    this.env.source = src;
    // also send search request to get the right messages
    if (this.env.search_request)
      url += '&_search='+this.env.search_request;
    this.set_busy(true, 'loading');
    this.http_request('list', url, true);
    };
@@ -2247,18 +2366,28 @@
      {
      add_url = '&_framed=1';
      target = window.frames[this.env.contentframe];
      document.getElementById(this.env.contentframe).style.visibility = 'inherit';
      this.show_contentframe(true);
      }
    else if (framed)
      return false;
    if (action && (cid || action=='add'))
    if (action && (cid || action=='add') && !this.drag_active)
      {
      this.set_busy(true);
      target.location.href = this.env.comm_path+'&_action='+action+'&_cid='+cid+add_url;
      target.location.href = this.env.comm_path+'&_action='+action+'&_source='+urlencode(this.env.source)+'&_cid='+urlencode(cid) + add_url;
      }
    return true;
    };
  // copy a contact to the specified target (group or directory)
  this.copy_contact = function(cid, to)
  {
    if (!cid)
      cid = this.contact_list.get_selection().join(',');
    if (to != this.env.source && cid && this.env.address_sources[to] && !this.env.address_sources[to].readonly)
      this.http_post('copy', '_cid='+urlencode(cid)+'&_source='+urlencode(this.env.source)+'&_to='+urlencode(to));
  };
  this.delete_contacts = function()
@@ -2269,6 +2398,7 @@
      return;
      
    var a_cids = new Array();
    var qs = '';
    if (this.env.cid)
      a_cids[a_cids.length] = this.env.cid;
@@ -2279,19 +2409,20 @@
        {
        id = selection[n];
        a_cids[a_cids.length] = id;
        this.contact_list.remove_row(id);
        this.contact_list.remove_row(id, (n == selection.length-1));
        }
      // hide content frame if we delete the currently displayed contact
      if (selection.length==1 && this.env.contentframe)
        {
        var elm = document.getElementById(this.env.contentframe);
        elm.style.visibility = 'hidden';
        }
      if (selection.length == 1)
        this.show_contentframe(false);
      }
    // also send search request to get the right records from the next page
    if (this.env.search_request)
      qs += '&_search='+this.env.search_request;
    // send request to server
    this.http_request('delete', '_cid='+a_cids.join(',')+'&_from='+(this.env.action ? this.env.action : ''));
    this.http_post('delete', '_cid='+urlencode(a_cids.join(','))+'&_from='+(this.env.action ? this.env.action : '')+qs);
    return true;
    };
@@ -2312,55 +2443,30 @@
    return false;
    };
  // load ldap search form
  // deprecated
  this.ldappublicsearch = function(action)
    {
    var add_url = '';
    var target = window;
    if (this.env.contentframe && window.frames && window.frames[this.env.contentframe])
      {
      add_url = '&_framed=1';
      target = window.frames[this.env.contentframe];
      document.getElementById(this.env.contentframe).style.visibility = 'inherit';
      }
    else
      return false;
    if (action == 'ldappublicsearch')
      target.location.href = this.env.comm_path+'&_action='+action+add_url;
    return true;
    };
  // add ldap contacts to address book
  this.add_ldap_contacts = function()
    {
    if (window.frames[this.env.contentframe].rcmail)
      {
      var frame = window.frames[this.env.contentframe];
      // build the url
      var url    = '&_framed=1';
      var emails = '&_emails=';
      var names  = '&_names=';
      var end    = '';
      for (var n=0; n<frame.rcmail.selection.length; n++)
        {
        end = n < frame.rcmail.selection.length - 1 ? ',' : '';
        emails += frame.rcmail.ldap_contact_rows[frame.rcmail.selection[n]].obj.cells[1].innerHTML + end;
        names  += frame.rcmail.ldap_contact_rows[frame.rcmail.selection[n]].obj.cells[0].innerHTML + end;
        }
      frame.location.href = this.env.comm_path + '&_action=save&_framed=1' + emails + names;
      }
    return false;
    }
  /*********************************************************/
  /*********        user settings methods          *********/
  /*********************************************************/
  this.init_subscription_list = function()
    {
    var p = this;
    this.subscription_list = new rcube_list_widget(this.gui_objects.subscriptionlist, {multiselect:false, draggable:true, keyboard:false, toggleselect:true});
    this.subscription_list.addEventListener('select', function(o){ p.subscription_select(o); });
    this.subscription_list.addEventListener('dragstart', function(o){ p.drag_active = true; });
    this.subscription_list.addEventListener('dragend', function(o){ p.subscription_move_folder(o); });
    this.subscription_list.row_init = function (row)
      {
      var anchors = row.obj.getElementsByTagName('A');
      if (anchors[0])
        anchors[0].onclick = function() { p.rename_folder(row.id); return false; };
      if (anchors[1])
        anchors[1].onclick = function() { p.delete_folder(row.id); return false; };
      row.obj.onmouseover = function() { p.focus_subscription(row.id); };
      row.obj.onmouseout = function() { p.unfocus_subscription(row.id); };
      }
    this.subscription_list.init();
    }
  this.identity_select = function(list)
    {
@@ -2393,7 +2499,6 @@
    };
  this.delete_identity = function(id)
    {
    // exit if no mailbox specified or if selection is empty
@@ -2404,65 +2509,105 @@
    if (!id)
      id = this.env.iid ? this.env.iid : selection[0];
/*
    // 'remove' row from list (just hide it)
    if (this.identity_rows && this.identity_rows[id].obj)
      {
      this.clear_selection();
      this.identity_rows[id].obj.style.display = 'none';
      }
*/
    // if (this.env.framed && id)
    this.goto_url('delete-identity', '_iid='+id, true);
    return true;
    };
  this.focus_subscription = function(id)
    {
    var row, folder;
    var reg = RegExp('['+RegExp.escape(this.env.delimiter)+']?[^'+RegExp.escape(this.env.delimiter)+']+$');
    if (this.drag_active && (row = document.getElementById(id)))
      if (this.env.subscriptionrows[id] &&
          (folder = this.env.subscriptionrows[id][0]))
        {
        if (this.check_droptarget(folder) &&
            (folder != this.env.folder.replace(reg, '')) &&
            (!folder.match(new RegExp('^'+RegExp.escape(this.env.folder+this.env.delimiter)))))
          {
          this.set_env('dstfolder', folder);
          this.set_classname(row, 'droptarget', true);
          }
        }
      else if (this.env.folder.match(new RegExp(RegExp.escape(this.env.delimiter))))
        {
        this.set_env('dstfolder', this.env.delimiter);
        this.set_classname(this.subscription_list.frame, 'droptarget', true);
        }
    }
  this.unfocus_subscription = function(id)
    {
      var row;
      this.set_env('dstfolder', null);
      if (this.env.subscriptionrows[id] &&
          (row = document.getElementById(id)))
        this.set_classname(row, 'droptarget', false);
      else
        this.set_classname(this.subscription_list.frame, 'droptarget', false);
    }
  this.subscription_select = function(list)
    {
    var id, folder;
    if ((id = list.get_single_selection()) &&
        this.env.subscriptionrows['rcmrow'+id] &&
        (folder = this.env.subscriptionrows['rcmrow'+id][0]) &&
        (find_in_array(this.env.defaultfolders, folder)!=0))
      this.set_env('folder', folder);
    else
      this.set_env('folder', null);
    if (this.gui_objects.createfolderhint)
      this.gui_objects.createfolderhint.innerHTML = this.env.folder ? this.get_label('addsubfolderhint') : '';
    };
  this.subscription_move_folder = function(list)
    {
    var reg = RegExp('['+RegExp.escape(this.env.delimiter)+']?[^'+RegExp.escape(this.env.delimiter)+']+$');
    if (this.env.folder && this.env.dstfolder && (this.env.dstfolder != this.env.folder) &&
        (this.env.dstfolder != this.env.folder.replace(reg, '')))
      {
      var reg = new RegExp('[^'+RegExp.escape(this.env.delimiter)+']*['+RegExp.escape(this.env.delimiter)+']', 'g');
      var basename = this.env.folder.replace(reg, '');
      var newname = this.env.dstfolder==this.env.delimiter ? basename : this.env.dstfolder+this.env.delimiter+basename;
      this.http_post('rename-folder', '_folder_oldname='+urlencode(this.env.folder)+'&_folder_newname='+urlencode(newname));
      }
    this.drag_active = false;
    this.unfocus_subscription(this.get_folder_row_id(this.env.dstfolder));
    };
  // tell server to create and subscribe a new mailbox
  this.create_folder = function(name)
    {
  if (this.edit_folder)
    this.reset_folder_rename();
    if (this.edit_folder)
      this.reset_folder_rename();
    var form;
    if ((form = this.gui_objects.editform) && form.elements['_folder_name'])
      name = form.elements['_folder_name'].value;
    if (this.env.folder && name != '')
      name = this.env.folder+this.env.delimiter+name;
    if (name)
      this.http_request('create-folder', '_name='+urlencode(name), true);
      this.http_post('create-folder', '_name='+urlencode(name), true);
    else if (form.elements['_folder_name'])
      form.elements['_folder_name'].focus();
    };
  // entry point for folder renaming
  this.rename_folder = function(props)
    {
    var form, oldname, newname;
    // rename a specific mailbox
    if (props)
      this.edit_foldername(props);
    // use a dropdown and input field (old behavior)
    else if ((form = this.gui_objects.editform) && form.elements['_folder_oldname'] && form.elements['_folder_newname'])
      {
      oldname = form.elements['_folder_oldname'].value;
      newname = form.elements['_folder_newname'].value;
      }
    if (oldname && newname)
      this.http_request('rename-folder', '_folder_oldname='+urlencode(oldname)+'&_folder_newname='+urlencode(newname));
    };
  // start editing the mailbox name.
  // start renaming the mailbox name.
  // this will replace the name string with an input field
  this.edit_foldername = function(folder)
  this.rename_folder = function(id)
    {
    var temp, row, form;
    var id = this.get_folder_row_id(folder);
    // reset current renaming
  if (temp = this.edit_folder)
@@ -2472,11 +2617,15 @@
      return;
    }
    if (id && (row = document.getElementById(id)))
    if (id && this.env.subscriptionrows[id] && (row = document.getElementById(id)))
      {
      var reg = new RegExp('.*['+RegExp.escape(this.env.delimiter)+']');
      this.name_input = document.createElement('INPUT');
      this.name_input.value = this.env.subscriptionrows[id][1];
      this.name_input.value = this.env.subscriptionrows[id][1].replace(reg, '');
      this.name_input.style.width = '100%';
      reg = new RegExp('['+RegExp.escape(this.env.delimiter)+']?[^'+RegExp.escape(this.env.delimiter)+']+$');
      this.name_input.__parent = this.env.subscriptionrows[id][0].replace(reg, '');
      this.name_input.onkeypress = function(e){ rcmail.name_input_keypress(e); };
      
      row.cells[0].replaceChild(this.name_input, row.cells[0].firstChild);
@@ -2494,7 +2643,10 @@
    {
    var cell = this.name_input ? this.name_input.parentNode : null;
    if (cell && this.edit_folder && this.env.subscriptionrows[this.edit_folder])
      cell.innerHTML = this.env.subscriptionrows[this.edit_folder][1];
      {
      var reg = new RegExp('[^'+RegExp.escape(this.env.delimiter)+']*['+RegExp.escape(this.env.delimiter)+']', 'g');
      cell.innerHTML = this.env.subscriptionrows[this.edit_folder][1].replace(reg, '&nbsp;&nbsp;&nbsp;&nbsp;');
      }
      
    this.edit_folder = null;
    };
@@ -2503,14 +2655,18 @@
  // handler for keyboard events on the input field
  this.name_input_keypress = function(e)
    {
    var key = document.all ? event.keyCode : document.getElementById ? e.keyCode : 0;
    var key = rcube_event.get_keycode(e);
    // enter
    if (key==13)
      {
      var newname = this.name_input ? this.name_input.value : null;
      if (this.edit_folder && newname)
        this.http_request('rename-folder', '_folder_oldname='+urlencode(this.env.subscriptionrows[this.edit_folder][0])+'&_folder_newname='+urlencode(newname));
        {
        if (this.name_input.__parent)
          newname = this.name_input.__parent + this.env.delimiter + newname;
        this.http_post('rename-folder', '_folder_oldname='+urlencode(this.env.subscriptionrows[this.edit_folder][0])+'&_folder_newname='+urlencode(newname));
        }
      }
    // escape
    else if (key==27)
@@ -2519,13 +2675,22 @@
  // delete a specific mailbox with all its messages
  this.delete_folder = function(folder)
  this.delete_folder = function(id)
    {
  if (this.edit_folder)
    this.reset_folder_rename();
    if (folder)
      this.http_request('delete-folder', '_mboxes='+urlencode(folder));
    var folder = this.env.subscriptionrows[id][0];
    if (this.edit_folder)
      this.reset_folder_rename();
    if (folder && confirm(this.get_label('deletefolderconfirm')))
      {
      this.http_post('delete-folder', '_mboxes='+urlencode(folder));
      this.set_env('folder', null);
      if (this.gui_objects.createfolderhint)
        this.gui_objects.createfolderhint.innerHTML = '';
      }
    };
@@ -2542,7 +2707,14 @@
    var refrow, form;
    var tbody = this.gui_objects.subscriptionlist.tBodies[0];
    var id = replace && replace.id ? replace.id : tbody.childNodes.length+1;
    var id = 'rcmrow'+(tbody.childNodes.length+1);
    var selection = this.subscription_list.get_single_selection();
    if (replace && replace.id)
    {
      id = replace.id;
      refid = replace.id;
    }
    if (!id || !(refrow = document.getElementById(refid)))
      {
@@ -2553,29 +2725,29 @@
      {
      // clone a table row if there are existing rows
      var row = this.clone_table_row(refrow);
      row.id = 'rcmrow'+id;
      row.id = id;
      if (replace)
        tbody.replaceChild(row, replace);
      else
        tbody.appendChild(row);
      }
    // add to folder/row-ID map
    this.env.subscriptionrows[row.id] = [name, display_name];
    // set folder name
    row.cells[0].innerHTML = display_name;
    if (row.cells[1] && row.cells[1].firstChild.tagName=='INPUT')
    // set messages count to zero
    if (!replace)
      row.cells[1].innerHTML = '*';
    if (!replace && row.cells[2] && row.cells[2].firstChild.tagName=='INPUT')
      {
      row.cells[1].firstChild.value = name;
      row.cells[1].firstChild.checked = true;
      row.cells[2].firstChild.value = name;
      row.cells[2].firstChild.checked = true;
      }
    if (row.cells[2] && row.cells[2].firstChild.tagName=='A')
      row.cells[2].firstChild.onclick = new Function(this.ref+".command('rename-folder','"+name.replace('\'','\\\'')+"')");
    if (row.cells[3] && row.cells[3].firstChild.tagName=='A')
      row.cells[3].firstChild.onclick = new Function(this.ref+".command('delete-folder','"+name.replace('\'','\\\'')+"')");
    // add new folder to rename-folder list and clear input field
    if (!replace && (form = this.gui_objects.editform))
      {
@@ -2585,6 +2757,13 @@
        form.elements['_folder_name'].value = ''; 
      }
    this.sort_subscription_list();
    this.init_subscription_list();
    if (selection && document.getElementById('rcmrow'+selection))
      this.subscription_list.select_row(selection);
    if (document.getElementById(id).scrollIntoView)
      document.getElementById(id).scrollIntoView();
    };
@@ -2596,7 +2775,6 @@
    
    // replace an existing table row (if found)
    this.add_folder_row(newfolder, display_name, row);
    this.env.subscriptionrows[id] = null;
    
    // rename folder in rename-folder dropdown
    var form, elm;
@@ -2647,59 +2825,17 @@
  this.subscribe_folder = function(folder)
    {
    var form;
    if ((form = this.gui_objects.editform) && form.elements['_unsubscribed'])
      this.change_subscription('_unsubscribed', '_subscribed', 'subscribe');
    else if (folder)
      this.http_request('subscribe', '_mboxes='+urlencode(folder));
    if (folder)
      this.http_post('subscribe', '_mbox='+urlencode(folder));
    };
  this.unsubscribe_folder = function(folder)
    {
    var form;
    if ((form = this.gui_objects.editform) && form.elements['_subscribed'])
      this.change_subscription('_subscribed', '_unsubscribed', 'unsubscribe');
    else if (folder)
      this.http_request('unsubscribe', '_mboxes='+urlencode(folder));
    if (folder)
      this.http_post('unsubscribe', '_mbox='+urlencode(folder));
    };
    
  this.change_subscription = function(from, to, action)
    {
    var form;
    if (form = this.gui_objects.editform)
      {
      var a_folders = new Array();
      var list_from = form.elements[from];
      for (var i=0; list_from && i<list_from.options.length; i++)
        {
        if (list_from.options[i] && list_from.options[i].selected)
          {
          a_folders[a_folders.length] = list_from.options[i].value;
          list_from[i] = null;
          i--;
          }
        }
      // yes, we have some folders selected
      if (a_folders.length)
        {
        var list_to = form.elements[to];
        var index;
        for (var n=0; n<a_folders.length; n++)
          {
          index = list_to.options.length;
          list_to[index] = new Option(a_folders[n]);
          }
        this.http_request(action, '_mboxes='+urlencode(a_folders.join(',')));
        }
      }
    };
  // helper method to find a specific mailbox row ID
  this.get_folder_row_id = function(folder)
@@ -2733,6 +2869,32 @@
    return new_row;
    };
  // sort subscription folder list
  this.sort_subscription_list = function()
    {
    var index = new Array();
    var tbody = this.gui_objects.subscriptionlist.tBodies[0];
    var swapped = false;
    for (var i = 0; i<tbody.childNodes.length; i++)
      if (this.env.subscriptionrows[tbody.childNodes[i].id]!=null)
        index.push(i);
    for (i = 0; i<(index.length-1); i++)
      {
      var one = tbody.childNodes[index[i]];
      var two = tbody.childNodes[index[i+1]];
      if (this.env.subscriptionrows[one.id][0].toLowerCase()>
          this.env.subscriptionrows[two.id][0].toLowerCase())
        {
        var swap = one.cloneNode(true);
        tbody.replaceChild(swap, two);
        tbody.replaceChild(two, one);
        swapped = true;
        }
      }
    if (swapped)
      this.sort_subscription_list();
    };
  /*********************************************************/
  /*********           GUI functionality           *********/
@@ -2764,8 +2926,12 @@
      obj = document.getElementById(button.id);
      // get default/passive setting of the button
      if (obj && button.type=='image' && !button.status)
      if (obj && button.type=='image' && !button.status) {
        button.pas = obj._original_src ? obj._original_src : obj.src;
        // respect PNG fix on IE browsers
        if (obj.runtimeStyle && obj.runtimeStyle.filter && obj.runtimeStyle.filter.match(/src=['"]([^'"]+)['"]/))
          button.pas = RegExp.$1;
      }
      else if (obj && !button.status)
        button.pas = String(obj.className);
@@ -2790,6 +2956,28 @@
      }
    };
  // display a specific alttext
  this.set_alttext = function(command, label)
    {
      if (!this.buttons[command] || !this.buttons[command].length)
        return;
      var button, obj, link;
      for (var n=0; n<this.buttons[command].length; n++)
      {
        button = this.buttons[command][n];
        obj = document.getElementById(button.id);
        if (button.type=='image' && obj)
        {
          obj.setAttribute('alt', this.get_label(label));
          if ((link = obj.parentNode) && link.tagName == 'A')
            link.setAttribute('title', this.get_label(label));
        }
        else if (obj)
          obj.setAttribute('title', this.get_label(label));
      }
    };
  // mouse over button
  this.button_over = function(command, id)
@@ -2866,23 +3054,27 @@
    };
  // display a specific alttext
  this.alttext = function(text)
    {
    };
  // write to the document/window title
  this.set_pagetitle = function(title)
  {
    if (title && document.title)
      document.title = title;
  }
  // display a system message
  this.display_message = function(msg, type, hold)
    {
    this.set_busy(false);
    if (!this.loaded)  // save message in order to display after page loaded
      {
      this.pending_message = new Array(msg, type);
      return true;
      }
    // pass command to parent window
    if (this.env.framed && parent.rcmail)
      return parent.rcmail.display_message(msg, type, hold);
    if (!this.gui_objects.message)
      return false;
@@ -2893,15 +3085,15 @@
    if (type)
      cont = '<div class="'+type+'">'+cont+'</div>';
    this.gui_objects.message._rcube = this;
    var _rcube = this;
    this.gui_objects.message.innerHTML = cont;
    this.gui_objects.message.style.display = 'block';
    if (type!='loading')
      this.gui_objects.message.onmousedown = function(){ this._rcube.hide_message(); return true; };
      this.gui_objects.message.onmousedown = function(){ _rcube.hide_message(); return true; };
    
    if (!hold)
      this.message_timer = setTimeout(this.ref+'.hide_message()', this.message_time);
      this.message_timer = setTimeout(function(){ ref.hide_message(); }, this.message_time);
    };
@@ -2917,38 +3109,37 @@
  // mark a mailbox as selected and set environment variable
  this.select_mailbox = function(mbox)
  this.select_folder = function(name, old)
  {
    if (this.gui_objects.folderlist)
    {
    if (this.gui_objects.mailboxlist )
      {
      var item, reg, text_obj;
      var current_li = this.get_mailbox_li();
      var mbox_li = this.get_mailbox_li(mbox);
      var current_li, target_li;
      
      if (current_li)
        {
      if ((current_li = this.get_folder_li(old)))
      {
        this.set_classname(current_li, 'selected', false);
        this.set_classname(current_li, 'unfocused', false);
        }
      if (mbox_li || this.env.mailbox == mbox)
        {
        this.set_classname(mbox_li, 'unfocused', false);
        this.set_classname(mbox_li, 'selected', true);
        }
      }
    // also update mailbox name in window title
    if (document.title)
      if ((target_li = this.get_folder_li(name)))
      {
      var doc_title = String(document.title);
      var reg = new RegExp(this.env.mailbox.toLowerCase(), 'i');
      if (this.env.mailbox && doc_title.match(reg))
        document.title = doc_title.replace(reg, mbox).replace(/^\([0-9]+\)\s+/i, '');
        this.set_classname(target_li, 'unfocused', false);
        this.set_classname(target_li, 'selected', true);
      }
    this.env.mailbox = mbox;
    };
    }
  };
  // helper method to find a folder list item
  this.get_folder_li = function(name)
  {
    if (this.gui_objects.folderlist)
    {
      name = String(name).replace(this.identifier_expr, '');
      return document.getElementById('rcmli'+name);
    }
    return null;
  };
  // for reordering column array, Konqueror workaround
@@ -2976,8 +3167,10 @@
        cell.id = 'rcmHead'+col;
        }
      if (col == 'subject' && this.message_list)
        this.message_list.subject_col = n+1;
      }
  };
  // create a table row in the message list
@@ -3040,14 +3233,14 @@
    };
  // replace content of quota display
   this.set_quota = function()
     {
     if (this.gui_objects.quotadisplay &&
         this.gui_objects.quotadisplay.attributes.getNamedItem('display') &&
         this.gui_objects.quotadisplay.attributes.getNamedItem('id'))
       this.http_request('quotadisplay', '_display='+
         this.gui_objects.quotadisplay.attributes.getNamedItem('display').nodeValue+
         '&_id='+this.gui_objects.quotadisplay.attributes.getNamedItem('id').nodeValue, false);
  this.set_quota = function()
    {
    if (this.gui_objects.quotadisplay &&
        this.gui_objects.quotadisplay.attributes.getNamedItem('display') &&
        this.gui_objects.quotadisplay.attributes.getNamedItem('id'))
      this.http_request('quotadisplay', '_display='+
      this.gui_objects.quotadisplay.attributes.getNamedItem('display').nodeValue+
      '&_id='+this.gui_objects.quotadisplay.attributes.getNamedItem('id').nodeValue, false);
     };
@@ -3057,14 +3250,8 @@
    if (!this.gui_objects.mailboxlist)
      return false;
    if (mbox==this.env.mailbox)
      set_title = true;
    var reg, text_obj;
    var item = this.get_mailbox_li(mbox);
    mbox = String(mbox).toLowerCase().replace(this.mbox_expression, '');
    if (item && item.className && item.className.indexOf('mailbox '+mbox)>=0)
    var reg, text_obj, item;
    if (item = this.get_folder_li(mbox))
      {
      // set new text
      text_obj = item.firstChild;
@@ -3086,13 +3273,16 @@
    if (set_title && document.title)
      {
      var doc_title = String(document.title);
      var new_title = "";
      if (count && doc_title.match(reg))
        document.title = doc_title.replace(reg, '('+count+') ');
        new_title = doc_title.replace(reg, '('+count+') ');
      else if (count)
        document.title = '('+count+') '+doc_title;
        new_title = '('+count+') '+doc_title;
      else
        document.title = doc_title.replace(reg, '');
        new_title = doc_title.replace(reg, '');
      this.set_pagetitle(new_title);
      }
    };
@@ -3146,14 +3336,21 @@
  /*********        remote request methods        *********/
  /********************************************************/
  this.redirect = function(url, lock)
    {
    if (lock || lock === null)
      this.set_busy(true);
    if (this.env.framed && window.parent)
      parent.location.href = url;
    else
      location.href = url;
    };
  this.goto_url = function(action, query, lock)
    {
    if (lock)
    this.set_busy(true);
    var querystring = query ? '&'+query : '';
    location.href = this.env.comm_path+'&_action='+action+querystring;
    this.redirect(this.env.comm_path+'&_action='+action+querystring, lock);
    };
@@ -3189,20 +3386,45 @@
    // send request
    if (request_obj)
      {
      // prompt('request', this.env.comm_path+'&_action='+urlencode(action)+'&'+querystring);
      console('HTTP request: '+this.env.comm_path+'&_action='+action+'&'+querystring);
      console.log('HTTP request: '+this.env.comm_path+'&_action='+action+'&'+querystring);
      if (lock)
        this.set_busy(true);
      var rcm = this;
      request_obj.__lock = lock ? true : false;
      request_obj.__action = action;
      request_obj.onerror = function(o){ rcube_webmail_client.http_error(o); };
      request_obj.oncomplete = function(o){ rcube_webmail_client.http_response(o); };
      request_obj.onerror = function(o){ ref.http_error(o); };
      request_obj.oncomplete = function(o){ ref.http_response(o); };
      request_obj.GET(this.env.comm_path+'&_action='+action+'&'+querystring);
      }
    };
    // send a http POST request to the server
    this.http_post = function(action, postdata, lock)
      {
      var request_obj;
      if (postdata && typeof(postdata) == 'object')
        postdata._remote = 1;
      else
        postdata += (postdata ? '&' : '') + '_remote=1';
      // send request
      if (request_obj = this.get_request_obj())
        {
        console.log('HTTP POST: '+this.env.comm_path+'&_action='+action);
        if (lock)
          this.set_busy(true);
        var rcm = this;
        request_obj.__lock = lock ? true : false;
        request_obj.__action = action;
        request_obj.onerror = function(o){ rcm.http_error(o); };
        request_obj.oncomplete = function(o){ rcm.http_response(o); };
        request_obj.POST(this.env.comm_path+'&_action='+action, postdata);
        }
      };
  // handle HTTP response
  this.http_response = function(request_obj)
@@ -3214,9 +3436,10 @@
      ctype = ctype_array[0];
    }
    this.set_busy(false);
    if (request_obj.__lock)
        this.set_busy(false);
  console(request_obj.get_text());
    console.log(request_obj.get_text());
    // if we get javascript code from server -> execute it
    if (request_obj.get_text() && (ctype=='text/javascript' || ctype=='application/x-javascript'))
@@ -3235,11 +3458,17 @@
      case 'list':
        if (this.env.messagecount)
          this.enable_command('purge', (this.env.mailbox==this.env.trash_mailbox || this.env.mailbox==this.env.junk_mailbox));
     this.enable_command('purge', (this.env.mailbox==this.env.trash_mailbox || this.env.mailbox==this.env.junk_mailbox));
   this.msglist_select(this.message_list);
      case 'getunread':
   this.enable_command('sort', (this.env.messagecount > 0));
      case 'expunge':
        this.enable_command('select-all', 'select-none', 'expunge', this.env.messagecount ? true : false);
        break;
      }
    request_obj.reset();
@@ -3271,14 +3500,10 @@
  this.check_for_recent = function()
    {
    if (this.busy)
      {
      this.send_keep_alive();
      return;
      }
    this.set_busy(true, 'checkingmail');
    var d = new Date();
    this.http_request('check-recent', '_t='+d.getTime());
    this.http_request('check-recent', (this.env.search_request ? '_search='+this.env.search_request+'&' : '') + '_t='+(new Date().getTime()), true);
    };
@@ -3398,7 +3623,10 @@
    if (window.XMLHttpRequest)
      this.xmlhttp = new XMLHttpRequest();
    else if (window.ActiveXObject)
      this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
      {
      try { this.xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
      catch(e) { this.xmlhttp = null; }
      }
    else
      {
      
@@ -3416,12 +3644,13 @@
      return false;
      }
    var ref = this;
    var _ref = this;
    this.url = url;
    this.busy = true;
    this.xmlhttp.onreadystatechange = function(){ ref.xmlhttp_onreadystatechange(); };
    this.xmlhttp.onreadystatechange = function(){ _ref.xmlhttp_onreadystatechange(); };
    this.xmlhttp.open('GET', url);
    this.xmlhttp.setRequestHeader('X-RoundCube-Referer', bw.get_cookie('roundcube_sessid'));
    this.xmlhttp.send(null);
    };
@@ -3429,8 +3658,8 @@
  this.POST = function(url, body, contentType)
    {
    // default value for contentType if not provided
    contentType = typeof(contentType) != 'undefined' ?
      contentType : 'application/x-www-form-urlencoded';
    if (typeof(contentType) == 'undefined')
      contentType = 'application/x-www-form-urlencoded';
    this.build();
    
@@ -3439,15 +3668,24 @@
       this.onerror(this);
       return false;
    }
    var req_body = body;
    if (typeof(body) == 'object')
    {
      req_body = '';
      for (var p in body)
        req_body += (req_body ? '&' : '') + p+'='+urlencode(body[p]);
    }
    var ref=this;
    var ref = this;
    this.url = url;
    this.busy = true;
    
    this.xmlhttp.onreadystatechange = function() { ref.xmlhttp_onreadystatechange(); };
    this.xmlhttp.open('POST', url, true);
    this.xmlhttp.setRequestHeader('Content-Type', contentType);
    this.xmlhttp.send(body);
    this.xmlhttp.setRequestHeader('X-RoundCube-Referer', bw.get_cookie('roundcube_sessid'));
    this.xmlhttp.send(req_body);
    };
@@ -3509,11 +3747,5 @@
  {
  if (window[o] && window[o].init)
    setTimeout(o+'.init()', 200);
  }
function console(str)
  {
  if (document.debugform && document.debugform.console)
    document.debugform.console.value += str+'\n--------------------------------------\n';
  }