From 4764079c6af092a6dfa18306601e1b33482fb756 Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Thu, 05 May 2011 03:26:50 -0400
Subject: [PATCH] - Fix bug where messages were deleted instead moved to trash folder after Shift key was used (#1487902), small code improvements

---
 program/js/app.js |  336 +++++++++++++++++++++++++++++++------------------------
 1 files changed, 189 insertions(+), 147 deletions(-)

diff --git a/program/js/app.js b/program/js/app.js
index 84e018f..99446d6 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -135,6 +135,14 @@
       return;
     }
 
+    // Enable debug console
+    if (!window.console || !window.console.log) {
+      window.console = new rcube_console();
+    }
+    else {
+      $('#console').hide();
+    }
+
     // find all registered gui containers
     for (var n in this.gui_containers)
       this.gui_containers[n] = $('#'+this.gui_containers[n]);
@@ -227,7 +235,7 @@
           }
         }
         else if (this.env.action == 'compose') {
-          this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'toggle-editor'];
+          this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'cancel', 'toggle-editor'];
 
           if (this.env.drafts_mailbox)
             this.env.compose_commands.push('savedraft')
@@ -316,22 +324,9 @@
           }
         }
 
-        if ((this.env.action=='add' || this.env.action=='edit') && this.gui_objects.editform) {
+        if ((this.env.action == 'add' || this.env.action == 'edit') && this.gui_objects.editform) {
           this.enable_command('save', true);
-          this.enable_command('upload-photo', this.env.coltypes.photo ? true : false);
-          this.enable_command('delete-photo', this.env.coltypes.photo && this.env.action == 'edit');
-
-          for (var col in this.env.coltypes)
-            this.init_edit_field(col, null);
-
-          $('.contactfieldgroup .row a.deletebutton').click(function(){ ref.delete_edit_field(this); return false });
-
-          $('select.addfieldmenu').change(function(e){
-            ref.insert_edit_field($(this).val(), $(this).attr('rel'), this);
-            this.selectedIndex = 0;
-          });
-
-          $("input[type='text']").first().focus();
+          this.init_contact_form();
         }
         else if (this.gui_objects.qsearchbox) {
           this.enable_command('search', 'reset-search', 'moveto', true);
@@ -348,14 +343,14 @@
       case 'settings':
         this.enable_command('preferences', 'identities', 'save', 'folders', true);
 
-        if (this.env.action=='identities') {
+        if (this.env.action == 'identities') {
           this.enable_command('add', this.env.identities_level < 2);
         }
-        else if (this.env.action=='edit-identity' || this.env.action=='add-identity') {
+        else if (this.env.action == 'edit-identity' || this.env.action == 'add-identity') {
           this.enable_command('add', this.env.identities_level < 2);
           this.enable_command('save', 'delete', 'edit', 'toggle-editor', true);
         }
-        else if (this.env.action=='folders') {
+        else if (this.env.action == 'folders') {
           this.enable_command('subscribe', 'unsubscribe', 'create-folder', 'rename-folder', true);
         }
         else if (this.env.action == 'edit-folder' && this.gui_objects.editform) {
@@ -478,13 +473,13 @@
 
     // trigger plugin hooks
     this.triggerEvent('actionbefore', {props:props, action:command});
-    var event_ret = this.triggerEvent('before'+command, props);
-    if (event_ret !== undefined) {
+    var ret = this.triggerEvent('before'+command, props);
+    if (ret !== undefined) {
       // abort if one the handlers returned false
-      if (event_ret === false)
+      if (ret === false)
         return false;
       else
-        props = event_ret;
+        props = ret;
     }
 
     // process internal command
@@ -646,7 +641,7 @@
               input_name.focus();
               break;
             }
-            else if (input_email.length && !rcube_check_email(input_email.val())) {
+            else if (this.task == 'settings' && input_email.length && (this.env.identities_level % 2) == 0 && !rcube_check_email(input_email.val())) {
               alert(this.get_label('noemailwarning'));
               input_email.focus();
               break;
@@ -662,13 +657,13 @@
 
       case 'delete':
         // mail task
-        if (this.task=='mail')
+        if (this.task == 'mail')
           this.delete_messages();
         // addressbook task
-        else if (this.task=='addressbook')
+        else if (this.task == 'addressbook')
           this.delete_contacts();
         // user settings task
-        else if (this.task=='settings')
+        else if (this.task == 'settings')
           this.delete_identity();
         break;
 
@@ -813,10 +808,10 @@
       case 'compose':
         var url = this.env.comm_path+'&_action=compose';
 
-        if (this.task=='mail') {
+        if (this.task == 'mail') {
           url += '&_mbox='+urlencode(this.env.mailbox);
 
-          if (this.env.mailbox==this.env.drafts_mailbox) {
+          if (this.env.mailbox == this.env.drafts_mailbox) {
             var uid;
             if (uid = this.get_single_uid())
               url += '&_draft_uid='+uid;
@@ -825,7 +820,7 @@
              url += '&_to='+urlencode(props);
         }
         // modify url if we're in addressbook
-        else if (this.task=='addressbook') {
+        else if (this.task == 'addressbook') {
           // switch to mail compose step directly
           if (props && props.indexOf('@') > 0) {
             url = this.get_task_url('mail', url);
@@ -834,24 +829,21 @@
           }
 
           // use contact_id passed as command parameter
-          var a_cids = [];
+          var n, len, a_cids = [];
           if (props)
             a_cids.push(props);
           // get selected contacts
           else if (this.contact_list) {
             var selection = this.contact_list.get_selection();
-            for (var n=0; n<selection.length; n++)
+            for (n=0, len=selection.length; n<len; n++)
               a_cids.push(selection[n]);
           }
 
           if (a_cids.length)
-            this.http_request('mailto', '_cid='+urlencode(a_cids.join(','))+'&_source='+urlencode(this.env.source), true);
+            this.http_post('mailto', {_cid: a_cids.join(','), _source: this.env.source}, true);
 
           break;
         }
-
-        // don't know if this is necessary...
-        url = url.replace(/&_framed=1/, '');
 
         this.redirect(url);
         break;
@@ -1372,22 +1364,20 @@
 
   this.doc_mouse_up = function(e)
   {
-    var model, list, li;
+    var model, list, li, id;
 
-    if (this.message_list) {
-      if (!rcube_mouse_is_over(e, this.message_list.list.parentNode))
-        this.message_list.blur();
+    if (list = this.message_list) {
+      if (!rcube_mouse_is_over(e, list.list.parentNode))
+        list.blur();
       else
-        this.message_list.focus();
-      list = this.message_list;
+        list.focus();
       model = this.env.mailboxes;
     }
-    else if (this.contact_list) {
-      if (!rcube_mouse_is_over(e, this.contact_list.list.parentNode))
-        this.contact_list.blur();
+    else if (list = this.contact_list) {
+      if (!rcube_mouse_is_over(e, list.list.parentNode))
+        list.blur();
       else
-        this.contact_list.focus();
-      list = this.contact_list;
+        list.focus();
       model = this.env.contactfolders;
     }
     else if (this.ksearch_value) {
@@ -1408,7 +1398,7 @@
 
     // reset 'pressed' buttons
     if (this.buttons_sel) {
-      for (var id in this.buttons_sel)
+      for (id in this.buttons_sel)
         if (typeof id !== 'function')
           this.button_out(this.buttons_sel[id], id);
       this.buttons_sel = {};
@@ -1507,8 +1497,6 @@
       this.command('previouspage');
     else if (list.key_pressed == 34)
       this.command('nextpage');
-    else
-      list.shiftkey = false;
   };
 
   this.msglist_get_preview = function()
@@ -1851,7 +1839,7 @@
       if (!this.env.frame_lock) {
         (this.is_framed() ? parent.rcmail : this).env.frame_lock = this.set_busy(true, 'loading');
       }
-      target.location.href = this.env.comm_path+url;
+      this.location_href(this.env.comm_path+url, target);
 
       // mark as read and change mbox unread counter
       if (action == 'preview' && this.message_list && this.message_list.rows[id] && this.message_list.rows[id].unread && this.env.preview_pane_mark_read >= 0) {
@@ -1973,7 +1961,7 @@
     // load message list to target frame/window
     if (mbox) {
       this.set_busy(true, 'loading');
-      target.location.href = this.env.comm_path+'&_mbox='+urlencode(mbox)+(page ? '&_page='+page : '')+url;
+      this.location_href(this.env.comm_path+'&_mbox='+urlencode(mbox)+(page ? '&_page='+page : '')+url, target);
     }
   };
 
@@ -2434,17 +2422,19 @@
   // delete selected messages from the current mailbox
   this.delete_messages = function()
   {
-    var selection = this.message_list ? $.merge([], this.message_list.get_selection()) : [];
+    var uid, i, len, trash = this.env.trash_mailbox,
+      list = this.message_list,
+      selection = list ? $.merge([], list.get_selection()) : [];
 
     // exit if no mailbox specified or if selection is empty
     if (!this.env.uid && !selection.length)
       return;
 
     // also select childs of collapsed rows
-    for (var uid, i=0, len=selection.length; i<len; i++) {
+    for (i=0, len=selection.length; i<len; i++) {
       uid = selection[i];
-      if (this.message_list.rows[uid].has_children && !this.message_list.rows[uid].expanded)
-        this.message_list.select_childs(uid);
+      if (list.rows[uid].has_children && !list.rows[uid].expanded)
+        list.select_childs(uid);
     }
 
     // if config is set to flag for deletion
@@ -2453,17 +2443,18 @@
       return false;
     }
     // if there isn't a defined trash mailbox or we are in it
-    else if (!this.env.trash_mailbox || this.env.mailbox == this.env.trash_mailbox)
+    // @TODO: we should check if defined trash mailbox exists
+    else if (!trash || this.env.mailbox == trash)
       this.permanently_remove_messages();
     // if there is a trash mailbox defined and we're not currently in it
     else {
       // if shift was pressed delete it immediately
-      if (this.message_list && this.message_list.shiftkey) {
+      if (list && list.shiftkey) {
         if (confirm(this.get_label('deletemessagesconfirm')))
           this.permanently_remove_messages();
       }
       else
-        this.move_messages(this.env.trash_mailbox);
+        this.move_messages(trash);
     }
 
     return true;
@@ -3013,11 +3004,11 @@
   this.compose_field_hash = function(save)
   {
     // check input fields
-    var value_to = $("[name='_to']").val();
-    var value_cc = $("[name='_cc']").val();
-    var value_bcc = $("[name='_bcc']").val();
-    var value_subject = $("[name='_subject']").val();
-    var str = '';
+    var ed, str = '',
+      value_to = $("[name='_to']").val(),
+      value_cc = $("[name='_cc']").val(),
+      value_bcc = $("[name='_bcc']").val(),
+      value_subject = $("[name='_subject']").val();
 
     if (value_to)
       str += value_to+':';
@@ -3028,9 +3019,8 @@
     if (value_subject)
       str += value_subject+':';
 
-    var editor = tinyMCE.get(this.env.composebody);
-    if (editor)
-      str += editor.getContent();
+    if (window.tinyMCE && (ed = tinyMCE.get(this.env.composebody)))
+      str += ed.getContent();
     else
       str += $("[name='_message']").val();
 
@@ -3180,17 +3170,13 @@
     if (!form)
       return false;
 
-    // get file input fields
-    var send = false;
-    for (var n=0; n<form.elements.length; n++)
-      if (form.elements[n].type=='file' && form.elements[n].value) {
-        send = true;
-        break;
-      }
+    // get file input field, count files on capable browser
+    var field = $('input[type=file]', form).get(0),
+      files = field.files ? field.files.length : field.value ? 1 : 0;
 
     // create hidden iframe and post upload form
-    if (send) {
-      this.async_upload_form(form, 'upload', function(e) {
+    if (files) {
+      var frame_name = this.async_upload_form(form, 'upload', function(e) {
         var d, content = '';
         try {
           if (this.contentDocument) {
@@ -3199,7 +3185,7 @@
             d = this.contentWindow.document;
           }
           content = d.childNodes[0].innerHTML;
-        } catch (e) {}
+        } catch (err) {}
 
         if (!content.match(/add2attachment/) && (!bw.opera || (rcmail.env.uploadframe && rcmail.env.uploadframe == e.data.ts))) {
           if (!content.match(/display_message/))
@@ -3212,7 +3198,9 @@
       });
 
       // display upload indicator and cancel button
-      var content = this.get_label('uploading');
+      var content = this.get_label('uploading' + (files > 1 ? 'many' : '')),
+        ts = frame_name.replace(/^rcmupload/, '');
+
       if (this.env.loadingicon)
         content = '<img src="'+this.env.loadingicon+'" alt="" />'+content;
       if (this.env.cancelicon)
@@ -3232,8 +3220,7 @@
     if (!this.gui_objects.attachmentlist)
       return false;
 
-    var li = $('<li>').attr('id', name).html(att.html);
-    var indicator;
+    var indicator, li = $('<li>').attr('id', name).html(att.html);
 
     // replace indicator's li
     if (upload_id && (indicator = document.getElementById(upload_id))) {
@@ -3260,7 +3247,7 @@
       return false;
 
     var list = this.gui_objects.attachmentlist.getElementsByTagName("li");
-    for (i=0;i<list.length;i++)
+    for (i=0; i<list.length; i++)
       if (list[i].id == name)
         this.gui_objects.attachmentlist.removeChild(list[i]);
   };
@@ -3268,7 +3255,7 @@
   this.remove_attachment = function(name)
   {
     if (name && this.env.attachments[name])
-      this.http_post('remove-attachment', '_file='+urlencode(name));
+      this.http_post('remove-attachment', { _id:this.env.compose_id, _file:name });
 
     return true;
   };
@@ -3486,15 +3473,14 @@
     if (q == this.ksearch_value)
       return;
 
-    if (q.length < min) {
+    if (q.length && q.length < min) {
       if (!this.env.acinfo) {
-        var label = this.get_label('autocompletechars');
-        label = label.replace('$min', min);
-        this.env.acinfo = this.display_message(label);
+        this.env.acinfo = this.display_message(
+          this.get_label('autocompletechars').replace('$min', min));
       }
       return;
     }
-    else if (this.env.acinfo && q.length == min) {
+    else if (this.env.acinfo) {
       this.hide_message(this.env.acinfo);
     }
 
@@ -3590,7 +3576,7 @@
 
     if (this.ksearch_pane)
       this.ksearch_pane.hide();
-  };
+   };
 
 
   /*********************************************************/
@@ -3665,7 +3651,7 @@
       add_url += '&_search='+this.env.search_request;
 
     this.set_busy(true, 'loading');
-    target.location.href = this.env.comm_path + (src ? '&_source='+urlencode(src) : '') + add_url;
+    this.location_href(this.env.comm_path + (src ? '&_source='+urlencode(src) : '') + add_url, target);
   };
 
   // send remote request to load contacts list
@@ -3711,7 +3697,7 @@
         add_url += '&_gid='+urlencode(this.env.group);
 
       this.set_busy(true);
-      target.location.href = this.env.comm_path+'&_action='+action+'&_source='+urlencode(this.env.source)+'&_cid='+urlencode(cid) + add_url;
+      this.location_href(this.env.comm_path+'&_action='+action+'&_source='+urlencode(this.env.source)+'&_cid='+urlencode(cid) + add_url, target);
     }
     return true;
   };
@@ -3781,25 +3767,25 @@
   // update a contact record in the list
   this.update_contact_row = function(cid, cols_arr, newcid)
   {
-    var row;
-    if (this.contact_list.rows[cid] && (row = this.contact_list.rows[cid].obj)) {
-      for (var c=0; c<cols_arr.length; c++)
+    var c, row, list = this.contact_list;
+
+    cid = String(cid).replace(this.identifier_expr, '_');
+
+    if (list.rows[cid] && (row = list.rows[cid].obj)) {
+      for (c=0; c<cols_arr.length; c++)
         if (row.cells[c])
           $(row.cells[c]).html(cols_arr[c]);
 
       // cid change
       if (newcid) {
+        newcid = String(newcid).replace(this.identifier_expr, '_');
         row.id = 'rcmrow' + newcid;
-        this.contact_list.remove_row(cid);
-        this.contact_list.init_row(row);
-        this.contact_list.selection[0] = newcid;
+        list.remove_row(cid);
+        list.init_row(row);
+        list.selection[0] = newcid;
         row.style.display = '';
       }
-
-      return true;
     }
-
-    return false;
   };
 
   // add row to contacts list
@@ -3813,7 +3799,7 @@
       even = rowcount%2,
       row = document.createElement('tr');
 
-    row.id = 'rcmrow'+cid;
+    row.id = 'rcmrow'+String(cid).replace(this.identifier_expr, '_');
     row.className = 'contact '+(even ? 'even' : 'odd');
 
     if (this.contact_list.in_selection(cid))
@@ -3830,6 +3816,28 @@
     this.contact_list.insert_row(row);
 
     this.enable_command('export', (this.contact_list.rowcount > 0));
+  };
+
+  this.init_contact_form = function()
+  {
+    var ref = this, col;
+
+    this.set_photo_actions($('#ff_photo').val());
+
+    for (col in this.env.coltypes)
+      this.init_edit_field(col, null);
+
+    $('.contactfieldgroup .row a.deletebutton').click(function() {
+      ref.delete_edit_field(this);
+      return false;
+    });
+
+    $('select.addfieldmenu').change(function(e) {
+      ref.insert_edit_field($(this).val(), $(this).attr('rel'), this);
+      this.selectedIndex = 0;
+    });
+
+    $("input[type='text']:visible").first().focus();
   };
 
   this.group_create = function()
@@ -3945,6 +3953,7 @@
     this.env.contactfolders[key] = this.env.contactgroups[key] = prop;
 
     var link = $('<a>').attr('href', '#')
+      .attr('rel', prop.source+':'+prop.id)
       .bind('click', function() { return rcmail.command('listgroup', prop, this);})
       .html(prop.name);
     var li = $('<li>').attr('id', 'rcmli'+key.replace(this.identifier_expr, '_'))
@@ -3960,13 +3969,34 @@
   {
     this.reset_add_input();
 
-    var key = 'G'+prop.source+prop.id, link, li = this.get_folder_li(key);
+    var key = 'G'+prop.source+prop.id,
+      li = this.get_folder_li(key),
+      link;
 
-    if (li && (link = li.firstChild) && link.tagName.toLowerCase() == 'a')
+    // group ID has changed, replace link node and identifiers
+    if (li && prop.newid) {
+      var newkey = 'G'+prop.source+prop.newid;
+      li.id = String('rcmli'+newkey).replace(this.identifier_expr, '_');
+      this.env.contactfolders[newkey] = this.env.contactfolders[key];
+      this.env.contactfolders[newkey].id = prop.newid;
+      this.env.group = prop.newid;
+
+      var newprop = $.extend({}, prop);
+      newprop.id = prop.newid;
+      newprop.type = 'group';
+
+      link = $('<a>').attr('href', '#')
+        .attr('rel', prop.source+':'+prop.newid)
+        .bind('click', function() { return rcmail.command('listgroup', newprop, this);})
+        .html(prop.name);
+      $(li).children().replaceWith(link);
+    }
+    // update displayed group name
+    else if (li && (link = li.firstChild) && link.tagName.toLowerCase() == 'a')
       link.innerHTML = prop.name;
 
     this.env.contactfolders[key].name = this.env.contactgroups[key].name = prop.name;
-    this.triggerEvent('group_update', { id:prop.id, source:prop.source, name:prop.name, li:li[0] });
+    this.triggerEvent('group_update', { id:prop.id, source:prop.source, name:prop.name, li:li[0], newid:prop.newid });
   };
 
 
@@ -3974,10 +4004,10 @@
   {
     if (!elem)
       elem = $('.ff_' + col);
-    
+
     elem.focus(function(){ ref.focus_textfield(this); })
       .blur(function(){ ref.blur_textfield(this); })
-      .each(function(){ this._placeholder = ref.env.coltypes[col].label; ref.blur_textfield(this); });
+      .each(function(){ this._placeholder = this.title = ref.env.coltypes[col].label; ref.blur_textfield(this); });
   };
 
   this.insert_edit_field = function(col, section, menu)
@@ -4106,26 +4136,31 @@
       this.photo_upload_id = this.set_busy(true, 'uploading');
     }
   };
-  
+
   this.replace_contact_photo = function(id)
   {
-    $('#ff_photo').val(id);
-    
-    var buttons = this.buttons['upload-photo'];
-    for (var n=0; n < buttons.length; n++)
-      $('#'+buttons[n].id).html(this.get_label(id == '-del-' ? 'addphoto' : 'replacephoto'));
-    
     var img_src = id == '-del-' ? this.env.photo_placeholder :
       this.env.comm_path + '&_action=photo&_source=' + this.env.source + '&_cid=' + this.env.cid + '&_photo=' + id;
+
+    this.set_photo_actions(id);
     $(this.gui_objects.contactphoto).children('img').attr('src', img_src);
-    
-    this.enable_command('delete-photo', id != '-del-');
   };
-  
+
   this.photo_upload_end = function()
   {
     this.set_busy(false, null, this.photo_upload_id);
     delete this.photo_upload_id;
+  };
+
+  this.set_photo_actions = function(id)
+  {
+    var n, buttons = this.buttons['upload-photo'];
+    for (n=0; n < buttons.length; n++)
+      $('#'+buttons[n].id).html(this.get_label(id == '-del-' ? 'addphoto' : 'replacephoto'));
+
+    $('#ff_photo').val(id);
+    this.enable_command('upload-photo', this.env.coltypes.photo ? true : false);
+    this.enable_command('delete-photo', this.env.coltypes.photo && id != '-del-');
   };
 
 
@@ -4161,7 +4196,7 @@
         add_url = '&_framed=1';
         target = window.frames[this.env.contentframe];
       }
-      target.location.href = this.env.comm_path+'&_action=edit-prefs&_section='+id+add_url;
+      this.location_href(this.env.comm_path+'&_action=edit-prefs&_section='+id+add_url, target);
     }
 
     return true;
@@ -4190,7 +4225,7 @@
 
     if (action && (id || action=='add-identity')) {
       this.set_busy(true);
-      target.location.href = this.env.comm_path+'&_action='+action+'&_iid='+id+add_url;
+      this.location_href(this.env.comm_path+'&_action='+action+'&_iid='+id+add_url, target);
     }
 
     return true;
@@ -4455,7 +4490,7 @@
       if (!this.env.frame_lock) {
         (parent.rcmail ? parent.rcmail : this).env.frame_lock = this.set_busy(true, 'loading');
       }
-      target.location.href = this.env.comm_path+url;
+      this.location_href(this.env.comm_path+url, target);
     }
   };
 
@@ -4792,7 +4827,7 @@
       var current_li, target_li;
 
       if ((current_li = this.get_folder_li(old, prefix))) {
-        $(current_li).removeClass('selected').removeClass('unfocused');
+        $(current_li).removeClass('selected').addClass('unfocused');
       }
       if ((target_li = this.get_folder_li(name, prefix))) {
         $(target_li).removeClass('unfocused').addClass('selected');
@@ -4821,17 +4856,18 @@
   // and for setting some message list global variables
   this.set_message_coltypes = function(coltypes, repl)
   {
-    this.env.coltypes = coltypes;
+    var list = this.message_list,
+      thead = list ? list.list.tHead : null,
+      cell, col, n, len, th, tr;
 
-    // set correct list titles
-    var thead = this.gui_objects.messagelist ? this.gui_objects.messagelist.tHead : null,
-      cell, col, n, len;
+    this.env.coltypes = coltypes;
 
     // replace old column headers
     if (thead) {
       if (repl) {
-        var th = document.createElement('thead'),
-          tr = document.createElement('tr');
+        th = document.createElement('thead');
+        tr = document.createElement('tr');
+
         for (c=0, len=repl.length; c < len; c++) {
           cell = document.createElement('td');
           cell.innerHTML = repl[c].html;
@@ -4865,15 +4901,16 @@
 
     if ((n = $.inArray('subject', this.env.coltypes)) >= 0) {
       this.set_env('subject_col', n);
-      if (this.message_list)
-        this.message_list.subject_col = n;
+      if (list)
+        list.subject_col = n;
     }
     if ((n = $.inArray('flag', this.env.coltypes)) >= 0)
       this.set_env('flagged_col', n);
     if ((n = $.inArray('status', this.env.coltypes)) >= 0)
       this.set_env('status_col', n);
 
-    this.message_list.init_header();
+    if (list)
+      list.init_header();
   };
 
   // replace content of row count display
@@ -5042,8 +5079,9 @@
       quota_width = parseInt(quota / 100 * width),
       pos = $(obj).position();
 
-    // Opera bug?
+    // workarounds for Opera and Webkit bugs
     pos.top = Math.max(0, pos.top);
+    pos.left = Math.max(0, pos.left);
 
     this.env.indicator_width = width;
     this.env.indicator_height = height;
@@ -5081,7 +5119,7 @@
       bar1.addClass('quota_mid');
     }
     else {
-      main.addClass(' quota_text_normal');
+      main.addClass(' quota_text_low');
       bar1.addClass('quota_low');
     }
 
@@ -5159,15 +5197,24 @@
     if (lock || lock === null)
       this.set_busy(true);
 
-    if (this.env.framed && window.parent)
-      parent.location.href = url;
+    if (this.is_framed())
+      parent.rcmail.redirect(url, lock);
     else
-      location.href = url;
+      this.location_href(url, window);
   };
 
   this.goto_url = function(action, query, lock)
   {
     this.redirect(this.url(action, query));
+  };
+
+  this.location_href = function(url, target)
+  {
+    // simulate real link click to force IE to send referer header
+    if (bw.ie && target == window)
+      $('<a>').attr('href', url).appendTo(document.body).get(0).click();
+    else
+      target.location.href = url;
   };
 
   // send a http request to the server
@@ -5343,15 +5390,15 @@
     this.set_busy(false, null, lock);
     request.abort();
 
-    if (errmsg)
+    if (request.status && errmsg)
       this.display_message(this.get_label('servererror') + ' (' + errmsg + ')', 'error');
   };
 
   // post the given form to a hidden iframe
   this.async_upload_form = function(form, action, onload)
   {
-    var ts = new Date().getTime();
-    var frame_name = 'rcmupload'+ts;
+    var ts = new Date().getTime(),
+      frame_name = 'rcmupload'+ts;
 
     // have to do it this way for IE
     // otherwise the form will be posted to a new window
@@ -5373,9 +5420,11 @@
     $(frame_name).bind('load', {ts:ts}, onload);
 
     form.target = frame_name;
-    form.action = this.url(action, { _uploadid:ts });
+    form.action = this.url(action, { _id:this.env.compose_id||'', _uploadid:ts });
     form.setAttribute('enctype', 'multipart/form-data');
     form.submit();
+
+    return frame_name;
   };
   
   // starts interval for keep-alive/check-recent signal
@@ -5387,14 +5436,7 @@
     if (this.env.keep_alive && !this.env.framed && this.task == 'mail' && this.gui_objects.mailboxlist)
       this._int = setInterval(function(){ ref.check_for_recent(false); }, this.env.keep_alive * 1000);
     else if (this.env.keep_alive && !this.env.framed && this.task != 'login' && this.env.action != 'print')
-      this._int = setInterval(function(){ ref.send_keep_alive(); }, this.env.keep_alive * 1000);
-  };
-
-  // sends keep-alive signal to the server
-  this.send_keep_alive = function()
-  {
-    var d = new Date();
-    this.http_request('keep-alive', '_t='+d.getTime());
+      this._int = setInterval(function(){ ref.http_request('keep-alive'); }, this.env.keep_alive * 1000);
   };
 
   // sends request to check for recent messages
@@ -5403,7 +5445,7 @@
     if (this.busy)
       return;
 
-    var lock, addurl = '_t=' + (new Date().getTime()) + '&_mbox=' + urlencode(this.env.mailbox);
+    var lock, addurl = '_mbox=' + urlencode(this.env.mailbox);
 
     if (refresh) {
       lock = this.set_busy(true, 'checkingmail');

--
Gitblit v1.9.1