feat(encodeEmail): add option to enable/disable mail obfuscation

Prior to version 1.6.1, emails would always be obfuscated through dec and hex encoding.
This option makes it possible to disable this.
This commit is contained in:
Estevao Soares dos Santos 2017-01-27 19:03:37 +00:00
parent e3ea1450cc
commit 90c52b83e7
13 changed files with 91 additions and 54 deletions

View File

@ -294,6 +294,9 @@ var defaultOptions = showdown.getDefaultOptions();
* **ghMentions**: (boolean) [default false] Enables github @mentions, which link to the username mentioned (since v1.6.0)
* **encodeEmails**: (boolean) [default true] Enables e-mail addresses encoding through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities. (since v1.6.1)
NOTE: Prior to version 1.6.1, emails would always be obfuscated through dec and hex encoding.
**NOTE**: Please note that until version 1.6.0, all of these options are ***DISABLED*** by default in the cli tool.

BIN
dist/showdown.js vendored

Binary file not shown.

BIN
dist/showdown.js.map vendored

Binary file not shown.

BIN
dist/showdown.min.js vendored

Binary file not shown.

Binary file not shown.

View File

@ -251,6 +251,46 @@ showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right
return finalStr;
};
/**
* Obfuscate an e-mail address through the use of Character Entities,
* transforming ASCII characters into their equivalent decimal or hex entities.
*
* Since it has a random component, subsequent calls to this function produce different results
*
* @param {string} mail
* @returns {string}
*/
showdown.helper.encodeEmailAddress = function (mail) {
'use strict';
var encode = [
function (ch) {
return '&#' + ch.charCodeAt(0) + ';';
},
function (ch) {
return '&#x' + ch.charCodeAt(0).toString(16) + ';';
},
function (ch) {
return ch;
}
];
mail = mail.replace(/./g, function (ch) {
if (ch === '@') {
// this *must* be encoded. I insist.
ch = encode[Math.floor(Math.random() * 2)](ch);
} else {
var r = Math.random();
// roughly 10% raw, 45% hex, 45% dec
ch = (
r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
);
}
return ch;
});
return mail;
};
/**
* POLYFILLS
*/

View File

@ -105,6 +105,11 @@ function getDefaultOpts(simple) {
defaultValue: false,
description: 'Enables github @mentions',
type: 'boolean'
},
encodeEmails: {
defaultValue: true,
description: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities',
type: 'boolean'
}
};
if (simple === false) {

View File

@ -36,8 +36,15 @@ showdown.subParser('autoLinks', function (text, options, globals) {
}
function replaceMail(wholeMatch, mail) {
var unescapedStr = showdown.subParser('unescapeSpecialChars')(mail);
return showdown.subParser('encodeEmailAddress')(unescapedStr);
var href = 'mailto:';
mail = showdown.subParser('unescapeSpecialChars')(mail);
if (options.encodeEmails) {
mail = showdown.helper.encodeEmailAddress(mail);
href = showdown.helper.encodeEmailAddress(href + mail);
} else {
href = href + mail;
}
return '<a href="' + href + '">' + mail + '</a>';
}
text = globals.converter._dispatch('autoLinks.after', text, options, globals);

View File

@ -1,52 +0,0 @@
/**
* Input: an email address, e.g. "foo@example.com"
*
* Output: the email address as a mailto link, with each character
* of the address encoded as either a decimal or hex entity, in
* the hopes of foiling most address harvesting spam bots. E.g.:
*
* <a href="&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;
* x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;">&#102;&#111;&#111;
* &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>
*
* Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
* mailing list: <http://tinyurl.com/yu7ue>
*
*/
showdown.subParser('encodeEmailAddress', function (addr) {
'use strict';
var encode = [
function (ch) {
return '&#' + ch.charCodeAt(0) + ';';
},
function (ch) {
return '&#x' + ch.charCodeAt(0).toString(16) + ';';
},
function (ch) {
return ch;
}
];
addr = 'mailto:' + addr;
addr = addr.replace(/./g, function (ch) {
if (ch === '@') {
// this *must* be encoded. I insist.
ch = encode[Math.floor(Math.random() * 2)](ch);
} else if (ch !== ':') {
// leave ':' alone (to spot mailto: later)
var r = Math.random();
// roughly 10% raw, 45% hex, 45% dec
ch = (
r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
);
}
return ch;
});
addr = '<a href="' + addr + '">' + addr + '</a>';
addr = addr.replace(/">.+:/g, '">'); // strip the mailto: from the visible part
return addr;
});

View File

@ -0,0 +1 @@
<p>this email <a href="mailto:foobar@example.com">foobar@example.com</a> should not be encoded</p>

View File

@ -0,0 +1 @@
this email <foobar@example.com> should not be encoded

View File

@ -0,0 +1,30 @@
/**
* Created by Estevao on 27/01/2017.
*/
var bootstrap = require('../bootstrap.js'),
showdown = bootstrap.showdown,
encoder = showdown.helper.encodeEmailAddress;
describe('encodeEmailAddress', function () {
'use strict';
var email = 'foobar@example.com',
encodedEmail = encoder(email);
it('should encode email', function () {
encodedEmail.should.not.equal(email);
});
it('should decode to original email', function () {
var decodedEmail = encodedEmail.replace(/&#(.+?);/g, function (wm, cc) {
if (cc.charAt(0) === 'x') {
//hex
return String.fromCharCode('0' + cc);
} else {
//dec
return String.fromCharCode(cc);
}
});
decodedEmail.should.equal(email);
});
});

View File

@ -53,6 +53,8 @@ describe('makeHtml() features testsuite', function () {
converter = new showdown.Converter({ghCompatibleHeaderId: true});
} else if (testsuite[i].name === 'ghMentions') {
converter = new showdown.Converter({ghMentions: true});
} else if (testsuite[i].name === 'disable-email-encoding') {
converter = new showdown.Converter({encodeEmails: false});
} else {
converter = new showdown.Converter();
}