js: Configuration and Error handling
-- * 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
This commit is contained in:
parent
5befa1c975
commit
1fb310cabe
@ -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;
|
||||
}
|
||||
|
@ -18,99 +18,125 @@
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
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'
|
||||
},
|
||||
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'
|
||||
}
|
||||
};
|
||||
|
||||
// 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'
|
||||
},
|
||||
/**
|
||||
* 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 gpgme_error(code = 'GENERIC_ERROR', info){
|
||||
if (err_list.hasOwnProperty(code)){
|
||||
if (err_list[code].type === 'error'){
|
||||
return new GPGME_Error(code);
|
||||
}
|
||||
if (code === 'TODO'){
|
||||
alert('TODO_Error!');
|
||||
if (err_list[code].type === 'warning'){
|
||||
console.log(new GPGME_Error(code));
|
||||
}
|
||||
if (errors.hasOwnProperty(code)){
|
||||
code = 'GENERIC_ERROR';
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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});
|
||||
});
|
||||
});
|
||||
};
|
@ -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){
|
||||
|
@ -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');
|
||||
}
|
||||
}
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
@ -28,13 +28,13 @@
|
||||
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(){
|
||||
@ -44,9 +44,16 @@
|
||||
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(){
|
||||
@ -59,19 +66,23 @@
|
||||
* 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,
|
||||
@ -80,57 +91,66 @@
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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?
|
||||
*/
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user