diff options
author | Maximilian Krambach <[email protected]> | 2018-08-20 10:12:43 +0000 |
---|---|---|
committer | Maximilian Krambach <[email protected]> | 2018-08-20 10:12:43 +0000 |
commit | 1954d27be86b8e4eb801ca6ddcb670f8cfb149f5 (patch) | |
tree | 90183ad8fbc37e440a3f2949e3dc5c1fbc12bacb /lang/js/src/Connection.js | |
parent | js: decode arriving gpg message strings (diff) | |
download | gpgme-1954d27be86b8e4eb801ca6ddcb670f8cfb149f5.tar.gz gpgme-1954d27be86b8e4eb801ca6ddcb670f8cfb149f5.zip |
js: revert changes to class read/write restriction
--
* undoes 94ee0988d4eaac27785de6efb7c19ca9976e1e9c and
e16a87e83910ebb6bfdc4148369165f121f0997e.
I do not fully understand why my approach was bad, but I am not in
a position to argue. This revert was requested to me after a review,
and I'm doing it in the assumption that more experienced people know
better than me.
* unittests: Also changed some outdated tests that stopped working
since 754e799d35fd62d7a979452f44342934659908c7 (as GPGME_Key is not
exported, one cannot check for instanceof in the tests anymore)
Diffstat (limited to 'lang/js/src/Connection.js')
-rw-r--r-- | lang/js/src/Connection.js | 415 |
1 files changed, 208 insertions, 207 deletions
diff --git a/lang/js/src/Connection.js b/lang/js/src/Connection.js index 8d381f15..a60fd215 100644 --- a/lang/js/src/Connection.js +++ b/lang/js/src/Connection.js @@ -39,144 +39,146 @@ import { decode } from './Helpers'; export class Connection{ constructor(){ - let _connection = chrome.runtime.connectNative('gpgmejson'); - + this._connection = chrome.runtime.connectNative('gpgmejson'); + } - /** - * Immediately closes an open port. - */ - this.disconnect = function () { - if (_connection){ - _connection.disconnect(); - _connection = null; - } - }; + /** + * Immediately closes an open port. + */ + disconnect() { + if (this._connection){ + this._connection.disconnect(); + this._connection = null; + } + } - /** - * @typedef {Object} backEndDetails - * @property {String} gpgme Version number of gpgme - * @property {Array<Object>} info Further information about the backend - * and the used applications (Example: - * { - * "protocol": "OpenPGP", - * "fname": "/usr/bin/gpg", - * "version": "2.2.6", - * "req_version": "1.4.0", - * "homedir": "default" - * } - */ + /** + * @typedef {Object} backEndDetails + * @property {String} gpgme Version number of gpgme + * @property {Array<Object>} info Further information about the backend + * and the used applications (Example: + * { + * "protocol": "OpenPGP", + * "fname": "/usr/bin/gpg", + * "version": "2.2.6", + * "req_version": "1.4.0", + * "homedir": "default" + * } + */ - /** - * Retrieves the information about the backend. - * @param {Boolean} details (optional) If set to false, the promise will - * just return if a connection was successful. - * @returns {Promise<backEndDetails>|Promise<Boolean>} Details from the - * backend - * @async - */ - this.checkConnection = function(details = true){ - const msg = createMessage('version'); - if (details === true) { - return this.post(msg); - } else { - let me = this; - return new Promise(function(resolve) { - Promise.race([ - me.post(msg), - new Promise(function(resolve, reject){ - setTimeout(function(){ - reject(gpgme_error('CONN_TIMEOUT')); - }, 500); - }) - ]).then(function(){ // success - resolve(true); - }, function(){ // failure - resolve(false); - }); + /** + * Retrieves the information about the backend. + * @param {Boolean} details (optional) If set to false, the promise will + * just return if a connection was successful. + * @returns {Promise<backEndDetails>|Promise<Boolean>} Details from the + * backend + * @async + */ + checkConnection (details = true){ + const msg = createMessage('version'); + if (details === true) { + return this.post(msg); + } else { + let me = this; + return new Promise(function(resolve) { + Promise.race([ + me.post(msg), + new Promise(function(resolve, reject){ + setTimeout(function(){ + reject(gpgme_error('CONN_TIMEOUT')); + }, 500); + }) + ]).then(function(){ // success + resolve(true); + }, function(){ // failure + resolve(false); }); - } - }; + }); + } + } - /** - * Sends a {@link GPGME_Message} via tghe nativeMessaging port. It - * resolves with the completed answer after all parts have been - * received and reassembled, or rejects with an {@link GPGME_Error}. - * - * @param {GPGME_Message} message - * @returns {Promise<Object>} The collected answer - * @async - */ - this.post = function (message){ - if (!message || !(message instanceof GPGME_Message)){ - this.disconnect(); - return Promise.reject(gpgme_error( - 'PARAM_WRONG', 'Connection.post')); - } - if (message.isComplete() !== true){ - this.disconnect(); - return Promise.reject(gpgme_error('MSG_INCOMPLETE')); - } - let chunksize = message.chunksize; - return new Promise(function(resolve, reject){ - let answer = Object.freeze(new Answer(message)); - let listener = function(msg) { - if (!msg){ - _connection.onMessage.removeListener(listener); - _connection.disconnect(); - reject(gpgme_error('CONN_EMPTY_GPG_ANSWER')); + /** + * Sends a {@link GPGME_Message} via tghe nativeMessaging port. It + * resolves with the completed answer after all parts have been + * received and reassembled, or rejects with an {@link GPGME_Error}. + * + * @param {GPGME_Message} message + * @returns {Promise<Object>} The collected answer + * @async + */ + post(message){ + if (!message || !(message instanceof GPGME_Message)){ + this.disconnect(); + return Promise.reject(gpgme_error( + 'PARAM_WRONG', 'Connection.post')); + } + if (message.isComplete() !== true){ + this.disconnect(); + return Promise.reject(gpgme_error('MSG_INCOMPLETE')); + } + let chunksize = message.chunksize; + const me = this; + return new Promise(function(resolve, reject){ + let answer = new Answer(message); + let listener = function(msg) { + if (!msg){ + me._connection.onMessage.removeListener(listener); + me._connection.disconnect(); + reject(gpgme_error('CONN_EMPTY_GPG_ANSWER')); + } else { + let answer_result = answer.collect(msg); + if (answer_result !== true){ + me._connection.onMessage.removeListener(listener); + me._connection.disconnect(); + reject(answer_result); } else { - let answer_result = answer.collect(msg); - if (answer_result !== true){ - _connection.onMessage.removeListener(listener); - _connection.disconnect(); - reject(answer_result); + if (msg.more === true){ + me._connection.postMessage({ + 'op': 'getmore', + 'chunksize': chunksize + }); } else { - if (msg.more === true){ - _connection.postMessage({ - 'op': 'getmore', - 'chunksize': chunksize - }); + me._connection.onMessage.removeListener(listener); + me._connection.disconnect(); + const message = answer.getMessage(); + if (message instanceof Error){ + reject(message); } else { - _connection.onMessage.removeListener(listener); - _connection.disconnect(); - const message = answer.getMessage(); - if (message instanceof Error){ - reject(message); - } else { - resolve(message); - } + resolve(message); } } } - }; - _connection.onMessage.addListener(listener); - if (permittedOperations[message.operation].pinentry){ - return _connection.postMessage(message.message); - } else { - return Promise.race([ - _connection.postMessage(message.message), - function(resolve, reject){ - setTimeout(function(){ - _connection.disconnect(); - reject(gpgme_error('CONN_TIMEOUT')); - }, 5000); - }]).then(function(result){ - return result; - }, function(reject){ - if(!(reject instanceof Error)) { - _connection.disconnect(); - return gpgme_error('GNUPG_ERROR', reject); - } else { - return reject; - } - }); } - }); - }; + }; + me._connection.onMessage.addListener(listener); + if (permittedOperations[message.operation].pinentry){ + return me._connection.postMessage(message.message); + } else { + return Promise.race([ + me._connection.postMessage(message.message), + function(resolve, reject){ + setTimeout(function(){ + me._connection.disconnect(); + reject(gpgme_error('CONN_TIMEOUT')); + }, 5000); + } + ]).then(function(result){ + return result; + }, function(reject){ + if(!(reject instanceof Error)) { + me._connection.disconnect(); + return gpgme_error('GNUPG_ERROR', reject); + } else { + return reject; + } + }); + } + }); } } + /** * A class for answer objects, checking and processing the return messages of * the nativeMessaging communication. @@ -188,95 +190,94 @@ class Answer{ * @param {GPGME_Message} message */ constructor(message){ - const operation = message.operation; - const expected = message.getExpect(); - let response_b64 = null; + this._operation = message.operation; + this._expected = message.expected; + this._response_b64 = null; + } - this.getOperation = function(){ - return operation; - }; + get operation (){ + return this._operation; + } - this.getExpect = function(){ - return expected; - }; + get expected (){ + return this._expected; + } - /** - * Adds incoming base64 encoded data to the existing response - * @param {*} msg base64 encoded data. - * @returns {Boolean} - * - * @private - */ - this.collect = function (msg){ - if (typeof(msg) !== 'object' || !msg.hasOwnProperty('response')) { - return gpgme_error('CONN_UNEXPECTED_ANSWER'); - } - if (response_b64 === null){ - response_b64 = msg.response; - return true; - } else { - response_b64 += msg.response; - return true; - } - }; - /** - * Returns the base64 encoded answer data with the content verified - * against {@link permittedOperations}. - */ - this.getMessage = function (){ - if (response_b64 === undefined){ - return gpgme_error('CONN_UNEXPECTED_ANSWER'); - } - let _decodedResponse = JSON.parse(atob(response_b64)); - let _response = {}; - let messageKeys = Object.keys(_decodedResponse); - let poa = permittedOperations[this.getOperation()].answer; - if (messageKeys.length === 0){ - return gpgme_error('CONN_UNEXPECTED_ANSWER'); - } - for (let i= 0; i < messageKeys.length; i++){ - let key = messageKeys[i]; - switch (key) { - case 'type': - if (_decodedResponse.type === 'error'){ - return (gpgme_error('GNUPG_ERROR', - decode(_decodedResponse.msg))); - } else if (poa.type.indexOf(_decodedResponse.type) < 0){ - return gpgme_error('CONN_UNEXPECTED_ANSWER'); - } - break; - case 'base64': - break; - case 'msg': - if (_decodedResponse.type === 'error'){ - return (gpgme_error('GNUPG_ERROR', - _decodedResponse.msg)); - } - break; - default: - if (!poa.data.hasOwnProperty(key)){ - return gpgme_error('CONN_UNEXPECTED_ANSWER'); - } - if( typeof(_decodedResponse[key]) !== poa.data[key] ){ - return gpgme_error('CONN_UNEXPECTED_ANSWER'); - } - if (_decodedResponse.base64 === true - && poa.data[key] === 'string' - && this.getExpect() !== 'base64' - ){ - _response[key] = decodeURIComponent( - atob(_decodedResponse[key]).split('').map( - function(c) { - return '%' + - ('00' + c.charCodeAt(0).toString(16)).slice(-2); - }).join('')); - } else { - _response[key] = decode(_decodedResponse[key]); - } - break; + /** + * Adds incoming base64 encoded data to the existing response + * @param {*} msg base64 encoded data. + * @returns {Boolean} + * + * @private + */ + collect (msg){ + if (typeof(msg) !== 'object' || !msg.hasOwnProperty('response')) { + return gpgme_error('CONN_UNEXPECTED_ANSWER'); + } + if (!this._response_b64){ + this._response_b64 = msg.response; + return true; + } else { + this._response_b64 += msg.response; + return true; + } + } + /** + * Returns the base64 encoded answer data with the content verified + * against {@link permittedOperations}. + */ + getMessage(){ + if (this._response_b64 === null){ + return gpgme_error('CONN_UNEXPECTED_ANSWER'); + } + let _decodedResponse = JSON.parse(atob(this._response_b64)); + let _response = {}; + let messageKeys = Object.keys(_decodedResponse); + let poa = permittedOperations[this.operation].answer; + if (messageKeys.length === 0){ + return gpgme_error('CONN_UNEXPECTED_ANSWER'); + } + for (let i= 0; i < messageKeys.length; i++){ + let key = messageKeys[i]; + switch (key) { + case 'type': + if (_decodedResponse.type === 'error'){ + return (gpgme_error('GNUPG_ERROR', + decode(_decodedResponse.msg))); + } else if (poa.type.indexOf(_decodedResponse.type) < 0){ + return gpgme_error('CONN_UNEXPECTED_ANSWER'); + } + break; + case 'base64': + break; + case 'msg': + if (_decodedResponse.type === 'error'){ + return (gpgme_error('GNUPG_ERROR', _decodedResponse.msg)); + } + break; + default: + if (!poa.data.hasOwnProperty(key)){ + return gpgme_error('CONN_UNEXPECTED_ANSWER'); + } + if( typeof(_decodedResponse[key]) !== poa.data[key] ){ + return gpgme_error('CONN_UNEXPECTED_ANSWER'); + } + if (_decodedResponse.base64 === true + && poa.data[key] === 'string' + && this.expected !== 'base64' + ){ + _response[key] = decodeURIComponent( + atob(_decodedResponse[key]).split('').map( + function(c) { + return '%' + + ('00' + c.charCodeAt(0).toString(16)).slice(-2); + }).join('')); + } else { + _response[key] = decode(_decodedResponse[key]); } + break; } - return _response; - }; + } + return _response; } } |