From fda7b13f1b673962ce34b6f429158a7eb9cef47b Mon Sep 17 00:00:00 2001 From: Maximilian Krambach Date: Fri, 27 Apr 2018 20:03:09 +0200 Subject: js: more testing -- * Tests: initialization of the two modes, encryption * gpgme.js: reintroduced message check before calling Connection.post() * gpgmejs_openpgp.js: Fixed openpgp mode not passing keys * index.js: fixed some confusion in parseconfig() * Inserted some TODO stubs for missing error handling --- lang/js/src/Connection.js | 6 +-- lang/js/src/Key.js | 23 +++++---- lang/js/src/Keyring.js | 4 ++ lang/js/src/Message.js | 66 +++++++++++++++++++++---- lang/js/src/gpgmejs.js | 56 ++++++++++++---------- lang/js/src/gpgmejs_openpgpjs.js | 7 ++- lang/js/src/index.js | 23 +++++---- lang/js/src/permittedOperations.js | 98 ++++++++++++++++++++++++++++---------- 8 files changed, 201 insertions(+), 82 deletions(-) (limited to 'lang/js/src') diff --git a/lang/js/src/Connection.js b/lang/js/src/Connection.js index a10f9d9a..a198bdc6 100644 --- a/lang/js/src/Connection.js +++ b/lang/js/src/Connection.js @@ -100,9 +100,7 @@ export class Connection{ reject(gpgme_error('CONN_EMPTY_GPG_ANSWER')); } else if (msg.type === "error"){ me._connection.onMessage.removeListener(listener) - reject( - {code: 'GNUPG_ERROR', - msg: msg.msg} ); + reject(gpgme_error('GNUPG_ERROR', msg.msg)); } else { let answer_result = answer.add(msg); if (answer_result !== true){ @@ -129,6 +127,8 @@ export class Connection{ }, 5000); }]).then(function(result){ return result; + }, function(error){ + return error; }); } }); diff --git a/lang/js/src/Key.js b/lang/js/src/Key.js index 0b44b245..30449d63 100644 --- a/lang/js/src/Key.js +++ b/lang/js/src/Key.js @@ -51,10 +51,7 @@ export class GPGME_Key { * hasSecret returns true if a secret subkey is included in this Key */ get hasSecret(){ - checkKey(this._fingerprint, 'secret').then( function(result){ - return Promise.resolve(result); - }); - + return checkKey(this._fingerprint, 'secret'); } get isRevoked(){ @@ -130,6 +127,8 @@ export class GPGME_Key { } } return Promise.resolve(resultset); + }, function(error){ + //TODO checkKey fails }); } @@ -175,8 +174,7 @@ export class GPGME_Key { */ function checkKey(fingerprint, property){ return Promise.reject(gpgme_error('NOT_YET_IMPLEMENTED')); - if (!property || - permittedOperations[keyinfo].indexOf(property) < 0){ + if (!property || !permittedOperations[keyinfo].hasOwnProperty(property)){ return Promise.reject(gpgme_error('PARAM_WRONG')); } return new Promise(function(resolve, reject){ @@ -188,19 +186,20 @@ function checkKey(fingerprint, property){ reject(gpgme_error('PARAM_WRONG')); } msg.setParameter('fingerprint', this.fingerprint); - return (this.connection.post(msg)).then(function(result){ - if (result.hasOwnProperty(property)){ + return (this.connection.post(msg)).then(function(result, error){ + if (error){ + reject(gpgme_error('GNUPG_ERROR',error.msg)); + } else if (result.hasOwnProperty(property)){ resolve(result[property]); } else if (property == 'secret'){ - // TBD property undefined means "not true" in case of secret? - resolve(false); + // TBD property undefined means "not true" in case of secret? + resolve(false); } else { reject(gpgme_error('CONN_UNEXPECTED_ANSWER')); } }, function(error){ - reject({code: 'GNUPG_ERROR', - msg: error.msg}); + //TODO error handling }); }); }; \ No newline at end of file diff --git a/lang/js/src/Keyring.js b/lang/js/src/Keyring.js index 364bfb46..d1f4122e 100644 --- a/lang/js/src/Keyring.js +++ b/lang/js/src/Keyring.js @@ -78,6 +78,8 @@ export class GPGME_Keyring { } } return Promise.resolve(resultset); + }, function(error){ + //TODO error handling }); } @@ -151,6 +153,8 @@ export class GPGME_Keyring { } } return Promise.resolve(resultset); + }, function(error){ + //TODO error handling }); } diff --git a/lang/js/src/Message.js b/lang/js/src/Message.js index 95d043ba..c42480f2 100644 --- a/lang/js/src/Message.js +++ b/lang/js/src/Message.js @@ -73,11 +73,60 @@ export class GPGME_Message { if (!po){ return gpgme_error('MSG_WRONG_OP'); } - if (po.required.indexOf(param) >= 0 || po.optional.indexOf(param) >= 0){ - this._msg[param] = value; - return true; + let poparam = null; + if (po.required.hasOwnProperty(param)){ + poparam = po.required[param]; + } else if (po.optional.hasOwnProperty(param)){ + poparam = po.optional[param]; + } else { + return gpgme_error('PARAM_WRONG'); } - return gpgme_error('PARAM_WRONG'); + let checktype = function(val){ + switch(typeof(val)){ + case 'string': + case 'number': + case 'boolean': + if (poparam.allowed.indexOf(typeof(val)) >= 0){ + return true; + } + return gpgme_error('PARAM_WRONG'); + break; + case 'object': + if (Array.isArray(val)){ + if (poparam.array_allowed !== true){ + return gpgme_error('PARAM_WRONG'); + } + for (let i=0; i < val.length; i++){ + let res = checktype(val[i]); + if (res !== true){ + return res; + } + } + return true; + } else if (val instanceof Uint8Array){ + if (poparam.allowed.indexOf('Uint8Array') >= 0){ + return true; + } + return gpgme_error('PARAM_WRONG'); + } else { + return gpgme_error('PARAM_WRONG'); + } + break; + default: + return gpgme_error('PARAM_WRONG'); + } + }; + let typechecked = checktype(value); + if (typechecked !== true){ + return typechecked; + } + if (poparam.hasOwnProperty('allowed_data')){ + if (poparam.allowed_data.indexOf(value) < 0){ + return gpgme_error('PARAM_WRONG'); + } + } + this._msg[param] = value; + return true; } /** @@ -89,11 +138,12 @@ export class GPGME_Message { if (!this._msg.op){ return false; } - let reqParams = permittedOperations[this._msg.op].required; + let reqParams = Object.keys( + permittedOperations[this._msg.op].required); + let msg_params = Object.keys(this._msg); for (let i=0; i < reqParams.length; i++){ - - if (!this._msg.hasOwnProperty(reqParams[i])){ - console.log(reqParams[i] + 'missing'); + if (msg_params.indexOf(reqParams[i]) < 0){ + console.log(reqParams[i] + ' missing'); return false; } } diff --git a/lang/js/src/gpgmejs.js b/lang/js/src/gpgmejs.js index 2ddf2964..9475b2b0 100644 --- a/lang/js/src/gpgmejs.js +++ b/lang/js/src/gpgmejs.js @@ -33,25 +33,24 @@ export class GpgME { this.connection = connection; } - set connection(connection){ + set connection(conn){ if (this._connection instanceof Connection){ gpgme_error('CONN_ALREADY_CONNECTED'); - } - if (connection instanceof Connection){ - this._connection = connection; + } else if (conn instanceof Connection){ + this._connection = conn; } else { gpgme_error('PARAM_WRONG'); } } get connection(){ - if (this._connection instanceof Connection){ - if (this._connection.isConnected){ + if (this._connection){ + if (this._connection.isConnected === true){ return this._connection; } - return undefined; //TODO: connection was lost! + return undefined; } - return undefined; //TODO: no connection there + return undefined; } set Keyring(keyring){ @@ -85,8 +84,11 @@ export class GpgME { putData(msg, data); if (wildcard === true){msg.setParameter('throw-keyids', true); }; - - return (this.connection.post(msg)); + if (msg.isComplete === true){ + return this.connection.post(msg); + } else { + return Promise.reject(gpgme_error('MSG_INCOMPLETE')); + } } /** @@ -133,20 +135,24 @@ export class GpgME { msg.setParameter('delete_force', true); // TBD } - this.connection.post(msg).then(function(success){ - // TODO: it seems that there is always errors coming back: - }, function(error){ - switch (error.msg){ - case 'ERR_NO_ERROR': - return Promise.resolve('okay'); //TBD - default: - return Promise.reject(gpgme_error('TODO') ); // - // INV_VALUE, - // GPG_ERR_NO_PUBKEY, - // GPG_ERR_AMBIGUOUS_NAME, - // GPG_ERR_CONFLICT - } - }); + if (msg.isComplete === true){ + this.connection.post(msg).then(function(success){ + // TODO: it seems that there is always errors coming back: + }, function(error){ + switch (error.msg){ + case 'ERR_NO_ERROR': + return Promise.resolve('okay'); //TBD + default: + return Promise.reject(gpgme_error('TODO') ); // + // INV_VALUE, + // GPG_ERR_NO_PUBKEY, + // GPG_ERR_AMBIGUOUS_NAME, + // GPG_ERR_CONFLICT + } + }); + } else { + return Promise.reject(gpgme_error('MSG_INCOMPLETE')); + } } } @@ -162,7 +168,7 @@ function putData(message, data){ return gpgme_error('PARAM_WRONG'); } if (!data){ - message.setParameter('data', ''); + return gpgme_error('PARAM_WRONG'); } else if (data instanceof Uint8Array){ let decoder = new TextDecoder('utf8'); message.setParameter('base64', true); diff --git a/lang/js/src/gpgmejs_openpgpjs.js b/lang/js/src/gpgmejs_openpgpjs.js index cc2afde1..c80d5a86 100644 --- a/lang/js/src/gpgmejs_openpgpjs.js +++ b/lang/js/src/gpgmejs_openpgpjs.js @@ -109,7 +109,7 @@ return Promise.reject(GPMGEJS_Error('NOT_IMPLEMENTED')); } } - return this._GpgME.encrypt(data, translateKeyInput(publicKeys), wildcard); + return this._GpgME.encrypt(data, translateKeys(publicKeys), wildcard); } /** Decrypt Message @@ -201,6 +201,8 @@ class GPGME_Keyring_openpgpmode { // TODO: Can there be several default keys? return gpgme_error('TODO'); } + }, function(error){ + //TODO }); } @@ -264,6 +266,9 @@ class GPGME_Key_openpgpmode { * creates GPGME_Key_openpgpmode from GPGME_Keys */ function translateKeys(input){ + if (!input){ + return null; + } if (!Array.isArray(input)){ input = [input]; } diff --git a/lang/js/src/index.js b/lang/js/src/index.js index 4de98457..90fe99e3 100644 --- a/lang/js/src/index.js +++ b/lang/js/src/index.js @@ -53,18 +53,17 @@ function init(config){ }); } -function parseconfiguration(config){ - if (!config){ - return defaultConf; - } - if ( typeof(config) !== 'object'){ +function parseconfiguration(rawconfig = {}){ + if ( typeof(rawconfig) !== 'object'){ return gpgme_error('PARAM_WRONG'); }; - let result_config = defaultConf; - let conf_keys = Object.keys(config); - for (let i=0; i < conf_keys; i++){ + let result_config = {}; + let conf_keys = Object.keys(rawconfig); + + for (let i=0; i < conf_keys.length; i++){ + if (availableConf.hasOwnProperty(conf_keys[i])){ - let value = config[conf_keys[i]]; + let value = rawconfig[conf_keys[i]]; if (availableConf[conf_keys[i]].indexOf(value) < 0){ return gpgme_error('PARAM_WRONG'); } else { @@ -75,6 +74,12 @@ function parseconfiguration(config){ return gpgme_error('PARAM_WRONG'); } } + let default_keys = Object.keys(defaultConf); + for (let j=0; j < default_keys.length; j++){ + if (!result_config.hasOwnProperty(default_keys[j])){ + result_config[default_keys[j]] = defaultConf[default_keys[j]]; + } + } return result_config; }; diff --git a/lang/js/src/permittedOperations.js b/lang/js/src/permittedOperations.js index 79e74223..274e037e 100644 --- a/lang/js/src/permittedOperations.js +++ b/lang/js/src/permittedOperations.js @@ -21,9 +21,16 @@ /** * Definition of the possible interactions with gpgme-json. * operation: - required: Array - optional: Array - pinentry: Boolean If a pinentry dialog is expected, and a timeout of + required: Array + name The name of the property + allowed: Array of allowed types. Currently accepted values: + ['number', 'string', 'boolean', 'Uint8Array'] + array_allowed: Boolean. If the value can be an array of the above + allowed_data: If present, restricts to the given value + optional: Array + see 'required', with these parameters not being mandatory for a + complete message + pinentry: boolean If a pinentry dialog is expected, and a timeout of 5000 ms would be too short answer: type: