Aleksander Machniak
2015-12-17 c67e7e8f85ae9c05d1a04715d2a9ce7e84a50a45
program/js/app.js
@@ -156,8 +156,8 @@
    var n;
    this.task = this.env.task;
    // check browser
    if (this.env.server_error != 409 && (!bw.dom || !bw.xmlhttp_test() || (bw.mz && bw.vendver < 1.9) || (bw.ie && bw.vendver < 7))) {
    // check browser capabilities (never use version checks here)
    if (this.env.server_error != 409 && (!bw.dom || !bw.xmlhttp_test())) {
      this.goto_url('error', '_code=0x199');
      return;
    }
@@ -326,10 +326,7 @@
          this.enable_command('download', 'print', true);
        // show printing dialog
        else if (this.env.action == 'print' && this.env.uid) {
          if (bw.safari)
            setTimeout('window.print()', 10);
          else
            window.print();
          this.print_dialog();
        }
        // get unread count for each mailbox
@@ -439,6 +436,9 @@
          this.enable_command('save', true);
          if (this.env.action == 'add' || this.env.action == 'edit' || this.env.action == 'search')
              this.init_contact_form();
        }
        else if (this.env.action == 'print') {
          this.print_dialog();
        }
        break;
@@ -653,8 +653,10 @@
    }
    // check input before leaving compose step
    if (this.task == 'mail' && this.env.action == 'compose' && $.inArray(command, this.env.compose_commands) < 0 && !this.env.server_error) {
      if (this.cmp_hash != this.compose_field_hash() && !confirm(this.get_label('notsentwarning')))
    if (this.task == 'mail' && this.env.action == 'compose' && !this.env.server_error && command != 'save-pref'
      && $.inArray(command, this.env.compose_commands) < 0
    ) {
      if (!this.env.is_sent && this.cmp_hash != this.compose_field_hash() && !confirm(this.get_label('notsentwarning')))
        return false;
      // remove copy from local storage if compose screen is left intentionally
@@ -762,7 +764,7 @@
      case 'open':
        if (uid = this.get_single_uid()) {
          obj.href = this.url('show', {_mbox: this.get_message_mailbox(uid), _uid: uid});
          obj.href = this.url('show', this.params_from_uid(uid));
          return true;
        }
        break;
@@ -774,7 +776,7 @@
      case 'list':
        if (props && props != '') {
          this.reset_qsearch();
          this.reset_qsearch(true);
        }
        if (this.env.action == 'compose' && this.env.extwin) {
          window.close();
@@ -894,7 +896,7 @@
          else {
            // reload form
            if (props == 'reload') {
              form.action += '?_reload=1';
              form.action += '&_reload=1';
            }
            else if (this.task == 'settings' && (this.env.identities_level % 2) == 0  &&
              (input = $("input[name='_email']", form)) && input.length && !rcube_check_email(input.val())
@@ -1115,7 +1117,7 @@
        break;
      case 'send':
        if (!props.nocheck && !this.check_compose_input(command))
        if (!props.nocheck && !this.env.is_sent && !this.check_compose_input(command))
          break;
        // Reset the auto-save timer
@@ -1176,12 +1178,20 @@
        break;
      case 'print':
        if (this.env.action == 'get') {
        if (this.task == 'addressbook') {
          if (uid = this.contact_list.get_single_selection()) {
            url = '&_action=print&_cid=' + uid;
            if (this.env.source)
              url += '&_source=' + urlencode(this.env.source);
            this.open_window(this.env.comm_path + url, true, true);
          }
        }
        else if (this.env.action == 'get') {
          this.gui_objects.messagepartframe.contentWindow.print();
        }
        else if (uid = this.get_single_uid()) {
          url = '&_action=print&_uid='+uid+'&_mbox='+urlencode(this.get_message_mailbox(uid))+(this.env.safemode ? '&_safe=1' : '');
          if (this.open_window(this.env.comm_path + url, true, true)) {
          url = this.url('print', this.params_from_uid(uid, {_safe: this.env.safemode ? 1 : 0}));
          if (this.open_window(url, true, true)) {
            if (this.env.action != 'show')
              this.mark_message('read', uid);
          }
@@ -1190,7 +1200,7 @@
      case 'viewsource':
        if (uid = this.get_single_uid())
          this.open_window(this.env.comm_path+'&_action=viewsource&_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true, true);
          this.open_window(this.url('viewsource', this.params_from_uid(uid)), true, true);
        break;
      case 'download':
@@ -1198,7 +1208,7 @@
          location.href = location.href.replace(/_frame=/, '_download=');
        }
        else if (uid = this.get_single_uid()) {
          this.goto_url('viewsource', { _uid: uid, _mbox: this.get_message_mailbox(uid), _save: 1 });
          this.goto_url('viewsource', this.params_from_uid(uid, {_save: 1}));
        }
        break;
@@ -1213,17 +1223,16 @@
      // reset quicksearch
      case 'reset-search':
        var n, s = this.env.search_request || this.env.qsearch,
            ss = this.gui_objects.qsearchbox && this.gui_objects.qsearchbox.value != '';
        var n, s = this.env.search_request || this.env.qsearch;
        this.reset_qsearch();
        this.reset_qsearch(true);
        this.select_all_mode = false;
        if (s && this.env.action == 'compose') {
          if (this.contact_list)
            this.list_contacts_clear();
        }
        else if (s && ss && this.env.mailbox) {
        else if (s && this.env.mailbox) {
          this.list_mailbox(this.env.mailbox, 1);
        }
        else if (s && this.task == 'addressbook') {
@@ -1261,7 +1270,7 @@
        $('input[name="_unlock"]', form).val(importlock);
        if (!(flag = this.upload_file(form, 'import'))) {
        if (!(flag = this.upload_file(form, 'import', importlock))) {
          this.set_busy(false, null, importlock);
          if (flag !== false)
            alert(this.get_label('selectimportfile'));
@@ -1433,7 +1442,7 @@
    else if (delay)
      setTimeout(function() { ref.reload(); }, delay);
    else if (window.location)
      location.href = this.env.comm_path + (this.env.action ? '&_action='+this.env.action : '');
      location.href = this.url('', {_extwin: this.env.extwin});
  };
  // Add variable to GET string, replace old value if exists
@@ -1600,15 +1609,16 @@
  this.folder_collapsed = function(node)
  {
    var prefname = this.env.task == 'addressbook' ? 'collapsed_abooks' : 'collapsed_folders';
    var prefname = this.env.task == 'addressbook' ? 'collapsed_abooks' : 'collapsed_folders',
      old = this.env[prefname];
    if (node.collapsed) {
      this.env[prefname] = this.env[prefname] + '&'+urlencode(node.id)+'&';
      // select the folder if one of its childs is currently selected
      // don't select if it's virtual (#1488346)
      if (!node.virtual && this.env.mailbox && this.env.mailbox.startsWith(name + this.env.delimiter))
        this.command('list', name);
      if (!node.virtual && this.env.mailbox && this.env.mailbox.startsWith(node.id + this.env.delimiter))
        this.command('list', node.id);
    }
    else {
      var reg = new RegExp('&'+urlencode(node.id)+'&');
@@ -1616,7 +1626,8 @@
    }
    if (!this.drag_active) {
      this.command('save-pref', { name: prefname, value: this.env[prefname] });
      if (old !== this.env[prefname])
        this.command('save-pref', { name: prefname, value: this.env[prefname] });
      if (this.env.unread_counts)
        this.set_unread_count_display(node.id, false);
@@ -2224,35 +2235,33 @@
      return;
    var win, target = window,
      action = preview ? 'preview': 'show',
      url = '&_action='+action+'&_uid='+id+'&_mbox='+urlencode(this.get_message_mailbox(id));
      url = this.params_from_uid(id, {_caps: this.browser_capabilities()});
    if (preview && (win = this.get_frame_window(this.env.contentframe))) {
      target = win;
      url += '&_framed=1';
      url._framed = 1;
    }
    if (safe)
      url += '&_safe=1';
      url._safe = 1;
    // also send search request to get the right messages
    if (this.env.search_request)
      url += '&_search='+this.env.search_request;
    // add browser capabilities, so we can properly handle attachments
    url += '&_caps='+urlencode(this.browser_capabilities());
      url._search = this.env.search_request;
    if (this.env.extwin)
      url += '&_extwin=1';
      url._extwin = 1;
    url = this.url(preview ? 'preview': 'show', url);
    if (preview && String(target.location.href).indexOf(url) >= 0) {
      this.show_contentframe(true);
    }
    else {
      if (!preview && this.env.message_extwin && !this.env.extwin)
        this.open_window(this.env.comm_path+url, true);
        this.open_window(url, true);
      else
        this.location_href(this.env.comm_path+url, target, true);
        this.location_href(url, target, true);
      // mark as read and change mbox unread counter
      if (preview && this.message_list && this.message_list.rows[id] && this.message_list.rows[id].unread && this.env.preview_pane_mark_read > 0) {
@@ -2368,6 +2377,9 @@
  // list messages of a specific mailbox using filter
  this.filter_mailbox = function(filter)
  {
    if (this.filter_disabled)
      return;
    var lock = this.set_busy(true, 'searching');
    this.clear_message_list();
@@ -2401,16 +2413,17 @@
    if (sort)
      url._sort = sort;
    // also send search request to get the right messages
    if (this.env.search_request)
      url._search = this.env.search_request;
    // set page=1 if changeing to another mailbox
    // folder change, reset page, search scope, etc.
    if (this.env.mailbox != mbox) {
      page = 1;
      this.env.current_page = page;
      this.env.search_scope = 'base';
      this.select_all_mode = false;
      this.reset_search_filter();
    }
    // also send search request to get the right messages
    else if (this.env.search_request)
      url._search = this.env.search_request;
    if (!update_only) {
      // unselect selected messages and clear the list and message data
@@ -2475,22 +2488,23 @@
  // removes messages that doesn't exists from list selection array
  this.update_selection = function()
  {
    var selected = this.message_list.selection,
      rows = this.message_list.rows,
    var list = this.message_list,
      selected = list.selection,
      rows = list.rows,
      i, selection = [];
    for (i in selected)
      if (rows[selected[i]])
        selection.push(selected[i]);
    this.message_list.selection = selection;
    list.selection = selection;
    // reset preview frame, if currently previewed message is not selected (has been removed)
    try {
      var win = this.get_frame_window(this.env.contentframe),
        id = win.rcmail.env.uid;
      if (id && $.inArray(id, selection) < 0)
      if (id && !list.in_selection(id))
        this.show_contentframe(false);
    }
    catch (e) {};
@@ -3336,7 +3350,7 @@
    if (!this.gui_objects.messageform)
      return false;
    var i, pos, input_from = $("[name='_from']"),
    var i, elem, pos, input_from = $("[name='_from']"),
      input_to = $("[name='_to']"),
      input_subject = $("input[name='_subject']"),
      input_message = $("[name='_message']").get(0),
@@ -3371,13 +3385,15 @@
    if (!html_mode) {
      pos = this.env.top_posting ? 0 : input_message.value.length;
      this.set_caret_pos(input_message, pos);
      // add signature according to selected identity
      // if we have HTML editor, signature is added in callback
      // if we have HTML editor, signature is added in a callback
      if (input_from.prop('type') == 'select-one') {
        this.change_identity(input_from[0]);
      }
      // set initial cursor position
      this.set_caret_pos(input_message, pos);
      // scroll to the bottom of the textarea (#1490114)
      if (pos) {
@@ -3390,11 +3406,14 @@
      this.compose_restore_dialog(0, html_mode)
    if (input_to.val() == '')
      input_to.focus();
      elem = input_to;
    else if (input_subject.val() == '')
      input_subject.focus();
      elem = input_subject;
    else if (input_message)
      input_message.focus();
      elem = input_message;
    // focus first empty element (need to be visible on IE8)
    $(elem).filter(':visible').focus();
    this.env.compose_focus_elem = document.activeElement;
@@ -3481,15 +3500,35 @@
      .attr({ 'autocomplete': 'off', 'aria-autocomplete': 'list', 'aria-expanded': 'false', 'role': 'combobox' });
  };
  this.submit_messageform = function(draft)
  this.submit_messageform = function(draft, saveonly)
  {
    var form = this.gui_objects.messageform;
    if (!form)
      return;
    // the message has been sent but not saved, ask the user what to do
    if (!saveonly && this.env.is_sent) {
      return this.show_popup_dialog(this.get_label('messageissent'), '',
        [{
          text: this.get_label('save'),
          'class': 'mainaction',
          click: function() {
            ref.submit_messageform(false, true);
            $(this).dialog('close');
          }
        },
        {
          text: this.get_label('cancel'),
          click: function() {
            $(this).dialog('close');
          }
        }]
      );
    }
    // all checks passed, send message
    var msgid = this.set_busy(true, draft ? 'savingmessage' : 'sendingmessage'),
    var msgid = this.set_busy(true, draft || saveonly ? 'savingmessage' : 'sendingmessage'),
      lang = this.spellcheck_lang(),
      files = [];
@@ -3502,6 +3541,10 @@
    form.action = this.add_url(form.action, '_unlock', msgid);
    form.action = this.add_url(form.action, '_lang', lang);
    form.action = this.add_url(form.action, '_framed', 1);
    if (saveonly) {
      form.action = this.add_url(form.action, '_saveonly', 1);
    }
    // register timer to notify about connection timeout
    this.submit_timer = setTimeout(function(){
@@ -3553,7 +3596,7 @@
      var oldval = input.val(), rx = new RegExp(RegExp.escape(delim) + '\\s*$');
      if (oldval && !rx.test(oldval))
        oldval += delim + ' ';
      input.val(oldval + recipients.join(delim + ' ') + delim + ' ');
      input.val(oldval + recipients.join(delim + ' ') + delim + ' ').change();
      this.triggerEvent('add-recipient', { field:field, recipients:recipients });
    }
@@ -4051,7 +4094,7 @@
  };
  // upload (attachment) file
  this.upload_file = function(form, action)
  this.upload_file = function(form, action, lock)
  {
    if (!form)
      return;
@@ -4093,6 +4136,9 @@
          if (!content.match(/display_message/))
            ref.display_message(ref.get_label('fileuploaderror'), 'error');
          ref.remove_from_attachment_list(e.data.ts);
          if (lock)
            ref.set_busy(false, null, lock);
        }
        // Opera hack: handle double onload
        if (bw.opera)
@@ -4298,14 +4344,28 @@
    return url;
  };
  // reset search filter
  this.reset_search_filter = function()
  {
    this.filter_disabled = true;
    if (this.gui_objects.search_filter)
      $(this.gui_objects.search_filter).val('ALL').change();
    this.filter_disabled = false;
  };
  // reset quick-search form
  this.reset_qsearch = function()
  this.reset_qsearch = function(all)
  {
    if (this.gui_objects.qsearchbox)
      this.gui_objects.qsearchbox.value = '';
    if (this.env.qsearch)
      this.abort_request(this.env.qsearch);
    if (all) {
      this.env.search_scope = 'base';
      this.reset_search_filter();
    }
    this.env.qsearch = null;
    this.env.search_request = null;
@@ -4350,13 +4410,14 @@
  };
  // action executed after mail is sent
  this.sent_successfully = function(type, msg, folders)
  this.sent_successfully = function(type, msg, folders, save_error)
  {
    this.display_message(msg, type);
    this.compose_skip_unsavedcheck = true;
    if (this.env.extwin) {
      this.lock_form(this.gui_objects.messageform);
      if (!save_error)
        this.lock_form(this.gui_objects.messageform);
      var filter = {task: 'mail', action: ''},
        rc = this.opener(false, filter) || this.opener(true, filter);
@@ -4369,12 +4430,16 @@
        }
      }
      setTimeout(function() { window.close(); }, 1000);
      if (!save_error)
        setTimeout(function() { window.close(); }, 1000);
    }
    else {
    else if (!save_error) {
      // before redirect we need to wait some time for Chrome (#1486177)
      setTimeout(function() { ref.list_mailbox(); }, 500);
    }
    if (save_error)
      this.env.is_sent = true;
  };
@@ -4721,6 +4786,7 @@
      clearTimeout(this.preview_timer);
    var n, id, sid, contact, writable = false,
      selected = list.selection.length,
      source = this.env.source ? this.env.address_sources[this.env.source] : null;
    // we don't have dblclick handler here, so use 200 instead of this.dblclick_time
@@ -4729,7 +4795,7 @@
    else if (this.env.contentframe)
      this.show_contentframe(false);
    if (list.selection.length) {
    if (selected) {
      list.draggable = false;
      // no source = search result, we'll need to detect if any of
@@ -4764,11 +4830,12 @@
    // if a group is currently selected, and there is at least one contact selected
    // thend we can enable the group-remove-selected command
    this.enable_command('group-remove-selected', this.env.group && list.selection.length > 0 && writable);
    this.enable_command('compose', this.env.group || list.selection.length > 0);
    this.enable_command('export-selected', 'copy', list.selection.length > 0);
    this.enable_command('group-remove-selected', this.env.group && selected && writable);
    this.enable_command('compose', this.env.group || selected);
    this.enable_command('print', selected == 1);
    this.enable_command('export-selected', 'copy', selected > 0);
    this.enable_command('edit', id && writable);
    this.enable_command('delete', 'move', list.selection.length > 0 && writable);
    this.enable_command('delete', 'move', selected && writable);
    return false;
  };
@@ -4881,8 +4948,8 @@
    this.contact_list.data = {};
    this.contact_list.clear(true);
    this.show_contentframe(false);
    this.enable_command('delete', 'move', 'copy', false);
    this.enable_command('compose', this.env.group ? true : false);
    this.enable_command('delete', 'move', 'copy', 'print', false);
    this.enable_command('compose', this.env.group);
  };
  this.set_group_prop = function(prop)
@@ -4922,7 +4989,7 @@
        this.contact_list.clear_selection();
      this.enable_command('compose', rec && rec.email);
      this.enable_command('export-selected', rec && rec._type != 'group');
      this.enable_command('export-selected', 'print', rec && rec._type != 'group');
    }
    else if (framed)
      return false;
@@ -5175,7 +5242,7 @@
        changeYear: true,
        yearRange: '-120:+10',
        showOtherMonths: true,
        selectOtherMonths: true,
        selectOtherMonths: true
//        onSelect: function(dateText) { $(this).focus().val(dateText); }
      });
      $('input.datepicker').datepicker();
@@ -6667,6 +6734,9 @@
    this.env.listcols = listcols;
    if (!this.env.coltypes)
      this.env.coltypes = {};
    // replace old column headers
    if (thead) {
      if (repl) {
@@ -6994,7 +7064,7 @@
    if (show) {
      // truncate stack down to the one containing the ref link
      for (var i = this.menu_stack.length - 1; stack && i >= 0; i--) {
        if (!$(ref).parents('#'+this.menu_stack[i]).length)
        if (!$(ref).parents('#'+this.menu_stack[i]).length && $(event.target).parent().attr('role') != 'menuitem')
          this.hide_menu(this.menu_stack[i], event);
      }
      if (stack && this.menu_stack.length) {
@@ -7158,7 +7228,7 @@
  // compose a valid url with the given parameters
  this.url = function(action, query)
  {
    var querystring = typeof query === 'string' ? '&' + query : '';
    var querystring = typeof query === 'string' ? query : '';
    if (typeof action !== 'string')
      query = action;
@@ -7170,12 +7240,12 @@
    else if (this.env.action)
      query._action = this.env.action;
    var base = this.env.comm_path, k, param = {};
    var url = this.env.comm_path, k, param = {};
    // overwrite task name
    if (action && action.match(/([a-z0-9_-]+)\/([a-z0-9-_.]+)/)) {
      query._action = RegExp.$2;
      base = base.replace(/\_task=[a-z0-9_-]+/, '_task='+RegExp.$1);
      url = url.replace(/\_task=[a-z0-9_-]+/, '_task=' + RegExp.$1);
    }
    // remove undefined values
@@ -7184,7 +7254,13 @@
        param[k] = query[k];
    }
    return base + (base.indexOf('?') > -1 ? '&' : '?') + $.param(param) + querystring;
    if (param = $.param(param))
      url += (url.indexOf('?') > -1 ? '&' : '?') + param;
    if (querystring)
      url += (url.indexOf('?') > -1 ? '&' : '?') + querystring;
    return url;
  };
  this.redirect = function(url, lock)
@@ -7237,22 +7313,32 @@
  };
  // send a http request to the server
  this.http_request = function(action, query, lock)
  this.http_request = function(action, data, lock)
  {
    var url = this.url(action, query);
    if (typeof data !== 'object')
      data = rcube_parse_query(data);
    data._remote = 1;
    data._unlock = lock ? lock : 0;
    // trigger plugin hook
    var result = this.triggerEvent('request'+action, query);
    var result = this.triggerEvent('request' + action, data);
    if (result !== undefined) {
      // abort if one the handlers returned false
      if (result === false)
        return false;
      else
        url = this.url(action, result);
    // abort if one of the handlers returned false
    if (result === false) {
      if (data._unlock)
        this.set_busy(false, null, data._unlock);
      return false;
    }
    else if (result !== undefined) {
      data = result;
      if (data._action) {
        action = data._action;
        delete data._action;
      }
    }
    url += '&_remote=1';
    var url = this.url(action, data);
    // send request
    this.log('HTTP GET: ' + url);
@@ -7261,33 +7347,39 @@
    this.start_keepalive();
    return $.ajax({
      type: 'GET', url: url, data: { _unlock:(lock?lock:0) }, dataType: 'json',
      success: function(data){ ref.http_response(data); },
      type: 'GET', url: url, dataType: 'json',
      success: function(data) { ref.http_response(data); },
      error: function(o, status, err) { ref.http_error(o, status, err, lock, action); }
    });
  };
  // send a http POST request to the server
  this.http_post = function(action, postdata, lock)
  this.http_post = function(action, data, lock)
  {
    var url = this.url(action);
    if (typeof data !== 'object')
      data = rcube_parse_query(data);
    if (postdata && typeof postdata === 'object') {
      postdata._remote = 1;
      postdata._unlock = (lock ? lock : 0);
    }
    else
      postdata += (postdata ? '&' : '') + '_remote=1' + (lock ? '&_unlock='+lock : '');
    data._remote = 1;
    data._unlock = lock ? lock : 0;
    // trigger plugin hook
    var result = this.triggerEvent('request'+action, postdata);
    if (result !== undefined) {
      // abort if one of the handlers returned false
      if (result === false)
        return false;
      else
        postdata = result;
    var result = this.triggerEvent('request'+action, data);
    // abort if one of the handlers returned false
    if (result === false) {
      if (data._unlock)
        this.set_busy(false, null, data._unlock);
      return false;
    }
    else if (result !== undefined) {
      data = result;
      if (data._action) {
        action = data._action;
        delete data._action;
      }
    }
    var url = this.url(action);
    // send request
    this.log('HTTP POST: ' + url);
@@ -7296,7 +7388,7 @@
    this.start_keepalive();
    return $.ajax({
      type: 'POST', url: url, data: postdata, dataType: 'json',
      type: 'POST', url: url, data: data, dataType: 'json',
      success: function(data){ ref.http_response(data); },
      error: function(o, status, err) { ref.http_error(o, status, err, lock, action); }
    });
@@ -7365,7 +7457,7 @@
          this.enable_command('compose', (uid && this.contact_list.rows[uid]));
          this.enable_command('delete', 'edit', writable);
          this.enable_command('export', (this.contact_list && this.contact_list.rowcount > 0));
          this.enable_command('export-selected', false);
          this.enable_command('export-selected', 'print', false);
        }
      case 'move':
@@ -7412,32 +7504,36 @@
        this.env.qsearch = null;
      case 'list':
        if (this.task == 'mail') {
          var is_multifolder = this.is_multifolder_listing();
          var is_multifolder = this.is_multifolder_listing(),
            list = this.message_list,
            uid = this.env.list_uid;
          this.enable_command('show', 'select-all', 'select-none', this.env.messagecount > 0);
          this.enable_command('expunge', this.env.exists && !is_multifolder);
          this.enable_command('purge', this.purge_mailbox_test() && !is_multifolder);
          this.enable_command('import-messages', !is_multifolder);
          this.enable_command('expand-all', 'expand-unread', 'collapse-all', this.env.threading && this.env.messagecount && !is_multifolder);
          if ((response.action == 'list' || response.action == 'search') && this.message_list) {
            var list = this.message_list, uid = this.env.list_uid;
            // highlight message row when we're back from message page
            if (uid) {
              if (!list.rows[uid])
                uid += '-' + this.env.mailbox;
              if (list.rows[uid]) {
                list.select(uid);
          if (list) {
            if (response.action == 'list' || response.action == 'search') {
              // highlight message row when we're back from message page
              if (uid) {
                if (!list.rows[uid])
                  uid += '-' + this.env.mailbox;
                if (list.rows[uid]) {
                  list.select(uid);
                }
                delete this.env.list_uid;
              }
              delete this.env.list_uid;
              this.enable_command('set-listmode', this.env.threads && !is_multifolder);
              if (list.rowcount > 0 && !$(document.activeElement).is('input,textarea'))
                list.focus();
              this.msglist_select(list);
            }
            this.enable_command('set-listmode', this.env.threads && !is_multifolder);
            if (list.rowcount > 0)
              list.focus();
            this.msglist_select(list);
            this.triggerEvent('listupdate', { folder:this.env.mailbox, rowcount:list.rowcount });
            if (response.action != 'getunread')
              this.triggerEvent('listupdate', { folder:this.env.mailbox, rowcount:list.rowcount });
          }
        }
        else if (this.task == 'addressbook') {
@@ -7447,7 +7543,7 @@
            this.enable_command('search-create', this.env.source == '');
            this.enable_command('search-delete', this.env.search_id);
            this.update_group_commands();
            if (this.contact_list.rowcount > 0)
            if (this.contact_list.rowcount > 0 && !$(document.activeElement).is('input,textarea'))
              this.contact_list.focus();
            this.triggerEvent('listupdate', { folder:this.env.source, rowcount:this.contact_list.rowcount });
          }
@@ -7733,7 +7829,8 @@
    var submit_data = function() {
      var multiple = files.length > 1,
        ts = new Date().getTime(),
        content = '<span>' + (multiple ? ref.get_label('uploadingmany') : files[0].name) + '</span>';
        // jQuery way to escape filename (#1490530)
        content = $('<span>').text(multiple ? ref.get_label('uploadingmany') : files[0].name).html();
      // add to attachments list
      if (!ref.add2attachment_list(ts, { name:'', html:content, classname:'uploading', complete:false }))
@@ -7947,8 +8044,20 @@
  // get the IMP mailbox of the message with the given UID
  this.get_message_mailbox = function(uid)
  {
    var msg = this.env.messages ? this.env.messages[uid] : {};
    var msg = (this.env.messages && uid ? this.env.messages[uid] : null) || {};
    return msg.mbox || this.env.mailbox;
  };
  // build request parameters from single message id (maybe with mailbox name)
  this.params_from_uid = function(uid, params)
  {
    if (!params)
      params = {};
    params._uid = String(uid).split('-')[0];
    params._mbox = this.get_message_mailbox(uid);
    return params;
  };
  // gets cursor position
@@ -8046,14 +8155,10 @@
    if (!this.env.browser_capabilities)
      this.env.browser_capabilities = {};
    if (this.env.browser_capabilities.pdf === undefined)
      this.env.browser_capabilities.pdf = this.pdf_support_check();
    if (this.env.browser_capabilities.flash === undefined)
      this.env.browser_capabilities.flash = this.flash_support_check();
    if (this.env.browser_capabilities.tif === undefined)
      this.tif_support_check();
    $.each(['pdf', 'flash', 'tif'], function() {
      if (ref.env.browser_capabilities[this] === undefined)
        ref.env.browser_capabilities[this] = ref[this + '_support_check']();
    });
  };
  // Returns browser capabilities string
@@ -8072,11 +8177,14 @@
  this.tif_support_check = function()
  {
    var img = new Image();
    window.setTimeout(function() {
      var img = new Image();
      img.onload = function() { ref.env.browser_capabilities.tif = 1; };
      img.onerror = function() { ref.env.browser_capabilities.tif = 0; };
      img.src = ref.assets_path('program/resources/blank.tif');
    }, 10);
    img.onload = function() { ref.env.browser_capabilities.tif = 1; };
    img.onerror = function() { ref.env.browser_capabilities.tif = 0; };
    img.src = this.assets_path('program/resources/blank.tif');
    return 0;
  };
  this.pdf_support_check = function()
@@ -8111,6 +8219,14 @@
      else if (plugin.name && regex.test(plugin.name))
        return 1;
    }
    window.setTimeout(function() {
      $('<object>').css({position: 'absolute', left: '-10000px'})
        .attr({data: ref.assets_path('program/resources/dummy.pdf'), width: 1, height: 1, type: 'application/pdf'})
        .load(function() { ref.env.browser_capabilities.pdf = 1; })
        .error(function() { ref.env.browser_capabilities.pdf = 0; })
        .appendTo($('body'));
      }, 10);
    return 0;
  };
@@ -8159,15 +8275,16 @@
  // wrapper for localStorage.getItem(key)
  this.local_storage_get_item = function(key, deflt, encrypted)
  {
    var item;
    var item, result;
    // TODO: add encryption
    try {
      item = localStorage.getItem(this.get_local_storage_prefix() + key);
      result = JSON.parse(item);
    }
    catch (e) { }
    return item !== null ? JSON.parse(item) : (deflt || null);
    return result || deflt || null;
  };
  // wrapper for localStorage.setItem(key, data)
@@ -8197,6 +8314,14 @@
      return false;
    }
  };
  this.print_dialog = function()
  {
    if (bw.safari)
      setTimeout('window.print()', 10);
    else
      window.print();
  };
}  // end object rcube_webmail