js: Configuration and Error handling
authorMaximilian Krambach <maximilian.krambach@intevation.de>
Wed, 25 Apr 2018 13:59:36 +0000 (15:59 +0200)
committerMaximilian Krambach <maximilian.krambach@intevation.de>
Wed, 25 Apr 2018 13:59:36 +0000 (15:59 +0200)
--

* gpgmejs_openpgpjs
  - unsuported values with no negative consequences can now reject,
    warn or be ignored, according to config.unconsidered_params
  - cleanup of unsupported/supported parameters and TODOS

* A src/index.js init() now accepts a configuration object

* Errors will now be derived from Error, offering more info and a
  stacktrace.

* Fixed Connection.post() timeout triggering on wrong cases

* Added comments in permittedOperations.js, which gpgme interactions
  are still unimplemented and should be added next

lang/js/src/Connection.js
lang/js/src/Errors.js
lang/js/src/Helpers.js
lang/js/src/Key.js
lang/js/src/Keyring.js
lang/js/src/Message.js
lang/js/src/gpgmejs.js
lang/js/src/gpgmejs_openpgpjs.js
lang/js/src/index.js
lang/js/src/permittedOperations.js

index 4270be5..5b092ab 100644 (file)
@@ -24,7 +24,7 @@
  * expected.
  */
 import { permittedOperations } from './permittedOperations'
