From c41156c47ca5769406efd32550c670f1cbf42f1b Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Wed, 20 May 2015 15:24:08 +0000 Subject: [PATCH] check if we have PGP keys for all recipients, before switching to encrypted mail, when adding further recipients and before trying to send --- mail/js/app.js | 71 +++++++++++++++++------ phpgwapi/js/jsapi/app_base.js | 102 ++++++++++++++++++++++++++++------ 2 files changed, 139 insertions(+), 34 deletions(-) diff --git a/mail/js/app.js b/mail/js/app.js index d15f19adb8..bcd6ea33f5 100644 --- a/mail/js/app.js +++ b/mail/js/app.js @@ -4124,10 +4124,21 @@ app.classes.mail = AppJS.extend( }, /** - * Set email items draggable + * OnChange callback for recipients: + * - make them draggable + * - check if we have keys for recipients, if we compose an encrypted mail **/ set_dragging_dndCompose: function () { + // if we compose an encrypted mail, check if we have keys for new recipient + if (this.mailvelope_editor) + { + var self = this; + this.mailvelopeGetCheckRecipients().catch(function(_err) + { + self.egw.message(_err.message, 'error'); + }); + } var zIndex = 100; var dragItem = jQuery('div.ms-sel-item:not(div.ui-draggable)'); if (dragItem.length > 0) @@ -4458,6 +4469,7 @@ app.classes.mail = AppJS.extend( */ togglePgpEncrypt: function (_action) { + var self = this; if (_action.checked) { if (typeof mailvelope == 'undefined') @@ -4465,23 +4477,35 @@ app.classes.mail = AppJS.extend( this.egw.message(this.egw.lang('You need to install Mailvelope plugin available for Chrome and Firefox from %1.','mailvelope.com')+"\n"+ this.egw.lang('Add your domain as "%1" in options to list of email providers and enable API.', '*.'+this._mailvelopeDomain()), 'info'); + // switch encrypt button off again + this.et2.getWidgetById('composeToolbar')._actionManager.getActionById('pgp').set_checked(false); + jQuery('button#composeToolbar-pgp').toggleClass('toolbar_toggled'); return; } - var mimeType = this.et2.getWidgetById('mimeType'); - // currently Mailvelope only supports plain-text, switch to it if necessary - if (mimeType.get_value()) + // check if we have keys for all recipents, before switching + this.mailvelopeGetCheckRecipients().then(function(_recipients) { - mimeType.set_value(false); - this.et2._inst.submit(); - return; // ToDo: do that without reload - } - this.mailvelopeAvailable(this.mailvelopeCompose); - // ToDo: check recipients + var mimeType = self.et2.getWidgetById('mimeType'); + // currently Mailvelope only supports plain-text, switch to it if necessary + if (mimeType.get_value()) + { + mimeType.set_value(false); + self.et2._inst.submit(); + return; // ToDo: do that without reload + } + self.mailvelopeCompose(); + }) + .catch(function(_err) + { + self.egw.message(_err.message, 'error'); + self.et2.getWidgetById('composeToolbar')._actionManager.getActionById('pgp').set_checked(false); + jQuery('button#composeToolbar-pgp').toggleClass('toolbar_toggled'); + return; + }); } else { // switch Mailvelop off again, but warn user he will loose his content - var self = this; et2_dialog.show_dialog(function (_button_id) { if (_button_id == et2_dialog.YES_BUTTON ) @@ -4499,6 +4523,21 @@ app.classes.mail = AppJS.extend( } }, + /** + * Check if we have a key for all recipients + * + * @returns {Promise.} Array of recipients or Error with recipients without key + */ + mailvelopeGetCheckRecipients: function() + { + // collect all recipients + var recipients = this.et2.getWidgetById('to').get_value(); + recipients.concat(this.et2.getWidgetById('cc').get_value()); + recipients.concat(this.et2.getWidgetById('bcc').get_value()); + + return this._super.call(this, recipients); + }, + /** * Set the relevant widget to toolbar actions and submit * @@ -4509,16 +4548,16 @@ app.classes.mail = AppJS.extend( if (this.mailvelope_editor) { var self = this; - var recipients = this.et2.getWidgetById('to').get_value(); - recipients.concat(this.et2.getWidgetById('cc').get_value()); - // todo: bcc, do we disclosure them by adding them here? - this.mailvelope_editor.encrypt(recipients).then(function(_armored) + this.mailvelopeGetCheckRecipients().then(function(_recipients) + { + return self.mailvelope_editor.encrypt(_recipients); + }).then(function(_armored) { self.et2.getWidgetById('mimeType').set_value(false); self.et2.getWidgetById('mail_plaintext').set_disabled(false); self.et2.getWidgetById('mail_plaintext').set_value(_armored); self.et2._inst.submit(null,null,true); - }, function(_err) + }).catch(function(_err) { self.egw.message(_err.message, 'error'); }); diff --git a/phpgwapi/js/jsapi/app_base.js b/phpgwapi/js/jsapi/app_base.js index dd5c814011..3e778d8b38 100644 --- a/phpgwapi/js/jsapi/app_base.js +++ b/phpgwapi/js/jsapi/app_base.js @@ -835,47 +835,65 @@ var AppJS = Class.extend( mailvelopeAvailable: function(_callback) { var self = this; + var callback = jQuery.proxy(_callback, this); + if (typeof mailvelope !== 'undefined') { - self._mailvelopeOpenKeyring.call(self, _callback); + this.mailvelopeOpenKeyring().then(callback); } else { jQuery(window).on('mailvelope', function() { - self._mailvelopeOpenKeyring.call(self, _callback); + self.mailvelopeOpenKeyring.then(callback); }); } }, + /** + * Mailvelope "egroupware" Keyring + */ + mailvelope_keyring: undefined, + /** * Open (or create) "egroupware" keyring and call callback with it * - * @param {function} _callback called if and only if mailvelope is available (context is this!) + * @returns {Promise.} Keyring or Error with message */ - _mailvelopeOpenKeyring: function(_callback) + mailvelopeOpenKeyring: function() { - var callback = _callback; var self = this; - mailvelope.getKeyring('egroupware').then(function(_keyring) + return new Promise(function(_resolve, _reject) { - callback.call(self, _keyring); - }, - function(_err) - { - mailvelope.createKeyring('egroupware').then(function(_keyring) - { - self.egw.message(self.egw.lang('Keyring "%1" created.', self._mailvelopeDomain()+' (egroupware)')+"\n\n"+ - self.egw.lang('Please click on lock icon in lower right corner to create or import a key:')+"\n"+ - self.egw.lang("Go to Key Management and create a new key-pair or import your existing one.")+"\n\n"+ - self.egw.lang("You will NOT be able to send or receive encrypted mails before completing that step!"), 'info'); + if (self.mailvelope_keyring) _resolve(self.mailvelope_keyring); - callback.call(self, _keyring); + var resolve = _resolve; + var reject = _reject; + + mailvelope.getKeyring('egroupware').then(function(_keyring) + { + self.mailvelope_keyring = _keyring; + + resolve(_keyring); }, function(_err) { - self.egw.message(_err.message, 'error'); + mailvelope.createKeyring('egroupware').then(function(_keyring) + { + self.egw.message(self.egw.lang('Keyring "%1" created.', self._mailvelopeDomain()+' (egroupware)')+"\n\n"+ + self.egw.lang('Please click on lock icon in lower right corner to create or import a key:')+"\n"+ + self.egw.lang("Go to Key Management and create a new key-pair or import your existing one.")+"\n\n"+ + self.egw.lang("You will NOT be able to send or receive encrypted mails before completing that step!"), 'info'); + + self.mailvelope_keyring = _keyring; + + resolve(_keyring); + }, + function(_err) + { + reject(_err); + }); }); }); }, @@ -890,5 +908,53 @@ var AppJS = Class.extend( var parts = document.location.hostname.split('.'); if (parts.length > 1) parts.shift(); return parts.join('.'); + }, + + /** + * Check if we have a key for all recipients + * + * @param {Array} _recipients + * @returns {Promise.} Array of recipients or Error with recipients without key + */ + mailvelopeGetCheckRecipients: function(_recipients) + { + // replace rfc822 addresses with raw email, as Mailvelop does not like them + var rfc822_preg = /<([^'" <>]+)>$/; + var recipients = _recipients.map(function(_recipient) + { + var matches = _recipient.match(rfc822_preg); + return matches ? matches[1] : _recipient; + }); + + // check if we have keys for all recipients + var self = this; + return new Promise(function(_resolve, _reject) + { + var resolve = _resolve; + var reject = _reject; + self.mailvelopeOpenKeyring().then(function(_keyring) + { + _keyring.validKeyForAddress(recipients).then(function(_status) + { + var no_key = []; + for(var email in _status) + { + if (!_status[email]) no_key.push(email); + } + if (no_key.length) + { + reject(new Error(self.egw.lang('No key for recipient: '+no_key.join(', ')))); + } + else + { + resolve(recipients); + } + }); + }, + function(_err) + { + reject(_err); + }); + }); } });