diff options
Diffstat (limited to '')
| -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;      }  } | 
