Page MenuHome GnuPG

No OneTemporary

diff --git a/package/fixExchangeMsg.jsm b/package/fixExchangeMsg.jsm
index 7d49380f..73433e85 100644
--- a/package/fixExchangeMsg.jsm
+++ b/package/fixExchangeMsg.jsm
@@ -1,378 +1,378 @@
/*global Components: false */
/*jshint -W097 */
/*
* 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 http://mozilla.org/MPL/2.0/.
*/
"use strict";
var EXPORTED_SYMBOLS = ["EnigmailFixExchangeMsg"];
const Cu = Components.utils;
Cu.import("resource:///modules/MailUtils.js"); /*global MailUtils: false */
Cu.import("resource://enigmail/core.jsm"); /*global EnigmailCore: false */
Cu.import("resource://enigmail/funcs.jsm"); /*global EnigmailFuncs: false */
Cu.import("resource://enigmail/log.jsm"); /*global EnigmailLog: false */
Cu.import("resource://enigmail/streams.jsm"); /*global EnigmailStreams: false */
const EC = EnigmailCore;
const Cc = Components.classes;
const Ci = Components.interfaces;
const nsIEnigmail = Components.interfaces.nsIEnigmail;
const IOSERVICE_CONTRACTID = "@mozilla.org/network/io-service;1";
/*
* Fix a broken message from MS-Exchange and replace it with the original message
*
* @param nsIMsgDBHdr hdr Header of the message to fix (= pointer to message)
* @param String brokenByApp Type of app that created the message. Currently one of
* exchange, iPGMail
* @param String destFolderUri optional destination Folder URI
*
* @return Promise; upon success, the promise returns the messageKey
*/
const EnigmailFixExchangeMsg = {
fixExchangeMessage: function(hdr, brokenByApp, destFolderUri) {
var self = this;
return new Promise(
function fixExchangeMessage_p(resolve, reject) {
let msgUriSpec = hdr.folder.getUriForMsg(hdr);
EnigmailLog.DEBUG("fixExchangeMsg.jsm: fixExchangeMessage: msgUriSpec: " + msgUriSpec + "\n");
self.hdr = hdr;
self.destFolder = hdr.folder;
self.resolve = resolve;
self.reject = reject;
self.brokenByApp = brokenByApp;
if (destFolderUri) {
self.destFolder = MailUtils.getFolderForURI(destFolderUri, false);
}
let messenger = Cc["@mozilla.org/messenger;1"].createInstance(Ci.nsIMessenger);
self.msgSvc = messenger.messageServiceFromURI(msgUriSpec);
let p = self.getMessageBody();
p.then(
function resolved(fixedMsgData) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: fixExchangeMessage: got fixedMsgData\n");
self.copyToTargetFolder(fixedMsgData);
});
p.catch(
function rejected(reason) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: fixExchangeMessage: caught rejection: " + reason + "\n");
reject();
return;
});
}
);
},
getMessageBody: function() {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getMessageBody:\n");
var self = this;
return new Promise(
function(resolve, reject) {
let u = {};
self.msgSvc.GetUrlForUri(self.hdr.folder.getUriForMsg(self.hdr), u, null);
let op = (u.value.spec.indexOf("?") > 0 ? "&" : "?");
let url = u.value.spec; // + op + 'part=' + part+"&header=enigmailConvert";
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getting data from URL " + url + "\n");
let s = EnigmailStreams.newStringStreamListener(
function analyzeData(data) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: analyzeDecryptedData: got " + data.length + " bytes\n");
if (EnigmailLog.getLogLevel() > 5) {
EnigmailLog.DEBUG("*** start data ***\n'" + data + "'\n***end data***\n");
}
let hdrEnd = data.search(/\r?\n\r?\n/);
if (hdrEnd <= 0) {
// cannot find end of header data
reject(0);
return;
}
let hdrLines = data.substr(0, hdrEnd).split(/\r?\n/);
let hdrObj = self.getFixedHeaderData(hdrLines);
if (hdrObj.headers.length === 0 || hdrObj.boundary.length === 0) {
reject(1);
return;
}
let boundary = hdrObj.boundary;
let body;
switch (self.brokenByApp) {
case "exchange":
body = self.getCorrectedExchangeBodyData(data.substr(hdrEnd + 2), boundary);
break;
case "iPGMail":
body = self.getCorrectediPGMailBodyData(data.substr(hdrEnd + 2), boundary);
break;
default:
EnigmailLog.ERROR("fixExchangeMsg.jsm: getMessageBody: unknown appType " + self.brokenByApp + "\n");
reject(99);
return;
}
if (body) {
resolve(hdrObj.headers + "\r\n" + body);
return;
}
else {
reject(2);
return;
}
}
);
var ioServ = Components.classes[IOSERVICE_CONTRACTID].getService(Components.interfaces.nsIIOService);
try {
let channel = EnigmailStreams.createChannel(url);
channel.asyncOpen(s, null);
}
catch (e) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getMessageBody: exception " + e + "\n");
}
}
);
},
/**
* repair header data, such that they are working for PGP/MIME
*
* @return: object: {
* headers: String - all headers ready for appending to message
* boundary: String - MIME part boundary (incl. surrounding "" or '')
* }
*/
getFixedHeaderData: function(hdrLines) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getFixedHeaderData: hdrLines[]:'" + hdrLines.length + "'\n");
let r = {
headers: "",
boundary: ""
};
for (let i = 0; i < hdrLines.length; i++) {
if (hdrLines[i].search(/^content-type:/i) >= 0) {
// Join the rest of the content type lines together.
// See RFC 2425, section 5.8.1
let contentTypeLine = hdrLines[i];
i++;
while (i < hdrLines.length) {
// Does the line start with a space or a tab, followed by something else?
if (hdrLines[i].search(/^[ \t]+?/) === 0) {
contentTypeLine += hdrLines[i];
i++;
}
else {
// we got the complete content-type header
contentTypeLine = contentTypeLine.replace(/[\r\n]/g, "");
let h = EnigmailFuncs.getHeaderData(contentTypeLine);
r.boundary = h.boundary || "";
break;
}
}
}
else {
r.headers += hdrLines[i] + "\r\n";
}
}
r.boundary = r.boundary.replace(/^(['"])(.*)(['"])/, "$2");
r.headers += 'Content-Type: multipart/encrypted;\r\n' +
' protocol="application/pgp-encrypted";\r\n' +
' boundary="' + r.boundary + '"\r\n' +
'X-Enigmail-Info: Fixed broken PGP/MIME message\r\n';
return r;
},
/**
* Get corrected body for MS-Exchange messages
*/
getCorrectedExchangeBodyData: function(bodyData, boundary) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: boundary='" + boundary + "'\n");
let boundRx = new RegExp("^--" + boundary, "gm");
let match = boundRx.exec(bodyData);
if (match.index < 0) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: did not find index of mime type to skip\n");
return null;
}
let skipStart = match.index;
// found first instance -- that's the message part to ignore
match = boundRx.exec(bodyData);
if (match.index <= 0) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: did not find boundary of PGP/MIME version identification\n");
return null;
}
let versionIdent = match.index;
- if (bodyData.substring(skipStart, versionIdent).search(/^content-type:[ \t]*text\/plain/mi) < 0) {
- EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: first MIME part is not content-type text/plain\n");
+ if (bodyData.substring(skipStart, versionIdent).search(/^content-type:[ \t]*text\/(plain|html)/mi) < 0) {
+ EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: first MIME part is not content-type text/plain or text/html\n");
return null;
}
match = boundRx.exec(bodyData);
if (match.index < 0) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: did not find boundary of PGP/MIME encrypted data\n");
return null;
}
let encData = match.index;
let mimeHdr = Cc["@mozilla.org/messenger/mimeheaders;1"].createInstance(Ci.nsIMimeHeaders);
mimeHdr.initialize(bodyData.substring(versionIdent, encData));
let ct = mimeHdr.extractHeader("content-type", false);
if (!ct || ct.search(/application\/pgp-encrypted/i) < 0) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: wrong content-type of version-identification\n");
EnigmailLog.DEBUG(" ct = '" + ct + "'\n");
return null;
}
mimeHdr.initialize(bodyData.substr(encData, 5000));
ct = mimeHdr.extractHeader("content-type", false);
if (!ct || ct.search(/application\/octet-stream/i) < 0) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: wrong content-type of PGP/MIME data\n");
EnigmailLog.DEBUG(" ct = '" + ct + "'\n");
return null;
}
return bodyData.substr(versionIdent);
},
/**
* Get corrected body for iPGMail messages
*/
getCorrectediPGMailBodyData: function(bodyData, boundary) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectediPGMailBodyData: boundary='" + boundary + "'\n");
let boundRx = new RegExp("^--" + boundary, "gm");
let match = boundRx.exec(bodyData);
if (match.index < 0) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectediPGMailBodyData: did not find index of mime type to skip\n");
return null;
}
let skipStart = match.index;
// found first instance -- that's the message part to ignore
match = boundRx.exec(bodyData);
if (match.index <= 0) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectediPGMailBodyData: did not find boundary of text/plain msg part\n");
return null;
}
let encData = match.index;
match = boundRx.exec(bodyData);
if (match.index < 0) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectediPGMailBodyData: did not find end boundary of PGP/MIME encrypted data\n");
return null;
}
let mimeHdr = Cc["@mozilla.org/messenger/mimeheaders;1"].createInstance(Ci.nsIMimeHeaders);
mimeHdr.initialize(bodyData.substr(encData, 5000));
let ct = mimeHdr.extractHeader("content-type", false);
if (!ct || ct.search(/application\/pgp-encrypted/i) < 0) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: getCorrectediPGMailBodyData: wrong content-type of PGP/MIME data\n");
EnigmailLog.DEBUG(" ct = '" + ct + "'\n");
return null;
}
return "--" + boundary + "\r\n" +
"Content-Type: application/pgp-encrypted\r\n" +
"Content-Description: PGP/MIME version identification\r\n\r\n" +
"Version: 1\r\n\r\n" +
bodyData.substring(encData, match.index).
replace(/^Content-Type: +application\/pgp-encrypted/im,
"Content-Type: application/octet-stream") +
"--" + boundary + "--\r\n";
},
copyToTargetFolder: function(msgData) {
var self = this;
var tempFile = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
tempFile.append("message.eml");
tempFile.createUnique(0, 384); // octal 0600 - since octal is deprected in JS
// ensure that file gets deleted on exit, if something goes wrong ...
var extAppLauncher = Cc["@mozilla.org/mime;1"].getService(Ci.nsPIExternalAppLauncher);
var foStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
foStream.init(tempFile, 2, 0x200, false); // open as "write only"
foStream.write(msgData, msgData.length);
foStream.close();
extAppLauncher.deleteTemporaryFileOnExit(tempFile);
// note: nsIMsgFolder.copyFileMessage seems to have a bug on Windows, when
// the nsIFile has been already used by foStream (because of Windows lock system?), so we
// must initialize another nsIFile object, pointing to the temporary file
var fileSpec = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
fileSpec.initWithPath(tempFile.path);
var copyListener = {
QueryInterface: function(iid) {
if (iid.equals(Ci.nsIMsgCopyServiceListener) || iid.equals(Ci.nsISupports)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
msgKey: null,
GetMessageId: function(messageId) {},
OnProgress: function(progress, progressMax) {},
OnStartCopy: function() {},
SetMessageKey: function(key) {
this.msgKey = key;
},
OnStopCopy: function(statusCode) {
if (statusCode !== 0) {
EnigmailLog.DEBUG("fixExchangeMsg.jsm: error copying message: " + statusCode + "\n");
tempFile.remove(false);
self.reject(3);
return;
}
EnigmailLog.DEBUG("fixExchangeMsg.jsm: copy complete\n");
EnigmailLog.DEBUG("fixExchangeMsg.jsm: deleting message key=" + self.hdr.messageKey + "\n");
let msgArray = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
msgArray.appendElement(self.hdr, false);
self.hdr.folder.deleteMessages(msgArray, null, true, false, null, false);
EnigmailLog.DEBUG("fixExchangeMsg.jsm: deleted original message\n");
tempFile.remove(false);
self.resolve(this.msgKey);
return;
}
};
let copySvc = Cc["@mozilla.org/messenger/messagecopyservice;1"].getService(Ci.nsIMsgCopyService);
copySvc.CopyFileMessage(fileSpec, this.destFolder, null, false, this.hdr.flags, null, copyListener, null);
}
};
diff --git a/ui/content/enigmailMessengerOverlay.js b/ui/content/enigmailMessengerOverlay.js
index 121762b2..72c9e24f 100644
--- a/ui/content/enigmailMessengerOverlay.js
+++ b/ui/content/enigmailMessengerOverlay.js
@@ -1,2694 +1,2694 @@
/*global Components: false */
/*
* 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 http://mozilla.org/MPL/2.0/.
*/
"use strict";
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
try {
// TB with omnijar
Components.utils.import("resource:///modules/gloda/mimemsg.js"); /* global MsgHdrToMimeMessage: false */
}
catch (ex) {
// "old style" TB
Components.utils.import("resource://app/modules/gloda/mimemsg.js");
}
/* global EnigmailData: false, EnigmailApp: false, EnigmailDialog: false, EnigmailTimer: false, EnigmailWindows: false, EnigmailTime: false */
/* global EnigmailLocale: false, EnigmailLog: false, XPCOMUtils: false, EnigmailPrefs: false */
/* globals from Thunderbird: */
/* global ReloadMessage: false, gDBView: false, gSignatureStatus: false, gEncryptionStatus: false, showMessageReadSecurityInfo: false */
/* global gFolderDisplay: false, messenger: false, currentAttachments: false, msgWindow: false, ChangeMailLayout: false, MsgToggleMessagePane: false */
/* global currentHeaderData: false, gViewAllHeaders: false, gExpandedHeaderList: false, goDoCommand: false, HandleSelectedAttachments: false */
/* global statusFeedback: false, global displayAttachmentsForExpandedView: false */
Components.utils.import("resource://enigmail/core.jsm"); /*global EnigmailCore: false */
Components.utils.import("resource://enigmail/funcs.jsm"); /* global EnigmailFuncs: false */
Components.utils.import("resource://enigmail/mimeVerify.jsm"); /* global EnigmailVerify: false */
Components.utils.import("resource://enigmail/fixExchangeMsg.jsm"); /* global EnigmailFixExchangeMsg: false */
Components.utils.import("resource://enigmail/log.jsm");
Components.utils.import("resource://enigmail/prefs.jsm");
Components.utils.import("resource://enigmail/os.jsm"); /* global EnigmailOS: false */
Components.utils.import("resource://enigmail/locale.jsm");
Components.utils.import("resource://enigmail/files.jsm"); /* global EnigmailFiles: false */
Components.utils.import("resource://enigmail/key.jsm"); /* global EnigmailKey: false */
Components.utils.import("resource://enigmail/data.jsm");
Components.utils.import("resource://enigmail/app.jsm");
Components.utils.import("resource://enigmail/dialog.jsm");
Components.utils.import("resource://enigmail/timer.jsm");
Components.utils.import("resource://enigmail/windows.jsm");
Components.utils.import("resource://enigmail/time.jsm");
Components.utils.import("resource://enigmail/decryptPermanently.jsm"); /* global EnigmailDecryptPermanently: false */
Components.utils.import("resource://enigmail/streams.jsm"); /*global EnigmailStreams: false */
Components.utils.import("resource://enigmail/events.jsm"); /*global EnigmailEvents: false */
Components.utils.import("resource://enigmail/keyRing.jsm"); /*global EnigmailKeyRing: false */
Components.utils.import("resource://enigmail/attachment.jsm"); /*global EnigmailAttachment: false */
Components.utils.import("resource://enigmail/constants.jsm"); /*global EnigmailConstants: false */
Components.utils.import("resource://enigmail/passwords.jsm"); /*global EnigmailPassword: false */
Components.utils.import("resource://enigmail/keyUsability.jsm"); /*global EnigmailKeyUsability: false */
Components.utils.import("resource://enigmail/uris.jsm"); /*global EnigmailURIs: false */
Components.utils.import("resource://enigmail/protocolHandler.jsm"); /*global EnigmailProtocolHandler: false */
Components.utils.import("resource://enigmail/pEpAdapter.jsm"); /*global EnigmailPEPAdapter: false */
Components.utils.import("resource://enigmail/pEpDecrypt.jsm"); /*global EnigmailPEPDecrypt: false */
Components.utils.import("resource://enigmail/autocrypt.jsm"); /*global EnigmailAutocrypt: false */
Components.utils.import("resource://enigmail/mime.jsm"); /*global EnigmailMime: false */
Components.utils.import("resource://enigmail/webKey.jsm"); /*global EnigmailWks: false */
Components.utils.import("resource://enigmail/stdlib.jsm"); /*global EnigmailStdlib: false */
Components.utils.import("resource://enigmail/configure.jsm"); /*global EnigmailConfigure: false */
if (!Enigmail) var Enigmail = {};
Enigmail.getEnigmailSvc = function() {
return EnigmailCore.getService(window);
};
const IOSERVICE_CONTRACTID = "@mozilla.org/network/io-service;1";
const LOCAL_FILE_CONTRACTID = "@mozilla.org/file/local;1";
Enigmail.msg = {
createdURIs: [],
decryptedMessage: null,
securityInfo: null,
lastSaveDir: "",
messagePane: null,
noShowReload: false,
decryptButton: null,
savedHeaders: null,
removeListener: false,
enableExperiments: false,
headersList: ["content-type", "content-transfer-encoding",
"x-enigmail-version", "x-pgp-encoding-format",
"autocrypt"
],
buggyExchangeEmailContent: null, // for HACK for MS-EXCHANGE-Server Problem
buggyMailType: null,
lastSMimeReloadURI: "",
messengerStartup: function() {
// private function to overwrite attributes
function overrideAttribute(elementIdList, attrName, prefix, suffix) {
for (var index = 0; index < elementIdList.length; index++) {
var elementId = elementIdList[index];
var element = document.getElementById(elementId);
if (element) {
try {
var oldValue = element.getAttribute(attrName);
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: overrideAttribute " + attrName + ": oldValue=" + oldValue + "\n");
var newValue = prefix + elementId + suffix;
element.setAttribute(attrName, newValue);
}
catch (ex) {}
}
else {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: *** UNABLE to override id=" + elementId + "\n");
}
}
}
Enigmail.msg.messagePane = document.getElementById("messagepane");
if (!Enigmail.msg.messagePane) return; // TB on Mac OS X calls this twice -- once far too early
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: Startup\n");
// Override SMIME ui
var viewSecurityCmd = document.getElementById("cmd_viewSecurityStatus");
if (viewSecurityCmd) {
viewSecurityCmd.setAttribute("oncommand", "Enigmail.msg.viewSecurityInfo(null, true);");
}
// Override print command
var printElementIds = ["cmd_print", "cmd_printpreview", "key_print", "button-print",
"mailContext-print", "mailContext-printpreview"
];
overrideAttribute(printElementIds, "oncommand",
"Enigmail.msg.msgPrint('", "');");
Enigmail.msg.overrideLayoutChange();
Enigmail.msg.setMainMenuLabel();
Enigmail.msg.juniorModeObserver = EnigmailPEPAdapter.registerJuniorModeObserver(Enigmail.msg.setMainMenuLabel);
if (EnigmailPEPAdapter.usingPep()) {
document.getElementById("enigmailStatusCol").setAttribute("label", EnigmailLocale.getString("enigmailPep.msgViewColumn.label"));
}
else {
document.getElementById("enigmailStatusCol").setAttribute("label", EnigmailLocale.getString("enigmail.msgViewColumn.label"));
}
Enigmail.msg.savedHeaders = null;
Enigmail.msg.decryptButton = document.getElementById("button-enigmail-decrypt");
EnigmailTimer.setTimeout(function _f() {
// if nothing happened, then load all keys after 1 hour
// to trigger the key check
EnigmailKeyRing.getAllKeys();
}, 3600 * 1000); // 1 hour
// Need to add event listener to Enigmail.msg.messagePane to make it work
// Adding to msgFrame doesn't seem to work
Enigmail.msg.messagePane.addEventListener("unload", Enigmail.msg.messageFrameUnload.bind(Enigmail.msg), true);
var treeController = {
supportsCommand: function(command) {
// EnigmailLog.DEBUG("enigmailMessengerOverlay.js: treeCtrl: supportsCommand: "+command+"\n");
switch (command) {
case "button_enigmail_decrypt":
return true;
}
return false;
},
isCommandEnabled: function(command) {
// EnigmailLog.DEBUG("enigmailMessengerOverlay.js: treeCtrl: isCommandEnabled: "+command+"\n");
try {
if (gFolderDisplay.messageDisplay.visible) {
if (gFolderDisplay.selectedCount != 1) Enigmail.hdrView.statusBarHide();
return (gFolderDisplay.selectedCount == 1);
}
Enigmail.hdrView.statusBarHide();
}
catch (ex) {}
return false;
},
doCommand: function(command) {
//EnigmailLog.DEBUG("enigmailMessengerOverlay.js: treeCtrl: doCommand: "+command+"\n");
// nothing
},
onEvent: function(event) {
// EnigmailLog.DEBUG("enigmailMessengerOverlay.js: treeCtrl: onEvent: "+command+"\n");
// nothing
}
};
top.controllers.appendController(treeController);
if (EnigmailPrefs.getPref("configuredVersion") === "") {
EnigmailConfigure.configureEnigmail(window, false);
}
},
viewSecurityInfo: function(event, displaySmimeMsg) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: viewSecurityInfo\n");
if (event && event.button !== 0)
return;
if (gSignatureStatus >= 0 || gEncryptionStatus >= 0) {
showMessageReadSecurityInfo();
}
else {
if (Enigmail.msg.securityInfo)
this.viewOpenpgpInfo();
else
showMessageReadSecurityInfo();
}
},
viewOpenpgpInfo: function() {
if (Enigmail.msg.securityInfo) {
EnigmailDialog.info(window, EnigmailLocale.getString("securityInfo") + Enigmail.msg.securityInfo.statusInfo);
}
},
messageReload: function(noShowReload) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageReload: " + noShowReload + "\n");
Enigmail.msg.noShowReload = noShowReload;
ReloadMessage();
},
messengerClose: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messengerClose()\n");
if (this.juniorModeObserver) {
EnigmailPEPAdapter.unregisterJuniorModeObserver(this.juniorModeObserver);
this.juniorModeObserver = null;
}
},
reloadCompleteMsg: function() {
gDBView.reloadMessageWithAllParts();
},
setAttachmentReveal: function(attachmentList) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: setAttachmentReveal\n");
var revealBox = document.getElementById("enigmailRevealAttachments");
if (revealBox) {
// there are situations when evealBox is not yet present
revealBox.setAttribute("hidden", !attachmentList ? "true" : "false");
}
},
messageCleanup: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageCleanup\n");
var enigmailBox = document.getElementById("enigmailBox");
if (enigmailBox && !enigmailBox.collapsed) {
enigmailBox.setAttribute("collapsed", "true");
var statusText = document.getElementById("expandedEnigmailStatusText");
if (statusText)
statusText.value = "";
}
document.getElementById("enigmailBrokenExchangeBox").setAttribute("collapsed", "true");
this.setAttachmentReveal(null);
if (Enigmail.msg.createdURIs.length) {
// Cleanup messages belonging to this window (just in case)
var enigmailSvc = Enigmail.getEnigmailSvc();
if (enigmailSvc) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: Cleanup: Deleting messages\n");
for (var index = 0; index < Enigmail.msg.createdURIs.length; index++) {
enigmailSvc.deleteMessageURI(Enigmail.msg.createdURIs[index]);
}
Enigmail.msg.createdURIs = [];
}
}
Enigmail.msg.decryptedMessage = null;
Enigmail.msg.securityInfo = null;
},
messageFrameUnload: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageFrameUnload\n");
if (Enigmail.msg.noShowReload) {
Enigmail.msg.noShowReload = false;
}
else {
Enigmail.msg.savedHeaders = null;
Enigmail.msg.messageCleanup();
}
},
overrideLayoutChange: function() {
// Enigmail needs to listen to some layout changes in order to decrypt
// messages in case the user changes the layout
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: overrideLayoutChange\n");
var viewTypeElementIds = ["messagePaneVertical",
"messagePaneClassic",
"messagePaneWide"
];
var i;
for (i = 0; i < viewTypeElementIds.length; i++) {
let elementId = viewTypeElementIds[i];
let element = document.getElementById(elementId);
if (element) {
try {
var oldValue = element.getAttribute("oncommand").replace(/;/g, "");
var arg = oldValue.replace(/^(.*)(\(.*\))/, "$2");
element.setAttribute("oncommand", "Enigmail.msg.changeMailLayout" + arg);
}
catch (ex) {}
}
}
var toggleMsgPaneElementIds = ["cmd_toggleMessagePane"];
for (i = 0; i < toggleMsgPaneElementIds.length; i++) {
let elementId = toggleMsgPaneElementIds[i];
let element = document.getElementById(elementId);
if (element) {
try {
element.setAttribute("oncommand", "Enigmail.msg.toggleMessagePane()");
}
catch (ex) {}
}
}
},
changeMailLayout: function(viewType) {
// call the original layout change 1st
ChangeMailLayout(viewType);
// This event requires that we re-subscribe to these events!
Enigmail.msg.messagePane.addEventListener("unload", Enigmail.msg.messageFrameUnload.bind(Enigmail.msg), true);
this.messageReload(false);
},
toggleMessagePane: function() {
Enigmail.hdrView.statusBarHide();
MsgToggleMessagePane(true);
var button = document.getElementById("button_enigmail_decrypt");
if (gFolderDisplay.messageDisplay.visible) {
button.removeAttribute("disabled");
}
else {
button.setAttribute("disabled", "true");
}
},
getCurrentMsgUriSpec: function() {
try {
if (gFolderDisplay.selectedMessages.length != 1)
return "";
var uriSpec = gFolderDisplay.selectedMessageUris[0];
//EnigmailLog.DEBUG("enigmailMessengerOverlay.js: getCurrentMsgUriSpec: uriSpec="+uriSpec+"\n");
return uriSpec;
}
catch (ex) {
return "";
}
},
getCurrentMsgUrl: function() {
var uriSpec = this.getCurrentMsgUriSpec();
return this.getUrlFromUriSpec(uriSpec);
},
getUrlFromUriSpec: function(uriSpec) {
try {
if (!uriSpec)
return null;
var msgService = messenger.messageServiceFromURI(uriSpec);
var urlObj = {};
msgService.GetUrlForUri(uriSpec, urlObj, msgWindow);
var url = urlObj.value;
if (url.scheme == "file") {
return url;
}
else {
return url.QueryInterface(Components.interfaces.nsIMsgMailNewsUrl);
}
}
catch (ex) {
return null;
}
},
updateOptionsDisplay: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: updateOptionsDisplay: \n");
var optList = ["autoDecrypt"];
for (let j = 0; j < optList.length; j++) {
let menuElement = document.getElementById("enigmail_" + optList[j]);
menuElement.setAttribute("checked", EnigmailPrefs.getPref(optList[j]) ? "true" : "false");
menuElement = document.getElementById("enigmail_" + optList[j] + "2");
if (menuElement)
menuElement.setAttribute("checked", EnigmailPrefs.getPref(optList[j]) ? "true" : "false");
}
optList = ["decryptverify"];
for (let j = 0; j < optList.length; j++) {
let menuElement = document.getElementById("enigmail_" + optList[j]);
if (Enigmail.msg.decryptButton && Enigmail.msg.decryptButton.disabled) {
menuElement.setAttribute("disabled", "true");
}
else {
menuElement.removeAttribute("disabled");
}
menuElement = document.getElementById("enigmail_" + optList[j] + "2");
if (menuElement) {
if (Enigmail.msg.decryptButton && Enigmail.msg.decryptButton.disabled) {
menuElement.setAttribute("disabled", "true");
}
else {
menuElement.removeAttribute("disabled");
}
}
}
},
setMainMenuLabel: function() {
let usePep = EnigmailPEPAdapter.usingPep();
let o = ["menu_Enigmail", "menu_Enigmail2ndPane"];
for (let menuId of o) {
let menu = document.getElementById(menuId);
let lbl = menu.getAttribute(usePep ? "peplabel" : "enigmaillabel");
menu.setAttribute("label", lbl);
}
},
displayMainMenu: function(menuPopup) {
let usePep = EnigmailPEPAdapter.usingPep();
let obj = menuPopup.firstChild;
while (obj) {
if (obj.getAttribute("enigmailtype") == "enigmail" || obj.getAttribute("advanced") == "true") {
if (usePep) {
obj.setAttribute("hidden", "true");
}
else {
obj.removeAttribute("hidden");
}
}
obj = obj.nextSibling;
}
if (!usePep) {
EnigmailFuncs.collapseAdvanced(menuPopup, 'hidden', Enigmail.msg.updateOptionsDisplay());
}
},
setupMainMenu: function(menuPopup) {
function traverseTree(currentElement, func) {
if (currentElement) {
func(currentElement);
if (currentElement.id)
EnigmailLog.DEBUG("traverseTree: " + currentElement.id + "\n");
// Traverse the tree
var i = 0;
var currentElementChild = currentElement.childNodes[i];
while (currentElementChild) {
// Recursively traverse the tree structure of the child node
traverseTree(currentElementChild, func);
i++;
currentElementChild = currentElement.childNodes[i];
}
}
}
var p = menuPopup.parentNode;
var a = document.getElementById("menu_EnigmailPopup");
var c = a.cloneNode(true);
p.removeChild(menuPopup);
traverseTree(c, function _updNode(node) {
if (node.id && node.id.length > 0) node.id += "2";
});
p.appendChild(c);
},
toggleAttribute: function(attrName) {
EnigmailLog.DEBUG("enigmailMsgessengerOverlay.js: toggleAttribute('" + attrName + "')\n");
var menuElement = document.getElementById("enigmail_" + attrName);
var oldValue = EnigmailPrefs.getPref(attrName);
EnigmailPrefs.setPref(attrName, !oldValue);
this.updateOptionsDisplay();
if (attrName == "autoDecrypt")
this.messageReload(false);
},
messageImport: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageImport:\n");
return this.messageParse(true, true, "", this.getCurrentMsgUriSpec());
},
/***
* check that handler for multipart/signed is set to Enigmail.
* if handler is different, change it and reload message
*
* @return: - true if handler is OK
* - false if handler was changed and message is reloaded
*/
checkPgpmimeHandler: function() {
let uriSpec = this.getCurrentMsgUriSpec();
if (uriSpec !== this.lastSMimeReloadURI) {
if (EnigmailVerify.currentCtHandler !== EnigmailConstants.MIME_HANDLER_PGPMIME) {
this.lastSMimeReloadURI = uriSpec;
EnigmailVerify.registerContentTypeHandler();
this.messageReload();
return false;
}
}
return true;
},
// callback function for automatic decryption
messageAutoDecrypt: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageAutoDecrypt:\n");
Enigmail.msg.messageDecrypt(null, true);
},
// analyse message header and decrypt/verify message
messageDecrypt: function(event, isAuto) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageDecrypt: " + event + "\n");
event = event ? true : false;
var cbObj = {
event: event,
isAuto: isAuto
};
if (!isAuto) {
EnigmailVerify.setManualUri(this.getCurrentMsgUriSpec());
}
let contentType = "text/plain";
if ('content-type' in currentHeaderData) contentType = currentHeaderData['content-type'].headerValue;
// don't parse message if we know it's a PGP/MIME message
if (((contentType.search(/^multipart\/signed(;|$)/i) === 0) && (contentType.search(/application\/pgp-signature/i) > 0)) ||
((contentType.search(/^multipart\/encrypted(;|$)/i) === 0) && (contentType.search(/application\/pgp-encrypted/i) > 0))) {
if (EnigmailPEPAdapter.usingPep()) {
EnigmailPEPAdapter.processPGPMIME(currentHeaderData);
}
this.messageDecryptCb(event, isAuto, null);
this.movePEPsubject();
return;
}
if (EnigmailPEPAdapter.usingPep()) {
this.hidePgpKeys();
EnigmailPEPAdapter.processInlinePGP(this.getCurrentMsgUrl(), currentHeaderData);
}
try {
if (gFolderDisplay.selectedMessageIsNews) throw "dummy"; // workaround for broken NNTP support in Gloda
MsgHdrToMimeMessage(gFolderDisplay.selectedMessage, cbObj, Enigmail.msg.msgDecryptMimeCb, true, {
examineEncryptedParts: true,
partsOnDemand: false
});
}
catch (ex) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageDecrypt: cannot use MsgHdrToMimeMessage\n");
this.messageDecryptCb(event, isAuto, null);
}
},
msgDecryptMimeCb: function(msg, mimeMsg) {
// MsgHdrToMimeMessage is not on the main thread which may lead to problems with
// accessing DOM and debugging
EnigmailEvents.dispatchEvent(
function(argList) {
var enigmailSvc = Enigmail.getEnigmailSvc();
if (!enigmailSvc) return;
var event = argList[0];
var isAuto = argList[1];
var mimeMsg = argList[2];
Enigmail.msg.messageDecryptCb(event, isAuto, mimeMsg);
}, 0, [this.event, this.isAuto, mimeMsg]);
},
/***
* walk through the (sub-) mime tree and determine PGP/MIME encrypted and signed message parts
*
* @mimePart: parent object to walk through
* @resultObj: object containing two arrays. The resultObj must be pre-initialized by the caller
* - encrypted
* - signed
*/
enumerateMimeParts: function(mimePart, resultObj) {
EnigmailLog.DEBUG("enumerateMimeParts: partName=\"" + mimePart.partName + "\"\n");
EnigmailLog.DEBUG(" " + mimePart.headers["content-type"] + "\n");
EnigmailLog.DEBUG(" " + mimePart + "\n");
if (mimePart.parts) {
EnigmailLog.DEBUG(" " + mimePart.parts.length + " subparts\n");
}
else {
EnigmailLog.DEBUG(" 0 subparts\n");
}
try {
if (typeof(mimePart.contentType) == "string" &&
mimePart.contentType == "multipart/fake-container") {
// workaround for wrong content type of signed message
let signedPart = mimePart.parts[1];
if (typeof(signedPart.headers["content-type"][0]) == "string") {
if (signedPart.headers["content-type"][0].search(/application\/pgp-signature/i) >= 0) {
resultObj.signed.push(signedPart.partName.replace(/\.[0-9]+$/, ""));
EnigmailLog.DEBUG("enumerateMimeParts: found signed subpart " + resultObj.signed + "\n");
}
}
}
var ct = mimePart.headers["content-type"][0];
if (typeof(ct) == "string") {
ct = ct.replace(/[\r\n]/g, " ");
if (ct.search(/multipart\/signed.*application\/pgp-signature/i) >= 0) {
resultObj.signed.push(mimePart.partName);
}
else if (ct.search(/application\/pgp-encrypted/i) >= 0)
resultObj.encrypted.push(mimePart.partName);
}
}
catch (ex) {
// catch exception if no headers or no content-type defined.
}
var i;
for (i in mimePart.parts) {
this.enumerateMimeParts(mimePart.parts[i], resultObj);
}
},
messageDecryptCb: function(event, isAuto, mimeMsg) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageDecryptCb:\n");
this.buggyExchangeEmailContent = null; // reinit HACK for MS-EXCHANGE-Server Problem
var enigmailSvc;
try {
var showHeaders = 0;
var contentType = "";
if (!mimeMsg) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageDecryptCb: mimeMsg is null\n");
try {
contentType = currentHeaderData['content-type'].headerValue;
}
catch (ex) {
contentType = "text/plain";
}
mimeMsg = {
headers: {
'content-type': [contentType]
},
contentType: contentType,
partName: "1",
parts: []
};
}
// Copy selected headers
Enigmail.msg.savedHeaders = {};
for (var index = 0; index < Enigmail.msg.headersList.length; index++) {
var headerName = Enigmail.msg.headersList[index];
var headerValue = "";
if (mimeMsg.headers[headerName]) {
headerValue = (headerName === "autocrypt" ? mimeMsg.headers[headerName] : mimeMsg.headers[headerName].toString());
}
Enigmail.msg.savedHeaders[headerName] = headerValue;
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: header " + headerName + ": '" + headerValue + "'\n");
}
if (("autocrypt" in Enigmail.msg.savedHeaders) && Enigmail.msg.savedHeaders.autocrypt.length > 0 &&
("from" in currentHeaderData)) {
EnigmailAutocrypt.processAutocryptHeader(currentHeaderData.from.headerValue,
Enigmail.msg.savedHeaders.autocrypt,
currentHeaderData.date.headerValue);
}
else {
Enigmail.msg.createArtificialAutocryptHeader();
}
var msgSigned = null;
var msgEncrypted = null;
var resultObj = {
encrypted: [],
signed: []
};
if (mimeMsg.parts) {
this.enumerateMimeParts(mimeMsg, resultObj);
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: embedded objects: " + resultObj.encrypted.join(", ") + " / " + resultObj.signed.join(", ") + "\n");
msgSigned = resultObj.signed.length > 0;
msgEncrypted = resultObj.encrypted.length > 0;
if ("autocrypt-setup-message" in mimeMsg.headers && mimeMsg.headers["autocrypt-setup-message"].join("").toLowerCase() === "v1") {
if (currentAttachments[0].contentType.search(/^application\/autocrypt-key-backup$/i) === 0) {
EnigmailAutocrypt.handleBackupMessage(window, currentAttachments[0].url);
return;
}
}
// HACK for Zimbra OpenPGP Zimlet
// Zimbra illegally changes attachment content-type to application/pgp-encrypted which interfers with below
// see https://sourceforge.net/p/enigmail/bugs/600/
try {
if (mimeMsg.parts && mimeMsg.parts.length && mimeMsg.parts.length == 1 &&
mimeMsg.headers["x-mailer"][0].indexOf("ZimbraWebClient") >= 0 &&
mimeMsg.parts[0].parts[0].headers["content-type"][0].indexOf("text/plain") >= 0 &&
mimeMsg.parts[0].headers["content-type"][0].indexOf("multipart/mixed") >= 0 &&
mimeMsg.parts[0].parts[0].body.indexOf("Version: OpenPGP.js") >= 0 &&
mimeMsg.parts[0].parts[1].headers["content-type"][0].indexOf("application/pgp-encrypted") >= 0) {
this.messageParse(event, false, Enigmail.msg.savedHeaders["content-transfer-encoding"], this.getCurrentMsgUriSpec());
return;
}
}
catch (ex) {}
// HACK for MS-EXCHANGE-Server Problem:
// check for possible bad mime structure due to buggy exchange server:
// - multipart/mixed Container with
// - application/pgp-encrypted Attachment with name "PGPMIME Versions Identification"
// - application/octet-stream Attachment with name "encrypted.asc" having the encrypted content in base64
// - see:
// - http://www.mozilla-enigmail.org/forum/viewtopic.php?f=4&t=425
// - http://sourceforge.net/p/enigmail/forum/support/thread/4add2b69/
// iPGMail produces a similar broken structure, see here:
// - https://sourceforge.net/p/enigmail/forum/support/thread/afc9c246/#5de7
if (mimeMsg.parts && mimeMsg.parts.length && mimeMsg.parts.length == 1 &&
mimeMsg.parts[0].parts && mimeMsg.parts[0].parts.length && mimeMsg.parts[0].parts.length == 3 &&
mimeMsg.parts[0].headers["content-type"][0].indexOf("multipart/mixed") >= 0 &&
mimeMsg.parts[0].parts[0].headers["content-type"][0].search(/multipart\/encrypted/i) < 0 &&
- mimeMsg.parts[0].parts[0].headers["content-type"][0].indexOf("text/plain") >= 0 &&
+ mimeMsg.parts[0].parts[0].headers["content-type"][0].search(/text\/(plain|html)/i) >= 0 &&
mimeMsg.parts[0].parts[1].headers["content-type"][0].indexOf("application/pgp-encrypted") >= 0) {
if (mimeMsg.parts[0].parts[1].headers["content-type"][0].search(/multipart\/encrypted/i) < 0 &&
mimeMsg.parts[0].parts[1].headers["content-type"][0].search(/PGP\/?MIME Versions? Identification/i) >= 0 &&
mimeMsg.parts[0].parts[2].headers["content-type"][0].indexOf("application/octet-stream") >= 0 &&
mimeMsg.parts[0].parts[2].headers["content-type"][0].indexOf("encrypted.asc") >= 0) {
this.buggyMailType = "exchange";
}
else {
this.buggyMailType = "iPGMail";
}
// signal that the structure matches to save the content later on
EnigmailLog.DEBUG("enigmailMessengerOverlay: messageDecryptCb: enabling MS-Exchange hack\n");
this.buggyExchangeEmailContent = "???";
this.buggyMailHeader();
return;
}
}
var contentEncoding = "";
var xEnigmailVersion = "";
var msgUriSpec = this.getCurrentMsgUriSpec();
var encrypedMsg;
if (Enigmail.msg.savedHeaders) {
contentType = Enigmail.msg.savedHeaders["content-type"];
contentEncoding = Enigmail.msg.savedHeaders["content-transfer-encoding"];
xEnigmailVersion = Enigmail.msg.savedHeaders["x-enigmail-version"];
}
let smime = (contentType.search(/multipart\/signed; protocol="application\/pkcs7-signature/i) >= 0);
if (!smime && (msgSigned || msgEncrypted)) {
// PGP/MIME messages
enigmailSvc = Enigmail.getEnigmailSvc();
if (!enigmailSvc)
return;
if (!Enigmail.msg.checkPgpmimeHandler()) return;
if (isAuto && (!EnigmailPrefs.getPref("autoDecrypt"))) {
if (EnigmailVerify.getManualUri() != this.getCurrentMsgUriSpec()) {
// decryption set to manual
Enigmail.hdrView.updateHdrIcons(EnigmailConstants.POSSIBLE_PGPMIME, 0, // exitCode, statusFlags
"", "", // keyId, userId
"", // sigDetails
EnigmailLocale.getString("possiblyPgpMime"), // infoMsg
null, // blockSeparation
"", // encToDetails
null); // xtraStatus
}
}
else if (!isAuto) {
Enigmail.msg.messageReload(false);
}
return;
}
// inline-PGP messages
if (!isAuto || EnigmailPrefs.getPref("autoDecrypt")) {
this.messageParse(event, false, contentEncoding, msgUriSpec);
}
}
catch (ex) {
EnigmailLog.writeException("enigmailMessengerOverlay.js: messageDecryptCb", ex);
}
},
// display header about reparing buggy MS-Exchange messages
buggyMailHeader: function() {
let headerSink = msgWindow.msgHeaderSink.securityInfo.QueryInterface(Components.interfaces.nsIEnigMimeHeaderSink);
let uriStr = EnigmailURIs.createMessageURI(this.getCurrentMsgUrl(),
"message/rfc822",
"",
"??",
false);
let ph = new EnigmailProtocolHandler();
let uri = ph.newURI(uriStr, "", "");
headerSink.updateSecurityStatus("", 0, 0, "", "", "", "", "", uri, "", "1");
},
messageParse: function(interactive, importOnly, contentEncoding, msgUriSpec) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageParse: " + interactive + "\n");
var bodyElement = this.getBodyElement();
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: bodyElement=" + bodyElement + "\n");
if (!bodyElement) return;
let topElement = bodyElement;
var findStr = /* interactive ? null : */ "-----BEGIN PGP";
var msgText = null;
var foundIndex = -1;
if (bodyElement.firstChild) {
let node = bodyElement.firstChild;
while (node) {
if (node.nodeName == "DIV") {
foundIndex = node.textContent.indexOf(findStr);
if (foundIndex >= 0) {
if (node.textContent.indexOf(findStr + " LICENSE AUTHORIZATION") == foundIndex)
foundIndex = -1;
}
if (foundIndex >= 0) {
bodyElement = node;
break;
}
}
node = node.nextSibling;
}
}
if (foundIndex >= 0) {
if (Enigmail.msg.savedHeaders["content-type"].search(/^text\/html/i) === 0) {
let p = Components.classes["@mozilla.org/parserutils;1"].createInstance(Components.interfaces.nsIParserUtils);
const de = Components.interfaces.nsIDocumentEncoder;
msgText = p.convertToPlainText(topElement.innerHTML, de.OutputRaw | de.OutputBodyOnly, 0);
}
else {
msgText = bodyElement.textContent;
}
}
if (!msgText) {
// No PGP content
// but this might be caused by the HACK for MS-EXCHANGE-Server Problem
// - so return only if:
if (!this.buggyExchangeEmailContent || this.buggyExchangeEmailContent == "???") {
return;
}
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageParse: got buggyExchangeEmailContent = " + this.buggyExchangeEmailContent.substr(0, 50) + "\n");
// fix the whole invalid email by replacing the contents by the decoded text
// as plain inline format
if (this.displayBuggyExchangeMail()) {
return;
}
else {
msgText = this.buggyExchangeEmailContent;
}
msgText = msgText.replace(/\r\n/g, "\n");
msgText = msgText.replace(/\r/g, "\n");
// content is in encrypted.asc part:
let idx = msgText.search(/Content-Type: application\/octet-stream; name="encrypted.asc"/i);
if (idx >= 0) {
msgText = msgText.slice(idx);
}
// check whether we have base64 encoding
var isBase64 = false;
idx = msgText.search(/Content-Transfer-Encoding: base64/i);
if (idx >= 0) {
isBase64 = true;
}
// find content behind part header
idx = msgText.search(/\n\n/);
if (idx >= 0) {
msgText = msgText.slice(idx);
}
// remove stuff behind content block (usually a final boundary row)
idx = msgText.search(/\n\n--/);
if (idx >= 0) {
msgText = msgText.slice(0, idx + 1);
}
// decode base64 if it is encoded that way
if (isBase64) {
try {
msgText = EnigmailData.decodeBase64(msgText);
}
catch (ex) {
EnigmailLog.writeException("enigmailMessengerOverlay.js: decodeBase64() ", ex);
}
//EnigmailLog.DEBUG("nach base64 decode: \n" + msgText + "\n");
}
}
var charset = msgWindow ? msgWindow.mailCharacterSet : "";
// Encode ciphertext to charset from unicode
msgText = EnigmailData.convertFromUnicode(msgText, charset);
var mozPlainText = bodyElement.innerHTML.search(/class="moz-text-plain"/);
if ((mozPlainText >= 0) && (mozPlainText < 40)) {
// workaround for too much expanded emoticons in plaintext msg
var r = new RegExp(/( )(;-\)|:-\)|;\)|:\)|:-\(|:\(|:-\\|:-P|:-D|:-\[|:-\*|>:o|8-\)|:-\$|:-X|=-O|:-!|O:-\)|:'\()( )/g);
if (msgText.search(r) >= 0) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageParse: performing emoticons fixing\n");
msgText = msgText.replace(r, "$2");
}
}
// extract text preceeding and/or following armored block
var head = "";
var tail = "";
if (findStr) {
head = msgText.substring(0, msgText.indexOf(findStr)).replace(/^[\n\r\s]*/, "");
head = head.replace(/[\n\r\s]*$/, "");
var endStart = msgText.indexOf("-----END PGP");
var nextLine = msgText.substring(endStart).search(/[\n\r]/);
if (nextLine > 0) {
tail = msgText.substring(endStart + nextLine).replace(/^[\n\r\s]*/, "");
}
}
//EnigmailLog.DEBUG("enigmailMessengerOverlay.js: msgText='"+msgText+"'\n");
var mailNewsUrl = this.getUrlFromUriSpec(msgUriSpec);
var urlSpec = mailNewsUrl ? mailNewsUrl.spec : "";
let retry = (charset != "UTF-8" ? 1 : 2);
Enigmail.msg.messageParseCallback(msgText, contentEncoding, charset, interactive,
importOnly, urlSpec, "", retry, head, tail,
msgUriSpec);
},
getBodyElement: function() {
let msgFrame = EnigmailWindows.getFrame(window, "messagepane");
let bodyElement = msgFrame.document.getElementsByTagName("body")[0];
return bodyElement;
},
messageParseCallback: function(msgText, contentEncoding, charset, interactive,
importOnly, messageUrl, signature, retry,
head, tail, msgUriSpec) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageParseCallback: " + interactive + ", " + interactive + ", importOnly=" + importOnly + ", charset=" + charset + ", msgUrl=" +
messageUrl +
", retry=" + retry + ", signature='" + signature + "'\n");
const nsIEnigmail = Components.interfaces.nsIEnigmail;
if (!msgText)
return;
var enigmailSvc = Enigmail.getEnigmailSvc();
if (!enigmailSvc)
return;
var plainText;
var exitCode;
var newSignature = "";
var statusFlags = 0;
var errorMsgObj = {
value: ""
};
var keyIdObj = {};
var userIdObj = {};
var sigDetailsObj = {};
var encToDetailsObj = {};
var pEpResult = null;
var blockSeparationObj = {
value: ""
};
if (importOnly) {
// Import public key
exitCode = EnigmailKeyRing.importKey(window, true, msgText, "",
errorMsgObj);
}
else {
if (msgText.indexOf("\nCharset:") > 0) {
// Check if character set needs to be overridden
var startOffset = msgText.indexOf("-----BEGIN PGP ");
if (startOffset >= 0) {
var subText = msgText.substr(startOffset);
subText = subText.replace(/\r\n/g, "\n");
subText = subText.replace(/\r/g, "\n");
var endOffset = subText.search(/\n\n/);
if (endOffset > 0) {
subText = subText.substr(0, endOffset) + "\n";
let matches = subText.match(/\nCharset: *(.*) *\n/i);
if (matches && (matches.length > 1)) {
// Override character set
charset = matches[1];
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageParseCallback: OVERRIDING charset=" + charset + "\n");
}
}
}
}
var exitCodeObj = {};
var statusFlagsObj = {};
var signatureObj = {};
signatureObj.value = signature;
var uiFlags = interactive ? (nsIEnigmail.UI_INTERACTIVE |
nsIEnigmail.UI_ALLOW_KEY_IMPORT |
nsIEnigmail.UI_UNVERIFIED_ENC_OK) : 0;
if (EnigmailPEPAdapter.usingPep()) {
let addresses = {
from: null,
to: EnigmailFuncs.parseEmails(gFolderDisplay.selectedMessage.recipients),
cc: EnigmailFuncs.parseEmails(gFolderDisplay.selectedMessage.ccList)
};
let fromAddr = EnigmailFuncs.parseEmails(gFolderDisplay.selectedMessage.author);
if (fromAddr.length > 0) addresses.from = fromAddr[0];
pEpResult = EnigmailPEPDecrypt.decryptMessageData(false, msgText, addresses);
if (pEpResult) {
plainText = pEpResult.longmsg;
if (pEpResult.shortmsg.length > 0) {
Enigmail.hdrView.setSubject(pEpResult.shortmsg);
}
exitCode = 0;
}
else {
plainText = "";
exitCode = 1;
}
}
else {
plainText = enigmailSvc.decryptMessage(window, uiFlags, msgText,
signatureObj, exitCodeObj, statusFlagsObj,
keyIdObj, userIdObj, sigDetailsObj,
errorMsgObj, blockSeparationObj, encToDetailsObj);
//EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageParseCallback: plainText='"+plainText+"'\n");
exitCode = exitCodeObj.value;
newSignature = signatureObj.value;
if (plainText === "" && exitCode === 0) {
plainText = " ";
}
statusFlags = statusFlagsObj.value;
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageParseCallback: newSignature='" + newSignature + "'\n");
}
}
var errorMsg = errorMsgObj.value;
if (importOnly) {
if (interactive && errorMsg)
EnigmailDialog.alert(window, errorMsg);
return;
}
var displayedUriSpec = Enigmail.msg.getCurrentMsgUriSpec();
if (!msgUriSpec || (displayedUriSpec == msgUriSpec)) {
if (EnigmailPEPAdapter.usingPep() && pEpResult) {
Enigmail.hdrView.displayPepStatus(pEpResult.rating, pEpResult.fpr, null, pEpResult.persons);
}
else {
Enigmail.hdrView.updateHdrIcons(exitCode, statusFlags, keyIdObj.value, userIdObj.value,
sigDetailsObj.value,
errorMsg,
null, // blockSeparation
encToDetailsObj.value,
null); // xtraStatus
}
}
var noSecondTry = nsIEnigmail.GOOD_SIGNATURE |
nsIEnigmail.EXPIRED_SIGNATURE |
nsIEnigmail.EXPIRED_KEY_SIGNATURE |
nsIEnigmail.EXPIRED_KEY |
nsIEnigmail.REVOKED_KEY |
nsIEnigmail.NO_PUBKEY |
nsIEnigmail.NO_SECKEY |
nsIEnigmail.IMPORTED_KEY |
nsIEnigmail.MISSING_PASSPHRASE |
nsIEnigmail.BAD_PASSPHRASE |
nsIEnigmail.UNKNOWN_ALGO |
nsIEnigmail.DECRYPTION_OKAY |
nsIEnigmail.OVERFLOWED;
if ((exitCode !== 0) && (!(statusFlags & noSecondTry))) {
// Bad signature/armor
if (retry == 1) {
msgText = EnigmailData.convertFromUnicode(msgText, "UTF-8");
Enigmail.msg.messageParseCallback(msgText, contentEncoding, charset,
interactive, importOnly, messageUrl,
signature, retry + 1,
head, tail, msgUriSpec);
return;
}
else if (retry == 2) {
// Try to verify signature by accessing raw message text directly
// (avoid recursion by setting retry parameter to false on callback)
newSignature = "";
Enigmail.msg.msgDirectDecrypt(interactive, importOnly, contentEncoding, charset,
newSignature, 0, head, tail, msgUriSpec,
Enigmail.msg.messageParseCallback);
return;
}
else if (retry == 3) {
msgText = EnigmailData.convertToUnicode(msgText, "UTF-8");
Enigmail.msg.messageParseCallback(msgText, contentEncoding, charset, interactive,
importOnly, messageUrl, null, retry + 1,
head, tail, msgUriSpec);
return;
}
}
if (!plainText) {
if (interactive && Enigmail.msg.securityInfo && Enigmail.msg.securityInfo.statusInfo)
EnigmailDialog.info(window, Enigmail.msg.securityInfo.statusInfo);
return;
}
if (retry >= 2) {
plainText = EnigmailData.convertFromUnicode(EnigmailData.convertToUnicode(plainText, "UTF-8"), charset);
}
if (blockSeparationObj.value.indexOf(" ") >= 0) {
var blocks = blockSeparationObj.value.split(/ /);
var blockInfo = blocks[0].split(/:/);
plainText = EnigmailData.convertFromUnicode(EnigmailLocale.getString("notePartEncrypted"), charset) +
"\n\n" + plainText.substr(0, blockInfo[1]) + "\n\n" + EnigmailLocale.getString("noteCutMessage");
}
// Save decrypted message status, headers, and content
var headerList = {
"subject": "",
"from": "",
"date": "",
"to": "",
"cc": ""
};
var index, headerName;
if (!gViewAllHeaders) {
for (index = 0; index < headerList.length; index++) {
headerList[index] = "";
}
}
else {
for (index = 0; index < gExpandedHeaderList.length; index++) {
headerList[gExpandedHeaderList[index].name] = "";
}
for (headerName in currentHeaderData) {
headerList[headerName] = "";
}
}
for (headerName in headerList) {
if (currentHeaderData[headerName])
headerList[headerName] = currentHeaderData[headerName].headerValue;
}
// WORKAROUND
if (headerList.cc == headerList.to)
headerList.cc = "";
var hasAttachments = currentAttachments && currentAttachments.length;
var attachmentsEncrypted = true;
for (index in currentAttachments) {
if (!Enigmail.msg.checkEncryptedAttach(currentAttachments[index])) {
if (!Enigmail.msg.checkSignedAttachment(currentAttachments, index)) attachmentsEncrypted = false;
}
}
var msgRfc822Text = "";
if (head || tail) {
if (head) {
// print a warning if the signed or encrypted part doesn't start
// quite early in the message
let matches = head.match(/(\n)/g);
if (matches && matches.length > 10) {
msgRfc822Text = EnigmailData.convertFromUnicode(EnigmailLocale.getString("notePartEncrypted"), charset) + "\n\n";
}
msgRfc822Text += head + "\n\n";
}
msgRfc822Text += EnigmailData.convertFromUnicode(EnigmailLocale.getString("beginPgpPart"), charset) + "\n\n";
}
msgRfc822Text += plainText;
if (head || tail) {
msgRfc822Text += "\n\n" + EnigmailData.convertFromUnicode(EnigmailLocale.getString("endPgpPart"), charset) + "\n\n" + tail;
}
Enigmail.msg.decryptedMessage = {
url: messageUrl,
uri: msgUriSpec,
headerList: headerList,
hasAttachments: hasAttachments,
attachmentsEncrypted: attachmentsEncrypted,
charset: charset,
plainText: msgRfc822Text
};
// don't display decrypted message if message selection has changed
displayedUriSpec = Enigmail.msg.getCurrentMsgUriSpec();
if (msgUriSpec && displayedUriSpec && (displayedUriSpec != msgUriSpec)) return;
// Create and load one-time message URI
var messageContent = Enigmail.msg.getDecryptedMessage("message/rfc822", false);
Enigmail.msg.noShowReload = true;
var node;
var bodyElement = this.getBodyElement();
if (bodyElement.firstChild) {
node = bodyElement.firstChild;
var foundIndex = -1;
var findStr = "-----BEGIN PGP";
while (node) {
if (node.nodeName == "DIV") {
foundIndex = node.textContent.indexOf(findStr);
if (foundIndex >= 0) {
if (node.textContent.indexOf(findStr + " LICENSE AUTHORIZATION") == foundIndex)
foundIndex = -1;
}
if (foundIndex >= 0) {
node.innerHTML = EnigmailFuncs.formatPlaintextMsg(EnigmailData.convertToUnicode(messageContent, charset));
this.movePEPsubject();
return;
}
}
node = node.nextSibling;
}
// if no <DIV> node is found, try with <PRE> (bug 24762)
node = bodyElement.firstChild;
foundIndex = -1;
while (node) {
if (node.nodeName == "PRE") {
foundIndex = node.textContent.indexOf(findStr);
if (foundIndex >= 0) {
if (node.textContent.indexOf(findStr + " LICENSE AUTHORIZATION") == foundIndex)
foundIndex = -1;
}
if (foundIndex >= 0) {
node.innerHTML = EnigmailFuncs.formatPlaintextMsg(EnigmailData.convertToUnicode(messageContent, charset));
this.movePEPsubject();
return;
}
}
node = node.nextSibling;
}
// HACK for MS-EXCHANGE-Server Problem:
// - remove empty text/plain part
// and set message content as inner text
// - missing:
// - signal in statusFlags so that we warn in Enigmail.hdrView.updateHdrIcons()
if (this.buggyExchangeEmailContent) {
if (this.displayBuggyExchangeMail()) {
return;
}
EnigmailLog.DEBUG("enigmailMessengerOverlay: messageParseCallback: got broken MS-Exchange mime message\n");
messageContent = messageContent.replace(/^\s{0,2}Content-Transfer-Encoding: quoted-printable\s*Content-Type: text\/plain;\s*charset=windows-1252/i, "");
node = bodyElement.firstChild;
while (node) {
if (node.nodeName == "DIV") {
node.innerHTML = EnigmailFuncs.formatPlaintextMsg(EnigmailData.convertToUnicode(messageContent, charset));
Enigmail.hdrView.updateHdrIcons(exitCode, statusFlags, keyIdObj.value, userIdObj.value,
sigDetailsObj.value,
errorMsg,
null, // blockSeparation
encToDetailsObj.value,
"buggyMailFormat");
return;
}
node = node.nextSibling;
}
}
}
EnigmailLog.ERROR("enigmailMessengerOverlay.js: no node found to replace message display\n");
return;
},
/**
* Extract the subject from the 1st content line and move it to the subject line
*/
movePEPsubject: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: movePEPsubject:\n");
let bodyElement = this.getBodyElement();
if (bodyElement.textContent.search(/^\r?\n?Subject: [^\r\n]+\r?\n\r?\n/i) === 0 &&
("subject" in currentHeaderData) &&
currentHeaderData.subject.headerValue === "pEp") {
if (gFolderDisplay.selectedMessage) {
let m = EnigmailMime.extractSubjectFromBody(bodyElement.textContent);
if (m) {
let node = bodyElement.firstChild;
let found = false;
while ((!found) && node) {
if (node.nodeName == "DIV") {
node.innerHTML = EnigmailFuncs.formatPlaintextMsg(m.messageBody);
found = true;
}
node = node.nextSibling;
}
// if no <DIV> node is found, try with <PRE> (bug 24762)
node = bodyElement.firstChild;
while ((!found) && node) {
if (node.nodeName == "PRE") {
node.innerHTML = EnigmailFuncs.formatPlaintextMsg(m.messageBody);
found = true;
}
node = node.nextSibling;
}
Enigmail.hdrView.setSubject(m.subject);
}
}
}
},
// check if an attachment could be signed
checkSignedAttachment: function(attachmentObj, index) {
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(attName.replace(/\.(sig|asc)$/, ""));
}
else
findFile = new RegExp(attName + ".(sig|asc)$");
for (let i in attachmentList) {
if ((i != index) &&
(this.getAttachmentName(attachmentList[i]).toLowerCase().search(findFile) === 0))
signed = true;
}
return signed;
},
/**
* Fix broken PGP/MIME messages from MS-Exchange by replacing the broken original
* message with a fixed copy.
*
* no return
*/
fixBuggyExchangeMail: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: fixBuggyExchangeMail:\n");
function hideAndResetExchangePane() {
document.getElementById("enigmailBrokenExchangeBox").setAttribute("collapsed", "true");
document.getElementById("enigmailFixBrokenMessageProgress").setAttribute("collapsed", "true");
document.getElementById("enigmailFixBrokenMessageButton").removeAttribute("collapsed");
}
document.getElementById("enigmailFixBrokenMessageButton").setAttribute("collapsed", "true");
document.getElementById("enigmailFixBrokenMessageProgress").removeAttribute("collapsed");
let msg = gFolderDisplay.messageDisplay.displayedMessage;
let p = EnigmailFixExchangeMsg.fixExchangeMessage(msg, this.buggyMailType);
p.then(
function _success(msgKey) {
// display message with given msgKey
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: fixBuggyExchangeMail: _success: msgKey=" + msgKey + "\n");
if (msgKey) {
let index = gFolderDisplay.view.dbView.findIndexFromKey(msgKey, true);
EnigmailLog.DEBUG(" ** index = " + index + "\n");
EnigmailTimer.setTimeout(function() {
gFolderDisplay.view.dbView.selectMsgByKey(msgKey);
}, 750);
}
hideAndResetExchangePane();
}
);
p.catch(function _rejected() {
EnigmailDialog.alert(window, EnigmailLocale.getString("fixBrokenExchangeMsg.failed"));
hideAndResetExchangePane();
});
},
/**
* Hide attachments containing OpenPGP keys
*/
hidePgpKeys: function() {
let keys = [];
for (let i = 0; i < currentAttachments.length; i++) {
if (currentAttachments[i].contentType.search(/^application\/pgp-keys/i) === 0) {
keys.push(i);
}
}
if (keys.length > 0) {
let attachmentList = document.getElementById("attachmentList");
for (let i = keys.length; i > 0; i--) {
currentAttachments.splice(keys[i - 1], 1);
}
if (attachmentList) {
// delete all keys from attachment list
while (attachmentList.itemCount > 0) {
attachmentList.removeItemAt(0);
}
// build new attachment list
/* global gBuildAttachmentsForCurrentMsg: true */
let orig = gBuildAttachmentsForCurrentMsg;
gBuildAttachmentsForCurrentMsg = false;
displayAttachmentsForExpandedView();
gBuildAttachmentsForCurrentMsg = orig;
}
}
},
/**
* Attempt to work around bug with headers of MS-Exchange message.
* Reload message content
*
* @return: true: message displayed
* false: could not handle message
*/
displayBuggyExchangeMail: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: displayBuggyExchangeMail\n");
let hdrs = Components.classes["@mozilla.org/messenger/mimeheaders;1"].createInstance(Components.interfaces.nsIMimeHeaders);
hdrs.initialize(this.buggyExchangeEmailContent);
let ct = hdrs.extractHeader("content-type", true);
if (ct && ct.search(/^text\/plain/i) === 0) {
let bi = this.buggyExchangeEmailContent.search(/\r?\n/);
let boundary = this.buggyExchangeEmailContent.substr(2, bi - 2);
let startMsg = this.buggyExchangeEmailContent.search(/\r?\n\r?\n/);
let msgText;
if (this.buggyMailType == "exchange") {
msgText = 'Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="' + boundary + '"\r\n' +
this.buggyExchangeEmailContent.substr(startMsg);
}
else {
msgText = 'Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="' + boundary + '"\r\n' +
"\r\n" + boundary + "\r\n" +
"Content-Type: application/pgp-encrypted\r\n" +
"Content-Description: PGP/MIME version identification\r\n\r\n" +
"Version: 1\r\n\r\n" +
this.buggyExchangeEmailContent.substr(startMsg).replace(/^Content-Type: +application\/pgp-encrypted/im,
"Content-Type: application/octet-stream");
}
let enigmailSvc = Enigmail.getEnigmailSvc();
if (!enigmailSvc) return false;
let uri = enigmailSvc.createMessageURI(this.getCurrentMsgUrl(),
"message/rfc822",
"",
msgText,
false);
EnigmailVerify.setMsgWindow(msgWindow, null);
messenger.loadURL(window, uri);
// Thunderbird
let atv = document.getElementById("attachmentView");
if (atv) {
atv.setAttribute("collapsed", "true");
}
// SeaMonkey
let eab = document.getElementById("expandedAttachmentBox");
if (eab) {
eab.setAttribute("collapsed", "true");
}
return true;
}
return false;
},
// check if the attachment could be encrypted
checkEncryptedAttach: function(attachment) {
return (this.getAttachmentName(attachment).match(/\.(gpg|pgp|asc)$/i) ||
(attachment.contentType.match(/^application\/pgp(-.*)?$/i)) &&
(attachment.contentType.search(/^application\/pgp-signature/i) < 0));
},
getAttachmentName: function(attachment) {
if ("name" in attachment) {
// Thunderbird
return attachment.name;
}
else
// SeaMonkey
return attachment.displayName;
},
escapeTextForHTML: function(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
var addrs = text.match(/\b[A-Za-z0-9_+.-]+@[A-Za-z0-9.-]+\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
var urls = text.match(/\b(http|https|ftp):\S+\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;
},
getDecryptedMessage: function(contentType, includeHeaders) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: getDecryptedMessage: " + contentType + ", " + includeHeaders + "\n");
if (!Enigmail.msg.decryptedMessage)
return "No decrypted message found!\n";
var enigmailSvc = Enigmail.getEnigmailSvc();
if (!enigmailSvc)
return "";
var headerList = Enigmail.msg.decryptedMessage.headerList;
var statusLine = Enigmail.msg.securityInfo ? Enigmail.msg.securityInfo.statusLine : "";
var contentData = "";
var headerName;
if (contentType == "message/rfc822") {
// message/rfc822
if (includeHeaders) {
try {
var msg = gFolderDisplay.selectedMessage;
if (msg) {
let msgHdr = {
"From": msg.author,
"Subject": msg.subject,
"To": msg.recipients,
"Cc": msg.ccList,
"Date": EnigmailTime.getDateTime(msg.dateInSeconds, true, true)
};
if (gFolderDisplay.selectedMessageIsNews) {
if (currentHeaderData.newsgroups) {
msgHdr.Newsgroups = currentHeaderData.newsgroups.headerValue;
}
}
for (let headerName in msgHdr) {
if (msgHdr[headerName] && msgHdr[headerName].length > 0)
contentData += headerName + ": " + msgHdr[headerName] + "\r\n";
}
}
}
catch (ex) {
// the above seems to fail every now and then
// so, here is the fallback
for (let headerName in headerList) {
let headerValue = headerList[headerName];
contentData += headerName + ": " + headerValue + "\r\n";
}
}
contentData += "Content-Type: text/plain";
if (Enigmail.msg.decryptedMessage.charset) {
contentData += "; charset=" + Enigmail.msg.decryptedMessage.charset;
}
contentData += "\r\n";
}
contentData += "\r\n";
if (Enigmail.msg.decryptedMessage.hasAttachments && (!Enigmail.msg.decryptedMessage.attachmentsEncrypted)) {
contentData += EnigmailData.convertFromUnicode(EnigmailLocale.getString("enigContentNote"), Enigmail.msg.decryptedMessage.charset);
}
contentData += Enigmail.msg.decryptedMessage.plainText;
}
else {
// text/html or text/plain
if (contentType == "text/html") {
contentData += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=" + Enigmail.msg.decryptedMessage.charset + "\">\r\n";
contentData += "<html><head></head><body>\r\n";
}
if (statusLine) {
if (contentType == "text/html") {
contentData += "<b>" + EnigmailLocale.getString("enigHeader") + "</b> " +
this.escapeTextForHTML(statusLine, false) + "<br>\r\n<hr>\r\n";
}
else {
contentData += EnigmailLocale.getString("enigHeader") + " " + statusLine + "\r\n\r\n";
}
}
if (includeHeaders) {
for (headerName in headerList) {
let headerValue = headerList[headerName];
if (headerValue) {
if (contentType == "text/html") {
contentData += "<b>" + this.escapeTextForHTML(headerName, false) + ":</b> " +
this.escapeTextForHTML(headerValue, false) + "<br>\r\n";
}
else {
contentData += headerName + ": " + headerValue + "\r\n";
}
}
}
}
if (contentType == "text/html") {
contentData += "<pre>" + this.escapeTextForHTML(Enigmail.msg.decryptedMessage.plainText, false) + "</pre>\r\n";
contentData += "</body></html>\r\n";
}
else {
contentData += "\r\n" + Enigmail.msg.decryptedMessage.plainText;
}
if (!(EnigmailOS.isDosLike)) {
contentData = contentData.replace(/\r\n/g, "\n");
}
}
return contentData;
},
msgDefaultPrint: function(elementId) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: this.msgDefaultPrint: " + elementId + "\n");
goDoCommand(elementId.indexOf("printpreview") >= 0 ? "cmd_printpreview" : "cmd_print");
},
msgPrint: function(elementId) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: msgPrint: " + elementId + "\n");
var contextMenu = (elementId.search("Context") > -1);
if (!Enigmail.msg.decryptedMessage || typeof(Enigmail.msg.decryptedMessage) == "undefined") {
this.msgDefaultPrint(elementId);
return;
}
var mailNewsUrl = this.getCurrentMsgUrl();
if (!mailNewsUrl) {
this.msgDefaultPrint(elementId);
return;
}
if (Enigmail.msg.decryptedMessage.url != mailNewsUrl.spec) {
Enigmail.msg.decryptedMessage = null;
this.msgDefaultPrint(elementId);
return;
}
var enigmailSvc = Enigmail.getEnigmailSvc();
if (!enigmailSvc) {
this.msgDefaultPrint(elementId);
return;
}
// Note: Trying to print text/html content does not seem to work with
// non-ASCII chars
var msgContent = this.getDecryptedMessage("message/rfc822", true);
var uri = enigmailSvc.createMessageURI(Enigmail.msg.decryptedMessage.url,
"message/rfc822",
"",
msgContent,
false);
Enigmail.msg.createdURIs.push(uri);
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: msgPrint: uri=" + uri + "\n");
var messageList = [uri];
var printPreview = (elementId.indexOf("printpreview") >= 0);
window.openDialog("chrome://messenger/content/msgPrintEngine.xul",
"",
"chrome,dialog=no,all,centerscreen",
1, messageList, statusFeedback,
printPreview, Components.interfaces.nsIMsgPrintEngine.MNAB_PRINTPREVIEW_MSG,
window);
return;
},
messageSave: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageSave: \n");
if (!Enigmail.msg.decryptedMessage) {
EnigmailDialog.alert(window, EnigmailLocale.getString("noDecrypted"));
return;
}
var mailNewsUrl = this.getCurrentMsgUrl();
if (!mailNewsUrl) {
EnigmailDialog.alert(window, EnigmailLocale.getString("noMessage"));
return;
}
if (Enigmail.msg.decryptedMessage.url != mailNewsUrl.spec) {
Enigmail.msg.decryptedMessage = null;
EnigmailDialog.info(window, EnigmailLocale.getString("useButton"));
return;
}
var saveFile = EnigmailDialog.filePicker(window, EnigmailLocale.getString("saveHeader"),
Enigmail.msg.lastSaveDir, true, "txt",
null, ["Text files", "*.txt"]);
if (!saveFile) return;
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: messageSave: path=" + saveFile.path + "\n");
if (saveFile.parent)
Enigmail.msg.lastSaveDir = EnigmailFiles.getFilePath(saveFile.parent);
var textContent = this.getDecryptedMessage("text/plain", true);
if (!EnigmailFiles.writeFileContents(saveFile.path, textContent, null)) {
EnigmailDialog.alert(window, EnigmailLocale.getString("fileSaveError", [saveFile.path]));
return;
}
return;
},
msgDirectDecrypt: function(interactive, importOnly, contentEncoding, charset, signature,
bufferSize, head, tail, msgUriSpec, callbackFunction) {
EnigmailLog.WRITE("enigmailMessengerOverlay.js: msgDirectDecrypt: contentEncoding=" + contentEncoding + ", signature=" + signature + "\n");
var mailNewsUrl = this.getCurrentMsgUrl();
if (!mailNewsUrl)
return;
var callbackArg = {
interactive: interactive,
importOnly: importOnly,
contentEncoding: contentEncoding,
charset: charset,
messageUrl: mailNewsUrl.spec,
msgUriSpec: msgUriSpec,
signature: signature,
data: "",
head: head,
tail: tail,
callbackFunction: callbackFunction
};
var msgSvc = messenger.messageServiceFromURI(msgUriSpec);
var listener = {
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIStreamListener]),
onStartRequest: function() {
this.data = "";
this.inStream = Components.classes["@mozilla.org/scriptableinputstream;1"].
createInstance(Components.interfaces.nsIScriptableInputStream);
},
onDataAvailable: function(req, sup, stream, offset, count) {
this.inStream.init(stream);
this.data += this.inStream.read(count);
},
onStopRequest: function() {
var start = this.data.indexOf("-----BEGIN PGP");
var end = this.data.indexOf("-----END PGP");
if (start >= 0 && end > start) {
var tStr = this.data.substr(end);
var n = tStr.indexOf("\n");
var r = tStr.indexOf("\r");
var lEnd = -1;
if (n >= 0 && r >= 0) {
lEnd = Math.min(r, n);
}
else if (r >= 0) {
lEnd = r;
}
else if (n >= 0)
lEnd = n;
if (lEnd >= 0) {
end += lEnd;
}
callbackArg.data = this.data.substring(start, end + 1);
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: data: >" + callbackArg.data + "<\n");
Enigmail.msg.msgDirectCallback(callbackArg);
}
}
};
msgSvc.streamMessage(msgUriSpec,
listener,
msgWindow,
null,
false,
null,
false);
},
msgDirectCallback: function(callbackArg) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: msgDirectCallback: \n");
var mailNewsUrl = Enigmail.msg.getCurrentMsgUrl();
var urlSpec = mailNewsUrl ? mailNewsUrl.spec : "";
var newBufferSize = 0;
var l = urlSpec.length;
if (urlSpec.substr(0, l) != callbackArg.messageUrl.substr(0, l)) {
EnigmailLog.ERROR("enigmailMessengerOverlay.js: msgDirectCallback: Message URL mismatch " + mailNewsUrl.spec + " vs. " + callbackArg.messageUrl + "\n");
return;
}
var msgText = callbackArg.data;
msgText = EnigmailData.convertFromUnicode(msgText, "UTF-8");
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: msgDirectCallback: msgText='" + msgText + "'\n");
var f = function(argList) {
var msgText = argList[0];
var cb = argList[1];
cb.callbackFunction(msgText, cb.contentEncoding,
cb.charset,
cb.interactive,
cb.importOnly,
cb.messageUrl,
cb.signature,
3,
cb.head,
cb.tail,
cb.msgUriSpec);
};
EnigmailEvents.dispatchEvent(f, 0, [msgText, callbackArg]);
},
verifyEmbeddedMsg: function(window, msgUrl, msgWindow, msgUriSpec, contentEncoding, event) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: verifyEmbeddedMsg: msgUrl" + msgUrl + "\n");
var callbackArg = {
data: "",
window: window,
msgUrl: msgUrl,
msgWindow: msgWindow,
msgUriSpec: msgUriSpec,
contentEncoding: contentEncoding,
event: event
};
var requestCallback = function _cb(data) {
callbackArg.data = data;
Enigmail.msg.verifyEmbeddedCallback(callbackArg);
};
var bufferListener = EnigmailStreams.newStringStreamListener(requestCallback);
var channel = EnigmailStreams.createChannelFromURI(msgUrl);
channel.asyncOpen(bufferListener, msgUrl);
},
verifyEmbeddedCallback: function(callbackArg) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: verifyEmbeddedCallback: \n");
// HACK for MS-EXCHANGE-Server Problem:
// - now let's save the mail content for later processing
if (this.buggyExchangeEmailContent == "???") {
EnigmailLog.DEBUG("enigmailMessengerOverlay: verifyEmbeddedCallback: got broken MS-Exchange mime message\n");
this.buggyExchangeEmailContent = callbackArg.data.replace(/^(\r?\n)*/, "");
if (this.displayBuggyExchangeMail()) {
return;
}
}
// try inline PGP
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: verifyEmbeddedCallback: try inline PGP\n");
Enigmail.msg.messageParse(!callbackArg.event, false, callbackArg.contentEncoding, callbackArg.msgUriSpec);
},
revealAttachments: function(index) {
if (!index) index = 0;
if (index < currentAttachments.length) {
this.handleAttachment("revealName/" + index.toString(), currentAttachments[index]);
}
},
// handle the attachment view toggle
handleAttchmentEvent: function() {
let attList = document.getElementById("attachmentList");
if (attList && attList.itemCount > 0) {
for (let i = 0; i < attList.itemCount; i++) {
let att = attList.getItemAtIndex(i);
att.addEventListener("click", function _f(event) {
Enigmail.msg.attachmentListClick('attachmentList', event);
}, true);
}
}
},
// handle a selected attachment (decrypt & open or save)
handleAttachmentSel: function(actionType) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: handleAttachmentSel: actionType=" + actionType + "\n");
var selectedAttachments;
var anAttachment;
// Thunderbird
var contextMenu = document.getElementById('attachmentItemContext');
if (contextMenu) {
// Thunderbird
selectedAttachments = contextMenu.attachments;
anAttachment = selectedAttachments[0];
}
else {
// SeaMonkey
contextMenu = document.getElementById('attachmentListContext');
selectedAttachments = document.getElementById('attachmentList').selectedItems;
anAttachment = selectedAttachments[0].attachment;
}
switch (actionType) {
case "saveAttachment":
case "openAttachment":
case "importKey":
case "revealName":
this.handleAttachment(actionType, anAttachment);
break;
case "verifySig":
this.verifyDetachedSignature(anAttachment);
break;
}
},
/**
* save the original file plus the signature file to disk and then verify the signature
*/
verifyDetachedSignature: function(anAttachment) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: verifyDetachedSignature: url=" + anAttachment.url + "\n");
var enigmailSvc = Enigmail.getEnigmailSvc();
if (!enigmailSvc) return;
var origAtt, signatureAtt;
if ((this.getAttachmentName(anAttachment).search(/\.sig$/i) > 0) ||
(anAttachment.contentType.search(/^application\/pgp-signature/i) === 0)) {
// we have the .sig file; need to know the original file;
signatureAtt = anAttachment;
var origName = this.getAttachmentName(anAttachment).replace(/\.sig$/i, "");
for (let i = 0; i < currentAttachments.length; i++) {
if (origName == this.getAttachmentName(currentAttachments[i])) {
origAtt = currentAttachments[i];
break;
}
}
}
else {
// we have a supposedly original file; need to know the .sig file;
origAtt = anAttachment;
var sigName = this.getAttachmentName(anAttachment) + ".sig";
for (let i = 0; i < currentAttachments.length; i++) {
if (sigName == this.getAttachmentName(currentAttachments[i])) {
signatureAtt = currentAttachments[i];
break;
}
}
}
if (!signatureAtt) {
EnigmailDialog.alert(window, EnigmailLocale.getString("attachment.noMatchToSignature", [this.getAttachmentName(origAtt)]));
return;
}
if (!origAtt) {
EnigmailDialog.alert(window, EnigmailLocale.getString("attachment.noMatchFromSignature", [this.getAttachmentName(signatureAtt)]));
return;
}
// open
var tmpDir = EnigmailFiles.getTempDir();
var outFile1, outFile2;
outFile1 = Components.classes[LOCAL_FILE_CONTRACTID].
createInstance(Components.interfaces.nsIFile);
outFile1.initWithPath(tmpDir);
if (!(outFile1.isDirectory() && outFile1.isWritable())) {
EnigmailDialog.alert(window, EnigmailLocale.getString("noTempDir"));
return;
}
outFile1.append(this.getAttachmentName(origAtt));
outFile1.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0x180); // equals 0800
this.writeUrlToFile(origAtt.url, outFile1);
outFile2 = Components.classes[LOCAL_FILE_CONTRACTID].
createInstance(Components.interfaces.nsIFile);
outFile2.initWithPath(tmpDir);
outFile2.append(this.getAttachmentName(signatureAtt));
outFile2.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0x180); // equals 0800
this.writeUrlToFile(signatureAtt.url, outFile2);
var statusFlagsObj = {};
var errorMsgObj = {};
var r = enigmailSvc.verifyAttachment(window, outFile1, outFile2, statusFlagsObj, errorMsgObj);
if (r === 0)
EnigmailDialog.info(window, EnigmailLocale.getString("signature.verifiedOK", [this.getAttachmentName(origAtt)]) + "\n\n" + errorMsgObj.value);
else
EnigmailDialog.alert(window, EnigmailLocale.getString("signature.verifyFailed", [this.getAttachmentName(origAtt)]) + "\n\n" +
errorMsgObj.value);
outFile1.remove(false);
outFile2.remove(false);
},
writeUrlToFile: function(srcUrl, outFile) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: writeUrlToFile: outFile=" + outFile.path + "\n");
var ioServ = Components.classes[IOSERVICE_CONTRACTID].
getService(Components.interfaces.nsIIOService);
var msgUri = ioServ.newURI(srcUrl, null, null);
var channel = EnigmailStreams.createChannelFromURI(msgUri);
var istream = channel.open();
var fstream = Components.classes["@mozilla.org/network/safe-file-output-stream;1"]
.createInstance(Components.interfaces.nsIFileOutputStream);
var buffer = Components.classes["@mozilla.org/network/buffered-output-stream;1"]
.createInstance(Components.interfaces.nsIBufferedOutputStream);
fstream.init(outFile, 0x04 | 0x08 | 0x20, 0x180, 0); // write, create, truncate
buffer.init(fstream, 8192);
while (istream.available() > 0) {
buffer.writeFrom(istream, istream.available());
}
// Close the output streams
if (buffer instanceof Components.interfaces.nsISafeOutputStream)
buffer.finish();
else
buffer.close();
if (fstream instanceof Components.interfaces.nsISafeOutputStream)
fstream.finish();
else
fstream.close();
// Close the input stream
istream.close();
},
handleAttachment: function(actionType, anAttachment) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: handleAttachment: actionType=" + actionType + ", anAttachment(url)=" + anAttachment.url + "\n");
var argumentsObj = {
actionType: actionType,
attachment: anAttachment,
forceBrowser: false,
data: ""
};
var f = function _cb(data) {
argumentsObj.data = data;
Enigmail.msg.decryptAttachmentCallback([argumentsObj]);
};
var bufferListener = EnigmailStreams.newStringStreamListener(f);
var ioServ = Components.classes[IOSERVICE_CONTRACTID].getService(Components.interfaces.nsIIOService);
var msgUri = ioServ.newURI(argumentsObj.attachment.url, null, null);
var channel = EnigmailStreams.createChannelFromURI(msgUri);
channel.asyncOpen(bufferListener, msgUri);
},
setAttachmentName: function(attachment, newLabel, index) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: setAttachmentName (" + newLabel + "):\n");
var attList = document.getElementById("attachmentList");
if (attList) {
var attNode = attList.firstChild;
while (attNode) {
// TB <= 9
if (attNode.getAttribute("attachmentUrl") == attachment.url)
attNode.setAttribute("label", newLabel);
// TB >= 10
if (attNode.getAttribute("name") == attachment.name)
attNode.setAttribute("name", newLabel);
attNode = attNode.nextSibling;
}
}
if (typeof(attachment.displayName) == "undefined") {
attachment.name = newLabel;
}
else
attachment.displayName = newLabel;
if (index && index.length > 0) {
this.revealAttachments(parseInt(index, 10) + 1);
}
},
decryptAttachmentCallback: function(cbArray) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: decryptAttachmentCallback:\n");
var callbackArg = cbArray[0];
const nsIEnigmail = Components.interfaces.nsIEnigmail;
var exitCodeObj = {};
var statusFlagsObj = {};
var errorMsgObj = {};
var exitStatus = -1;
var enigmailSvc = Enigmail.getEnigmailSvc();
var outFile;
var origFilename;
var rawFileName = Enigmail.msg.getAttachmentName(callbackArg.attachment).replace(/\.(asc|pgp|gpg)$/i, "");
if (callbackArg.actionType != "importKey") {
origFilename = EnigmailAttachment.getFileName(window, callbackArg.data);
if (origFilename && origFilename.length > rawFileName.length) rawFileName = origFilename;
}
if (callbackArg.actionType == "saveAttachment") {
outFile = EnigmailDialog.filePicker(window, EnigmailLocale.getString("saveAttachmentHeader"),
Enigmail.msg.lastSaveDir, true, "",
rawFileName, null);
if (!outFile) return;
}
else if (callbackArg.actionType.substr(0, 10) == "revealName") {
if (origFilename && origFilename.length > 0) {
Enigmail.msg.setAttachmentName(callbackArg.attachment, origFilename + ".pgp", callbackArg.actionType.substr(11, 10));
}
Enigmail.msg.setAttachmentReveal(null);
return;
}
else {
// open
var tmpDir = EnigmailFiles.getTempDir();
try {
outFile = Components.classes[LOCAL_FILE_CONTRACTID].createInstance(Components.interfaces.nsIFile);
outFile.initWithPath(tmpDir);
if (!(outFile.isDirectory() && outFile.isWritable())) {
errorMsgObj.value = EnigmailLocale.getString("noTempDir");
return;
}
outFile.append(rawFileName);
outFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0x180); // equals 0800
}
catch (ex) {
errorMsgObj.value = EnigmailLocale.getString("noTempDir");
return;
}
}
if (callbackArg.actionType == "importKey") {
var preview = EnigmailKey.getKeyListFromKeyBlock(callbackArg.data, errorMsgObj);
if (errorMsgObj.value === "") {
if (preview.length > 0) {
if (preview.length == 1) {
exitStatus = EnigmailDialog.confirmDlg(window, EnigmailLocale.getString("doImportOne", [preview[0].name, preview[0].id]));
}
else {
exitStatus = EnigmailDialog.confirmDlg(window,
EnigmailLocale.getString("doImportMultiple", [
preview.map(function(a) {
return "\t" + a.name + " (" + a.id + ")";
}).
join("\n")
]));
}
if (exitStatus) {
try {
exitStatus = EnigmailKeyRing.importKey(parent, false, callbackArg.data, "", errorMsgObj);
}
catch (ex) {}
if (exitStatus === 0) {
var keyList = preview.map(function(a) {
return a.id;
});
EnigmailDialog.keyImportDlg(window, keyList);
}
else {
EnigmailDialog.alert(window, EnigmailLocale.getString("failKeyImport") + "\n" + errorMsgObj.value);
}
}
}
else {
EnigmailDialog.alert(window, EnigmailLocale.getString("noKeyFound") + "\n" + errorMsgObj.value);
}
}
else {
EnigmailDialog.alert(window, EnigmailLocale.getString("previewFailed") + "\n" + errorMsgObj.value);
}
return;
}
exitStatus = enigmailSvc.decryptAttachment(window, outFile,
Enigmail.msg.getAttachmentName(callbackArg.attachment),
callbackArg.data,
exitCodeObj, statusFlagsObj,
errorMsgObj);
if ((!exitStatus) || exitCodeObj.value !== 0) {
exitStatus = false;
if ((statusFlagsObj.value & nsIEnigmail.DECRYPTION_OKAY) &&
(statusFlagsObj.value & nsIEnigmail.UNVERIFIED_SIGNATURE)) {
if (callbackArg.actionType == "openAttachment") {
exitStatus = EnigmailDialog.confirmDlg(window, EnigmailLocale.getString("decryptOkNoSig"), EnigmailLocale.getString("msgOvl.button.contAnyway"));
}
else {
EnigmailDialog.info(window, EnigmailLocale.getString("decryptOkNoSig"));
}
}
else {
EnigmailDialog.info(window, EnigmailLocale.getString("failedDecrypt") + "\n\n" + errorMsgObj.value);
exitStatus = false;
}
}
if (exitStatus) {
if (statusFlagsObj.value & nsIEnigmail.IMPORTED_KEY) {
if (exitCodeObj.keyList) {
let importKeyList = exitCodeObj.keyList.map(function(a) {
return a.id;
});
EnigmailDialog.keyImportDlg(window, importKeyList);
}
}
else if (statusFlagsObj.value & nsIEnigmail.DISPLAY_MESSAGE) {
HandleSelectedAttachments('open');
}
else if ((statusFlagsObj.value & nsIEnigmail.DISPLAY_MESSAGE) ||
(callbackArg.actionType == "openAttachment")) {
var ioServ = Components.classes[IOSERVICE_CONTRACTID].getService(Components.interfaces.nsIIOService);
var outFileUri = ioServ.newFileURI(outFile);
var fileExt = outFile.leafName.replace(/(.*\.)(\w+)$/, "$2");
if (fileExt && !callbackArg.forceBrowser) {
var extAppLauncher = Components.classes["@mozilla.org/mime;1"].getService(Components.interfaces.nsPIExternalAppLauncher);
extAppLauncher.deleteTemporaryFileOnExit(outFile);
try {
var mimeService = Components.classes["@mozilla.org/mime;1"].getService(Components.interfaces.nsIMIMEService);
var fileMimeType = mimeService.getTypeFromFile(outFile);
var fileMimeInfo = mimeService.getFromTypeAndExtension(fileMimeType, fileExt);
fileMimeInfo.launchWithFile(outFile);
}
catch (ex) {
// if the attachment file type is unknown, an exception is thrown,
// so let it be handled by a browser window
Enigmail.msg.loadExternalURL(outFileUri.asciiSpec);
}
}
else {
// open the attachment using an external application
Enigmail.msg.loadExternalURL(outFileUri.asciiSpec);
}
}
}
},
loadExternalURL: function(url) {
if (EnigmailApp.isSuite()) {
Enigmail.msg.loadURLInNavigatorWindow(url, true);
}
else {
messenger.launchExternalURL(url);
}
},
// retrieves the most recent navigator window (opens one if need be)
loadURLInNavigatorWindow: function(url, aOpenFlag) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: loadURLInNavigatorWindow: " + url + ", " + aOpenFlag + "\n");
var navWindow;
// if this is a browser window, just use it
if ("document" in top) {
var possibleNavigator = top.document.getElementById("main-window");
if (possibleNavigator &&
possibleNavigator.getAttribute("windowtype") == "navigator:browser")
navWindow = top;
}
// if not, get the most recently used browser window
if (!navWindow) {
var wm;
wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(
Components.interfaces.nsIWindowMediator);
navWindow = wm.getMostRecentWindow("navigator:browser");
}
if (navWindow) {
if ("loadURI" in navWindow)
navWindow.loadURI(url);
else
navWindow._content.location.href = url;
}
else if (aOpenFlag) {
// if no browser window available and it's ok to open a new one, do so
navWindow = window.open(url, "Enigmail");
}
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: loadURLInNavigatorWindow: navWindow=" + navWindow + "\n");
return navWindow;
},
// handle double click events on Attachments
attachmentListClick: function(elementId, event) {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: attachmentListClick: event=" + event + "\n");
var attachment = event.target.attachment;
if (this.checkEncryptedAttach(attachment)) {
if (event.button === 0 && event.detail == 2) { // double click
this.handleAttachment("openAttachment", attachment);
event.stopPropagation();
}
}
},
// create a decrypted copy of all selected messages in a target folder
decryptToFolder: function(destFolder) {
let msgHdrs = gFolderDisplay ? gFolderDisplay.selectedMessages : null;
if (!msgHdrs || msgHdrs.length === 0) return;
EnigmailDecryptPermanently.dispatchMessages(msgHdrs, destFolder.URI, false, false);
},
importAttachedKeys: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: importAttachedKeys\n");
let keyFound = false;
const nsIEnigmail = Components.interfaces.nsIEnigmail;
for (let i in currentAttachments) {
if (currentAttachments[i].contentType.search(/application\/pgp-keys/i) >= 0) {
// found attached key
this.handleAttachment("importKey", currentAttachments[i]);
keyFound = true;
}
}
return keyFound;
},
importKeyFromKeyserver: function() {
var pubKeyId = "0x" + Enigmail.msg.securityInfo.keyId;
var inputObj = {
searchList: [pubKeyId],
autoKeyServer: EnigmailPrefs.getPref("autoKeyServerSelection") ? EnigmailPrefs.getPref("keyserver").split(/[ ,;]/g)[0] : null
};
var resultObj = {};
EnigmailWindows.downloadKeys(window, inputObj, resultObj);
if (resultObj.importedKeys > 0) {
return true;
}
return false;
},
// download or import keys
handleUnknownKey: function() {
const nsIEnigmail = Components.interfaces.nsIEnigmail;
let imported = false;
// handline keys embedded in message body
if (Enigmail.msg.securityInfo.statusFlags & nsIEnigmail.INLINE_KEY) {
return Enigmail.msg.messageDecrypt(true, false);
}
imported = this.importAttachedKeys();
if (!imported) imported = this.importKeyFromKeyserver();
if (imported) this.messageReload(false);
return null;
},
/**
* Create an artificial Autocrypt: header if there was no such header on the message
* and the message was signed
*/
createArtificialAutocryptHeader: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: createArtificialAutocryptHeader\n");
const nsIEnigmail = Components.interfaces.nsIEnigmail;
if (Enigmail.msg.savedHeaders && ("autocrypt" in Enigmail.msg.savedHeaders) && Enigmail.msg.savedHeaders.autocrypt.length > 0) return;
let created = false;
if (Enigmail.msg.securityInfo && Enigmail.msg.securityInfo.statusFlags) {
let securityInfo = Enigmail.msg.securityInfo;
let keyObj = EnigmailKeyRing.getKeyById(securityInfo.keyId);
if (keyObj && keyObj.getEncryptionValidity().keyValid) {
if (securityInfo.statusFlags & nsIEnigmail.GOOD_SIGNATURE) {
let hdrData = "addr=" + EnigmailFuncs.stripEmail(currentHeaderData.from.headerValue) +
((securityInfo.statusFlags & nsIEnigmail.DECRYPTION_OKAY) ||
(securityInfo.statusFlags & nsIEnigmail.PGP_MIME_ENCRYPTED) ? "; prefer-encrypt=mutual" : "") +
"; _enigmail_artificial=yes; _enigmail_fpr=" + keyObj.fpr + '; keydata="LQ=="';
created = true;
EnigmailAutocrypt.processAutocryptHeader(currentHeaderData.from.headerValue, [hdrData],
currentHeaderData.date.headerValue);
}
}
}
if (!created) {
let hdrData = "addr=" + EnigmailFuncs.stripEmail(currentHeaderData.from.headerValue) +
'; prefer-encrypt=reset; _enigmail_artificial=yes; keydata="LQ=="';
EnigmailAutocrypt.processAutocryptHeader(currentHeaderData.from.headerValue, [hdrData],
currentHeaderData.date.headerValue);
}
},
confirmWksRequest: function() {
EnigmailLog.DEBUG("enigmailMessengerOverlay.js: confirmWksRequest\n");
try {
var msg = gFolderDisplay.selectedMessage;
if (!(!msg || !msg.folder)) {
var accMgr = Components.classes["@mozilla.org/messenger/account-manager;1"].
getService(Components.interfaces.nsIMsgAccountManager);
var msgHdr = msg.folder.GetMessageHeader(msg.messageKey);
let email = EnigmailFuncs.stripEmail(msgHdr.recipients);
let maybeIdent = EnigmailStdlib.getIdentityForEmail(email);
if (maybeIdent && maybeIdent.identity) {
EnigmailStdlib.msgHdrsModifyRaw([msgHdr], function(data) {
EnigmailWks.confirmKey(maybeIdent.identity, data, window, function(ret) {
if (ret) {
EnigmailDialog.info(window, EnigmailLocale.getString("wksConfirmSuccess"));
}
else {
EnigmailDialog.alert(window, EnigmailLocale.getString("wksConfirmFailure"));
}
});
return null;
});
}
else {
EnigmailDialog.alert(window, EnigmailLocale.getString("wksNoIdentity", [email]));
}
}
}
catch (e) {
EnigmailLog.DEBUG(e + "\n");
}
}
};
window.addEventListener("load", Enigmail.msg.messengerStartup.bind(Enigmail.msg), false);
window.addEventListener("unload", Enigmail.msg.messengerClose.bind(Enigmail.msg), false);

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 18, 10:44 PM (5 h, 39 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
f6/7c/a49b3a7e03215e9fa7b1996dce80

Event Timeline