Updated openpgp module to 4.6.2
This commit is contained in:
parent
1af65868d5
commit
d9edce1ea7
4 changed files with 117 additions and 74 deletions
22
package.json
22
package.json
|
@ -37,7 +37,7 @@
|
||||||
"eslint-config-nodemailer": "^1.2.0",
|
"eslint-config-nodemailer": "^1.2.0",
|
||||||
"grunt": "^1.0.1",
|
"grunt": "^1.0.1",
|
||||||
"grunt-cli": "^1.2.0",
|
"grunt-cli": "^1.2.0",
|
||||||
"grunt-contrib-nodeunit": "^1.0.0",
|
"grunt-contrib-nodeunit": "^2.0.0",
|
||||||
"grunt-eslint": "^20.1.0",
|
"grunt-eslint": "^20.1.0",
|
||||||
"jsxgettext-andris": "^0.9.0-patch.1",
|
"jsxgettext-andris": "^0.9.0-patch.1",
|
||||||
"lodash": "^4.17.4",
|
"lodash": "^4.17.4",
|
||||||
|
@ -61,10 +61,11 @@
|
||||||
"connect-redis": "^3.3.0",
|
"connect-redis": "^3.3.0",
|
||||||
"cookie-parser": "^1.4.3",
|
"cookie-parser": "^1.4.3",
|
||||||
"cors": "^2.8.4",
|
"cors": "^2.8.4",
|
||||||
|
"country-list": "^2.2.0",
|
||||||
"csurf": "^1.9.0",
|
"csurf": "^1.9.0",
|
||||||
"csv-parse": "^1.2.3",
|
"csv-parse": "^4.6.5",
|
||||||
"device": "^0.3.8",
|
"device": "^0.3.8",
|
||||||
"dompurify": "^1.0.2",
|
"dompurify": "^2.0.7",
|
||||||
"escape-html": "^1.0.3",
|
"escape-html": "^1.0.3",
|
||||||
"escape-string-regexp": "^1.0.5",
|
"escape-string-regexp": "^1.0.5",
|
||||||
"express": "^4.15.5",
|
"express": "^4.15.5",
|
||||||
|
@ -72,11 +73,11 @@
|
||||||
"faker": "^4.1.0",
|
"faker": "^4.1.0",
|
||||||
"feedparser": "^2.2.1",
|
"feedparser": "^2.2.1",
|
||||||
"fs-extra": "^4.0.2",
|
"fs-extra": "^4.0.2",
|
||||||
"geoip-ultralight": "^0.1.5",
|
"geoip-country": "^3.2.6",
|
||||||
"gettext-parser": "^1.3.0",
|
"gettext-parser": "^1.3.0",
|
||||||
"gm": "^1.23.0",
|
"gm": "^1.23.0",
|
||||||
"handlebars": "^4.0.10",
|
"handlebars": "^4.4.5",
|
||||||
"hbs": "^4.0.1",
|
"hbs": "^4.0.6",
|
||||||
"he": "^1.1.1",
|
"he": "^1.1.1",
|
||||||
"html-to-text": "^3.3.0",
|
"html-to-text": "^3.3.0",
|
||||||
"humanize": "0.0.9",
|
"humanize": "0.0.9",
|
||||||
|
@ -88,7 +89,7 @@
|
||||||
"juice": "^4.1.1",
|
"juice": "^4.1.1",
|
||||||
"libmime": "^3.1.0",
|
"libmime": "^3.1.0",
|
||||||
"mailparser": "^2.0.5",
|
"mailparser": "^2.0.5",
|
||||||
"marked": "^0.3.6",
|
"marked": "^0.7.0",
|
||||||
"memory-cache": "^0.2.0",
|
"memory-cache": "^0.2.0",
|
||||||
"mjml": "4.5.0",
|
"mjml": "4.5.0",
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
|
@ -100,13 +101,14 @@
|
||||||
"node-gettext": "^2.0.0",
|
"node-gettext": "^2.0.0",
|
||||||
"node-mocks-http": "^1.6.5",
|
"node-mocks-http": "^1.6.5",
|
||||||
"nodemailer": "^4.1.1",
|
"nodemailer": "^4.1.1",
|
||||||
"nodemailer-openpgp": "^1.1.0",
|
"nodemailer-openpgp": "^1.2.0",
|
||||||
"npmlog": "^4.1.2",
|
"npmlog": "^4.1.2",
|
||||||
"object-hash": "^1.1.8",
|
"object-hash": "^1.1.8",
|
||||||
"openpgp": "^2.5.11",
|
"openpgp": "^4.6.2",
|
||||||
"passport": "^0.4.0",
|
"passport": "^0.4.0",
|
||||||
|
"passport-ldapauth": "^2.1.3",
|
||||||
|
"passport-ldapjs": "^1.0.3",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"passport-ldapauth": "^2.0.0",
|
|
||||||
"premailer-api": "^1.0.4",
|
"premailer-api": "^1.0.4",
|
||||||
"redfour": "^1.0.2",
|
"redfour": "^1.0.2",
|
||||||
"redis": "^2.8.0",
|
"redis": "^2.8.0",
|
||||||
|
|
118
routes/lists.js
118
routes/lists.js
|
@ -206,57 +206,85 @@ router.post('/ajax/:id', (req, res) => {
|
||||||
|
|
||||||
let statuses = [_('Unknown'), _('Subscribed'), _('Unsubscribed'), _('Bounced'), _('Complained')];
|
let statuses = [_('Unknown'), _('Subscribed'), _('Unsubscribed'), _('Bounced'), _('Complained')];
|
||||||
|
|
||||||
res.json({
|
let dataPromise = Promise.all(data.map((row, i) => Promise.all([
|
||||||
draw: req.body.draw,
|
Promise.resolve([
|
||||||
recordsTotal: total,
|
|
||||||
recordsFiltered: filteredTotal,
|
|
||||||
data: data.map((row, i) => [
|
|
||||||
(Number(req.body.start) || 0) + 1 + i,
|
(Number(req.body.start) || 0) + 1 + i,
|
||||||
htmlescape(row.email || ''),
|
htmlescape(row.email || ''),
|
||||||
htmlescape(row.firstName || ''),
|
htmlescape(row.firstName || ''),
|
||||||
htmlescape(row.lastName || '')
|
htmlescape(row.lastName || ''),
|
||||||
].concat(fields.getRow(fieldList, row).map(cRow => {
|
]),
|
||||||
if (cRow.type === 'number') {
|
new Promise((resolve) => {
|
||||||
return htmlescape(cRow.value && humanize.numberFormat(cRow.value, 0) || '');
|
let fieldsPromise = Promise.all(fields.getRow(fieldList, row).map( async (cRow) => {
|
||||||
} else if (cRow.type === 'longtext') {
|
switch (cRow.type) {
|
||||||
let value = (cRow.value || '');
|
case 'number':
|
||||||
if (value.length > 50) {
|
return Promise.resolve(htmlescape(cRow.value && humanize.numberFormat(cRow.value, 0) || ''));
|
||||||
value = value.substr(0, 47).trim() + '…';
|
case 'longtext':
|
||||||
}
|
let value = (cRow.value || '');
|
||||||
return htmlescape(value);
|
if (value.length > 50) {
|
||||||
} else if (cRow.type === 'gpg') {
|
value = value.substr(0, 47).trim() + '…';
|
||||||
let value = (cRow.value || '').trim();
|
}
|
||||||
try {
|
return Promise.resolve(htmlescape(value));
|
||||||
value = openpgp.key.readArmored(value);
|
case 'gpg':
|
||||||
if (value) {
|
return new Promise((resolve) => {
|
||||||
|
let value = (cRow.value || '').trim();
|
||||||
let keys = value.keys;
|
if (!value.length) {
|
||||||
for (let i = 0; i < keys.length; i++) {
|
resolve(''); // no key
|
||||||
let key = keys[i];
|
|
||||||
switch (key.verifyPrimaryKey()) {
|
|
||||||
case 0:
|
|
||||||
return _('Invalid key');
|
|
||||||
case 1:
|
|
||||||
return _('Expired key');
|
|
||||||
case 2:
|
|
||||||
return _('Revoked 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 (!(typeof value === 'object') || !('keys' in value)) { throw noResultsError }
|
||||||
if (value) {
|
if (value.err && value.err.length) { throw value.err[0] }
|
||||||
value = '0x' + value.substr(-16).toUpperCase();
|
if (!value.keys.length) { throw noResultsError }
|
||||||
}
|
|
||||||
}
|
let keysVerification = Promise.race(value.keys.map((key) => key.verifyPrimaryKey()));
|
||||||
} catch (E) {
|
|
||||||
value = 'parse error';
|
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('<span title="' + message + '" class="subscriber-status-4">' + _('Parse error') + ' <a class="glyphicon glyphicon-info-sign" style="text-decoration:none" title="' + message + '"> </a></span>');
|
||||||
|
});
|
||||||
|
}).catch((error) => log.error('GPG', error));
|
||||||
|
default:
|
||||||
|
return Promise.resolve(htmlescape(cRow.value || ''));
|
||||||
}
|
}
|
||||||
return htmlescape(value || '');
|
}));
|
||||||
} else {
|
|
||||||
return htmlescape(cRow.value || '');
|
fieldsPromise.then(fieldsResults => {
|
||||||
}
|
resolve(fieldsResults);
|
||||||
})).concat(config.views.lists.statuscolored ? '<span class="subscriber-status-' + row.status + '">' + statuses[row.status] + '</span>' : statuses[row.status]).concat(row.created && row.created.toISOString ? '<span class="datestring" data-date="' + row.created.toISOString() + '" title="' + row.created.toISOString() + '">' + row.created.toISOString() + '</span>' : 'N/A').concat('<a href="/lists/subscription/' + list.id + '/edit/' + row.cid + '">' + _('Edit') + '</a>'))
|
}).catch((error) => log.error('Lists', error));
|
||||||
});
|
}),
|
||||||
|
Promise.resolve(config.views.lists.statuscolored ? '<span class="subscriber-status-' + row.status + '">' + statuses[row.status] + '</span>' : statuses[row.status] ),
|
||||||
|
Promise.resolve(row.created && row.created.toISOString ? '<span class="datestring" data-date="' + row.created.toISOString() + '" title="' + row.created.toISOString() + '">' + row.created.toISOString() + '</span>' : 'N/A' ),
|
||||||
|
Promise.resolve('<a href="/lists/subscription/' + list.id + '/edit/' + row.cid + '">' + _('Edit') + '</a>' )
|
||||||
|
])));
|
||||||
|
|
||||||
|
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 }));
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -864,30 +864,43 @@ router.post('/publickey', passport.parseForm, (req, res, next) => {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
let privKey;
|
const sendError = () => {
|
||||||
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) {
|
|
||||||
err = new Error(_('Public key is not set'));
|
err = new Error(_('Public key is not set'));
|
||||||
err.status = 404;
|
err.status = 404;
|
||||||
return next(err);
|
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, {
|
openpgp.key.readArmored(configItems.pgpPrivateKey).
|
||||||
'Content-Type': 'application/octet-stream',
|
then((armored) => {
|
||||||
'Content-Disposition': 'attachment; filename=public.asc'
|
let privKey = armored.keys[0];
|
||||||
});
|
if (configItems.pgpPassphrase) {
|
||||||
|
privKey.decrypt(configItems.pgpPassphrase).
|
||||||
res.end(pubkey);
|
then((success) => {
|
||||||
|
if (success) {
|
||||||
|
sendResult(privKey);
|
||||||
|
}
|
||||||
|
}).
|
||||||
|
catch((error) => {
|
||||||
|
log.error('GPG', error);
|
||||||
|
sendError();
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
sendResult(privKey);
|
||||||
|
}
|
||||||
|
}).
|
||||||
|
catch((error) => {
|
||||||
|
log.error('GPG', error);
|
||||||
|
sendError();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
<button class="btn-download-pubkey" type="submit" form="download-pubkey">{{#translate}}Download signature verification key{{/translate}}</button>
|
<button class="btn-download-pubkey" type="submit" form="download-pubkey">{{#translate}}Download signature verification key{{/translate}}</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<textarea class="form-control gpg-text" rows="4" name="{{column}}" placeholder="{{#translate}}Begins with{{/translate}} '-----BEGIN PGP PUBLIC KEY BLOCK-----'">{{value}}</textarea>
|
<textarea class="form-control gpg-text" rows="4" name="{{column}}" placeholder="{{#translate}}Begins with{{/translate}} '-----BEGIN PGP PUBLIC KEY BLOCK-----'">{{value}}</textarea>
|
||||||
<span class="help-block">
|
<span class="help-block" style="padding:10px 0;">
|
||||||
{{#translate}}Insert your GPG public key here to encrypt messages sent to your address{{/translate}} <em>({{#translate}}optional{{/translate}})</em>
|
{{#translate}}Insert your GPG public key here to encrypt messages sent to your address{{/translate}} <em>({{#translate}}optional{{/translate}})</em>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue