Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F35134576
enigmailMessengerOverlay.js
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
90 KB
Subscribers
None
enigmailMessengerOverlay.js
View Options
/*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
].
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
,
"&"
);
if
(
text
.
indexOf
(
"<"
)
>
-
1
)
text
=
text
.
replace
(
/</g
,
"<"
);
if
(
text
.
indexOf
(
">"
)
>
-
1
)
text
=
text
.
replace
(
/>/g
,
">"
);
if
(
text
.
indexOf
(
"\""
)
>
-
1
)
text
=
text
.
replace
(
/"/g
,
"""
);
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
(
/([),.']|>|")$/
,
""
);
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
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 1, 7:51 PM (21 h, 33 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
e5/8c/c97db3c4185224ad07d30f9ca059
Attached To
rENIG Enigmail
Event Timeline
Log In to Comment