From 82dcbb7488ce1625ba4f41fbdc8e6319d3da9691 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak <alec@alec.pl> Date: Sun, 20 Sep 2015 11:45:53 -0400 Subject: [PATCH] Fix various issues in Mailvelope integration (#1490533) --- program/js/app.js | 174 ++++++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 114 insertions(+), 60 deletions(-) diff --git a/program/js/app.js b/program/js/app.js index fcba219..8a9712f 100644 --- a/program/js/app.js +++ b/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; } @@ -325,7 +325,9 @@ else if (this.env.action == 'get') this.enable_command('download', 'print', true); // show printing dialog - else if (this.env.action == 'print' && this.env.uid) { + else if (this.env.action == 'print' && this.env.uid + && !this.env.is_pgp_content && !this.env.pgp_mime_part + ) { this.print_dialog(); } @@ -512,8 +514,11 @@ break; case 'login': - var input_user = $('#rcmloginuser'); - input_user.bind('keyup', function(e){ return ref.login_user_keyup(e); }); + var tz, tz_name, jstz = window.jstz, + input_user = $('#rcmloginuser'), + input_tz = $('#rcmlogintz'); + + input_user.bind('keyup', function(e) { return ref.login_user_keyup(e); }); if (input_user.val() == '') input_user.focus(); @@ -521,14 +526,10 @@ $('#rcmloginpwd').focus(); // detect client timezone - if (window.jstz) { - var timezone = jstz.determine(); - if (timezone.name()) - $('#rcmlogintz').val(timezone.name()); - } - else { - $('#rcmlogintz').val(new Date().getStdTimezoneOffset() / -60); - } + if (jstz && (tz = jstz.determine())) + tz_name = tz.name(); + + input_tz.val(tz_name ? tz_name : (new Date().getStdTimezoneOffset() / -60)); // display 'loading' message on form submit, lock submit button $('form').submit(function () { @@ -594,7 +595,7 @@ .bind('mouseup', body_mouseup) .bind('keydown', function(e){ return ref.doc_keypress(e); }); - $('iframe').load(function(e) { + $('iframe').on('load', function(e) { try { $(this.contentDocument || this.contentWindow).on('mouseup', body_mouseup); } catch (e) {/* catch possible "Permission denied" error in IE */ } }) @@ -655,7 +656,9 @@ } // 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.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; @@ -764,7 +767,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; @@ -1190,8 +1193,8 @@ 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); } @@ -1200,7 +1203,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': @@ -1208,7 +1211,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; @@ -1270,7 +1273,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')); @@ -1617,8 +1620,8 @@ // 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)+'&'); @@ -2175,10 +2178,16 @@ this.set_list_sorting = function(sort_col, sort_order) { + var sort_old = this.env.sort_col == 'arrival' ? 'date' : this.env.sort_col, + sort_new = sort_col == 'arrival' ? 'date' : sort_col; + // set table header class - $('#rcm'+this.env.sort_col).removeClass('sorted'+(this.env.sort_order.toUpperCase())); - if (sort_col) - $('#rcm'+sort_col).addClass('sorted'+sort_order); + $('#rcm' + sort_old).removeClass('sorted' + this.env.sort_order.toUpperCase()); + if (sort_new) + $('#rcm' + sort_new).addClass('sorted' + sort_order); + + // if sorting by 'arrival' is selected, click on date column should not switch to 'date' + $('#rcmdate > a').prop('rel', sort_col == 'arrival' ? 'arrival' : 'date'); this.env.sort_col = sort_col; this.env.sort_order = sort_order; @@ -2235,35 +2244,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) { @@ -3356,13 +3363,13 @@ } }; - // + // Load Mailvelope functionality (and initialize keyring if needed) this.mailvelope_load = function(action) { if (this.env.browser_capabilities) this.env.browser_capabilities['pgpmime'] = 1; - var keyring = this.get_local_storage_prefix(); + var keyring = this.env.user_id; mailvelope.getKeyring(keyring).then(function(kr) { ref.mailvelope_keyring = kr; @@ -3378,17 +3385,20 @@ }); }; - // + // Initializes Mailvelope editor or display container this.mailvelope_init = function(action, keyring) { - if (action == 'show' || action == 'preview') { + if (!window.mailvelope) + return; + + if (action == 'show' || action == 'preview' || action == 'print') { // decrypt text body - if (this.env.is_pgp_content && window.mailvelope) { + if (this.env.is_pgp_content) { var data = $(this.env.is_pgp_content).text(); ref.mailvelope_display_container(this.env.is_pgp_content, data, keyring); } // load pgp/mime message and pass it to the mailvelope display container - else if (this.env.pgp_mime_part && window.mailvelope) { + else if (this.env.pgp_mime_part) { var msgid = this.display_message(this.get_label('loadingdata'), 'loading'), selector = this.env.pgp_mime_container; @@ -3404,21 +3414,32 @@ }); } } - else if (action == 'compose' && window.mailvelope) { + else if (action == 'compose') { this.env.compose_commands.push('compose-encrypted'); + // display the toolbar button + $('#' + this.buttons['compose-encrypted'][0].id).show(); + + var is_html = $('input[name="_is_html"]').val() > 0; if (this.env.pgp_mime_message) { // fetch PGP/Mime part and open load into Mailvelope editor var lock = this.set_busy(true, this.get_label('loadingdata')); + $.ajax({ type: 'GET', url: this.url('get', this.env.pgp_mime_message), error: function(o, status, err) { ref.http_error(o, status, err, lock); - ref.enable_command('compose-encrypted', true); + ref.enable_command('compose-encrypted', !is_html); }, success: function(data) { ref.set_busy(false, null, lock); + + if (is_html) { + ref.command('toggle-editor', {html: false, noconvert: true}); + $('#' + ref.env.composebody).val(''); + } + ref.compose_encrypted({ quotedMail: data }); ref.enable_command('compose-encrypted', true); } @@ -3426,7 +3447,7 @@ } else { // enable encrypted compose toggle - this.enable_command('compose-encrypted', true); + this.enable_command('compose-encrypted', !is_html); } } }; @@ -3434,7 +3455,7 @@ // handler for the 'compose-encrypted' command this.compose_encrypted = function(props) { - var container = $('#' + this.env.composebody).parent(); + var options, container = $('#' + this.env.composebody).parent(); // remove Mailvelope editor if active if (ref.mailvelope_editor) { @@ -3446,13 +3467,23 @@ .find('iframe:not([aria-hidden=true])').remove(); $('#' + ref.env.composebody).show(); $("[name='_pgpmime']").remove(); + + // disable commands that operate on the compose body + ref.enable_command('spellcheck', 'insert-sig', 'toggle-editor', 'insert-response', 'save-response', true); + ref.triggerEvent('compose-encrypted', { active:false }); } // embed Mailvelope editor container else { - var options = { predefinedText: $('#' + this.env.composebody).val() }; + if (this.spellcheck_state()) + this.editor.spellcheck_stop(); + if (props.quotedMail) { options = { quotedMail: props.quotedMail, quotedMailIndent: false }; } + else { + options = { predefinedText: $('#' + this.env.composebody).val() }; + } + if (this.env.compose_mode == 'reply') { options.quotedMailIndent = true; options.quotedMailHeader = this.env.compose_reply_header; @@ -3466,6 +3497,10 @@ container.addClass('mailvelope'); $('#' + ref.env.composebody).hide(); + // disable commands that operate on the compose body + ref.enable_command('spellcheck', 'insert-sig', 'toggle-editor', 'insert-response', 'save-response', false); + ref.triggerEvent('compose-encrypted', { active:true }); + // notify user about loosing attachments if (ref.env.attachments && !$.isEmptyObject(ref.env.attachments)) { alert(ref.get_label('encryptnoattachments')); @@ -3476,6 +3511,7 @@ } }).catch(function(err) { console.error(err); + console.log(options); }); } }; @@ -3615,7 +3651,7 @@ this.mailvelope_display_container = function(selector, data, keyring, msgid) { mailvelope.createDisplayContainer(selector, data, keyring, { showExternalContent: this.env.safemode }).then(function() { - $(selector).addClass('mailvelope').find('.message-part, .part-notice').hide(); + $(selector).addClass('mailvelope').children().not('iframe').hide(); ref.hide_message(msgid); setTimeout(function() { $(window).resize(); }, 10); }).catch(function(err) { @@ -3758,7 +3794,7 @@ ref.hide_message(lock); if (errorCode) { - ref.display_message('Failed to get key from keyserver', 'error'); + ref.display_message(ref.get_label('keyservererror'), 'error'); return; } @@ -3768,9 +3804,9 @@ // alert(ref.get_label('Key import was rejected')); } else { + var $key = keyid.substr(-8).toUpperCase(); btn.closest('.key').fadeOut(); - ref.display_message(ref.get_label('Public key $key successfully imported into your key ring') - .replace('$key', keyid.substr(-8).toUpperCase()), 'confirmation'); + ref.display_message(ref.get_label('keyimportsuccess').replace('$key', $key), 'confirmation'); } }).catch(function(err) { console.log(err); @@ -4126,7 +4162,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 }); } @@ -4230,6 +4266,8 @@ if (result) { // update internal format flag $("input[name='_is_html']").val(props.html ? 1 : 0); + // enable encrypted compose toggle + this.enable_command('compose-encrypted', !props.html); } return result; @@ -4409,7 +4447,7 @@ } }, 5000); - $(window).unload(function() { + $(window).on('unload', function() { // remove copy from local storage if compose screen is left after warning if (!ref.env.server_error) ref.remove_compose_data(ref.env.compose_id); @@ -4629,7 +4667,7 @@ }; // upload (attachment) file - this.upload_file = function(form, action) + this.upload_file = function(form, action, lock) { if (!form) return; @@ -4671,6 +4709,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) @@ -7598,7 +7639,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) { @@ -8061,7 +8102,7 @@ } this.enable_command('set-listmode', this.env.threads && !is_multifolder); - if (list.rowcount > 0) + if (list.rowcount > 0 && !$(document.activeElement).is('input,textarea')) list.focus(); this.msglist_select(list); } @@ -8077,7 +8118,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 }); } @@ -8363,7 +8404,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 })) @@ -8577,10 +8619,22 @@ // 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 this.get_caret_pos = function(obj) { -- Gitblit v1.9.1