summaryrefslogtreecommitdiffstats
path: root/comm/mail/extensions/openpgp/content/modules/msgRead.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/extensions/openpgp/content/modules/msgRead.jsm')
-rw-r--r--comm/mail/extensions/openpgp/content/modules/msgRead.jsm289
1 files changed, 289 insertions, 0 deletions
diff --git a/comm/mail/extensions/openpgp/content/modules/msgRead.jsm b/comm/mail/extensions/openpgp/content/modules/msgRead.jsm
new file mode 100644
index 0000000000..04f38bf602
--- /dev/null
+++ b/comm/mail/extensions/openpgp/content/modules/msgRead.jsm
@@ -0,0 +1,289 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+"use strict";
+
+var EXPORTED_SYMBOLS = ["EnigmailMsgRead"];
+
+/**
+ * Message-reading related functions
+ */
+
+const { XPCOMUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/XPCOMUtils.sys.mjs"
+);
+
+const lazy = {};
+
+XPCOMUtils.defineLazyModuleGetters(lazy, {
+ EnigmailFuncs: "chrome://openpgp/content/modules/funcs.jsm",
+ EnigmailKeyRing: "chrome://openpgp/content/modules/keyRing.jsm",
+});
+
+var EnigmailMsgRead = {
+ /**
+ * Ensure that Thunderbird prepares certain headers during message reading
+ */
+ ensureExtraAddonHeaders() {
+ let hdr = Services.prefs.getCharPref("mailnews.headers.extraAddonHeaders");
+
+ if (hdr !== "*") {
+ // do nothing if extraAddonHeaders is "*" (all headers)
+ for (let h of ["autocrypt", "openpgp"]) {
+ if (hdr.search(h) < 0) {
+ if (hdr.length > 0) {
+ hdr += " ";
+ }
+ hdr += h;
+ }
+ }
+ Services.prefs.setCharPref("mailnews.headers.extraAddonHeaders", hdr);
+ }
+ },
+
+ /**
+ * Get a mail URL from a uriSpec
+ *
+ * @param uriSpec: String - URI of the desired message
+ *
+ * @returns Object: nsIURL or nsIMsgMailNewsUrl object
+ */
+ getUrlFromUriSpec(uriSpec) {
+ return lazy.EnigmailFuncs.getUrlFromUriSpec(uriSpec);
+ },
+
+ /**
+ * Determine if an attachment is possibly signed
+ */
+ checkSignedAttachment(attachmentObj, index, currentAttachments) {
+ function escapeRegex(string) {
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
+ }
+
+ var attachmentList;
+ if (index !== null) {
+ attachmentList = attachmentObj;
+ } else {
+ attachmentList = currentAttachments;
+ for (let i = 0; i < attachmentList.length; i++) {
+ if (attachmentList[i].url == attachmentObj.url) {
+ index = i;
+ break;
+ }
+ }
+ if (index === null) {
+ return false;
+ }
+ }
+
+ var signed = false;
+ var findFile;
+
+ var attName = this.getAttachmentName(attachmentList[index])
+ .toLowerCase()
+ .replace(/\+/g, "\\+");
+
+ // check if filename is a signature
+ if (
+ this.getAttachmentName(attachmentList[index]).search(/\.(sig|asc)$/i) >
+ 0 ||
+ attachmentList[index].contentType.match(/^application\/pgp-signature/i)
+ ) {
+ findFile = new RegExp(escapeRegex(attName.replace(/\.(sig|asc)$/, "")));
+ } else if (attName.search(/\.pgp$/i) > 0) {
+ findFile = new RegExp(
+ escapeRegex(attName.replace(/\.pgp$/, "")) + "(\\.pgp)?\\.(sig|asc)$"
+ );
+ } else {
+ findFile = new RegExp(escapeRegex(attName) + "\\.(sig|asc)$");
+ }
+
+ for (let i in attachmentList) {
+ if (
+ i != index &&
+ this.getAttachmentName(attachmentList[i])
+ .toLowerCase()
+ .search(findFile) === 0
+ ) {
+ signed = true;
+ }
+ }
+
+ return signed;
+ },
+
+ /**
+ * Get the name of an attachment from the attachment object
+ */
+ getAttachmentName(attachment) {
+ return attachment.name;
+ },
+
+ /**
+ * Escape text such that it can be used as HTML text
+ */
+ escapeTextForHTML(text, hyperlink) {
+ // Escape special characters
+ if (text.indexOf("&") > -1) {
+ text = text.replace(/&/g, "&amp;");
+ }
+
+ if (text.indexOf("<") > -1) {
+ text = text.replace(/</g, "&lt;");
+ }
+
+ if (text.indexOf(">") > -1) {
+ text = text.replace(/>/g, "&gt;");
+ }
+
+ if (text.indexOf('"') > -1) {
+ text = text.replace(/"/g, "&quot;");
+ }
+
+ if (!hyperlink) {
+ return text;
+ }
+
+ // Hyperlink email addresses (we accept at most 1024 characters before and after the @)
+ var addrs = text.match(
+ /\b[A-Za-z0-9_+.-]{1,1024}@[A-Za-z0-9.-]{1,1024}\b/g
+ );
+
+ var newText, offset, loc;
+ if (addrs && addrs.length) {
+ newText = "";
+ offset = 0;
+
+ for (var j = 0; j < addrs.length; j++) {
+ var addr = addrs[j];
+
+ loc = text.indexOf(addr, offset);
+ if (loc < offset) {
+ break;
+ }
+
+ if (loc > offset) {
+ newText += text.substr(offset, loc - offset);
+ }
+
+ // Strip any period off the end of address
+ addr = addr.replace(/[.]$/, "");
+
+ if (!addr.length) {
+ continue;
+ }
+
+ newText += '<a href="mailto:' + addr + '">' + addr + "</a>";
+
+ offset = loc + addr.length;
+ }
+
+ newText += text.substr(offset, text.length - offset);
+
+ text = newText;
+ }
+
+ // Hyperlink URLs (we don't accept URLS or more than 1024 characters length)
+ var urls = text.match(/\b(http|https|ftp):\S{1,1024}\s/g);
+
+ if (urls && urls.length) {
+ newText = "";
+ offset = 0;
+
+ for (var k = 0; k < urls.length; k++) {
+ var url = urls[k];
+
+ loc = text.indexOf(url, offset);
+ if (loc < offset) {
+ break;
+ }
+
+ if (loc > offset) {
+ newText += text.substr(offset, loc - offset);
+ }
+
+ // Strip delimiters off the end of URL
+ url = url.replace(/\s$/, "");
+ url = url.replace(/([),.']|&gt;|&quot;)$/, "");
+
+ if (!url.length) {
+ continue;
+ }
+
+ newText += '<a href="' + url + '">' + url + "</a>";
+
+ offset = loc + url.length;
+ }
+
+ newText += text.substr(offset, text.length - offset);
+
+ text = newText;
+ }
+
+ return text;
+ },
+
+ /**
+ * Match the key to the sender's from address
+ *
+ * @param {string} keyId: signing key ID
+ * @param {string} fromAddr: sender's email address
+ *
+ * @returns Promise<String>: matching email address
+ */
+ matchUidToSender(keyId, fromAddr) {
+ if (!fromAddr || !keyId) {
+ return null;
+ }
+
+ try {
+ fromAddr = lazy.EnigmailFuncs.stripEmail(fromAddr).toLowerCase();
+ } catch (ex) {
+ console.debug(ex);
+ }
+
+ let keyObj = lazy.EnigmailKeyRing.getKeyById(keyId);
+ if (!keyObj) {
+ return null;
+ }
+
+ let userIdList = keyObj.userIds;
+
+ try {
+ for (let i = 0; i < userIdList.length; i++) {
+ if (
+ fromAddr ==
+ lazy.EnigmailFuncs.stripEmail(userIdList[i].userId).toLowerCase()
+ ) {
+ let result = lazy.EnigmailFuncs.stripEmail(userIdList[i].userId);
+ return result;
+ }
+ }
+ } catch (ex) {
+ console.debug(ex);
+ }
+ return null;
+ },
+
+ searchQuotedPgp(node) {
+ if (
+ node.nodeName.toLowerCase() === "blockquote" &&
+ node.textContent.includes("-----BEGIN PGP ")
+ ) {
+ return true;
+ }
+
+ if (node.firstChild && this.searchQuotedPgp(node.firstChild)) {
+ return true;
+ }
+
+ if (node.nextSibling && this.searchQuotedPgp(node.nextSibling)) {
+ return true;
+ }
+
+ return false;
+ },
+};