'; } preface += '"; } preface += '\n'; } else if (citeLevel < oldCiteLevel) { preface = ""; for (let j = 0; j < oldCiteLevel - citeLevel; j++) { preface += "
\n'; } if (logLineStart.value > 0) { preface += '"; //EnigmailLog.DEBUG("funcs.jsm: r='"+r+"'\n"); return r; }, /** * extract the data fields following a header. * e.g. ContentType: xyz; Aa=b; cc=d * * @data: |string| containing a single header * * @returns |array| of |arrays| containing pairs of aa/b and cc/d */ getHeaderData(data) { lazy.EnigmailLog.DEBUG( "funcs.jsm: getHeaderData: " + data.substr(0, 100) + "\n" ); var a = data.split(/\n/); var res = []; for (let i = 0; i < a.length; i++) { if (a[i].length === 0) { break; } let b = a[i].split(/;/); // extract "abc = xyz" tuples for (let j = 0; j < b.length; j++) { let m = b[j].match(/^(\s*)([^=\s;]+)(\s*)(=)(\s*)(.*)(\s*)$/); if (m) { // m[2]: identifier / m[6]: data res[m[2].toLowerCase()] = m[6].replace(/\s*$/, ""); lazy.EnigmailLog.DEBUG( "funcs.jsm: getHeaderData: " + m[2].toLowerCase() + " = " + res[m[2].toLowerCase()] + "\n" ); } } if (i === 0 && !a[i].includes(";")) { break; } if (i > 0 && a[i].search(/^\s/) < 0) { break; } } return res; }, /*** * Get the text for the encrypted subject (either configured by user or default) */ getProtectedSubjectText() { return "..."; }, cloneObj(orig) { let newObj; if (typeof orig !== "object" || orig === null || orig === undefined) { return orig; } if ("clone" in orig && typeof orig.clone === "function") { return orig.clone(); } if (Array.isArray(orig) && orig.length > 0) { newObj = []; for (let i in orig) { if (typeof orig[i] === "object") { newObj.push(this.cloneObj(orig[i])); } else { newObj.push(orig[i]); } } } else { newObj = {}; for (let i in orig) { if (typeof orig[i] === "object") { newObj[i] = this.cloneObj(orig[i]); } else { newObj[i] = orig[i]; } } } return newObj; }, /** * Compare two MIME part numbers to determine which of the two is earlier in the tree * MIME part numbers have the structure "x.y.z...", e.g 1, 1.2, 2.3.1.4.5.1.2 * * @param mime1, mime2 - String the two mime part numbers to compare. * * @returns Number (one of -2, -1, 0, 1 , 2) * - Negative number if mime1 is before mime2 * - Positive number if mime1 is after mime2 * - 0 if mime1 and mime2 are equal * - if mime1 is a parent of mime2 the return value is -2 * - if mime2 is a parent of mime1 the return value is 2 * * Throws an error if mime1 or mime2 do not comply to the required format */ compareMimePartLevel(mime1, mime2) { let s = new RegExp("^[0-9]+(\\.[0-9]+)*$"); if (mime1.search(s) < 0) { throw new Error("Invalid mime1"); } if (mime2.search(s) < 0) { throw new Error("Invalid mime2"); } let a1 = mime1.split(/\./); let a2 = mime2.split(/\./); for (let i = 0; i < Math.min(a1.length, a2.length); i++) { if (Number(a1[i]) < Number(a2[i])) { return -1; } if (Number(a1[i]) > Number(a2[i])) { return 1; } } if (a2.length > a1.length) { return -2; } if (a2.length < a1.length) { return 2; } return 0; }, /** * Get the nsIMsgAccount associated with a given nsIMsgIdentity */ getAccountForIdentity(identity) { for (let ac of MailServices.accounts.accounts) { for (let id of ac.identities) { if (id.key === identity.key) { return ac; } } } return null; }, /** * Get the default identity of the default account */ getDefaultIdentity() { try { let ac; if (MailServices.accounts.defaultAccount) { ac = MailServices.accounts.defaultAccount; } else { for (ac of MailServices.accounts.accounts) { if ( ac.incomingServer.type === "imap" || ac.incomingServer.type === "pop3" ) { break; } } } if (ac.defaultIdentity) { return ac.defaultIdentity; } return ac.identities[0]; } catch (x) { return null; } }, /** * Get a list of all own email addresses, taken from all identities * and all reply-to addresses */ getOwnEmailAddresses() { let ownEmails = {}; // Determine all sorts of own email addresses for (let id of MailServices.accounts.allIdentities) { if (id.email && id.email.length > 0) { ownEmails[id.email.toLowerCase()] = 1; } if (id.replyTo && id.replyTo.length > 0) { try { let replyEmails = this.stripEmail(id.replyTo) .toLowerCase() .split(/,/); for (let j in replyEmails) { ownEmails[replyEmails[j]] = 1; } } catch (ex) {} } } return ownEmails; }, /** * Determine the distinct number of non-self recipients of a message. * Only To: and Cc: fields are considered. */ getNumberOfRecipients(msgCompField) { let recipients = {}, ownEmails = this.getOwnEmailAddresses(); let allAddr = ( this.stripEmail(msgCompField.to) + "," + this.stripEmail(msgCompField.cc) ).toLowerCase(); let emails = allAddr.split(/,+/); for (let i = 0; i < emails.length; i++) { let r = emails[i]; if (r && !(r in ownEmails)) { recipients[r] = 1; } } return recipients.length; }, /** * Get a mail URL from a uriSpec. * * @param {string} uriSpec - URL spec of the desired message. * * @returns {nsIURL|nsIMsgMailNewsUrl|null} The necko url. */ getUrlFromUriSpec(uriSpec) { try { if (!uriSpec) { return null; } let msgService = MailServices.messageServiceFromURI(uriSpec); let url = msgService.getUrlForUri(uriSpec); if (url.scheme == "file") { return url; } return url.QueryInterface(Ci.nsIMsgMailNewsUrl); } catch (ex) { return null; } }, /** * Test if the given string looks roughly like an email address, * returns true or false. */ stringLooksLikeEmailAddress(str) { return /^[^ @]+@[^ @]+$/.test(str); }, /** * Extract an email address from the given string, using MailServices. * However, be more strict, and avoid strings that appear to be * invalid addresses. * * If more than one email address is found, only return the first. * * If we fail to extract an email address from the given string, * because the given string doesn't conform to expectations, * an empty string is returned. */ getEmailFromUserID(uid) { let addresses = MailServices.headerParser.makeFromDisplayAddress(uid); if ( !addresses[0] || !EnigmailFuncs.stringLooksLikeEmailAddress(addresses[0].email) ) { console.debug("failed to extract email address from: " + uid); return ""; } return addresses[0].email.trim(); }, }; "; } else if (lines[i] == "-- ") { preface += ''; isSignature = true; } lines[i] = preface + gTxtConverter.scanTXT(lines[i].substr(logLineStart.value), convFlags); } var r = '" : "") + "' + lines.join("\n") + (isSignature ? "