| | |
| | | this.http_post(postact, postdata); |
| | | } |
| | | |
| | | this.check_mailvelope(this.env.action); |
| | | |
| | | // detect browser capabilities |
| | | if (!this.is_framed() && !this.env.extwin) |
| | | this.browser_capabilities_check(); |
| | |
| | | $('input.rcpagejumper').val(this.env.current_page).prop('disabled', this.env.pagecount < 2); |
| | | }; |
| | | |
| | | // check for mailvelope API |
| | | this.check_mailvelope = function(action) |
| | | { |
| | | if (typeof window.mailvelope !== 'undefined') { |
| | | this.mailvelope_load(action); |
| | | } |
| | | else { |
| | | $(window).on('mailvelope', function() { |
| | | ref.mailvelope_load(action); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | // |
| | | this.mailvelope_load = function(action) |
| | | { |
| | | if (this.env.browser_capabilities) |
| | | this.env.browser_capabilities['pgpmime'] = 1; |
| | | |
| | | var keyring = this.get_local_storage_prefix(); |
| | | |
| | | mailvelope.getKeyring(keyring).then(function(kr) { |
| | | ref.mailvelope_keyring = kr; |
| | | ref.mailvelope_init(action, kr); |
| | | }).catch(function(err) { |
| | | // attempt to create a new keyring for this app/user |
| | | mailvelope.createKeyring(keyring).then(function(kr) { |
| | | ref.mailvelope_keyring = kr; |
| | | ref.mailvelope_init(action, kr); |
| | | }).catch(function(err) { |
| | | console.error(err); |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | // |
| | | this.mailvelope_init = function(action, keyring) |
| | | { |
| | | if (action == 'show' || action == 'preview') { |
| | | // decrypt text body |
| | | if (this.env.is_pgp_content && window.mailvelope) { |
| | | 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) { |
| | | var msgid = this.display_message(this.get_label('loadingdata'), 'loading'), |
| | | selector = this.env.pgp_mime_container; |
| | | |
| | | $.ajax({ |
| | | type: 'GET', |
| | | url: this.url('get', { '_mbox': this.env.mailbox, '_uid': this.env.uid, '_part': this.env.pgp_mime_part }), |
| | | error: function(o, status, err) { |
| | | ref.http_error(o, status, err, msgid); |
| | | }, |
| | | success: function(data) { |
| | | ref.mailvelope_display_container(selector, data, keyring, msgid); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | else if (action == 'compose' && window.mailvelope) { |
| | | this.env.compose_commands.push('compose-encrypted'); |
| | | |
| | | 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); |
| | | }, |
| | | success: function(data) { |
| | | ref.set_busy(false, null, lock); |
| | | ref.compose_encrypted({ quotedMail: data }); |
| | | ref.enable_command('compose-encrypted', true); |
| | | } |
| | | }); |
| | | } |
| | | else { |
| | | // enable encrypted compose toggle |
| | | this.enable_command('compose-encrypted', true); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // handler for the 'compose-encrypted' command |
| | | this.compose_encrypted = function(props) |
| | | { |
| | | var container = $('#' + this.env.composebody).parent(); |
| | | |
| | | // remove Mailvelope editor if active |
| | | if (ref.mailvelope_editor) { |
| | | ref.mailvelope_editor = null; |
| | | ref.compose_skip_unsavedcheck = false; |
| | | ref.set_button('compose-encrypted', 'act'); |
| | | |
| | | container.removeClass('mailvelope') |
| | | .find('iframe:not([aria-hidden=true])').remove(); |
| | | $('#' + ref.env.composebody).show(); |
| | | $("[name='_pgpmime']").remove(); |
| | | } |
| | | // embed Mailvelope editor container |
| | | else { |
| | | var options = { predefinedText: $('#' + this.env.composebody).val() }; |
| | | if (props.quotedMail) { |
| | | options = { quotedMail: props.quotedMail, quotedMailIndent: false }; |
| | | } |
| | | if (this.env.compose_mode == 'reply') { |
| | | options.quotedMailIndent = true; |
| | | options.quotedMailHeader = this.env.compose_reply_header; |
| | | } |
| | | |
| | | mailvelope.createEditorContainer('#' + container.attr('id'), ref.mailvelope_keyring, options).then(function(editor) { |
| | | ref.mailvelope_editor = editor; |
| | | ref.compose_skip_unsavedcheck = true; |
| | | ref.set_button('compose-encrypted', 'sel'); |
| | | |
| | | container.addClass('mailvelope'); |
| | | $('#' + ref.env.composebody).hide(); |
| | | |
| | | // notify user about loosing attachments |
| | | if (ref.env.attachments && !$.isEmptyObject(ref.env.attachments)) { |
| | | alert(ref.get_label('encryptnoattachments')); |
| | | |
| | | $.each(ref.env.attachments, function(name, attach) { |
| | | ref.remove_from_attachment_list(name); |
| | | }); |
| | | } |
| | | }).catch(function(err) { |
| | | console.error(err); |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | // callback to replace the message body with the full armored |
| | | this.mailvelope_submit_messageform = function(draft, saveonly) |
| | | { |
| | | // get recipients |
| | | var recipients = []; |
| | | $.each(['to', 'cc', 'bcc'], function(i,field) { |
| | | var pos, rcpt, val = $.trim($('[name="_' + field + '"]').val()); |
| | | while (val.length && rcube_check_email(val, true)) { |
| | | rcpt = RegExp.$2; |
| | | recipients.push(rcpt); |
| | | val = val.substr(val.indexOf(rcpt) + rcpt.length + 1).replace(/^\s*,\s*/, ''); |
| | | } |
| | | }); |
| | | |
| | | // check if we have keys for all recipients |
| | | var isvalid = recipients.length > 0; |
| | | ref.mailvelope_keyring.validKeyForAddress(recipients).then(function(status) { |
| | | var missing_keys = []; |
| | | $.each(status, function(k,v) { |
| | | if (v === false) { |
| | | isvalid = false; |
| | | missing_keys.push(k); |
| | | } |
| | | }); |
| | | |
| | | // list recipients with missing keys |
| | | if (!isvalid && missing_keys.length) { |
| | | // load publickey.js |
| | | if (!$('script#publickeyjs').length) { |
| | | $('<script>') |
| | | .attr('id', 'publickeyjs') |
| | | .attr('src', ref.assets_path('program/js/publickey.js')) |
| | | .appendTo(document.body); |
| | | } |
| | | |
| | | // display dialog with missing keys |
| | | ref.show_popup_dialog( |
| | | ref.get_label('nopubkeyfor').replace('$email', missing_keys.join(', ')) + |
| | | '<p>' + ref.get_label('searchpubkeyservers') + '</p>', |
| | | ref.get_label('encryptedsendialog'), |
| | | [{ |
| | | text: ref.get_label('search'), |
| | | 'class': 'mainaction', |
| | | click: function() { |
| | | var $dialog = $(this); |
| | | ref.mailvelope_search_pubkeys(missing_keys, function() { |
| | | $dialog.dialog('close') |
| | | }); |
| | | } |
| | | }, |
| | | { |
| | | text: ref.get_label('cancel'), |
| | | click: function(){ |
| | | $(this).dialog('close'); |
| | | } |
| | | }] |
| | | ); |
| | | return false; |
| | | } |
| | | |
| | | if (!isvalid) { |
| | | if (!recipients.length) { |
| | | alert(ref.get_label('norecipientwarning')); |
| | | $("[name='_to']").focus(); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | // add sender identity to recipients to be able to decrypt our very own message |
| | | var senders = [], selected_sender = ref.env.identities[$("[name='_from'] option:selected").val()]; |
| | | $.each(ref.env.identities, function(k, sender) { |
| | | senders.push(sender.email); |
| | | }); |
| | | |
| | | ref.mailvelope_keyring.validKeyForAddress(senders).then(function(status) { |
| | | valid_sender = null; |
| | | $.each(status, function(k,v) { |
| | | if (v !== false) { |
| | | valid_sender = k; |
| | | if (valid_sender == selected_sender) { |
| | | return false; // break |
| | | } |
| | | } |
| | | }); |
| | | |
| | | if (!valid_sender) { |
| | | if (!confirm(ref.get_label('nopubkeyforsender'))) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | recipients.push(valid_sender); |
| | | |
| | | ref.mailvelope_editor.encrypt(recipients).then(function(armored) { |
| | | // all checks passed, send message |
| | | var form = ref.gui_objects.messageform, |
| | | hidden = $("[name='_pgpmime']", form), |
| | | msgid = ref.set_busy(true, draft || saveonly ? 'savingmessage' : 'sendingmessage') |
| | | |
| | | form.target = 'savetarget'; |
| | | form._draft.value = draft ? '1' : ''; |
| | | form.action = ref.add_url(form.action, '_unlock', msgid); |
| | | form.action = ref.add_url(form.action, '_framed', 1); |
| | | |
| | | if (saveonly) { |
| | | form.action = ref.add_url(form.action, '_saveonly', 1); |
| | | } |
| | | |
| | | // send pgp conent via hidden field |
| | | if (!hidden.length) { |
| | | hidden = $('<input type="hidden" name="_pgpmime">').appendTo(form); |
| | | } |
| | | hidden.val(armored); |
| | | |
| | | form.submit(); |
| | | |
| | | }).catch(function(err) { |
| | | console.log(err); |
| | | }); // mailvelope_editor.encrypt() |
| | | |
| | | }).catch(function(err) { |
| | | console.error(err); |
| | | }); // mailvelope_keyring.validKeyForAddress(senders) |
| | | |
| | | }).catch(function(err) { |
| | | console.error(err); |
| | | }); // mailvelope_keyring.validKeyForAddress(recipients) |
| | | |
| | | return false; |
| | | }; |
| | | |
| | | // wrapper for the mailvelope.createDisplayContainer API call |
| | | 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(); |
| | | ref.hide_message(msgid); |
| | | setTimeout(function() { $(window).resize(); }, 10); |
| | | }).catch(function(err) { |
| | | console.error(err); |
| | | ref.hide_message(msgid); |
| | | ref.display_message('Message decryption failed: ' + err.message, 'error') |
| | | }); |
| | | }; |
| | | |
| | | // subroutine to query keyservers for public keys |
| | | this.mailvelope_search_pubkeys = function(emails, resolve) |
| | | { |
| | | // query with publickey.js |
| | | var deferreds = [], |
| | | pk = new PublicKey(), |
| | | lock = ref.display_message(ref.get_label('loading'), 'loading'); |
| | | |
| | | $.each(emails, function(i, email) { |
| | | var d = $.Deferred(); |
| | | pk.search(email, function(results, errorCode) { |
| | | if (errorCode !== null) { |
| | | // rejecting would make all fail |
| | | // d.reject(email); |
| | | d.resolve([email]); |
| | | } |
| | | else { |
| | | d.resolve([email].concat(results)); |
| | | } |
| | | }); |
| | | deferreds.push(d); |
| | | }); |
| | | |
| | | $.when.apply($, deferreds).then(function() { |
| | | var missing_keys = [], |
| | | key_selection = []; |
| | | |
| | | // alanyze results of all queries |
| | | $.each(arguments, function(i, result) { |
| | | var email = result.shift(); |
| | | if (!result.length) { |
| | | missing_keys.push(email); |
| | | } |
| | | else { |
| | | key_selection = key_selection.concat(result); |
| | | } |
| | | }); |
| | | |
| | | ref.hide_message(lock); |
| | | resolve(true); |
| | | |
| | | // show key import dialog |
| | | if (key_selection.length) { |
| | | ref.mailvelope_key_import_dialog(key_selection); |
| | | } |
| | | // some keys could not be found |
| | | if (missing_keys.length) { |
| | | ref.display_message(ref.get_label('nopubkeyfor').replace('$email', missing_keys.join(', ')), 'warning'); |
| | | } |
| | | }, function() { |
| | | console.error('Pubkey lookup failed with', arguments); |
| | | ref.hide_message(lock); |
| | | ref.display_message('pubkeysearcherror', 'error'); |
| | | resolve(false); |
| | | }); |
| | | }; |
| | | |
| | | // list the given public keys in a dialog with options to import |
| | | // them into the local Maivelope keyring |
| | | this.mailvelope_key_import_dialog = function(candidates) |
| | | { |
| | | var ul = $('<div>').addClass('listing mailvelopekeyimport'); |
| | | $.each(candidates, function(i, keyrec) { |
| | | var li = $('<div>').addClass('key'); |
| | | if (keyrec.revoked) li.addClass('revoked'); |
| | | if (keyrec.disabled) li.addClass('disabled'); |
| | | if (keyrec.expired) li.addClass('expired'); |
| | | |
| | | li.append($('<label>').addClass('keyid').text(ref.get_label('keyid'))); |
| | | li.append($('<a>').text(keyrec.keyid.substr(-8).toUpperCase()) |
| | | .attr('href', keyrec.info) |
| | | .attr('target', '_blank') |
| | | .attr('tabindex', '-1')); |
| | | |
| | | li.append($('<label>').addClass('keylen').text(ref.get_label('keylength'))); |
| | | li.append($('<span>').text(keyrec.keylen)); |
| | | |
| | | if (keyrec.expirationdate) { |
| | | li.append($('<label>').addClass('keyexpired').text(ref.get_label('keyexpired'))); |
| | | li.append($('<span>').text(new Date(keyrec.expirationdate * 1000).toDateString())); |
| | | } |
| | | |
| | | if (keyrec.revoked) { |
| | | li.append($('<span>').addClass('keyrevoked').text(ref.get_label('keyrevoked'))); |
| | | } |
| | | |
| | | var ul_ = $('<ul>').addClass('uids'); |
| | | $.each(keyrec.uids, function(j, uid) { |
| | | var li_ = $('<li>').addClass('uid'); |
| | | if (uid.revoked) li_.addClass('revoked'); |
| | | if (uid.disabled) li_.addClass('disabled'); |
| | | if (uid.expired) li_.addClass('expired'); |
| | | |
| | | ul_.append(li_.text(uid.uid)); |
| | | }); |
| | | |
| | | li.append(ul_); |
| | | li.append($('<input>') |
| | | .attr('type', 'button') |
| | | .attr('rel', keyrec.keyid) |
| | | .attr('value', ref.get_label('import')) |
| | | .addClass('button importkey') |
| | | .prop('disabled', keyrec.revoked || keyrec.disabled || keyrec.expired)); |
| | | |
| | | ul.append(li); |
| | | }); |
| | | |
| | | // display dialog with missing keys |
| | | ref.show_popup_dialog( |
| | | $('<div>') |
| | | .append($('<p>').html(ref.get_label('encryptpubkeysfound'))) |
| | | .append(ul), |
| | | ref.get_label('importpubkeys'), |
| | | [{ |
| | | text: ref.get_label('close'), |
| | | click: function(){ |
| | | $(this).dialog('close'); |
| | | } |
| | | }] |
| | | ); |
| | | |
| | | // delegate handler for import button clicks |
| | | ul.on('click', 'input.button.importkey', function() { |
| | | var btn = $(this), |
| | | keyid = btn.attr('rel'), |
| | | pk = new PublicKey(), |
| | | lock = ref.display_message(ref.get_label('loading'), 'loading'); |
| | | |
| | | // fetch from keyserver and import to Mailvelope keyring |
| | | pk.get(keyid, function(armored, errorCode) { |
| | | ref.hide_message(lock); |
| | | |
| | | if (errorCode) { |
| | | ref.display_message('Failed to get key from keyserver', 'error'); |
| | | return; |
| | | } |
| | | |
| | | // import to keyring |
| | | ref.mailvelope_keyring.importPublicKey(armored).then(function(status) { |
| | | if (status === 'REJECTED') { |
| | | // alert(ref.get_label('Key import was rejected')); |
| | | } |
| | | else { |
| | | 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'); |
| | | } |
| | | }).catch(function(err) { |
| | | console.log(err); |
| | | }); |
| | | }); |
| | | }); |
| | | |
| | | }; |
| | | |
| | | |
| | | /*********************************************************/ |
| | | /********* mailbox folders methods *********/ |
| | | /*********************************************************/ |
| | |
| | | } |
| | | }] |
| | | ); |
| | | } |
| | | |
| | | // delegate sending to Mailvelope routine |
| | | if (this.mailvelope_editor) { |
| | | return this.mailvelope_submit_messageform(draft, saveonly); |
| | | } |
| | | |
| | | // all checks passed, send message |
| | |
| | | |
| | | // reset history of hidden iframe used for saving draft (#1489643) |
| | | // but don't do this on timer-triggered draft-autosaving (#1489789) |
| | | if (window.frames['savetarget'] && window.frames['savetarget'].history && !this.draft_autosave_submit) { |
| | | if (window.frames['savetarget'] && window.frames['savetarget'].history && !this.draft_autosave_submit && !this.mailvelope_editor) { |
| | | window.frames['savetarget'].history.back(); |
| | | } |
| | | |
| | |
| | | for (id in this.env.attachments) |
| | | str += id; |
| | | |
| | | // we can't detect changes in the Mailvelope editor so assume it changed |
| | | if (this.mailvelope_editor) { |
| | | str += ';' + new Date().getTime(); |
| | | } |
| | | |
| | | if (save) |
| | | this.cmp_hash = str; |
| | | |