From d9edce1ea7c6c8e053997bc9d59b337f16d6fd9b Mon Sep 17 00:00:00 2001 From: Dominique Da Silva Date: Sun, 10 Nov 2019 01:22:11 +0000 Subject: [PATCH] Updated openpgp module to 4.6.2 --- package.json | 22 ++-- routes/lists.js | 118 +++++++++++------- routes/subscription.js | 49 +++++--- .../partials/subscription-custom-fields.hbs | 2 +- 4 files changed, 117 insertions(+), 74 deletions(-) diff --git a/package.json b/package.json index 2a22cdb0..81e3218d 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "eslint-config-nodemailer": "^1.2.0", "grunt": "^1.0.1", "grunt-cli": "^1.2.0", - "grunt-contrib-nodeunit": "^1.0.0", + "grunt-contrib-nodeunit": "^2.0.0", "grunt-eslint": "^20.1.0", "jsxgettext-andris": "^0.9.0-patch.1", "lodash": "^4.17.4", @@ -61,10 +61,11 @@ "connect-redis": "^3.3.0", "cookie-parser": "^1.4.3", "cors": "^2.8.4", + "country-list": "^2.2.0", "csurf": "^1.9.0", - "csv-parse": "^1.2.3", + "csv-parse": "^4.6.5", "device": "^0.3.8", - "dompurify": "^1.0.2", + "dompurify": "^2.0.7", "escape-html": "^1.0.3", "escape-string-regexp": "^1.0.5", "express": "^4.15.5", @@ -72,11 +73,11 @@ "faker": "^4.1.0", "feedparser": "^2.2.1", "fs-extra": "^4.0.2", - "geoip-ultralight": "^0.1.5", + "geoip-country": "^3.2.6", "gettext-parser": "^1.3.0", "gm": "^1.23.0", - "handlebars": "^4.0.10", - "hbs": "^4.0.1", + "handlebars": "^4.4.5", + "hbs": "^4.0.6", "he": "^1.1.1", "html-to-text": "^3.3.0", "humanize": "0.0.9", @@ -88,7 +89,7 @@ "juice": "^4.1.1", "libmime": "^3.1.0", "mailparser": "^2.0.5", - "marked": "^0.3.6", + "marked": "^0.7.0", "memory-cache": "^0.2.0", "mjml": "4.5.0", "mkdirp": "^0.5.1", @@ -100,13 +101,14 @@ "node-gettext": "^2.0.0", "node-mocks-http": "^1.6.5", "nodemailer": "^4.1.1", - "nodemailer-openpgp": "^1.1.0", + "nodemailer-openpgp": "^1.2.0", "npmlog": "^4.1.2", "object-hash": "^1.1.8", - "openpgp": "^2.5.11", + "openpgp": "^4.6.2", "passport": "^0.4.0", + "passport-ldapauth": "^2.1.3", + "passport-ldapjs": "^1.0.3", "passport-local": "^1.0.0", - "passport-ldapauth": "^2.0.0", "premailer-api": "^1.0.4", "redfour": "^1.0.2", "redis": "^2.8.0", diff --git a/routes/lists.js b/routes/lists.js index 0318db12..4247afb3 100644 --- a/routes/lists.js +++ b/routes/lists.js @@ -206,57 +206,85 @@ router.post('/ajax/:id', (req, res) => { let statuses = [_('Unknown'), _('Subscribed'), _('Unsubscribed'), _('Bounced'), _('Complained')]; - res.json({ - draw: req.body.draw, - recordsTotal: total, - recordsFiltered: filteredTotal, - data: data.map((row, i) => [ + let dataPromise = Promise.all(data.map((row, i) => Promise.all([ + Promise.resolve([ (Number(req.body.start) || 0) + 1 + i, htmlescape(row.email || ''), htmlescape(row.firstName || ''), - htmlescape(row.lastName || '') - ].concat(fields.getRow(fieldList, row).map(cRow => { - if (cRow.type === 'number') { - return htmlescape(cRow.value && humanize.numberFormat(cRow.value, 0) || ''); - } else if (cRow.type === 'longtext') { - let value = (cRow.value || ''); - if (value.length > 50) { - value = value.substr(0, 47).trim() + '…'; - } - return htmlescape(value); - } else if (cRow.type === 'gpg') { - let value = (cRow.value || '').trim(); - try { - value = openpgp.key.readArmored(value); - if (value) { - - let keys = value.keys; - for (let i = 0; i < keys.length; i++) { - let key = keys[i]; - switch (key.verifyPrimaryKey()) { - case 0: - return _('Invalid key'); - case 1: - return _('Expired key'); - case 2: - return _('Revoked key'); + htmlescape(row.lastName || ''), + ]), + new Promise((resolve) => { + let fieldsPromise = Promise.all(fields.getRow(fieldList, row).map( async (cRow) => { + switch (cRow.type) { + case 'number': + return Promise.resolve(htmlescape(cRow.value && humanize.numberFormat(cRow.value, 0) || '')); + case 'longtext': + let value = (cRow.value || ''); + if (value.length > 50) { + value = value.substr(0, 47).trim() + '…'; + } + return Promise.resolve(htmlescape(value)); + case 'gpg': + return new Promise((resolve) => { + let value = (cRow.value || '').trim(); + if (!value.length) { + resolve(''); // no key } - } + openpgp.key.readArmored(value). + then((value) => { + const noResultsError = new Error('No armored keys returned'); - value = value.keys && value.keys[0] && value.keys[0].primaryKey.fingerprint; - if (value) { - value = '0x' + value.substr(-16).toUpperCase(); - } - } - } catch (E) { - value = 'parse error'; + if (!(typeof value === 'object') || !('keys' in value)) { throw noResultsError } + if (value.err && value.err.length) { throw value.err[0] } + if (!value.keys.length) { throw noResultsError } + + let keysVerification = Promise.race(value.keys.map((key) => key.verifyPrimaryKey())); + + keysVerification.then((verifiedKey) => { + switch (verifiedKey) { + case 0: + return resolve(_('Invalid key')); + case 1: + return resolve(_('Expired key')); + case 2: + return resolve(_('Revoked key')); + } + value = value.keys[0].primaryKey.fingerprint.join(''); + if (value) { + value = '0x' + value.substr(-16).toUpperCase(); + } + return resolve(htmlescape(value || '')); + }); + }). + catch((error) => { + const message = error.message || error || _('Unexpected error'); + resolve('' + _('Parse error') + '   '); + }); + }).catch((error) => log.error('GPG', error)); + default: + return Promise.resolve(htmlescape(cRow.value || '')); } - return htmlescape(value || ''); - } else { - return htmlescape(cRow.value || ''); - } - })).concat(config.views.lists.statuscolored ? '' + statuses[row.status] + '' : statuses[row.status]).concat(row.created && row.created.toISOString ? '' + row.created.toISOString() + '' : 'N/A').concat('' + _('Edit') + '')) - }); + })); + + fieldsPromise.then(fieldsResults => { + resolve(fieldsResults); + }).catch((error) => log.error('Lists', error)); + }), + Promise.resolve(config.views.lists.statuscolored ? '' + statuses[row.status] + '' : statuses[row.status] ), + Promise.resolve(row.created && row.created.toISOString ? '' + row.created.toISOString() + '' : 'N/A' ), + Promise.resolve('' + _('Edit') + '' ) + ]))); + + dataPromise.then(data => { + data = data.map(row => row.reduce((acc, val) => acc.concat(val), [])); // flatten results + res.json({ + draw: req.body.draw, + recordsTotal: total, + recordsFiltered: filteredTotal, + data: data + }) + }).catch((error) => res.json({ draw: req.body.draw, recordsTotal: 0, recordsFiltered: 0, data:[], error: error.message })); + }); }); }); diff --git a/routes/subscription.js b/routes/subscription.js index a1d24644..3c198eff 100644 --- a/routes/subscription.js +++ b/routes/subscription.js @@ -864,30 +864,43 @@ router.post('/publickey', passport.parseForm, (req, res, next) => { return next(err); } - let privKey; - try { - privKey = openpgp.key.readArmored(configItems.pgpPrivateKey).keys[0]; - if (configItems.pgpPassphrase && !privKey.decrypt(configItems.pgpPassphrase)) { - privKey = false; - } - } catch (E) { - // just ignore if failed - } - - if (!privKey) { + const sendError = () => { err = new Error(_('Public key is not set')); err.status = 404; return next(err); } - let pubkey = privKey.toPublic().armor(); + const sendResult = (privKey) => { + let pubkey = privKey.toPublic().armor(); + res.writeHead(200, { + 'Content-Type': 'application/octet-stream', + 'Content-Disposition': 'attachment; filename=public.asc' + }); + res.end(pubkey); + } - res.writeHead(200, { - 'Content-Type': 'application/octet-stream', - 'Content-Disposition': 'attachment; filename=public.asc' - }); - - res.end(pubkey); + openpgp.key.readArmored(configItems.pgpPrivateKey). + then((armored) => { + let privKey = armored.keys[0]; + if (configItems.pgpPassphrase) { + privKey.decrypt(configItems.pgpPassphrase). + then((success) => { + if (success) { + sendResult(privKey); + } + }). + catch((error) => { + log.error('GPG', error); + sendError(); + }) + } else { + sendResult(privKey); + } + }). + catch((error) => { + log.error('GPG', error); + sendError(); + }); }); }); diff --git a/views/subscription/partials/subscription-custom-fields.hbs b/views/subscription/partials/subscription-custom-fields.hbs index f63a1b80..dab3d0a2 100644 --- a/views/subscription/partials/subscription-custom-fields.hbs +++ b/views/subscription/partials/subscription-custom-fields.hbs @@ -70,7 +70,7 @@ {{/if}} - + {{#translate}}Insert your GPG public key here to encrypt messages sent to your address{{/translate}} ({{#translate}}optional{{/translate}})