-import { GPGMEJS_Error } from "./Errors"
+import { gpgme_error } from "./Errors"
 import { GPGME_Message } from "./Message";
 
 /**
@@ -62,7 +62,7 @@ export class Connection{
      */
     connect(){
         if (this._isConnected === true){
-            GPGMEJS_Error('CONN_ALREADY_CONNECTED');
+            gpgme_error('CONN_ALREADY_CONNECTED');
         } else {
             this._isConnected = true;
             this._connection = chrome.runtime.connectNative('gpgmejson');
@@ -83,13 +83,13 @@ export class Connection{
      */
     post(message){
         if (!this.isConnected){
-            return Promise.reject(GPGMEJS_Error('CONN_NO_CONNECT'));
+            return Promise.reject(gpgme_error('CONN_NO_CONNECT'));
         }
         if (!message || !message instanceof GPGME_Message){
-            return Promise.reject(GPGMEJS_Error('PARAM_WRONG'), message);
+            return Promise.reject(gpgme_error('PARAM_WRONG'), message);
         }
         if (message.isComplete !== true){
-            return Promise.reject(GPGMEJS_Error('MSG_INCOMPLETE'));
+            return Promise.reject(gpgme_error('MSG_INCOMPLETE'));
         }
         let me = this;
         return new Promise(function(resolve, reject){
@@ -97,7 +97,7 @@ export class Connection{
             let listener = function(msg) {
                 if (!msg){
                     me._connection.onMessage.removeListener(listener)
-                    reject(GPGMEJS_Error('CONN_EMPTY_GPG_ANSWER'));
+                    reject(gpgme_error('CONN_EMPTY_GPG_ANSWER'));
                 } else if (msg.type === "error"){
                     me._connection.onMessage.removeListener(listener)
                     reject(
@@ -118,17 +118,18 @@ export class Connection{
             };
 
             me._connection.onMessage.addListener(listener);
-            let timeout = new Promise(function(resolve, reject){
-                setTimeout(function(){
-                    reject(GPGMEJS_Error('CONN_TIMEOUT'));
-                }, 5000);
-            });
             if (permittedOperations[message.operation].pinentry){
                 return me._connection.postMessage(message.message);
             } else {
-                return Promise.race([timeout,
-                    me._connection.postMessage(message.message)
-                ]);
+                return Promise.race([
+                    me._connection.postMessage(message.message),
+                    function(resolve, reject){
+                        setTimeout(function(){
+                            reject(gpgme_error('CONN_TIMEOUT'));
+                        }, 5000);
+                    }]).then(function(result){
+                    return result;
+                });
             }
         });
      }
@@ -148,7 +149,7 @@ class Answer{
     /**
      * Add the information to the answer
      * @param {Object} msg The message as received with nativeMessaging
-     * returns true if successfull, GPGMEJS_Error otherwise
+     * returns true if successfull, gpgme_error otherwise
      */
     add(msg){
         if (this._response === undefined){
@@ -157,14 +158,14 @@ class Answer{
         let messageKeys = Object.keys(msg);
         let poa = permittedOperations[this.operation].answer;
         if (messageKeys.length === 0){
-            return GPGMEJS_Error('CONN_UNEXPECTED_ANSWER');
+            return gpgme_error('CONN_UNEXPECTED_ANSWER');
         }
         for (let i= 0; i < messageKeys.length; i++){
             let key = messageKeys[i];
             switch (key) {
                 case 'type':
                     if ( msg.type !== 'error' && poa.type.indexOf(msg.type) < 0){
-                        return GPGMEJS_Error('CONN_UNEXPECTED_ANSWER');
+                        return gpgme_error('CONN_UNEXPECTED_ANSWER');
                     }
                     break;
                 case 'more':
@@ -183,7 +184,7 @@ class Answer{
                             this._response[key] = msg[key];
                         }
                         else if (this._response[key] !== msg[key]){
-                                return GPGMEJS_Error('CONN_UNEXPECTED_ANSWER',msg[key]);
+                                return gpgme_error('CONN_UNEXPECTED_ANSWER',msg[key]);
                         }
                     }
                     //infos may be json objects etc. Not yet defined.
@@ -195,7 +196,7 @@ class Answer{
                         this._response.push(msg[key]);
                     }
                     else {
-                        return GPGMEJS_Error('CONN_UNEXPECTED_ANSWER', key);
+                        return gpgme_error('CONN_UNEXPECTED_ANSWER', key);
                     }
                     break;
             }
index 04b13e1..2f53aa8 100644 (file)
  * SPDX-License-Identifier: LGPL-2.1+
  */
 
+const err_list = {
+    // Connection
+    'CONN_NO_CONNECT': {
+        msg:'Connection with the nativeMessaging host could not be'
+            + ' established.',
+        type: 'error'
+    },
+    'CONN_DISCONNECTED': {
+        msg:'Connection with the nativeMessaging host was lost.',
+        type: 'error'
+    },
+    'CONN_EMPTY_GPG_ANSWER':{
+        msg: 'The nativeMessaging answer was empty.',
+        type: 'error'
+    },
+    'CONN_TIMEOUT': {
+        msg: 'A connection timeout was exceeded.',
+        type: 'error'
+    },
+    'CONN_UNEXPECTED_ANSWER': {
+        msg: 'The answer from gnupg was not as expected.',
+        type: 'error'
+    },
+    'CONN_ALREADY_CONNECTED':{
+        msg: 'A connection was already established.',
+        type: 'warning'
+    },
+    // Message/Data
+    'MSG_INCOMPLETE': {
+        msg: 'The Message did not match the minimum requirements for'
+            + ' the interaction.',
+        type: 'error'
+    },
+    'MSG_EMPTY' : {
+        msg: 'The Message is empty.',
+        type: 'error'
+    },
+    'MSG_OP_PENDING': {
+        msg: 'There is no operation specified yet. The parameter cannot'
+            + ' be set',
+        type: 'warning'
+    },
+    'MSG_WRONG_OP': {
+        msg: 'The operation requested could not be found',
+        type: 'warning'
+    },
+    'MSG_NO_KEYS' : {
+        msg: 'There were no valid keys provided.',
+        type: 'warning'
+    },
+    'MSG_NOT_A_FPR': {
+        msg: 'The String is not an accepted fingerprint',
+        type: 'warning'
+    },
+    'KEY_INVALID': {
+        msg:'Key object is invalid',
+        type: 'error'
+    },
+    // generic
+    'PARAM_WRONG':{
+        msg: 'invalid parameter was found',
+        type: 'error'
+    },
+    'PARAM_IGNORED': {
+        msg: 'An parameter was set that has no effect in gpgmejs',
+        type: 'warning'
+    },
+    'NOT_IMPLEMENTED': {
+        msg: 'A openpgpjs parameter was submitted that is not implemented',
+        type: 'error'
+    },
+    'NOT_YET_IMPLEMENTED': {
+        msg: 'Support of this is probable, but it is not implemented yet',
+        type: 'error'
+    },
+    'GENERIC_ERROR': {
+        msg: 'Unspecified error',
+        type: 'error'
+    }
+};
+
 /**
- * Checks the given error code and returns some information about it's meaning
- * @param {String} code The error code
- * @returns {Object} An object containing string properties code and msg
- * TODO: error-like objects with the code 'GNUPG_ERROR' are errors sent
- * directly by gnupg as answer in Connection.post()
+ * Checks the given error code and returns an error object with some
+ * information about meaning and origin
+ * @param {*} code Error code. Should be in err_list or 'GNUPG_ERROR'
+ * @param {*} info Error message passed through if code is 'GNUPG_ERROR'
  */
-export function GPGMEJS_Error(code = 'GENERIC_ERROR'){
-        if (!typeof(code) === 'string'){
-            code = 'GENERIC_ERROR';
-        }
-        let errors = { //TODO: someplace else
-            // Connection
-            'CONN_NO_CONNECT': {
-                msg:'Connection with the nativeMessaging host could not be'
-                    + ' established.',
-                type: 'error'
-            },
-            'CONN_EMPTY_GPG_ANSWER':{
-                msg: 'The nativeMessaging answer was empty.',
-                type: 'error'
-            },
-            'CONN_TIMEOUT': {
-                msg: 'A connection timeout was exceeded.',
-                type: 'error'
-            },
-            'CONN_UNEXPECTED_ANSWER': {
-                msg: 'The answer from gnupg was not as expected.',
-                type: 'error'
-            },
-            'CONN_ALREADY_CONNECTED':{
-                msg: 'A connection was already established.',
-                type: 'warn'
-            },
-            // Message/Data
-            'MSG_INCOMPLETE': {
-                msg: 'The Message did not match the minimum requirements for'
-                    + ' the interaction.',
-                type: 'error'
-            },
-            'MSG_EMPTY' : {
-                msg: 'The Message is empty.',
-                type: 'error'
-            },
-            'MSG_OP_PENDING': {
-                msg: 'There is no operation specified yet. The parameter cannot'
-                    + ' be set',
-                type: 'warning'
-            },
-            'MSG_WRONG_OP': {
-                msg: 'The operation requested could not be found',
-                type: 'warning'
-            },
-            'MSG_NO_KEYS' : {
-                msg: 'There were no valid keys provided.',
-                type: 'warn'
-            },
-            'MSG_NOT_A_FPR': {
-                msg: 'The String is not an accepted fingerprint',
-                type: 'warn'
-            },
-
-            // generic
-            'PARAM_WRONG':{
-                msg: 'invalid parameter was found',
-                type: 'error'
-            },
-            'NOT_IMPLEMENTED': {
-                msg: 'A openpgpjs parameter was submitted that is not implemented',
-                type: 'error'
-            },
-            'NOT_YET_IMPLEMENTED': {
-                msg: 'Support of this is probable, but it is not implemented yet',
-                type: 'error'
-            },
-            'GENERIC_ERROR': {
-                msg: 'Unspecified error',
-                type: 'error'
-            },
-        }
-        if (code === 'TODO'){
-            alert('TODO_Error!');
+export function gpgme_error(code = 'GENERIC_ERROR', info){
+    if (err_list.hasOwnProperty(code)){
+        if (err_list[code].type === 'error'){
+            return new GPGME_Error(code);
         }
-        if (errors.hasOwnProperty(code)){
-            code = 'GENERIC_ERROR';
+        if (err_list[code].type === 'warning'){
+            console.log(new GPGME_Error(code));
         }
-        if (errors.type === 'error'){
-            return {code: 'code',
-                    msg: errors[code].msg
-                };
-        }
-        if (errors.type === 'warning'){
-            console.log(code + ': ' + error[code].msg);
-        }
-        return undefined;
+        return null;
+    } else if (code === 'GNUPG_ERROR'){
+        return new GPGME_Error(code, info.msg);
+    }
+    else {
+        return new GPGME_Error('GENERIC_ERROR');
+    }
 }
+
+class GPGME_Error extends Error{
+    constructor(code, msg=''){
+        if (code === 'GNUPG_ERROR' && typeof(msg) === 'string'){
+            super(msg);
+        } else if (err_list.hasOwnProperty(code)){
+            super(err_list[code].msg);
+        } else {
+            super(err_list['GENERIC_ERROR'].msg);
+        }
+        this.code = code || 'GENERIC_ERROR';
+    }
+    set code(value){
+        this._code = value;
+    }
+    get code(){
+        return this._code;
+    }
+}
\ No newline at end of file
index d9750ba..841c0ed 100644 (file)
@@ -17,7 +17,7 @@
  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  * SPDX-License-Identifier: LGPL-2.1+
  */
-import { GPGMEJS_Error } from "./Errors";
+import { gpgme_error } from "./Errors";
 
 /**
  * Tries to return an array of fingerprints, either from input fingerprints or
@@ -28,7 +28,7 @@ import { GPGMEJS_Error } from "./Errors";
 
 export function toKeyIdArray(input, nocheck){
     if (!input){
-        GPGMEJS_Error('MSG_NO_KEYS');
+        gpgme_error('MSG_NO_KEYS');
         return [];
     }
     if (!Array.isArray(input)){
@@ -40,7 +40,7 @@ export function toKeyIdArray(input, nocheck){
             if (isFingerprint(input[i]) === true){
                 result.push(input[i]);
             } else {
-                GPGMEJS_Error('MSG_NOT_A_FPR');
+                gpgme_error('MSG_NOT_A_FPR');
             }
         } else if (typeof(input[i]) === 'object'){
             let fpr = '';
@@ -53,14 +53,14 @@ export function toKeyIdArray(input, nocheck){
             if (isFingerprint(fpr) === true){
                 result.push(fpr);
             } else {
-                GPGMEJS_Error('MSG_NOT_A_FPR');
+                gpgme_error('MSG_NOT_A_FPR');
             }
         } else {
-            return GPGMEJS_Error('PARAM_WRONG');
+            return gpgme_error('PARAM_WRONG');
         }
     }
     if (result.length === 0){
-        GPGMEJS_Error('MSG_NO_KEYS');
+        gpgme_error('MSG_NO_KEYS');
         return [];
     } else {
         return result;
index 5ae8043..f6fa7ae 100644 (file)
@@ -27,7 +27,9 @@
  */
 
 import {isFingerprint} from './Helpers'
-import {GPGMEJS_Error} from './Errors'
+import {gpgme_error} from './Errors'
+import { GPGME_Message } from './Message';
+import { permittedOperations } from './permittedOperations';
 
 export class GPGME_Key {
 
@@ -172,32 +174,30 @@ export class GPGME_Key {
  *
  */
 function checkKey(fingerprint, property){
-    return Promise.reject(GPGMEJS_Error('NOT_YET_IMPLEMENTED'));
-
+    return Promise.reject(gpgme_error('NOT_YET_IMPLEMENTED'));
+    if (!property ||
+        permittedOperations[keyinfo].indexOf(property) < 0){
+            return Promise.reject(gpgme_error('PARAM_WRONG'));
+    }
     return new Promise(function(resolve, reject){
         if (!isFingerprint(fingerprint)){
-            reject('not a fingerprint'); //TBD
+            reject('KEY_INVALID');
         }
-        let conn = new Connection();
-        conn.post('getkey',{ // TODO not yet implemented in gpgme
-            'fingerprint': this.fingerprint})
-        .then(function(result){
-            if (property !== undefined){
-                if (result.hasOwnProperty(key)){
-                    resolve(result[property]);
-                }
-                else if (property == 'secret'){
-                    // property undefined means "not true" in case of secret
-                    resolve(false);
-                } else {
-                    reject('ERR_INVALID_PROPERTY') //TBD
-                }
+        let msg = new GPGME_Message('keyinfo');
+        msg.setParameter('fingerprint', this.fingerprint);
+        return (this.connection.post(msg)).then(function(result){
+            if (result.hasOwnProperty(property)){
+                resolve(result[property]);
+            }
+            else if (property == 'secret'){
+                // TBD property undefined means "not true" in case of secret?
+                resolve(false);
+            } else {
+                reject(gpgme_error('CONN_UNEXPECTED_ANSWER'));
             }
-
-
-            resolve(result);
         }, function(error){
-            reject(error);
+            reject({code: 'GNUPG_ERROR',
+                         msg: error.msg});
         });
     });
 };
\ No newline at end of file
index ef8028f..e1f0a50 100644 (file)
@@ -21,6 +21,7 @@
 import {GPGME_Message} from './Message'
 import {GPGME_Key} from './Key'
 import { isFingerprint, isLongId } from './Helpers';
+import { gpgme_error } from './Errors';
 
 export class GPGME_Keyring {
     constructor(connection){
@@ -37,9 +38,9 @@ export class GPGME_Keyring {
             if (this._connection.isConnected){
                 return this._connection;
             }
-            return undefined; //TODO: connection was lost!
+            return gpgme_error('CONN_DISCONNECTED');
         }
-        return undefined; //TODO: no connection there
+        return gpgme_error('CONN_NO_CONNECT');
     }
 
     /**
@@ -81,9 +82,7 @@ export class GPGME_Keyring {
      * filters described below. True will filter on the condition, False will
      * reverse the filter, if not present or undefined, the filter will not be
      * considered. Please note that some combination may not make sense
-     * @param {Boolean} flags.defaultKey Only Keys marked as Default Keys
      * @param {Boolean} flags.secret Only Keys containing a secret part.
-     * @param {Boolean} flags.valid Valid Keys only
      * @param {Boolean} flags.revoked revoked Keys only
      * @param {Boolean} flags.expired Expired Keys only
      * @param {String} (optional) pattern A pattern to search for, in userIds or KeyIds
@@ -108,16 +107,20 @@ export class GPGME_Keyring {
                 } else if (secretflag === false){
                     anticonditions.push('hasSecret');
                 }
+                /**
                 if (flags.defaultKey === true){
                     conditions.push('isDefault');
                 } else if (flags.defaultKey === false){
                     anticonditions.push('isDefault');
                 }
-                if (flags.valid === true){
+                */
+                /**
+                 * if (flags.valid === true){
                     anticonditions.push('isInvalid');
                 } else if (flags.valid === false){
                     conditions.push('isInvalid');
                 }
+                */
                 if (flags.revoked === true){
                     conditions.push('isRevoked');
                 } else if (flags.revoked === false){
index 1b36f11..06ac8db 100644 (file)
@@ -18,7 +18,7 @@
  * SPDX-License-Identifier: LGPL-2.1+
  */
 import { permittedOperations } from './permittedOperations'
-import { GPGMEJS_Error } from './Errors'
+import { gpgme_error } from './Errors'
 export class GPGME_Message {
     //TODO getter
 
@@ -39,20 +39,20 @@ export class GPGME_Message {
      */
     setParameter(param,value){
         if (!param || typeof(param) !== 'string'){
-            return GPGMEJS_Error('PARAM_WRONG');
+            return gpgme_error('PARAM_WRONG');
         }
         if (!this._msg || !this._msg.op){
-            return GPGMEJS_Error('MSG_OP_PENDING');
+            return gpgme_error('MSG_OP_PENDING');
         }
         let po = permittedOperations[this._msg.op];
         if (!po){
-            return GPGMEJS_Error('MSG_WRONG_OP');
+            return gpgme_error('MSG_WRONG_OP');
         }
         if (po.required.indexOf(param) >= 0 || po.optional.indexOf(param) >= 0){
             this._msg[param] = value;
             return true;
         }
-        return GPGMEJS_Error('PARAM_WRONG');
+        return gpgme_error('PARAM_WRONG');
     }
 
     /**
@@ -98,7 +98,7 @@ export class GPGME_Message {
  */
 function setOperation (scope, operation){
     if (!operation || typeof(operation) !== 'string'){
-        return GPGMEJS_Error('PARAM_WRONG');
+        return gpgme_error('PARAM_WRONG');
     }
     if (permittedOperations.hasOwnProperty(operation)){
         if (!scope._msg){
@@ -106,6 +106,6 @@ function setOperation (scope, operation){
         }
         scope._msg.op = operation;
     } else {
-        return GPGMEJS_Error('MSG_WRONG_OP');
+        return gpgme_error('MSG_WRONG_OP');
     }
 }
\ No newline at end of file
index b20ff0f..b504a45 100644 (file)
@@ -21,7 +21,7 @@
 import {Connection} from "./Connection"
 import {GPGME_Message} from './Message'
 import {toKeyIdArray} from "./Helpers"
-import {GPGMEJS_Error as Error, GPGMEJS_Error} from "./Errors"
+import { gpgme_error } from "./Errors"
 import { GPGME_Keyring } from "./Keyring";
 
 export class GpgME {
@@ -35,10 +35,12 @@ export class GpgME {
 
     set connection(connection){
         if (this._connection instanceof Connection){
-            //TODO Warning: Connection already established
+            gpgme_error('CONN_ALREADY_CONNECTED');
         }
         if (connection instanceof Connection){
             this._connection = connection;
+        } else {
+            gpgme_error('PARAM_WRONG');
         }
     }
 
@@ -54,11 +56,12 @@ export class GpgME {
 
     set Keyring(keyring){
         if (ring && ring instanceof GPGME_Keyring){
-            this.Keyring = ring;
+            this._Keyring = ring;
         }
     }
 
     get Keyring(){
+        return this._Keyring;
     }
 
     /**
@@ -96,7 +99,7 @@ export class GpgME {
 
     decrypt(data){
         if (data === undefined){
-            return Promise.reject(GPGMEJS_Error('MSG_EMPTY'));
+            return Promise.reject(gpgme_error('MSG_EMPTY'));
         }
         let msg = new GPGME_Message('decrypt');
         putData(msg, data);
@@ -105,7 +108,7 @@ export class GpgME {
     }
 
     deleteKey(key, delete_secret = false, no_confirm = false){
-        return Promise.reject(GPGMEJS_Error('NOT_YET_IMPLEMENTED'));
+        return Promise.reject(gpgme_error('NOT_YET_IMPLEMENTED'));
         let msg = new GPGME_Message('deletekey');
         let key_arr = toKeyIdArray(key);
         if (key_arr.length !== 1){
@@ -126,7 +129,7 @@ export class GpgME {
             case 'ERR_NO_ERROR':
                 return Promise.resolve('okay'); //TBD
             default:
-                return Promise.reject(GPGMEJS_Error('TODO') ); //
+                return Promise.reject(gpgme_error('TODO') ); //
                 // INV_VALUE,
                 // GPG_ERR_NO_PUBKEY,
                 // GPG_ERR_AMBIGUOUS_NAME,
@@ -145,7 +148,7 @@ export class GpgME {
  */
 function putData(message, data){
     if (!message || !message instanceof GPGME_Message ) {
-        return GPGMEJS_Error('PARAM_WRONG');
+        return gpgme_error('PARAM_WRONG');
     }
     if (!data){
         message.setParameter('data', '');
@@ -164,6 +167,6 @@ function putData(message, data){
             message.setParameter ('data', decoder.decode(txt));
         }
     } else {
-        return GPGMEJS_Error('PARAM_WRONG');
+        return gpgme_error('PARAM_WRONG');
     }
 }
index e32f43a..4e5e1ea 100644 (file)
  import {GPGME_Keyring}  from "./Keyring"
  import { GPGME_Key } from "./Key";
  import { isFingerprint } from "./Helpers"
- import { GPGMEJS_Error } from './Errors'
+ import { gpgme_error } from "./Errors"
 
 
  export class GpgME_openpgpmode {
 
-    constructor(connection){
-        this.initGpgME(connection);
+    constructor(connection, config = {}){
+        this.initGpgME(connection, config);
     }
 
     get Keyring(){
         return undefined;
     }
 
-    initGpgME(connection){
-        this._GpgME = new GpgME(connection);
-        this._Keyring = new GPGME_Keyring_openpgpmode(connection);
+    initGpgME(connection, config = {}){
+        if (connection && typeof(config) ==='object'){
+            this._config = config;
+            if (!this._GPGME){
+                this._GpgME = new GpgME(connection, config);
+            }
+            if (!this._Keyring){
+                this._Keyring = new GPGME_Keyring_openpgpmode(connection);
+            }
+        }
     }
 
     get GpgME(){
      * Encrypt Message
      * Supported:
      * @param  {String|Uint8Array} data
+     * //an openpgp Message also accepted here. TODO: is this wanted?
      * @param  {Key|Array<Key>} publicKeys
+     * //Strings of Fingerprints
      * @param  {Boolean} wildcard
      * TODO:
-     * @param  {Key|Array<Key>} privateKeys
-     * @param  {String} filename
-     * @param  {module:enums.compression} compression
-     * @param  {Boolean} armor
-     * @param  {Boolean} detached
+     * @param  {Key|Array<Key>} privateKeys // -> encryptsign
+     * @param  {module:enums.compression} compression //TODO accepts integer, if 0 (no compression) it won't compress
+     * @param  {Boolean} armor // TODO base64 switch
+     * @param  {Boolean} detached // --> encryptsign
      * unsupported:
      * @param  {String|Array<String>} passwords
      * @param  {Object} sessionKey
      * @param  {Signature} signature
      * @param  {Boolean} returnSessionKey
+     * @param  {String} filename
+     *
+     * Can be set, but will be ignored:
      *
      * @returns {Promise<Object>}
      *      {data: ASCII armored message,
     * @async
     * @static
     */
-    encrypt({data = '', publicKeys = '', privateKeys, passwords, sessionKey,
-        filename, compression, armor=true, detached=false, signature=null,
-        returnSessionKey=null, wildcard=false, date=null}) {
-        if (passwords !== undefined
-            || sessionKey !== undefined
+    encrypt({data = '', publicKeys = '', privateKeys, passwords=null,
+        sessionKey = null, filename, compression, armor=true, detached=false,
+        signature=null, returnSessionKey=null, wildcard=false, date=null}) {
+        if (passwords !== null
+            || sessionKey !== null
             || signature !== null
             || returnSessionKey !== null
-            || date !== null){
+            || date !== null
+            ){
             return Promise.reject(GPMGEJS_Error('NOT_IMPLEMENTED'));
         }
         if ( privateKeys
-            || filename
             || compression
             || armor === false
             || detached == true){
-                return Promise.reject(GPGMEJS_Error('NOT_YET_IMPLEMENTED'));
+                return Promise.reject(gpgme_error('NOT_YET_IMPLEMENTED'));
+        }
+        if (filename){
+            if (this._config.unconsidered_params === 'warn'){
+                GPMGEJS_Error('PARAM_IGNORED');
+            } else if (this._config.unconsidered_params === 'error'){
+                return Promise.reject(GPMGEJS_Error('NOT_IMPLEMENTED'));
+            }
         }
         return this.GpgME.encrypt(data, translateKeyInput(publicKeys), wildcard);
     }
 
     /** Decrypt Message
-    * supported
-    * TODO: @param {Message} message TODO: for now it accepts an armored string only
+    * supported openpgpjs parameters:
+    * @param {Message|Uint8Array|String} message Message object from openpgpjs
     * Unsupported:
     * @param  {String|Array<String>} passwords
+    * @param  {Key|Array<Key>} privateKeys
     * @param  {Object|Array<Object>} sessionKeys
-    * @param  {Date} date
-
-    * TODO
-    * @param  {Key|Array<Key>} privateKey
-    * @param  {Key|Array<Key>} publicKeys
+    * Not yet supported, but planned
     * @param  {String} format                    (optional) return data format either as 'utf8' or 'binary'
     * @param  {Signature} signature              (optional) detached signature for verification
-
+    * Ignored values: can be safely set, but have no effect
+    * @param  {Date} date
+    * @param  {Key|Array<Key>} publicKeys
+    *
     * @returns {Promise<Object>}             decrypted and verified message in the form:
     *                                         { data:Uint8Array|String, filename:String, signatures:[{ keyid:String, valid:Boolean }] }
     * @async
     * @static
     */
-    decrypt({ message, privateKeys, passwords, sessionKeys, publicKeys, format='utf8', signature=null, date}) {
-        if (passwords !== undefined
-            || sessionKeys
-            || date){
-            return Promise.reject(GPGMEJS_Error('NOT_IMPLEMENTED'));
+    decrypt({ message, privateKeys, passwords=null, sessionKeys,
+        publicKeys, format='utf8', signature=null, date= null}) {
+        if (passwords !== null || sessionKeys || privateKeys){
+            return Promise.reject(gpgme_error('NOT_IMPLEMENTED'));
         }
-        if ( privateKeys
-            || publicKeys
-            || format !== 'utf8'
-            || signature
-        ){
-            return Promise.reject(GPGMEJS_Error('NOT_YET_IMPLEMENTED'));
+        if ( format !== 'utf8' || signature){
+            return Promise.reject(gpgme_error('NOT_YET_IMPLEMENTED'));
+        }
+        if (date !== null || publicKeys){
+            if (this._config.unconsidered_params === 'warn'){
+                GPMGEJS_Error('PARAM_IGNORED');
+            } else if (this._config.unconsidered_params === 'reject'){
+                return Promise.reject(GPMGEJS_Error('NOT_IMPLEMENTED'));
+            }
         }
         return this.GpgME.decrypt(message);
         // TODO: translate between:
@@ -185,7 +205,7 @@ class GPGME_Keyring_openpgpmode {
             else {
                 // TODO: Can there be "no default key"?
                 // TODO: Can there be several default keys?
-                return GPGMEJS_Error('TODO');
+                return gpgme_error('TODO');
             }
         });
     }
@@ -202,10 +222,10 @@ class GPGME_Keyring_openpgpmode {
      */
     deleteKey(key){
         if (typeof(key) !== "object"){
-            return Promise.reject(GPGMEJS_Error('PARAM_WRONG'));
+            return Promise.reject(gpgme_error('PARAM_WRONG'));
         }
         if ( !key.fingerprint || ! isFingerprint(key.fingerprint)){
-            return Promise.reject(GPGMEJS_Error('PARAM_WRONG'));
+            return Promise.reject(gpgme_error('PARAM_WRONG'));
         }
         let key_to_delete = new GPGME_Key(key.fingerprint);
         return key_to_delete.deleteKey(key.secret);
@@ -224,8 +244,8 @@ class GPGME_Key_openpgpmode {
     set init (value){
         if (!this._GPGME_Key && value instanceof GPGME_Key){
             this._GPGME_Key = value;
-        } else if (!this._GPGME_Key && isFingerprint(fpr)){
-            this._GPGME_Key = new GPGME_Key;
+        } else if (!this._GPGME_Key && isFingerprint(value)){
+            this._GPGME_Key = new GPGME_Key(value);
         }
     }
 
index a54277c..4890431 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 import { GpgME } from "./gpgmejs";
-import { GPGMEJS_Error } from "./Errors";
+import { gpgme_error } from "./Errors";
 import { GpgME_openpgpmode } from "./gpgmejs_openpgpjs";
 import { Connection } from "./Connection";
 
@@ -29,7 +29,8 @@ import { Connection } from "./Connection";
  */
 function init( config = {
     api_style: 'gpgme', //  | gpgme_openpgpjs
-    null_expire_is_never: true // Boolean
+    null_expire_is_never: true, // Boolean
+    unconsidered_params: 'warn'//'warn' || 'reject'
     }){
         return new Promise(function(resolve, reject){
             let connection = new Connection;
@@ -41,12 +42,12 @@ function init( config = {
                     let gpgme = null;
                     if (config.api_style && config.api_style === 'gpgme_openpgpjs'){
                         resolve(
-                            new GpgME_openpgpmode(connection));
+                            new GpgME_openpgpmode(connection, config));
                     } else {
                         resolve(new GpgME(connection));
                     }
                 } else {
-                    reject(GPGMEJS_Error('CONN_NO_CONNECT'));
+                    reject(gpgme_error('CONN_NO_CONNECT'));
                 }
             };
             setTimeout(delayedreaction, 5);
index 892f4f2..79e7422 100644 (file)
@@ -31,7 +31,7 @@
                 partial and in need of concatenation
           params: Array<String> Information that do not change throughout
                 the message
-          infos: Array<String> arbitrary information that may change
+          infos: Array<*> arbitrary information that may result in a list
       }
   }
   */
@@ -72,7 +72,55 @@ export const permittedOperations = {
             type: ['plaintext'],
             data: ['data'],
             params: ['base64', 'mime'],
-            infos: ['info']
+            infos: [] // pending. Info about signatures and validity
+                    //signature: [{Key Fingerprint, valid Boolean}]
+        }
+    },
+    /**
+    keyinfo: { // querying the Key's information.
+        required: ['fingerprint'],
+        anser: {
+            type: ['TBD'],
+            data: [],
+            params: ['hasSecret', 'isRevoked', 'isExpired', 'armored',
+                'timestamp', 'expires', 'pubkey_algo'],
+            infos: ['subkeys', 'userIds']
+    }*/
+
+    /**
+    listkeys:{
+        optional: ['with-secret', 'pattern'],
+    answer: {
+        type: ['TBD'], //Array of fingerprints?
+        infos: ['TBD'] //the property with infos
+    },
+    */
+
+    /**
+    importkey: {
+        required: ['keyarmored'],
+        answer: {
+            type: ['TBD'],
+            infos: [''], // for each key if import was a success, if it was an update
+        }
+    },
+    */
+
+    /**
+    deletekey:  {
+        required: ['fingerprint'],
+        answer: {
+            type ['TBD'],
+            infos: [''] //success:true? in gpgme, an error NO_ERROR is returned
         }
     }
+    */
+
+    /**
+     *get armored secret different treatment from keyinfo!
+     */
+
+    /**
+     * TBD key modification requests?
+     */
 }