OpenPGP improvements (first step)

openpgpjs: 0.7.2 -> 0.10.1
additional fixes
This commit is contained in:
RainLoop Team 2015-06-23 01:33:27 +04:00
parent 09334159c2
commit 34a9b8cbc5
28 changed files with 1363 additions and 644 deletions

View file

@ -109,6 +109,7 @@
'Settings': 'settings',
'Menu': 'menu',
'PopupComposeOpenPGP': 'compose-open-pgp',
'PopupMessageOpenPGP': 'message-open-pgp',
'PopupKeyboardShortcutsHelp': 'popup-keyboard-shortcuts-help',
'PopupAsk': 'popup-ask'
};

View file

@ -390,7 +390,7 @@
*/
Links.prototype.openPgpJs = function ()
{
return this.sStaticPrefix + 'js/min/openpgp.js';
return this.sStaticPrefix + 'js/min/openpgp.js';
};
/**

10
dev/External/ko.js vendored
View file

@ -7,6 +7,7 @@
window = require('window'),
_ = require('_'),
$ = require('$'),
JSON = require('JSON'),
Opentip = require('Opentip'),
fDisposalTooltipHelper = function (oElement) {
@ -63,6 +64,15 @@
}
};
ko.bindingHandlers.json = {
'init': function (oElement, fValueAccessor) {
$(oElement).text(JSON.stringify(ko.unwrap(fValueAccessor())));
},
'update': function (oElement, fValueAccessor) {
$(oElement).text(JSON.stringify(ko.unwrap(fValueAccessor())));
}
};
ko.bindingHandlers.tooltip = {
'init': function (oElement, fValueAccessor) {

View file

@ -14,8 +14,6 @@
Globals = require('Common/Globals'),
Links = require('Common/Links'),
PgpStore = require('Stores/User/Pgp'),
AttachmentModel = require('Model/Attachment'),
MessageHelper = require('Helper/Message'),
@ -82,7 +80,6 @@
}, this);
this.body = null;
this.plainRaw = '';
this.isHtml = ko.observable(false);
this.hasImages = ko.observable(false);
@ -984,25 +981,6 @@
{
this.body.data('rl-is-html', !!this.isHtml());
this.body.data('rl-has-images', !!this.hasImages());
this.body.data('rl-plain-raw', this.plainRaw);
if (require('Stores/User/Pgp').capaOpenPGP())
{
this.body.data('rl-plain-pgp-signed', !!this.isPgpSigned());
this.body.data('rl-plain-pgp-encrypted', !!this.isPgpEncrypted());
this.body.data('rl-pgp-verify-status', this.pgpSignedVerifyStatus());
this.body.data('rl-pgp-verify-user', this.pgpSignedVerifyUser());
}
}
};
MessageModel.prototype.storePgpVerifyDataInDom = function ()
{
if (this.body && require('Stores/User/Pgp').capaOpenPGP())
{
this.body.data('rl-pgp-verify-status', this.pgpSignedVerifyStatus());
this.body.data('rl-pgp-verify-user', this.pgpSignedVerifyUser());
}
};
@ -1012,157 +990,6 @@
{
this.isHtml(!!this.body.data('rl-is-html'));
this.hasImages(!!this.body.data('rl-has-images'));
this.plainRaw = Utils.pString(this.body.data('rl-plain-raw'));
if (require('Stores/User/Pgp').capaOpenPGP())
{
this.isPgpSigned(!!this.body.data('rl-plain-pgp-signed'));
this.isPgpEncrypted(!!this.body.data('rl-plain-pgp-encrypted'));
this.pgpSignedVerifyStatus(this.body.data('rl-pgp-verify-status'));
this.pgpSignedVerifyUser(this.body.data('rl-pgp-verify-user'));
}
else
{
this.isPgpSigned(false);
this.isPgpEncrypted(false);
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None);
this.pgpSignedVerifyUser('');
}
}
};
MessageModel.prototype.verifyPgpSignedClearMessage = function ()
{
if (this.isPgpSigned())
{
var
aRes = [],
mPgpMessage = null,
sFrom = this.from && this.from[0] && this.from[0].email ? this.from[0].email : '',
aPublicKeys = PgpStore.findPublicKeysByEmail(sFrom),
oValidKey = null,
oValidSysKey = null,
sPlain = ''
;
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Error);
this.pgpSignedVerifyUser('');
try
{
mPgpMessage = PgpStore.openpgp.cleartext.readArmored(this.plainRaw);
if (mPgpMessage && mPgpMessage.getText)
{
this.pgpSignedVerifyStatus(
aPublicKeys.length ? Enums.SignedVerifyStatus.Unverified : Enums.SignedVerifyStatus.UnknownPublicKeys);
aRes = mPgpMessage.verify(aPublicKeys);
if (aRes && 0 < aRes.length)
{
oValidKey = _.find(aRes, function (oItem) {
return oItem && oItem.keyid && oItem.valid;
});
if (oValidKey)
{
oValidSysKey = PgpStore.findPublicKeyByHex(oValidKey.keyid.toHex());
if (oValidSysKey)
{
sPlain = mPgpMessage.getText();
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Success);
this.pgpSignedVerifyUser(oValidSysKey.user);
sPlain =
Globals.$div.empty().append(
$('<pre class="b-plain-openpgp signed verified"></pre>').text(sPlain)
).html()
;
Globals.$div.empty();
this.replacePlaneTextBody(sPlain);
}
}
}
}
}
catch (oExc) {}
this.storePgpVerifyDataInDom();
}
};
MessageModel.prototype.decryptPgpEncryptedMessage = function (sPassword)
{
if (this.isPgpEncrypted())
{
var
aRes = [],
mPgpMessage = null,
mPgpMessageDecrypted = null,
sFrom = this.from && this.from[0] && this.from[0].email ? this.from[0].email : '',
aPublicKey = PgpStore.findPublicKeysByEmail(sFrom),
oPrivateKey = PgpStore.findSelfPrivateKey(sPassword),
oValidKey = null,
oValidSysKey = null,
sPlain = ''
;
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Error);
this.pgpSignedVerifyUser('');
if (!oPrivateKey)
{
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.UnknownPrivateKey);
}
try
{
mPgpMessage = PgpStore.openpgp.message.readArmored(this.plainRaw);
if (mPgpMessage && oPrivateKey && mPgpMessage.decrypt)
{
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Unverified);
mPgpMessageDecrypted = mPgpMessage.decrypt(oPrivateKey);
if (mPgpMessageDecrypted)
{
aRes = mPgpMessageDecrypted.verify(aPublicKey);
if (aRes && 0 < aRes.length)
{
oValidKey = _.find(aRes, function (oItem) {
return oItem && oItem.keyid && oItem.valid;
});
if (oValidKey)
{
oValidSysKey = PgpStore.findPublicKeyByHex(oValidKey.keyid.toHex());
if (oValidSysKey)
{
this.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.Success);
this.pgpSignedVerifyUser(oValidSysKey.user);
}
}
}
sPlain = mPgpMessageDecrypted.getText();
sPlain =
Globals.$div.empty().append(
$('<pre class="b-plain-openpgp signed verified"></pre>').text(sPlain)
).html()
;
Globals.$div.empty();
this.replacePlaneTextBody(sPlain);
}
}
}
catch (oExc) {}
this.storePgpVerifyDataInDom();
}
};

View file

@ -7,6 +7,8 @@
_ = require('_'),
ko = require('ko'),
PgpStore = require('Stores/User/Pgp'),
AbstractModel = require('Knoin/AbstractModel')
;
@ -45,6 +47,22 @@
OpenPgpKeyModel.prototype.armor = '';
OpenPgpKeyModel.prototype.isPrivate = false;
OpenPgpKeyModel.prototype.getNativeKeys = function ()
{
var oKey = null;
try
{
oKey = PgpStore.openpgp.key.readArmored(this.armor);
if (oKey && !oKey.err && oKey.keys && oKey.keys[0])
{
return oKey.keys;
}
}
catch (e) {}
return null;
};
module.exports = OpenPgpKeyModel;
}());

View file

@ -22,6 +22,7 @@
AppStore = require('Stores/User/App'),
FolderStore = require('Stores/User/Folder'),
PgpStore = require('Stores/User/Pgp'),
SettingsStore = require('Stores/User/Settings'),
Remote = require('Remote/User/Ajax'),
@ -502,6 +503,19 @@
}
};
/**
* @param {Object} oMessageTextBody
*/
MessageUserStore.prototype.initOpenPgpControls = function (oMessageTextBody)
{
if (oMessageTextBody && oMessageTextBody.find)
{
oMessageTextBody.find('.b-plain-openpgp:not(.inited)').each(function () {
PgpStore.initMessageBodyControls($(this));
});
}
};
MessageUserStore.prototype.setMessage = function (oData, bCached)
{
var
@ -512,6 +526,7 @@
oBody = null,
oTextBody = null,
sId = '',
sPlain = '',
sResultHtml = '',
bPgpSigned = false,
bPgpEncrypted = false,
@ -579,13 +594,13 @@
if ((oMessage.isPgpSigned() || oMessage.isPgpEncrypted()) && require('Stores/User/Pgp').capaOpenPGP())
{
oMessage.plainRaw = Utils.pString(oData.Result.Plain);
sPlain = Utils.pString(oData.Result.Plain);
bPgpEncrypted = /---BEGIN PGP MESSAGE---/.test(oMessage.plainRaw);
bPgpEncrypted = /---BEGIN PGP MESSAGE---/.test(sPlain);
if (!bPgpEncrypted)
{
bPgpSigned = /-----BEGIN PGP SIGNED MESSAGE-----/.test(oMessage.plainRaw) &&
/-----BEGIN PGP SIGNATURE-----/.test(oMessage.plainRaw);
bPgpSigned = /-----BEGIN PGP SIGNED MESSAGE-----/.test(sPlain) &&
/-----BEGIN PGP SIGNATURE-----/.test(sPlain);
}
Globals.$div.empty();
@ -593,7 +608,7 @@
{
sResultHtml =
Globals.$div.append(
$('<pre class="b-plain-openpgp signed"></pre>').text(oMessage.plainRaw)
$('<pre class="b-plain-openpgp signed"></pre>').text(sPlain)
).html()
;
}
@ -601,11 +616,13 @@
{
sResultHtml =
Globals.$div.append(
$('<pre class="b-plain-openpgp encrypted"></pre>').text(oMessage.plainRaw)
$('<pre class="b-plain-openpgp encrypted"></pre>').text(sPlain)
).html()
;
}
sPlain = '';
Globals.$div.empty();
oMessage.isPgpSigned(bPgpSigned);
@ -624,8 +641,6 @@
oMessage.isHtml(!!bIsHtml);
oMessage.hasImages(!!bHasExternals);
oMessage.pgpSignedVerifyStatus(Enums.SignedVerifyStatus.None);
oMessage.pgpSignedVerifyUser('');
oMessage.body = oBody;
if (oMessage.body)
@ -663,6 +678,8 @@
if (oBody)
{
this.initOpenPgpControls(oBody);
this.initBlockquoteSwitcher(oBody);
}

View file

@ -5,6 +5,10 @@
var
_ = require('_'),
ko = require('ko'),
$ = require('$'),
kn = require('Knoin/Knoin'),
Translator = require('Common/Translator'),
Utils = require('Common/Utils')
;
@ -41,32 +45,41 @@
PgpUserStore.prototype.findPublicKeyByHex = function (sHash)
{
return _.find(this.openpgpkeysPublic(), function (oItem) {
return oItem && sHash === oItem.id;
return sHash && oItem && sHash === oItem.id;
});
};
PgpUserStore.prototype.findPrivateKeyByHex = function (sHash)
{
return _.find(this.openpgpkeysPrivate(), function (oItem) {
return sHash && oItem && sHash === oItem.id;
});
};
PgpUserStore.prototype.findPublicKeysByEmail = function (sEmail)
{
return _.compact(_.flatten(_.map(this.openpgpkeysPublic(), function (oItem) {
var oKey = oItem && sEmail === oItem.email ? oItem : null;
return oKey ? oKey.getNativeKeys() : [null];
}), true));
};
PgpUserStore.prototype.findPublicKeysBySigningKeyIds = function (aSigningKeyIds)
{
var self = this;
return _.compact(_.map(this.openpgpkeysPublic(), function (oItem) {
return _.compact(_.flatten(_.map(aSigningKeyIds, function (oId) {
var oKey = oId && oId.toHex ? self.findPublicKeyByHex(oId.toHex()) : null;
return oKey ? oKey.getNativeKeys() : [null];
}), true));
};
var oKey = null;
if (oItem && sEmail === oItem.email)
{
try
{
oKey = self.openpgp.key.readArmored(oItem.armor);
if (oKey && !oKey.err && oKey.keys && oKey.keys[0])
{
return oKey.keys[0];
}
}
catch (e) {}
}
return null;
}));
PgpUserStore.prototype.findPrivateKeysByEncryptionKeyIds = function (aEncryptionKeyIds, bReturnWrapKeys)
{
var self = this;
return _.compact(_.flatten(_.map(aEncryptionKeyIds, function (oId) {
var oKey = oId && oId.toHex ? self.findPrivateKeyByHex(oId.toHex()) : null;
return oKey ? (bReturnWrapKeys ? [oKey] : oKey.getNativeKeys()) : [null];
}), true));
};
/**
@ -77,6 +90,7 @@
PgpUserStore.prototype.findPrivateKeyByEmail = function (sEmail, sPassword)
{
var
oPrivateKeys = [],
oPrivateKey = null,
oKey = _.find(this.openpgpkeysPrivate(), function (oItem) {
return oItem && sEmail === oItem.email;
@ -85,18 +99,15 @@
if (oKey)
{
oPrivateKeys = oKey.getNativeKeys();
oPrivateKey = oPrivateKeys[0] || null;
try
{
oPrivateKey = this.openpgp.key.readArmored(oKey.armor);
if (oPrivateKey && !oPrivateKey.err && oPrivateKey.keys && oPrivateKey.keys[0])
if (oPrivateKey)
{
oPrivateKey = oPrivateKey.keys[0];
oPrivateKey.decrypt(Utils.pString(sPassword));
}
else
{
oPrivateKey = null;
}
}
catch (e)
{
@ -116,6 +127,259 @@
return this.findPrivateKeyByEmail(require('Stores/User/Account').email(), sPassword);
};
PgpUserStore.prototype.decryptMessage = function (oMessage, fCallback)
{
var self = this, aPrivateKeys = [], aEncryptionKeyIds = [];
if (oMessage && oMessage.getSigningKeyIds)
{
aEncryptionKeyIds = oMessage.getEncryptionKeyIds();
if (aEncryptionKeyIds)
{
aPrivateKeys = this.findPrivateKeysByEncryptionKeyIds(aEncryptionKeyIds, true);
if (aPrivateKeys && 0 < aPrivateKeys.length)
{
kn.showScreenPopup(require('View/Popup/MessageOpenPgp'), [function (oDecriptedKey) {
if (oDecriptedKey)
{
var oPrivateKey = null, oDecryptedMessage = null;
try
{
oDecryptedMessage = oMessage.decrypt(oDecriptedKey);
}
catch (e)
{
oDecryptedMessage = null;
}
if (oDecryptedMessage)
{
oPrivateKey = self.findPrivateKeyByHex(oDecriptedKey.primaryKey.keyid.toHex());
if (oPrivateKey)
{
self.verifyMessage(oDecryptedMessage, function (oValidKey, aSigningKeyIds) {
fCallback(oPrivateKey, oDecryptedMessage, oValidKey || null, aSigningKeyIds || null);
});
}
else
{
fCallback(oPrivateKey, oDecryptedMessage);
}
}
else
{
fCallback(oPrivateKey, oDecryptedMessage);
}
}
else
{
fCallback(null, null);
}
}, aPrivateKeys]);
return false;
}
}
}
fCallback(null, null);
return false;
};
PgpUserStore.prototype.verifyMessage = function (oMessage, fCallback)
{
var oValid = null, aResult = [], aPublicKeys = [], aSigningKeyIds = [];
if (oMessage && oMessage.getSigningKeyIds)
{
aSigningKeyIds = oMessage.getSigningKeyIds();
if (aSigningKeyIds && 0 < aSigningKeyIds.length)
{
aPublicKeys = this.findPublicKeysBySigningKeyIds(aSigningKeyIds);
if (aPublicKeys && 0 < aPublicKeys.length)
{
try
{
aResult = oMessage.verify(aPublicKeys);
oValid = _.find(_.isArray(aResult) ? aResult : [], function (oItem) {
return oItem && oItem.valid && oItem.keyid;
});
if (oValid && oValid.keyid && oValid.keyid && oValid.keyid.toHex)
{
fCallback(this.findPublicKeyByHex(oValid.keyid.toHex()));
return true;
}
}
catch (e) {}
}
fCallback(null, aSigningKeyIds);
return false;
}
}
fCallback(null);
return false;
};
/**
* @param {*} mDom
*/
PgpUserStore.prototype.controlsHelper = function (mDom, oVerControl, bSuccess, sTitle, sText)
{
if (bSuccess)
{
mDom.removeClass('error').addClass('success').attr('title', sTitle);
oVerControl.removeClass('error').addClass('success').attr('title', sTitle);
}
else
{
mDom.removeClass('success').addClass('error').attr('title', sTitle);
oVerControl.removeClass('success').addClass('error').attr('title', sTitle);
}
if (undefined !== sText)
{
mDom.text(Utils.trim(sText.replace(/(\u200C|\u0002)/g, '')));
}
};
/**
* @param {*} mDom
*/
PgpUserStore.prototype.initMessageBodyControls = function (mDom)
{
if (mDom && !mDom.hasClass('inited'))
{
mDom.addClass('inited');
var
self = this,
bEncrypted = mDom.hasClass('encrypted'),
bSigned = mDom.hasClass('signed'),
oVerControl = null,
sData = ''
;
if (bEncrypted || bSigned)
{
sData = mDom.text();
mDom.data('openpgp-original', sData);
if (bEncrypted)
{
oVerControl = $('<div class="b-openpgp-control"><i class="icon-lock"></i></div>')
.attr('title', Translator.i18n('MESSAGE/PGP_ENCRYPTED_MESSAGE_DESC'));
oVerControl.on('click', function () {
if ($(this).hasClass('success'))
{
return false;
}
var oMessage = self.openpgp.message.readArmored(sData);
if (oMessage && oMessage.getText && oMessage.verify && oMessage.decrypt)
{
self.decryptMessage(oMessage, function (oValidPrivateKey, oDecriptedMessage, oValidPublicKey, aSigningKeyIds) {
if (oDecriptedMessage)
{
if (oValidPublicKey)
{
self.controlsHelper(mDom, oVerControl, true, Translator.i18n('PGP_NOTIFICATIONS/GOOD_SIGNATURE', {
'USER': oValidPublicKey.user + ' (' + oValidPublicKey.id + ')'
}), oDecriptedMessage.getText());
}
else if (oValidPrivateKey)
{
var
aKeyIds = Utils.isNonEmptyArray(aSigningKeyIds) ? aSigningKeyIds : null,
sAdditional = aKeyIds ? _.compact(_.map(aKeyIds, function (oItem) {
return oItem && oItem.toHex ? oItem.toHex() : null;
})).join(', ') : ''
;
self.controlsHelper(mDom, oVerControl, false,
Translator.i18n('PGP_NOTIFICATIONS/UNVERIFIRED_SIGNATURE') +
(sAdditional ? ' (' + sAdditional + ')' : ''),
oDecriptedMessage.getText());
}
else
{
self.controlsHelper(mDom, oVerControl, false,
Translator.i18n('PGP_NOTIFICATIONS/DECRYPTION_ERROR'));
}
}
else
{
self.controlsHelper(mDom, oVerControl, false,
Translator.i18n('PGP_NOTIFICATIONS/DECRYPTION_ERROR'));
}
});
return false;
}
self.controlsHelper(mDom, oVerControl, false, Translator.i18n('PGP_NOTIFICATIONS/DECRYPTION_ERROR'));
return false;
});
}
else if (bSigned)
{
oVerControl = $('<div class="b-openpgp-control"><i class="icon-lock"></i></div>')
.attr('title', Translator.i18n('MESSAGE/PGP_SIGNED_MESSAGE_DESC'));
oVerControl.on('click', function () {
if ($(this).hasClass('success') || $(this).hasClass('error'))
{
return false;
}
var oMessage = self.openpgp.cleartext.readArmored(sData);
if (oMessage && oMessage.getText && oMessage.verify)
{
self.verifyMessage(oMessage, function (oValidKey, aSigningKeyIds) {
if (oValidKey)
{
self.controlsHelper(mDom, oVerControl, true, Translator.i18n('PGP_NOTIFICATIONS/GOOD_SIGNATURE', {
'USER': oValidKey.user + ' (' + oValidKey.id + ')'
}), oMessage.getText());
}
else
{
var
aKeyIds = Utils.isNonEmptyArray(aSigningKeyIds) ? aSigningKeyIds : null,
sAdditional = aKeyIds ? _.compact(_.map(aKeyIds, function (oItem) {
return oItem && oItem.toHex ? oItem.toHex() : null;
})).join(', ') : ''
;
self.controlsHelper(mDom, oVerControl, false,
Translator.i18n('PGP_NOTIFICATIONS/UNVERIFIRED_SIGNATURE') +
(sAdditional ? ' (' + sAdditional + ')' : ''));
}
});
return false;
}
self.controlsHelper(mDom, oVerControl, false, Translator.i18n('PGP_NOTIFICATIONS/DECRYPTION_ERROR'));
return false;
});
}
if (oVerControl)
{
mDom.before(oVerControl).before('<div></div>');
}
}
}
};
module.exports = new PgpUserStore();
}());

View file

@ -407,6 +407,16 @@ html.rl-no-preview-pane {
display: inline-block;
padding: 6px 10px;
border: 1px dashed #666;
background: #fff;
&.success {
border-color: green;
background-color: rgba(0, 255, 0, 0.03);
}
&.error {
border-color: red;
background-color: rgba(255, 0, 0, 0.03);
}
}
blockquote {
@ -424,6 +434,27 @@ html.rl-no-preview-pane {
color: red;
}
}
.b-openpgp-control {
display: inline-block;
cursor: pointer;
color: #777;
/*float: left;*/
&:hover {
color: #111;
}
&.success {
color: green;
cursor: help;
}
&.error {
color: red;
}
}
}
}
}

View file

@ -1,5 +1,5 @@
.popups {
.b-open-pgp-key-view-content, .b-open-pgp-key-generate-content, .b-open-pgp-key-add-content, .b-compose-open-pgp-content {
.b-open-pgp-key-view-content, .b-open-pgp-key-generate-content, .b-open-pgp-key-add-content, .b-compose-open-pgp-content, .b-message-open-pgp-content {
.modal-header {
background-color: #fff;
@ -18,4 +18,35 @@
overflow: auto;
}
}
.b-message-open-pgp-content {
&.modal {
width: 700px;
}
.key-list {
margin-top: 5px;
overflow: hidden;
&__item {
color: #555;
cursor: pointer;
text-overflow: ellipsis;
white-space: nowrap;
&__radio {
padding-right: 5px;
}
&__name {
&:hover {
border-bottom: 1px dashed #555;
}
}
}
}
}
}

View file

@ -632,7 +632,7 @@
oEditor.setPlain(sResult);
});
},
this.oEditor.getData(),
this.oEditor.getData(false, true),
this.currentIdentity(),
this.to(),
this.cc(),

View file

@ -109,25 +109,20 @@
if (self.resultCallback && bResult)
{
try {
var oPromise = null;
try
{
if (oPrivateKey && 0 === aPublicKeys.length)
{
self.resultCallback(
PgpStore.openpgp.signClearMessage([oPrivateKey], self.text())
);
oPromise = PgpStore.openpgp.signClearMessage([oPrivateKey], self.text());
}
else if (oPrivateKey && 0 < aPublicKeys.length)
{
self.resultCallback(
PgpStore.openpgp.signAndEncryptMessage(aPublicKeys, oPrivateKey, self.text())
);
oPromise = PgpStore.openpgp.signAndEncryptMessage(aPublicKeys, oPrivateKey, self.text());
}
else if (!oPrivateKey && 0 < aPublicKeys.length)
{
self.resultCallback(
PgpStore.openpgp.encryptMessage(aPublicKeys, self.text())
);
oPromise = PgpStore.openpgp.encryptMessage(aPublicKeys, self.text());
}
}
catch (e)
@ -135,14 +130,30 @@
self.notification(Translator.i18n('PGP_NOTIFICATIONS/PGP_ERROR', {
'ERROR': '' + e
}));
bResult = false;
}
}
if (bResult)
{
self.cancelCommand();
if (oPromise)
{
try
{
oPromise.then(function (mData) {
self.resultCallback(mData);
self.cancelCommand();
})['catch'](function (e) {
self.notification(Translator.i18n('PGP_NOTIFICATIONS/PGP_ERROR', {
'ERROR': '' + e
}));
});
}
catch (e)
{
self.notification(Translator.i18n('PGP_NOTIFICATIONS/PGP_ERROR', {
'ERROR': '' + e
}));
}
}
}
self.submitRequest(false);

View file

@ -0,0 +1,179 @@
(function () {
'use strict';
var
_ = require('_'),
ko = require('ko'),
key = require('key'),
Utils = require('Common/Utils'),
Enums = require('Common/Enums'),
kn = require('Knoin/Knoin'),
AbstractView = require('Knoin/AbstractView')
;
/**
* @constructor
* @extends AbstractView
*/
function MessageOpenPgpPopupView()
{
AbstractView.call(this, 'Popups', 'PopupsMessageOpenPgp');
this.notification = ko.observable('');
this.selectedKey = ko.observable(null);
this.privateKeys = ko.observableArray([]);
this.password = ko.observable('');
this.password.focus = ko.observable(false);
this.buttonFocus = ko.observable(false);
this.resultCallback = null;
this.submitRequest = ko.observable(false);
// commands
this.doCommand = Utils.createCommand(this, function () {
this.submitRequest(true);
_.delay(_.bind(function() {
var
oPrivateKeys = [],
oPrivateKey = null
;
try
{
if (this.resultCallback && this.selectedKey())
{
oPrivateKeys = this.selectedKey().getNativeKeys();
oPrivateKey = oPrivateKeys && oPrivateKeys[0] ? oPrivateKeys[0] : null;
if (oPrivateKey)
{
try
{
if (!oPrivateKey.decrypt(Utils.pString(this.password())))
{
oPrivateKey = null;
}
}
catch (e)
{
oPrivateKey = null;
}
}
}
}
catch (oExc)
{
oPrivateKey = null;
}
this.submitRequest(false);
this.cancelCommand();
this.resultCallback(oPrivateKey);
}, this), 100);
}, function () {
return !this.submitRequest();
});
this.sDefaultKeyScope = Enums.KeyState.PopupMessageOpenPGP;
kn.constructorEnd(this);
}
kn.extendAsViewModel(['View/Popup/MessageOpenPgp'], MessageOpenPgpPopupView);
_.extend(MessageOpenPgpPopupView.prototype, AbstractView.prototype);
MessageOpenPgpPopupView.prototype.clearPopup = function ()
{
this.notification('');
this.password('');
this.password.focus(false);
this.buttonFocus(false);
this.selectedKey(false);
this.submitRequest(false);
this.resultCallback = null;
this.privateKeys([]);
};
MessageOpenPgpPopupView.prototype.onBuild = function (oDom)
{
key('tab,shift+tab', Enums.KeyState.PopupMessageOpenPGP, _.bind(function () {
switch (true)
{
case this.password.focus():
this.buttonFocus(true);
break;
case this.buttonFocus():
this.password.focus(true);
break;
}
return false;
}, this));
var self = this;
oDom
.on('click', '.key-list__item', function () {
oDom.find('.key-list__item .key-list__item__radio')
.addClass('icon-radio-unchecked')
.removeClass('icon-radio-checked')
;
$(this).find('.key-list__item__radio')
.removeClass('icon-radio-unchecked')
.addClass('icon-radio-checked')
;
self.selectedKey(ko.dataFor(this));
self.password.focus(true);
})
;
};
MessageOpenPgpPopupView.prototype.onHideWithDelay = function ()
{
this.clearPopup();
};
MessageOpenPgpPopupView.prototype.onShowWithDelay = function ()
{
this.password.focus(true);
// this.buttonFocus(true);
};
MessageOpenPgpPopupView.prototype.onShow = function (fCallback, aPrivateKeys)
{
this.clearPopup();
this.resultCallback = fCallback;
this.privateKeys(aPrivateKeys);
if (this.viewModelDom)
{
this.viewModelDom.find('.key-list__item').first().click();
}
};
module.exports = MessageOpenPgpPopupView;
}());

View file

@ -62,29 +62,36 @@
_.delay(function () {
mKeyPair = false;
var mPromise = false;
try {
mKeyPair = PgpStore.openpgp.generateKeyPair({
mPromise = PgpStore.openpgp.generateKeyPair({
'userId': sUserID,
'numBits': Utils.pInt(self.keyBitLength()),
'passphrase': Utils.trim(self.password())
});
} catch (e) {
// window.console.log(e);
}
if (mKeyPair && mKeyPair.privateKeyArmored)
{
oOpenpgpKeyring.privateKeys.importKey(mKeyPair.privateKeyArmored);
oOpenpgpKeyring.publicKeys.importKey(mKeyPair.publicKeyArmored);
oOpenpgpKeyring.store();
mPromise.then(function () {
require('App/User').reloadOpenPgpKeys();
Utils.delegateRun(self, 'cancelCommand');
}
self.submitRequest(false);
if (mKeyPair && mKeyPair.privateKeyArmored)
{
oOpenpgpKeyring.privateKeys.importKey(mKeyPair.privateKeyArmored);
oOpenpgpKeyring.publicKeys.importKey(mKeyPair.publicKeyArmored);
oOpenpgpKeyring.store();
require('App/User').reloadOpenPgpKeys();
Utils.delegateRun(self, 'cancelCommand');
}
})['catch'](function() {
self.submitRequest(false);
});
} catch (e) {}
self.submitRequest(false);
}, 100);
return true;

View file

@ -303,16 +303,6 @@
this.viewIsImportant = ko.observable(false);
this.viewIsFlagged = ko.observable(false);
// PGP
this.viewPgpPassword = ko.observable('');
this.viewPgpSignedVerifyStatus = ko.computed(function () {
return this.message() ? this.message().pgpSignedVerifyStatus() : Enums.SignedVerifyStatus.None;
}, this);
this.viewPgpSignedVerifyUser = ko.computed(function () {
return this.message() ? this.message().pgpSignedVerifyUser() : '';
}, this);
this.viewFromDkimStatusIconClass = ko.computed(function () {
var sResult = 'icon-none iconcolor-display-none';
@ -361,8 +351,6 @@
this.messageActiveDom(null);
this.viewPgpPassword('');
if (oMessage)
{
this.showAttachmnetControls(false);
@ -523,48 +511,6 @@
return sResult;
};
MessageViewMailBoxUserView.prototype.isPgpActionVisible = function ()
{
return Enums.SignedVerifyStatus.Success !== this.viewPgpSignedVerifyStatus();
};
MessageViewMailBoxUserView.prototype.isPgpStatusVerifyVisible = function ()
{
return Enums.SignedVerifyStatus.None !== this.viewPgpSignedVerifyStatus();
};
MessageViewMailBoxUserView.prototype.isPgpStatusVerifySuccess = function ()
{
return Enums.SignedVerifyStatus.Success === this.viewPgpSignedVerifyStatus();
};
MessageViewMailBoxUserView.prototype.pgpStatusVerifyMessage = function ()
{
var sResult = '';
switch (this.viewPgpSignedVerifyStatus())
{
case Enums.SignedVerifyStatus.UnknownPublicKeys:
sResult = Translator.i18n('PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND');
break;
case Enums.SignedVerifyStatus.UnknownPrivateKey:
sResult = Translator.i18n('PGP_NOTIFICATIONS/NO_PRIVATE_KEY_FOUND');
break;
case Enums.SignedVerifyStatus.Unverified:
sResult = Translator.i18n('PGP_NOTIFICATIONS/UNVERIFIRED_SIGNATURE');
break;
case Enums.SignedVerifyStatus.Error:
sResult = Translator.i18n('PGP_NOTIFICATIONS/DECRYPTION_ERROR');
break;
case Enums.SignedVerifyStatus.Success:
sResult = Translator.i18n('PGP_NOTIFICATIONS/GOOD_SIGNATURE', {
'USER': this.viewPgpSignedVerifyUser()
});
break;
}
return sResult;
};
MessageViewMailBoxUserView.prototype.fullScreen = function ()
{
this.fullScreenMode(true);
@ -1256,31 +1202,6 @@
return 0 < iCnt ? (100 > iCnt ? iCnt : '99+') : '';
};
/**
* @param {MessageModel} oMessage
*/
MessageViewMailBoxUserView.prototype.verifyPgpSignedClearMessage = function (oMessage)
{
if (oMessage)
{
oMessage.verifyPgpSignedClearMessage();
}
this.checkHeaderHeight();
};
/**
* @param {MessageModel} oMessage
*/
MessageViewMailBoxUserView.prototype.decryptPgpEncryptedMessage = function (oMessage)
{
if (oMessage)
{
oMessage.decryptPgpEncryptedMessage(this.viewPgpPassword());
}
};
/**
* @param {MessageModel} oMessage
*/