Commit 340aa45d authored by Patrick Brunschwig's avatar Patrick Brunschwig

extended hack for buggy messages to include fix for iPGMail

parent 7e0a5f32
......@@ -74,6 +74,8 @@ const nsIEnigmail = Components.interfaces.nsIEnigmail;
* 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
......@@ -81,7 +83,7 @@ const nsIEnigmail = Components.interfaces.nsIEnigmail;
// TODO: change to creating new object
EnigmailFixExchangeMsg = {
fixExchangeMessage: function (hdr, destFolderUri) {
fixExchangeMessage: function (hdr, brokenByApp, destFolderUri) {
var self = this;
return new Promise(
function fixExchangeMessage_p(resolve, reject) {
......@@ -93,6 +95,7 @@ EnigmailFixExchangeMsg = {
self.destFolder = hdr.folder;
self.resolve = resolve;
self.reject = reject;
self.brokenByApp = brokenByApp;
if (destFolderUri) {
self.destFolder = MailUtils.getFolderForURI(destFolderUri, false)
......@@ -112,6 +115,7 @@ EnigmailFixExchangeMsg = {
function rejected(reason) {
EC.DEBUG_LOG("fixExchangeMsg.jsm: fixExchangeMessage: caught rejection: " + reason + "\n");
reject();
return;
});
}
);
......@@ -145,6 +149,7 @@ EnigmailFixExchangeMsg = {
if (hdrEnd <= 0) {
// cannot find end of header data
reject(0);
return;
}
let hdrLines = data.substr(0, hdrEnd).split(/\r?\n/);
......@@ -152,16 +157,32 @@ EnigmailFixExchangeMsg = {
if (hdrObj.headers.length == 0 || hdrObj.boundary.length == 0) {
reject(1);
return;
}
let boundary = hdrObj.boundary.replace(/^(['"])(.*)(['"])/, "$2");
let body = self.getCorrectedBodyData(data.substr(hdrEnd+2), boundary);
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:
EC.ERROR_LOG("fixExchangeMsg.jsm: getMessageBody: unknown appType " + self.brokenByApp +"\n");
reject(99);
return;
}
if (body) {
resolve(hdrObj.headers + "\r\n" + body);
return;
}
else {
reject(2);
return;
}
}
);
......@@ -172,7 +193,7 @@ EnigmailFixExchangeMsg = {
channel.asyncOpen(s, null);
}
catch(e) {
EC.DEBUG_LOG("fixExchangeMsg.jsm: getMessageBody: exception " + e +"\n")
EC.DEBUG_LOG("fixExchangeMsg.jsm: getMessageBody: exception " + e +"\n");
}
}
);
......@@ -219,22 +240,27 @@ EnigmailFixExchangeMsg = {
}
}
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 MS-Exchange PGP/MIME message\r\n';
' boundary="' + r.boundary + '"\r\n' +
'X-Enigmail-Info: Fixed broken PGP/MIME message\r\n';
return r;
},
getCorrectedBodyData: function(bodyData, boundary) {
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedBodyData: boundary='"+ boundary +"'\n");
/**
* Get corrected body for MS-Exchange messages
*/
getCorrectedExchangeBodyData: function(bodyData, boundary) {
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: boundary='"+ boundary +"'\n");
let boundRx = RegExp("^--" + boundary, "ym");
let match = boundRx.exec(bodyData);
if (match.index < 0) {
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedBodyData: did not find index of mime type to skip\n");
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: did not find index of mime type to skip\n");
return null;
}
......@@ -242,20 +268,20 @@ EnigmailFixExchangeMsg = {
// found first instance -- that's the message part to ignore
match = boundRx.exec(bodyData);
if (match.index <= 0) {
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedBodyData: did not find boundary of PGP/MIME version identification\n");
EC.DEBUG_LOG("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) {
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedBodyData: first MIME part is not content-type text/plain\n");
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: first MIME part is not content-type text/plain\n");
return null;
}
match = boundRx.exec(bodyData);
if (match.index < 0) {
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedBodyData: did not find boundary of PGP/MIME encrypted data\n");
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: did not find boundary of PGP/MIME encrypted data\n");
return null;
}
......@@ -265,7 +291,7 @@ EnigmailFixExchangeMsg = {
let ct = mimeHdr.extractHeader("content-type", false);
if (!ct || ct.search(/application\/pgp-encrypted/i) < 0) {
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedBodyData: wrong content-type of version-identification\n");
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: wrong content-type of version-identification\n");
EC.DEBUG_LOG(" ct = '"+ct+"'\n");
return null;
}
......@@ -273,7 +299,7 @@ EnigmailFixExchangeMsg = {
mimeHdr.initialize(bodyData.substr(encData, 500));
ct = mimeHdr.extractHeader("content-type", false);
if (!ct || ct.search(/application\/octet-stream/i) < 0) {
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedBodyData: wrong content-type of PGP/MIME data\n");
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectedExchangeBodyData: wrong content-type of PGP/MIME data\n");
EC.DEBUG_LOG(" ct = '"+ct+"'\n");
return null;
}
......@@ -281,6 +307,56 @@ EnigmailFixExchangeMsg = {
return bodyData.substr(versionIdent);
},
/**
* Get corrected body for iPGMail messages
*/
getCorrectediPGMailBodyData: function(bodyData, boundary) {
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectediPGMailBodyData: boundary='"+ boundary +"'\n");
let boundRx = RegExp("^--" + boundary, "ym");
let match = boundRx.exec(bodyData);
if (match.index < 0) {
EC.DEBUG_LOG("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) {
EC.DEBUG_LOG("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) {
EC.DEBUG_LOG("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, 500));
ct = mimeHdr.extractHeader("content-type", false);
if (!ct || ct.search(/application\/pgp-encrypted/i) < 0) {
EC.DEBUG_LOG("fixExchangeMsg.jsm: getCorrectediPGMailBodyData: wrong content-type of PGP/MIME data\n");
EC.DEBUG_LOG(" 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);
......@@ -337,6 +413,7 @@ EnigmailFixExchangeMsg = {
tempFile.remove(false);
self.resolve(this.msgKey);
return;
}
};
......
......@@ -71,6 +71,7 @@ Enigmail.msg = {
headersList: ["content-type", "content-transfer-encoding",
"x-enigmail-version", "x-pgp-encoding-format" ],
buggyExchangeEmailContent: null, // for HACK for MS-EXCHANGE-Server Problem
buggyMailType: null,
messengerStartup: function ()
{
......@@ -640,17 +641,29 @@ Enigmail.msg = {
// - 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].size == 0 &&
mimeMsg.parts[0].parts[0].size < 5 &&
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[1].headers["content-type"][0].indexOf("application/pgp-encrypted") >= 0 &&
mimeMsg.parts[0].parts[1].headers["content-type"][0].search(/multipart\/encrypted/i) < 0 &&
mimeMsg.parts[0].parts[1].headers["content-type"][0].search(/PGPMIME 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) {
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(/PGPMIME 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
EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay: messageDecryptCb: enabling MS-Exchange hack\n");
this.buggyExchangeEmailContent = "???";
......@@ -1296,7 +1309,7 @@ Enigmail.msg = {
let msg = gFolderDisplay.messageDisplay.displayedMessage;
let p = EnigmailFixExchangeMsg.fixExchangeMessage(msg);
let p = EnigmailFixExchangeMsg.fixExchangeMessage(msg, this.buggyMailType);
p.then(
function _success(msgKey) {
// display message with given msgKey
......@@ -1334,12 +1347,26 @@ Enigmail.msg = {
hdrs.initialize(this.buggyExchangeEmailContent);
let ct = hdrs.extractHeader("content-type", true);
if (ct.search(/^text\/plain/i) == 0) {
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 = 'Content-Type: multipart/encrypted; protocol="application/pgp-encrypted"; boundary="'+ boundary + '"\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;
......@@ -1367,6 +1394,10 @@ Enigmail.msg = {
return true;
}
else {
EnigmailCommon.alert(window, "PGPMail");
}
return false;
},
......@@ -1871,7 +1902,7 @@ Enigmail.msg = {
// - now let's save the mail content for later processing
if (this.buggyExchangeEmailContent == "???") {
EnigmailCommon.DEBUG_LOG("enigmailMessengerOverlay: verifyEmbeddedCallback: got broken MS-Exchange mime message\n");
this.buggyExchangeEmailContent = callbackArg.data;
this.buggyExchangeEmailContent = callbackArg.data.replace(/^(\r?\n)*/, "");
if (this.displayBuggyExchangeMail()) {
return;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment