diff --git a/package/chrome.manifest b/package/chrome.manifest index f8424b11..73b51c7a 100755 --- a/package/chrome.manifest +++ b/package/chrome.manifest @@ -1,91 +1,94 @@ content enigmail jar:chrome/enigmail.jar!/content/enigmail/ locale enigmail en-US jar:chrome/enigmail.jar!/locale/en-US/ # Skin for TBird Mac OS X skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/tb-mac/enigmail/ application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} os=Darwin # Skin for TBird Windows skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/tb-win-xp/enigmail/ application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} os=WINNT osversion<6 skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/aero/enigmail/ application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} os=WINNT osversion>=6 skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/tb-win-xp/enigmail/ application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} os=OS2 # Skin for TBird other OS (e.g. Linux) skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/tb-linux/enigmail/ application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} os=Linux skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/tb-linux/enigmail/ application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} os=SunOS skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/tb-linux/enigmail/ application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} os=FreeBSD skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/tb-linux/enigmail/ application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} os=OpenBSD skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/tb-linux/enigmail/ application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} os=NetBSD skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/tb-linux/enigmail/ application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} os=AIX skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/tb-linux/enigmail/ application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} os=HP-UX skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/tb-linux/enigmail/ application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} os=DragonFly # Skin for SeaMonkey skin enigmail classic/1.0 jar:chrome/enigmail.jar!/skin/classic-seamonkey/enigmail/ application={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} skin enigmail modern/1.0 jar:chrome/enigmail.jar!/skin/modern/enigmail/ overlay chrome://messenger/content/messengercompose/messengercompose.xul chrome://enigmail/content/enigmailCheckLanguage.xul overlay chrome://messenger/content/messengercompose/messengercompose.xul chrome://enigmail/content/enigmailMsgComposeOverlay.xul overlay chrome://messenger/content/mailWindowOverlay.xul chrome://enigmail/content/enigmailCheckLanguage.xul overlay chrome://messenger/content/messenger.xul chrome://enigmail/content/columnOverlay.xul overlay chrome://messenger/content/csMailWindowOverlay.xul chrome://enigmail/content/enigmailCheckLanguage.xul # Overlay for mailWindowOverlay on Spicebird overlay chrome://messenger/content/csMailWindowOverlay.xul chrome://enigmail/content/messengerOverlay-tbird.xul # Overlay for mailWindowOverlay on Thunderbird overlay chrome://messenger/content/mailWindowOverlay.xul chrome://enigmail/content/messengerOverlay-tbird.xul application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} overlay chrome://enigmail/content/messengerOverlay-tbird.xul chrome://enigmail/content/enigmailMessengerOverlay.xul application!={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} # Overlay for mailWindowOverlay on SeaMonkey overlay chrome://messenger/content/mailWindowOverlay.xul chrome://enigmail/content/messengerOverlay-sm.xul application={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} overlay chrome://enigmail/content/messengerOverlay-sm.xul chrome://enigmail/content/enigmailMessengerOverlay.xul application={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} overlay chrome://messenger/content/msgHdrViewOverlay.xul chrome://enigmail/content/enigmailMsgHdrViewOverlay.xul overlay chrome://messenger/content/FilterEditor.xul chrome://enigmail/content/enigmailFilterEditorOverlay.xul overlay chrome://messenger/content/FilterListDialog.xul chrome://enigmail/content/enigmailFilterListOverlay.xul overlay chrome://messenger/content/msgPrintEngine.xul chrome://enigmail/content/enigmailMsgPrintOverlay.xul overlay chrome://messenger/content/am-identity-edit.xul chrome://enigmail/content/enigmailAmIdEditOverlay.xul overlay chrome://messenger/content/am-identity-edit.xul chrome://enigmail/content/enigmailEditIdentity.xul overlay chrome://messenger/content/addressbook/addressbook.xul chrome://enigmail/content/enigmailAbCardViewOverlay.xul overlay chrome://messenger/content/addressbook/csContactsOverlay.xul chrome://enigmail/content/enigmailAbCardViewOverlay.xul overlay chrome://messenger/content/addressbook/abContactsPanel.xul chrome://enigmail/content/enigmailAbContactsPanel.xul overlay chrome://global/content/customizeToolbar.xul chrome://enigmail/content/enigmailCustToolOverlay.xul overlay chrome://enigmail/content/am-enigprefs.xul chrome://enigmail/content/enigmailEditIdentity.xul overlay chrome://enigmail/content/am-enigprefs-edit.xul chrome://enigmail/content/enigmailEditIdentity.xul # Overlay for privacy preferences in Thunderbird overlay chrome://messenger/content/preferences/privacy.xul chrome://enigmail/content/enigmailPrivacyOverlay.xul +# Overlay for S/Mime preferences +overlay chrome://messenger/content/am-smime.xul chrome://enigmail/content/enigmail-am-smime.xul + # Resource module registration resource enigmail modules/ ## Gecko 2.0 JavaScript component registration # Enigmail component {847b3a01-7ab1-11d4-8f02-006008948af5} components/enigmail.js contract @mozdev.org/enigmail/enigmail;1 {847b3a01-7ab1-11d4-8f02-006008948af5} # EnigmailProtocolHandler component {847b3a11-7ab1-11d4-8f02-006008948af5} components/enigmail.js contract @mozilla.org/network/protocol;1?name=enigmail {847b3a11-7ab1-11d4-8f02-006008948af5} # Command line service component {847b3ab1-7ab1-11d4-8f02-006008948af5} components/enigmail.js contract @mozilla.org/enigmail/cline-handler;1 {847b3ab1-7ab1-11d4-8f02-006008948af5} category command-line-handler cline-enigmail @mozilla.org/enigmail/cline-handler;1 # EnigMsgCompFields component {847b3a30-7ab1-11d4-8f02-006008948af5} components/msgCompFields.js contract @mozdev.org/enigmail/composefields;1 {847b3a30-7ab1-11d4-8f02-006008948af5} # registration of service to decrypt PGP/MIME messages component {7514cbeb-2bfd-4b2c-829b-1a4691fa0ac8} components/pgpmimeHandler.js contract @mozilla.org/mime/pgp-mime-js-decrypt;1 {7514cbeb-2bfd-4b2c-829b-1a4691fa0ac8} # registration of service to create PGP/MIME enrypted messages component {1b040e64-e704-42b9-b05a-942e569afffc} components/mimeEncrypt.js contract @mozilla.org/messengercompose/composesecure;1 {1b040e64-e704-42b9-b05a-942e569afffc} # Preference Service component {847b3ab0-7ab1-11d4-8f02-006008948af5} components/prefs-service.js contract @mozilla.org/accountmanager/extension;1?name=enigprefs {847b3ab0-7ab1-11d4-8f02-006008948af5} category mailnews-accountmanager-extensions enigmail-account-manager-extension @mozilla.org/accountmanager/extension;1?name=enigprefs ## interface specifiacations interfaces components/enigmail.xpt diff --git a/package/pEpAdapter.jsm b/package/pEpAdapter.jsm index e3f0a15a..18598b38 100644 --- a/package/pEpAdapter.jsm +++ b/package/pEpAdapter.jsm @@ -1,942 +1,977 @@ /*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"; /** * Module for interfacing to pEp (Enigmail-specific functions) */ const Cu = Components.utils; const Cc = Components.classes; const Ci = Components.interfaces; Cu.import("resource://enigmail/core.jsm"); /*global EnigmailCore: false */ Cu.import("resource://enigmail/pEp.jsm"); /*global EnigmailpEp: false */ Cu.import("resource://enigmail/pEpListener.jsm"); /*global EnigmailpEpListener: false */ Cu.import("resource://enigmail/prefs.jsm"); /*global EnigmailPrefs: false */ Cu.import("resource://enigmail/log.jsm"); /*global EnigmailLog: false */ Cu.import("resource://enigmail/mime.jsm"); /*global EnigmailMime: false */ Cu.import("resource://gre/modules/PromiseUtils.jsm"); /* global PromiseUtils: false */ Cu.import("resource://enigmail/rng.jsm"); /*global EnigmailRNG: false */ Cu.import("resource://enigmail/lazy.jsm"); /*global EnigmailLazy: false */ Cu.import("resource://enigmail/streams.jsm"); /*global EnigmailStreams: false */ Cu.import("resource://enigmail/pEpMessageHist.jsm"); /*global EnigmailPEPMessageHist: false */ Cu.import("resource://enigmail/addrbook.jsm"); /*global EnigmailAddrbook: false */ Cu.import("resource://enigmail/locale.jsm"); /*global EnigmailLocale: false */ Cu.import("resource://enigmail/funcs.jsm"); /*global EnigmailFuncs: false */ Cu.import("resource://enigmail/pEpFilter.jsm"); /*global EnigmailPEPFilter: false */ Cu.import("resource://enigmail/subprocess.jsm"); /*global subprocess: false */ Cu.import("resource://enigmail/installPep.jsm"); /*global EnigmailInstallPep: false */ Cu.import("resource://gre/modules/jsmime.jsm"); /*global jsmime: false*/ Cu.import("resource://enigmail/pEpKeySync.jsm"); /*global EnigmailPEPKeySync: false */ Cu.import("resource://enigmail/timer.jsm"); /*global EnigmailTimer: false */ Cu.import("resource://enigmail/filters.jsm"); /*global EnigmailFilters: false */ const getFiles = EnigmailLazy.loader("enigmail/files.jsm", "EnigmailFiles"); // pEp JSON Server executable name const PEP_SERVER_EXECUTABLE = "pep-json-server"; var gPepVersion = null; var gSecurityToken = null; var gPepAvailable = null; var gPepListenerPort = -1; var gOwnIdentities = []; +var gJmObservers = null; +var gJmObserverId = 0; var EXPORTED_SYMBOLS = ["EnigmailPEPAdapter"]; function pepCallback(dataObj) { EnigmailLog.DEBUG("pEpAdapter.jsm: pepCallback()\n"); if ("method" in dataObj) { switch (dataObj.method) { case "messageToSend": EnigmailLog.DEBUG("pEpAdapter.jsm: pepCallback: messageToSend\n"); EnigmailPEPKeySync.sendMessage(dataObj.params[0]); return 0; case "notifyHandshake": EnigmailLog.DEBUG("pEpAdapter.jsm: pepCallback: notifyHandshake\n"); EnigmailPEPKeySync.notifyHandshake(dataObj.params); return 0; } } return 1; } function startListener() { EnigmailLog.DEBUG("pEpAdapter.jsm: startListener():\n"); gSecurityToken = EnigmailRNG.generateRandomString(40); gPepListenerPort = EnigmailpEpListener.createListener(pepCallback, gSecurityToken); if (gPepListenerPort < 0) { EnigmailLog.DEBUG("pEpAdapter.jsm: startListener: could not open socket\n"); return; } EnigmailpEp.registerTbListener(gPepListenerPort, gSecurityToken).then(function _ok(data) { EnigmailLog.DEBUG("pEpAdapter.jsm: startListener: registration with pEp OK\n"); }).catch(function _fail(data) { EnigmailLog.DEBUG("pEpAdapter.jsm: startListener: registration with pEp failed\n"); }); } var EnigmailPEPAdapter = { pep: EnigmailpEp, filter: EnigmailPEPFilter, /** * Get the pEp JSON server version number. * * @return String: * - null if the module is not initialized * - a non-empty string if pEp is available * - "" in case pEp is not available */ getPepVersion: function() { return gPepVersion; }, /** * Determine if pEp is available * * @return: Boolean: true - pEp is available / false - pEp is not usable */ usingPep: function() { if (!this.getPepJuniorMode()) return false; if ((typeof(gPepVersion) === "string") && gPepVersion.length > 0) { return true; } return false; }, /** * Determine if the pEp JSON adapter is available at all * * @param attemptInstall: Boolean - try to install pEp if possible * * @return Boolean - true if pEp is available / false otherwise */ isPepAvailable: function(attemptInstall = true) { EnigmailLog.DEBUG("pEpAdapter.jsm: isPepAvailable()\n"); if (gPepAvailable === null) { gPepAvailable = false; let execFile = getFiles().resolvePathWithEnv(PEP_SERVER_EXECUTABLE); if (execFile && execFile.exists() && execFile.isExecutable()) { EnigmailCore.getService(null, true); let pepVersionStr = ""; let process = subprocess.call({ command: execFile, arguments: ["--version"], charset: null, environment: EnigmailCore.getEnvList(), mergeStderr: false, stdin: function(stdin) { // do nothing }, stdout: function(data) { pepVersionStr += data; }, stderr: function(data) { // do nothing } }); process.wait(); EnigmailLog.DEBUG("pEpAdapter.jsm: isPepAvailable: got version '" + pepVersionStr + "'\n"); if (pepVersionStr.search(/pEp JSON/i) >= 0) { gPepAvailable = true; } } else if (attemptInstall) { this.installPep(); } } return gPepAvailable; }, /** * try to download and install pEp (runs asynchronously!) */ installPep: function() { EnigmailLog.DEBUG("pEpAdapter.jsm: installPep()\n"); + + let self = this; let progressListener = { onError: function(err) { EnigmailLog.DEBUG("pEpAdapter.jsm: installPep: got error " + err.type + "\n"); }, onInstalled: function() { EnigmailLog.DEBUG("pEpAdapter.jsm: installPep: installation completed\n"); gPepAvailable = null; + + self.initialize(); } }; EnigmailInstallPep.startInstaller(progressListener); }, /** * Determine if pEp should be used or Enigmail * * @return: Boolean: true - use pEp / false - use Enigmail */ getPepJuniorMode: function() { let mode = EnigmailPrefs.getPref("juniorMode"); if (mode === 0) return false; // manual pEp or automatic mode if (mode === 2 || (!this.isAccountCryptEnabled())) { return this.isPepAvailable(true); } return false; }, /** * Determine if any account is enabled for crypto (S/MIME or Enigmail) * * @return: Boolean: true if at least one account is enabled for S/MIME or Enigmail, * false otherwise */ isAccountCryptEnabled: function() { // automatic mode: go through all identities let amService = Components.classes["@mozilla.org/messenger/account-manager;1"].getService(Ci.nsIMsgAccountManager); amService.LoadAccounts(); let ids = amService.allIdentities; for (let i = 0; i < ids.length; i++) { let msgId = ids.queryElementAt(i, Ci.nsIMsgIdentity); if ((msgId.getUnicharAttribute("signing_cert_name") !== "") || (msgId.getUnicharAttribute("encryption_cert_name") !== "") || msgId.getBoolAttribute("enablePgp")) { return true; } } return false; }, /** * Thunderbird shutdown callback (called from enigmail.js) */ onShutdown: function() { EnigmailLog.DEBUG("pEpAdapter.jsm: onShutdown()\n"); if (gPepListenerPort > 0) { let inspector = Cc["@mozilla.org/jsinspector;1"].createInstance(Ci.nsIJSInspector); EnigmailTimer.setTimeout(function _f() { // wait at most 1 second to continue shutdown if (gPepListenerPort > 0) { inspector.exitNestedEventLoop(); } }, 1000); EnigmailpEp.unregisterListener().then(function _ok(data) { EnigmailLog.DEBUG("pEpAdapter.jsm: onShutdown: de-registring from pEp OK\n"); gPepListenerPort = -1; inspector.exitNestedEventLoop(); }).catch(function _fail(data) { EnigmailLog.DEBUG("pEpAdapter.jsm: onShutdown: de-registring from pEp failed\n"); gPepListenerPort = -1; inspector.exitNestedEventLoop(); }); // onShutdown should be synchronus in order for Thunderbird to wait // with shutting down until we're completed inspector.enterNestedEventLoop(0); EnigmailpEp.registerLogHandler(null); } }, /** * Initialize the pEpAdapter (should be called during startup of application) * * no input and no retrun values */ initialize: function() { EnigmailLog.DEBUG("pEpAdapter.jsm: initialize:\n"); - let self = this; + + if (gJmObservers === null) { + gJmObservers = {}; + EnigmailPrefs.registerPrefObserver("juniorMode", self.handleJuniorModeChange); + } + + EnigmailpEp.registerLogHandler(EnigmailLog.DEBUG); + let pEpMode = EnigmailPrefs.getPref("juniorMode"); // force using Enigmail (do not use pEp) if (pEpMode === 0) return; - EnigmailpEp.registerLogHandler(EnigmailLog.DEBUG); - // automatic mode, with Crypto enabled (do not use pEp) if (this.isAccountCryptEnabled() && pEpMode !== 2) return; let execFile = getFiles().resolvePathWithEnv(PEP_SERVER_EXECUTABLE); if (execFile) EnigmailpEp.setServerPath(execFile.path); try { EnigmailpEp.getPepVersion().then(function _success(data) { EnigmailLog.DEBUG("pEpAdapter.jsm: initialize: success '" + JSON.stringify(data) + "'\n"); if (typeof(data) === "string") { gPepVersion = data; startListener(); self.setupIncomingFilter(); + self.handleJuniorModeChange(); } return EnigmailpEp.getGpgEnv(); }). then(function _gotGpgEnv(gpgEnv) { EnigmailLog.DEBUG("pEpAdapter.jsm: initialize: got GnuPG env '" + JSON.stringify(gpgEnv) + "'\n"); let envStr = ""; if (gpgEnv && typeof gpgEnv === "object" && "gnupg_path" in gpgEnv) { EnigmailLog.DEBUG("pEpAdapter.jsm: initialize: got GnuPG path '" + gpgEnv.gnupg_path + "'\n"); if (typeof(gpgEnv.gpg_agent_info) === "string" && gpgEnv.gpg_agent_info.length > 0) { envStr += "GPG_AGENT_INFO=" + gpgEnv.gpg_agent_info + "\n"; } if (typeof(gpgEnv.gnupg_home) === "string" && gpgEnv.gnupg_home.length > 0) { envStr += "GNUPGHOME=" + gpgEnv.gnupg_home + "\n"; } let enigmailSvc = Cc["@mozdev.org/enigmail/enigmail;1"].getService(Ci.nsIEnigmail); enigmailSvc.perferGpgPath(gpgEnv.gnupg_path); enigmailSvc.overwriteEnvVar(envStr); if (enigmailSvc.initialized) { enigmailSvc.reinitialize(); } else { enigmailSvc.initialize(null, false); } } self.setOwnIdentities(0); }). catch(function failed(err) { EnigmailLog.DEBUG("pEpAdapter.jsm: initialize: error during pEp init:\n"); EnigmailLog.DEBUG(" " + err.code + ": " + ("exception" in err && err.exception ? err.exception.toString() : err.message) + "\n"); gPepVersion = ""; }); } catch (ex) {} }, setOwnIdentities: function(accountNum) { let self = this; let accountManager = Cc["@mozilla.org/messenger/account-manager;1"].getService(Ci.nsIMsgAccountManager); let id; // pEp currently only supports 1 identity per account, we therefore only set the 1st id of each accunt if (accountManager.accounts.length > accountNum) { let ac = accountManager.accounts.queryElementAt(accountNum, Ci.nsIMsgAccount); try { id = ac.identities.queryElementAt(0, Ci.nsIMsgIdentity); } catch (ex) { id = null; } if (!id) { self.setOwnIdentities(accountNum + 1); return; } let pepId = { address: id.email.toLowerCase(), user_id: "", username: id.fullName }; EnigmailLog.DEBUG("pEpAdapter.jsm: setOwnIdentities: " + id.identityName + "\n"); self.pep.setMyself(pepId).then( function _ok(data) { if (data) { self.processOwnIdentity(data); } self.setOwnIdentities(accountNum + 1); }).catch( function _err(data) { EnigmailLog.DEBUG("pEpAdapter.jsm: setOwnIdentities: ERROR: '" + JSON.stringify(data) + "'\n"); }); } else { EnigmailLog.DEBUG("pEpAdapter.jsm: setOwnIdentities: done.\n"); } }, processOwnIdentity: function(identityData) { EnigmailLog.DEBUG("pEpAdapter.jsm: processOwnIdentity()\n"); if ("result" in identityData) { let id = identityData.result.outParams[0]; gOwnIdentities[id.address.toLowerCase()] = id; } }, /** * get the pEp Identity of own emails (i.e. for those what we should have a secret key) * for a given email address. * * @param emailAddress: String - my own email address * * @return Object: pEp Identity or null (if not found) */ getOwnIdentityForEmail: function(emailAddress) { emailAddress = emailAddress.toLowerCase(); if (emailAddress in gOwnIdentities) { return gOwnIdentities[emailAddress]; } return null; }, /** * Get a MIME tree as String from the pEp-internal message object * * @param resObj: Object - result object from encryption * * @return String - a MIME string, or "" if no message extracted */ stripMsgHeadersFromEncryption: function(resObj) { let mimeStr = ""; if (Array.isArray(resObj) && typeof(resObj[0]) === "string") { mimeStr = resObj[0]; } let startPos = mimeStr.search(/\r?\n\r?\n/); if (startPos < 0) return ""; let headers = Cc["@mozilla.org/messenger/mimeheaders;1"].createInstance(Ci.nsIMimeHeaders); headers.initialize(mimeStr.substring(0, startPos)); let n = headers.headerNames; let printHdr = ""; while (n.hasMore()) { let hdr = n.getNext(); if (hdr.search(/^(from|to|mime-version)$/i) < 0) { printHdr += hdr + ": " + EnigmailMime.formatHeaderData(headers.extractHeader(hdr, true)) + "\r\n"; } } return printHdr + "\r\n" + mimeStr.substr(startPos); }, /** * Get the encryption quality rating for a list of recipients * * @param sender: - Object msgIAddressObject message sender * @param recipients: - Array of Object msgIAddressObject message recipients * * @return Number: quality of encryption (-3 ... 9) */ getOutgoingMessageRating: function(sender, recipients) { let resultObj = null; let inspector = Cc["@mozilla.org/jsinspector;1"].createInstance(Ci.nsIJSInspector); let from = this.emailToPepPerson(sender); let to = []; if (recipients.length === 0) { return 0; } for (let i of recipients) { to.push(EnigmailPEPAdapter.emailToPepPerson(i)); } EnigmailPEPAdapter.pep.outgoingMessageRating(from, to, "test").then(function _step2(res) { EnigmailLog.DEBUG("pEpAdapter.jsm: outgoingMessageRating: SUCCESS\n"); if ((typeof(res) === "object") && ("result" in res)) { resultObj = res.result.outParams; } else EnigmailLog.DEBUG("pEpAdapter.jsm: outgoingMessageRating: typeof res=" + typeof(res) + "\n"); if (inspector && inspector.eventLoopNestLevel > 0) { // unblock the waiting lock in finishCryptoEncapsulation inspector.exitNestedEventLoop(); } }).catch(function _error(err) { EnigmailLog.DEBUG("pEpAdapter.jsm: outgoingMessageRating: ERROR\n"); EnigmailLog.DEBUG(err.code + ": " + ("exception" in err ? err.exception.toString() : err.message) + "\n"); if (inspector && inspector.eventLoopNestLevel > 0) { // unblock the waiting lock in finishCryptoEncapsulation inspector.exitNestedEventLoop(); } }); // wait here for PEP to terminate inspector.enterNestedEventLoop(0); if (resultObj && Array.isArray(resultObj) && "rating" in resultObj[0]) { return resultObj[0].rating; } return 3; // unencrypted }, /** * Obtain a list of supported languages for trustwords * * @return Promise, delivering Array of Object: * - short: 2-Letter ISO-Codes * - long: Language name in the language * - desc: Describing sentence in the language */ getSupportedLanguages: function() { let deferred = PromiseUtils.defer(); EnigmailpEp.getLanguageList().then(function _success(res) { let outArr = EnigmailpEp.processLanguageList(res); deferred.resolve(outArr); }).catch(function _err(err) { deferred.resolve([]); }); return deferred.promise; }, getIdentityForEmail: function(emailAddress) { let deferred = PromiseUtils.defer(); EnigmailpEp.getIdentity(emailAddress, "TOFU_" + emailAddress).then(function _ok(data) { if (("result" in data) && typeof data.result === "object" && typeof data.result.outParams[0] === "object") { if ("username" in data.result.outParams[0] && data.result.outParams[0].username) { let u = jsmime.headerparser.parseAddressingHeader(data.result.outParams[0].username, true); if (Array.isArray(u) && u.length > 0) { data.result.outParams[0].username = u[0].name; } } } deferred.resolve(data); }).catch(function _err(data) { deferred.reject(data); }); return deferred.promise; }, /** * Convert an msgIAddressObject object into a pEpPerson object * If no name given, the name is looked up in the address book * * @param emailObj - Object msgIAddressObject * * @return pEpPerson object */ emailToPepPerson: function(emailObj) { let p = { user_id: "", username: "unknown", address: "" }; if (!emailObj) return p; if ("email" in emailObj) { p.address = emailObj.email; } if ("name" in emailObj && emailObj.name.length > 0) { p.username = emailObj.name; } else { let addr = EnigmailAddrbook.lookupEmailAddress(p.address); if (addr) { if (addr.card.displayName.length > 0) { p.username = addr.card.displayName; } else { p.username = (addr.card.firstName + " " + addr.card.lastName).trim(); } } } if (p.username.length === 0 || p.username === "unknown") { p.username = p.address.replace(/@.*$/, ""); } return p; }, /** * Update the last sent date for PGP/MIME messages. We only do this such that * we don't unnecessarily process earlier inline-PGP messages */ processPGPMIME: function(headerData) { EnigmailLog.DEBUG("pEpAdapter.jsm: processPGPMIME\n"); if (!(("from" in headerData) && ("date" in headerData))) return; EnigmailPEPMessageHist.isLatestMessage(headerData.from.headerValue, headerData.date.headerValue). then(function _result(latestMessage) { EnigmailLog.DEBUG("pEpAdapter.jsm: processPGPMIME: " + latestMessage + "\n"); }).catch(function _fail() { EnigmailLog.DEBUG("pEpAdapter.jsm: processPGPMIME: error\n"); }); }, /** * Update the last sent date for inline-PGP messages. We do this to make sure * that pEp can potentially derive information from the message (such as extracting an * attached key). */ processInlinePGP: function(msgUri, headerData) { EnigmailLog.DEBUG("pEpAdapter.jsm: processInlinePGP: " + msgUri + "\n"); if (!("from" in headerData) && ("date" in headerData)) return; let stream = EnigmailStreams.newStringStreamListener( function analyzeData(data) { EnigmailLog.DEBUG("pEpAdapter.jsm: processInlinePGP: got " + data.length + " bytes\n"); if (data.indexOf("From -") === 0) { // remove 1st line from Mails stored in msgbox format data = data.replace(/^From .*\r?\n/, ""); } EnigmailpEp.decryptMimeString(data). then(function _ignore() {}). catch(function _ignore() {}); } ); EnigmailPEPMessageHist.isLatestMessage(headerData.from.headerValue, headerData.date.headerValue). then(function _result(latestMessage) { EnigmailLog.DEBUG("pEpAdapter.jsm: processInlinePGP: " + latestMessage + "\n"); try { if (latestMessage) { var channel = EnigmailStreams.createChannel(msgUri.spec); channel.asyncOpen(stream, null); } } catch (e) { EnigmailLog.DEBUG("pEpAdapter.jsm: processInlinePGP: exception " + e.toString() + "\n"); } }).catch(function _fail() { EnigmailLog.DEBUG("pEpAdapter.jsm: processInlinePGP: error\n"); }); }, /** * prepare the relevant data for the Trustwords dialog * * @param emailAddress: String - the email address of the peer to verify * @param headerData: either: Object - nsIMsgHdr object for the message * (to identify the ideal own identity) * or: String - email address of own identity * @return Promise(object) */ prepareTrustWordsDlg: function(emailAddress, headerData) { let deferred = PromiseUtils.defer(); let emailId = null; let useOwnId = null; let emailIdRating = null; let useLocale = "en"; let ownIds = []; let supportedLocale = []; let uiLocale = EnigmailLocale.getUILocale().substr(0, 2).toLowerCase(); emailAddress = emailAddress.toLowerCase(); let allEmails = ""; if (typeof(headerData) === "string") { allEmails = headerData; } else { if ("from" in headerData) { allEmails += headerData.from.headerValue + ","; } if ("to" in headerData) { allEmails += headerData.to.headerValue + ","; } if ("cc" in headerData) { allEmails += headerData.cc.headerValue + ","; } } let emailsInMessage = EnigmailFuncs.stripEmail(allEmails.toLowerCase()).split(/,/); EnigmailPEPAdapter.pep.getOwnIdentities().then(function _gotOwnIds(data) { if (("result" in data) && typeof data.result.outParams[0] === "object" && Array.isArray(data.result.outParams[0])) { ownIds = data.result.outParams[0]; } for (let i = 0; i < ownIds.length; i++) { if (ownIds[i].address.toLowerCase() === emailAddress) { deferred.reject("cannotVerifyOwnId"); } useOwnId = ownIds[0]; for (let j = 0; j < emailsInMessage.length; j++) { if (ownIds[i].address.toLowerCase() === emailsInMessage[j]) { useOwnId = ownIds[i]; break; } } } return EnigmailPEPAdapter.getIdentityForEmail(emailAddress); }).then(function _gotIdentityForEmail(data) { if (("result" in data) && typeof data.result === "object" && typeof data.result.outParams[0] === "object") { emailId = data.result.outParams[0]; } else { deferred.reject("cannotFindKey"); } return EnigmailPEPAdapter.pep.getIdentityRating(emailId); }).then(function _gotIdentityRating(data) { if ("result" in data && Array.isArray(data.result.outParams) && typeof(data.result.outParams[0]) === "object" && "rating" in data.result.outParams[0]) { emailIdRating = data.result.outParams[0]; } return EnigmailPEPAdapter.getSupportedLanguages(); }).then(function _gotLocale(localeList) { supportedLocale = localeList; for (let i = 0; i < localeList.length; i++) { if (localeList[i].short === uiLocale) { useLocale = localeList[i].short; } } return EnigmailPEPAdapter.getTrustWordsForLocale(useOwnId, emailId, useLocale, false); }).then(function _gotTrustWords(data) { if (("result" in data) && typeof data.result === "object" && typeof data.result.outParams[1] === "string") { let trustWords = data.result.outParams[1]; deferred.resolve({ ownId: useOwnId, otherId: emailId, userRating: emailIdRating, locale: useLocale, supportedLocale: supportedLocale, trustWords: trustWords, dialogMode: 0 }); } else { deferred.reject("generalFailure"); } }).catch(function _err(errorMsg) { deferred.reject(errorMsg); }); return deferred.promise; }, /** * Get the trustwords for a pair of pEpPerson's and a given language * * @param ownId: Object - pEpPerson object of own id * @param otherId: Object - pEpPerson object of other person's identity * * @return Promise(data) */ getTrustWordsForLocale: function(ownId, otherId, language, longWords) { return EnigmailPEPAdapter.pep.getTrustWords(ownId, otherId, language, longWords); }, resetTrustForEmail: function(emailAddr) { let deferred = PromiseUtils.defer(); EnigmailPEPAdapter.getIdentityForEmail(emailAddr). then(function _gotIdentityForEmail(data) { if (("result" in data) && typeof data.result === "object" && typeof data.result.outParams[0] === "object") { let emailId = data.result.outParams[0]; EnigmailPEPAdapter.pep.resetIdentityTrust(emailId).then( function _ok() { deferred.resolve(); } ).catch(function _err() { deferred.resolve(); }); } }); return deferred.promise; }, getRatingsForEmails: function(emailArr) { EnigmailLog.DEBUG("pEpAdapter.getRatingsForEmails(" + emailArr.length + ")\n"); let deferred = PromiseUtils.defer(); let identities = []; function getNextIdentity(emailNum) { if (emailNum >= emailArr.length) { EnigmailLog.DEBUG("pEpAdapter.getRatingsForEmails: done\n"); deferred.resolve(identities); return; } if (emailArr[emailNum].indexOf("@") < 0) { // skip if not an email address getNextIdentity(emailNum + 1); return; } let identity = null; let rating = 3; // default rating: no key available EnigmailPEPAdapter.getIdentityForEmail(emailArr[emailNum]).then( function _gotIdentity(data) { if (data && ("result" in data) && typeof data.result === "object" && typeof data.result.outParams[0] === "object") { identity = data.result.outParams[0]; return EnigmailPEPAdapter.pep.getIdentityRating(identity); } else { let deferred = PromiseUtils.defer(); deferred.resolve({ status: 0 }); return deferred.promise; } }).then( function _gotRating(data) { if ("result" in data && Array.isArray(data.result.outParams) && typeof(data.result.outParams[0]) === "object" && "rating" in data.result.outParams[0]) { rating = data.result.outParams[0].rating; } identities.push({ email: emailArr[emailNum], user_id: identity, rating: rating }); getNextIdentity(emailNum + 1); }).catch( function _err(data) { EnigmailLog.DEBUG("pEpAdapter.getIdentitiesForEmails: ERROR: " + JSON.stringify(data) + "\n"); deferred.reject(data); }); } getNextIdentity(0); return deferred.promise; }, calculateColorFromRating: function(rating) { let color = "grey"; if (rating === -2 || rating === 2) { color = "grey"; } else if (rating < 0) { color = "red"; } else if (rating < 6) { color = "grey"; } else if (rating >= 7) { color = "green"; } else { color = "yellow"; } return color; }, /** * Get CSS class for pEp rating */ getRatingClass: function(rating) { let setClass = ""; let color = this.calculateColorFromRating(rating); switch (color) { case "grey": setClass = "enigmailPepIdentityUnknown"; break; case "red": setClass = "enigmailPepIdentityMistrust"; break; case "yellow": setClass = "enigmailPepIdentityReliable"; break; case "green": setClass = "enigmailPepIdentityTrusted"; } return setClass; }, getRatingLabel: function(ratingNum) { let ratingDesc = "Undefined"; switch (ratingNum) { case 1: ratingDesc = "CannotDecrypt"; break; case 2: ratingDesc = "HaveNoKey"; break; case 3: ratingDesc = "Unencrypted"; break; case 4: ratingDesc = "UnencryptedForSome"; break; case 5: ratingDesc = "Unreliable"; break; case 6: ratingDesc = "Reliable"; break; case 7: case 8: case 9: ratingDesc = "Trusted"; break; case -2: ratingDesc = "Broken"; break; case -1: ratingDesc = "Mistrust"; break; case -3: ratingDesc = "UnderAttack"; break; } return ratingDesc; }, setupIncomingFilter: function() { EnigmailFilters.addNewMailConsumer({ headersOnly: false, incomingMailOnly: true, unreadOnly: false, selfSentOnly: true, consumeMessage: EnigmailPEPFilter.newMailConsumer.bind(EnigmailPEPFilter) }); + }, + + registerJuniorModeObserver: function(observer) { + let observerId = "O" + (gJmObserverId++); + gJmObservers[observerId] = observer; + return observerId; + }, + + unregisterJuniorModeObserver: function(observerId) { + if (observerId in gJmObservers) { + delete gJmObservers[observerId]; + } + }, + + handleJuniorModeChange: function() { + for (let i in gJmObservers) { + try { + gJmObservers[i](); + } + catch (ex) {} + } } }; + +// Enigmail.msg.juniorModeObserver = EnigmailPrefs.registerPrefObserver("juniorMode", Enigmail.msg.setMainMenuLabel); diff --git a/ui/content/am-enigprefs.js b/ui/content/am-enigprefs.js index be88a7bf..182995dd 100644 --- a/ui/content/am-enigprefs.js +++ b/ui/content/am-enigprefs.js @@ -1,46 +1,61 @@ /* * 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/. */ +/* global Components: false */ "use strict"; +Components.utils.import("resource://enigmail/pEpAdapter.jsm"); /*global EnigmailPEPAdapter: false */ + if (!Enigmail) var Enigmail = {}; var gPref = null; +var gUsingPep = null; function onInit() { + gUsingPep = EnigmailPEPAdapter.usingPep(); Enigmail.edit.onInit(); } function onAcceptEditor() { Enigmail.edit.onSave(); } function onPreInit(account, accountValues) { Enigmail.edit.identity = account.defaultIdentity; Enigmail.edit.account = account; } function onSave() { Enigmail.edit.onSave(); + /* + let usingPep = EnigmailPEPAdapter.usingPep(); + + if (usingPep !== gUsingPep) { + EnigmailPEPAdapter.handleJuniorModeChange(); + } + + if (usingPep) { + EnigmailPEPAdapter.setOwnIdentities(0); + } */ } function onLockPreference() { // do nothing } // Does the work of disabling an element given the array which contains xul id/prefstring pairs. // Also saves the id/locked state in an array so that other areas of the code can avoid // stomping on the disabled state indiscriminately. function disableIfLocked(prefstrArray) { // do nothing } function enigmailOnAcceptEditor() { Enigmail.edit.onSave(); return true; // allow to close dialog in all cases } diff --git a/ui/content/enigmail-am-smime.js b/ui/content/enigmail-am-smime.js new file mode 100644 index 00000000..b392b016 --- /dev/null +++ b/ui/content/enigmail-am-smime.js @@ -0,0 +1,34 @@ +/* + * 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/. + */ + +/* global Components: false */ + +"use strict"; + +Components.utils.import("resource://enigmail/pEpAdapter.jsm"); /*global EnigmailPEPAdapter: false */ + + +var Enigmail = { + usingPep: null, + onLoad: function(event) { + this.usingPep = EnigmailPEPAdapter.usingPep(); + }, + + onUnload: function(event) { + let usingPep = EnigmailPEPAdapter.usingPep(); + + if (usingPep !== this.usingPep) { + EnigmailPEPAdapter.handleJuniorModeChange(); + } + + if (usingPep) { + EnigmailPEPAdapter.setOwnIdentities(0); + } + } +}; + +window.addEventListener("load", Enigmail.onLoad.bind(Enigmail), true); +window.addEventListener("unload", Enigmail.onUnload.bind(Enigmail), true); diff --git a/ui/content/enigmail-am-smime.xul b/ui/content/enigmail-am-smime.xul new file mode 100644 index 00000000..213181f0 --- /dev/null +++ b/ui/content/enigmail-am-smime.xul @@ -0,0 +1,16 @@ +<?xml version="1.0"?> + +<!-- + * 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/. +--> + + +<overlay id="enigmail-am-smime" + xmlns:html="http://www.w3.org/1999/xhtml" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/x-javascript" src="chrome://enigmail/content/enigmail-am-smime.js"/> + +</overlay> diff --git a/ui/content/enigmailEditIdentity.js b/ui/content/enigmailEditIdentity.js index 5b17dc9f..3f323fac 100644 --- a/ui/content/enigmailEditIdentity.js +++ b/ui/content/enigmailEditIdentity.js @@ -1,231 +1,243 @@ /*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/. */ /* global gAccount: false, gIdentity: false, onOk: false, smimeOnAcceptEditor: false */ "use strict"; Components.utils.import("resource://enigmail/funcs.jsm"); /* global EnigmailFuncs: false */ Components.utils.import("resource://enigmail/locale.jsm"); /* global EnigmailLocale: false */ Components.utils.import("resource://enigmail/windows.jsm"); /* global EnigmailWindows: false */ Components.utils.import("resource://enigmail/pEpAdapter.jsm"); /* global EnigmailPEPAdapter: false */ if (!Enigmail) var Enigmail = {}; Enigmail.edit = { account: null, identity: null, enablePgp: null, pgpKeyMode: null, pgpKeyId: null, cryptoChoicesEnabled: null, signingPolicy: null, // account specific: by default sign encryptionPolicy: null, // account specific: by default encrypt pgpMimeMode: null, // account specific: by default pgp/mime pgpSignPlainPolicy: null, pgpSignEncPolicy: null, autoEncryptDrafts: null, advancedSettings: null, + usingPep: null, onInit: function() { // initialize all of our elements based on the current identity values.... EnigmailFuncs.collapseAdvanced(document.getElementById("enigmail_PrefsBox"), "hidden"); this.enablePgp = document.getElementById("enigmail_enablePgp"); this.pgpKeyMode = document.getElementById("enigmail_pgpKeyMode"); this.pgpKeyId = document.getElementById("enigmail_identity.pgpkeyId"); this.signingPolicy = document.getElementById("enigmail_sign_ifPossible"); this.encryptionPolicy = document.getElementById("enigmail_encrypt_ifPossible"); this.pgpMimeMode = document.getElementById("enigmail_pgpMimeMode"); this.pgpSignEncPolicy = document.getElementById("enigmail_sign_encrypted"); this.pgpSignPlainPolicy = document.getElementById("enigmail_sign_notEncrypted"); this.autoEncryptDrafts = document.getElementById("enigmail_autoEncryptDrafts"); this.mimePreferOpenPGP = document.getElementById("enigmail_mimePreferOpenPGP"); + this.usingPep = EnigmailPEPAdapter.usingPep(); if (this.identity) { this.enablePgp.checked = this.identity.getBoolAttribute("enablePgp"); this.cryptoChoicesEnabled = this.enablePgp.checked; var selectedItemId = null; var keyPolicy = this.identity.getIntAttribute("pgpKeyMode"); switch (keyPolicy) { case 1: selectedItemId = 'enigmail_keymode_usePgpkeyId'; break; default: selectedItemId = 'enigmail_keymode_useFromAddress'; break; } this.pgpKeyMode.selectedItem = document.getElementById(selectedItemId); var mimePolicy = this.identity.getIntAttribute("mimePreferOpenPGP"); switch (mimePolicy) { case 1: selectedItemId = "enigmail_mime_preferEnigmail"; break; default: selectedItemId = "enigmail_mime_preferSMime"; break; } this.mimePreferOpenPGP.selectedItem = document.getElementById(selectedItemId); this.pgpKeyId.value = this.identity.getCharAttribute("pgpkeyId"); EnigmailFuncs.getSignMsg(this.identity); this.signingPolicy.checked = (this.identity.getIntAttribute("defaultSigningPolicy") > 0); this.encryptionPolicy.checked = (this.identity.getIntAttribute("defaultEncryptionPolicy") > 0); this.pgpMimeMode.checked = this.identity.getBoolAttribute("pgpMimeMode"); this.pgpSignEncPolicy.checked = this.identity.getBoolAttribute("pgpSignEncrypted"); this.pgpSignPlainPolicy.checked = this.identity.getBoolAttribute("pgpSignPlain"); this.autoEncryptDrafts.checked = this.identity.getBoolAttribute("autoEncryptDrafts"); this.advancedSettings = { openPgpHeaderMode: this.identity.getIntAttribute("openPgpHeaderMode"), openPgpUrlName: this.identity.getCharAttribute("openPgpUrlName"), attachPgpKey: this.identity.getBoolAttribute("attachPgpKey") }; } else { this.enablePgp.checked = false; this.cryptoChoicesEnabled = false; this.pgpMimeMode.checked = true; this.advancedSettings = { openPgpHeaderMode: 0, openPgpUrlName: "", attachPgpKey: false }; } // Disable all locked elements on the panel //onLockPreference(); this.enableAllPrefs(); }, onLoadEditor: function() { if (typeof(gAccount) == "object") { this.account = gAccount; this.identity = gIdentity; } else { this.identity = window.arguments[0].identity; this.account = window.arguments[0].account; } if (this.identity) { var idLabel = EnigmailLocale.getString("identityName", [this.identity.identityName]); document.getElementById("enigmail_identityName").value = idLabel; } var dlg = document.getElementsByTagName("dialog")[0]; dlg.setAttribute("ondialogaccept", "return Enigmail.edit.onAcceptEditor();"); this.onInit(); }, onAcceptEditor: function() { try { if (onOk() === false) { return false; } } catch (ex) {} this.onSave(); if (typeof(smimeOnAcceptEditor) == "function") { return smimeOnAcceptEditor(); } else return true; }, onSave: function() { if (!this.identity) { this.identity = gIdentity; } this.identity.setBoolAttribute("enablePgp", this.enablePgp.checked); if (this.enablePgp.checked) { // PGP is enabled this.identity.setIntAttribute("pgpKeyMode", this.pgpKeyMode.selectedItem.value); this.identity.setIntAttribute("mimePreferOpenPGP", this.mimePreferOpenPGP.selectedItem.value); this.identity.setCharAttribute("pgpkeyId", this.pgpKeyId.value); this.identity.setIntAttribute("defaultSigningPolicy", (this.signingPolicy.checked ? 1 : 0)); this.identity.setIntAttribute("defaultEncryptionPolicy", (this.encryptionPolicy.checked ? 1 : 0)); this.identity.setBoolAttribute("pgpMimeMode", this.pgpMimeMode.checked); this.identity.setBoolAttribute("pgpSignEncrypted", this.pgpSignEncPolicy.checked); this.identity.setBoolAttribute("pgpSignPlain", this.pgpSignPlainPolicy.checked); this.identity.setBoolAttribute("autoEncryptDrafts", this.autoEncryptDrafts.checked); this.identity.setIntAttribute("openPgpHeaderMode", this.advancedSettings.openPgpHeaderMode); this.identity.setCharAttribute("openPgpUrlName", this.advancedSettings.openPgpUrlName); this.identity.setBoolAttribute("attachPgpKey", this.advancedSettings.attachPgpKey); + } + + let usingPep = EnigmailPEPAdapter.usingPep(); + if (usingPep !== this.usingPep) { + EnigmailPEPAdapter.handleJuniorModeChange(); } + + if (usingPep) { + EnigmailPEPAdapter.setOwnIdentities(0); + } + }, toggleEnable: function() { this.cryptoChoicesEnabled = (!this.cryptoChoicesEnabled); this.enableAllPrefs(); }, enableAllPrefs: function() { var elem = document.getElementById("enigmail_bcEnablePgp"); if (this.cryptoChoicesEnabled) { if (elem) elem.removeAttribute("disabled"); } else { if (elem) { if (EnigmailPEPAdapter.usingPep()) { elem.removeAttribute("disabled"); } else { elem.setAttribute("disabled", "true"); } } } this.enableKeySel(this.cryptoChoicesEnabled && (this.pgpKeyMode.value == 1)); }, enableKeySel: function(enable) { if (enable) { document.getElementById("enigmail_bcUseKeyId").removeAttribute("disabled"); } else { document.getElementById("enigmail_bcUseKeyId").setAttribute("disabled", "true"); } }, selectKeyId: function() { var resultObj = {}; var inputObj = {}; inputObj.dialogHeader = EnigmailLocale.getString("encryptKeyHeader"); inputObj.options = "single,hidexpired,private,nosending"; var button = document.getElementById("enigmail_selectPgpKey"); var label = button.getAttribute("label"); inputObj.options += ",sendlabel=" + label; inputObj.options += ","; window.openDialog("chrome://enigmail/content/enigmailKeySelection.xul", "", "dialog,modal,centerscreen,resizable", inputObj, resultObj); try { if (resultObj.cancelled) return; var selKey = resultObj.userList[0]; //selKey = "0x"+selKey.substring(10,18); this.pgpKeyId.value = selKey; } catch (ex) { // cancel pressed -> don't send mail return; } }, advancedIdentitySettings: function() { var inputObj = { identitySettings: this.advancedSettings, pgpKeyMode: this.pgpKeyMode.selectedItem.value }; window.openDialog("chrome://enigmail/content/enigmailAdvancedIdentityDlg.xul", "", "dialog,modal,centerscreen", inputObj); } }; diff --git a/ui/content/enigmailMessengerOverlay.js b/ui/content/enigmailMessengerOverlay.js index c256f1a1..7038d97a 100644 --- a/ui/content/enigmailMessengerOverlay.js +++ b/ui/content/enigmailMessengerOverlay.js @@ -1,2638 +1,2638 @@ /*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 */ 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 = EnigmailPrefs.registerPrefObserver("juniorMode", 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) { - EnigmailPrefs.unregisterPrefObserver(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()) { 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; // HACK for Zimbra OpenPGP Zimlet // Zimbra illegally changes attachment content-type to application/pgp-encrypted which interfers with below // see https://sourceforge.net/p/enigmail/bugs/600/ try { if (mimeMsg.parts && mimeMsg.parts.length && mimeMsg.parts.length == 1 && mimeMsg.headers["x-mailer"][0].indexOf("ZimbraWebClient") >= 0 && mimeMsg.parts[0].parts[0].headers["content-type"][0].indexOf("text/plain") >= 0 && mimeMsg.parts[0].headers["content-type"][0].indexOf("multipart/mixed") >= 0 && mimeMsg.parts[0].parts[0].body.indexOf("Version: OpenPGP.js") >= 0 && mimeMsg.parts[0].parts[1].headers["content-type"][0].indexOf("application/pgp-encrypted") >= 0) { this.messageParse(event, false, Enigmail.msg.savedHeaders["content-transfer-encoding"], this.getCurrentMsgUriSpec()); return; } } catch (ex) {} // HACK for MS-EXCHANGE-Server Problem: // check for possible bad mime structure due to buggy exchange server: // - multipart/mixed Container with // - application/pgp-encrypted Attachment with name "PGPMIME Versions Identification" // - application/octet-stream Attachment with name "encrypted.asc" having the encrypted content in base64 // - see: // - http://www.mozilla-enigmail.org/forum/viewtopic.php?f=4&t=425 // - http://sourceforge.net/p/enigmail/forum/support/thread/4add2b69/ // iPGMail produces a similar broken structure, see here: // - https://sourceforge.net/p/enigmail/forum/support/thread/afc9c246/#5de7 if (mimeMsg.parts && mimeMsg.parts.length && mimeMsg.parts.length == 1 && mimeMsg.parts[0].parts && mimeMsg.parts[0].parts.length && mimeMsg.parts[0].parts.length == 3 && mimeMsg.parts[0].headers["content-type"][0].indexOf("multipart/mixed") >= 0 && mimeMsg.parts[0].parts[0].headers["content-type"][0].search(/multipart\/encrypted/i) < 0 && mimeMsg.parts[0].parts[0].headers["content-type"][0].indexOf("text/plain") >= 0 && mimeMsg.parts[0].parts[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(); }); }, /** * 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; if (!(Enigmail.msg.securityInfo && Enigmail.msg.securityInfo.statusFlags)) return; let securityInfo = Enigmail.msg.securityInfo; let keyObj = EnigmailKeyRing.getKeyById(securityInfo.keyId); if (keyObj && keyObj.getEncryptionValidity().keyValid) { if (securityInfo.statusFlags & nsIEnigmail.GOOD_SIGNATURE) { let hdrData = "to=" + EnigmailFuncs.stripEmail(currentHeaderData.from.headerValue) + "; prefer-encrypted=" + ((securityInfo.statusFlags & nsIEnigmail.DECRYPTION_OKAY) || (securityInfo.statusFlags & nsIEnigmail.PGP_MIME_ENCRYPTED) ? "yes" : "no") + "; _enigmail_artificial=yes; _enigmail_fpr=" + keyObj.fpr + "; key=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); diff --git a/ui/jar.mn b/ui/jar.mn index 39468090..29d91928 100644 --- a/ui/jar.mn +++ b/ui/jar.mn @@ -1,569 +1,571 @@ enigmail.jar: content/enigmail/columnOverlay.xul (content/columnOverlay.xul) content/enigmail/columnOverlay.js (content/columnOverlay.js) content/enigmail/enigmailCommon.js (content/enigmailCommon.js) content/enigmail/enigmailAbCardViewOverlay.xul (content/enigmailAbCardViewOverlay.xul) content/enigmail/enigmailAbContactsPanel.xul (content/enigmailAbContactsPanel.xul) content/enigmail/enigmailAbOverlay.js (content/enigmailAbOverlay.js) content/enigmail/enigmailAbout.xul (content/enigmailAbout.xul) content/enigmail/enigmailAbout.js (content/enigmailAbout.js) content/enigmail/enigmailAbout.htm (content/enigmailAbout.htm) content/enigmail/enigmailAddUidDlg.js (content/enigmailAddUidDlg.js) content/enigmail/enigmailAddUidDlg.xul (content/enigmailAddUidDlg.xul) content/enigmail/enigmailAdvancedIdentityDlg.js (content/enigmailAdvancedIdentityDlg.js) content/enigmail/enigmailAdvancedIdentityDlg.xul (content/enigmailAdvancedIdentityDlg.xul) content/enigmail/enigmailMsgBox.js (content/enigmailMsgBox.js) content/enigmail/enigmailMsgBox.xul (content/enigmailMsgBox.xul) content/enigmail/enigmailAttachmentsDialog.xul (content/enigmailAttachmentsDialog.xul) content/enigmail/enigmailAttachmentsDialog.js (content/enigmailAttachmentsDialog.js) content/enigmail/enigmailAmIdEditOverlay.js (content/enigmailAmIdEditOverlay.js) content/enigmail/enigmailAmIdEditOverlay.xul (content/enigmailAmIdEditOverlay.xul) content/enigmail/enigmailBuildDate.js (content/enigmailBuildDate.js) content/enigmail/enigmailCheckLanguage.xul (content/enigmailCheckLanguage.xul) content/enigmail/enigmailCardDetails.js (content/enigmailCardDetails.js) content/enigmail/enigmailCardDetails.xul (content/enigmailCardDetails.xul) content/enigmail/enigmailConsole.xul (content/enigmailConsole.xul) content/enigmail/enigmailConsole.js (content/enigmailConsole.js) content/enigmail/enigmailConsole.htm (content/enigmailConsole.htm) content/enigmail/enigmailCustToolOverlay.xul (content/enigmailCustToolOverlay.xul) content/enigmail/enigmailDispPhoto.js (content/enigmailDispPhoto.js) content/enigmail/enigmailDispPhoto.xul (content/enigmailDispPhoto.xul) content/enigmail/enigmailEditIdentity.js (content/enigmailEditIdentity.js) content/enigmail/enigmailEditIdentity.xul (content/enigmailEditIdentity.xul) content/enigmail/enigmailEditKeyExpiryDlg.js (content/enigmailEditKeyExpiryDlg.js) content/enigmail/enigmailEditKeyExpiryDlg.xul (content/enigmailEditKeyExpiryDlg.xul) content/enigmail/enigmailEditKeyTrustDlg.js (content/enigmailEditKeyTrustDlg.js) content/enigmail/enigmailEditKeyTrustDlg.xul (content/enigmailEditKeyTrustDlg.xul) content/enigmail/enigmailEncryptionDlg.xul (content/enigmailEncryptionDlg.xul) content/enigmail/enigmailEncryptionDlg.js (content/enigmailEncryptionDlg.js) content/enigmail/enigmailGenCardKey.js (content/enigmailGenCardKey.js) content/enigmail/enigmailGenCardKey.xul (content/enigmailGenCardKey.xul) content/enigmail/enigmailGenericDisplay.js (content/enigmailGenericDisplay.js) content/enigmail/enigmailGenericDisplay.xul (content/enigmailGenericDisplay.xul) content/enigmail/enigmailGenericDisplay.htm (content/enigmailGenericDisplay.htm) content/enigmail/enigmailHelp.xul (content/enigmailHelp.xul) content/enigmail/enigmailHelp.js (content/enigmailHelp.js) content/enigmail/enigmailImportPhoto.js (content/enigmailImportPhoto.js) content/enigmail/enigmailImportPhoto.xul (content/enigmailImportPhoto.xul) content/enigmail/keyDetailsDlg.js (content/keyDetailsDlg.js) content/enigmail/keyDetailsDlg.xul (content/keyDetailsDlg.xul) content/enigmail/enigmailKeyManager.xul (content/enigmailKeyManager.xul) content/enigmail/enigmailKeyManager.js (content/enigmailKeyManager.js) content/enigmail/enigmailManageUidDlg.js (content/enigmailManageUidDlg.js) content/enigmail/enigmailManageUidDlg.xul (content/enigmailManageUidDlg.xul) content/enigmail/enigmailRulesEditor.xul (content/enigmailRulesEditor.xul) content/enigmail/enigmailRulesEditor.js (content/enigmailRulesEditor.js) content/enigmail/enigmailSearchKey.js (content/enigmailSearchKey.js) content/enigmail/enigmailSearchKey.xul (content/enigmailSearchKey.xul) content/enigmail/enigmailKeyImportInfo.js (content/enigmailKeyImportInfo.js) content/enigmail/enigmailKeyImportInfo.xul (content/enigmailKeyImportInfo.xul) content/enigmail/enigmailSingleRcptSettings.js (content/enigmailSingleRcptSettings.js) content/enigmail/enigmailSingleRcptSettings.xul (content/enigmailSingleRcptSettings.xul) content/enigmail/enigmailSelectRule.js (content/enigmailSelectRule.js) content/enigmail/enigmailSelectRule.xul (content/enigmailSelectRule.xul) content/enigmail/enigmailSetCardPin.js (content/enigmailSetCardPin.js) content/enigmail/enigmailSetCardPin.xul (content/enigmailSetCardPin.xul) content/enigmail/enigmailSignKeyDlg.js (content/enigmailSignKeyDlg.js) content/enigmail/enigmailSignKeyDlg.xul (content/enigmailSignKeyDlg.xul) + content/enigmail/enigmail-am-smime.js (content/enigmail-am-smime.js) + content/enigmail/enigmail-am-smime.xul (content/enigmail-am-smime.xul) content/enigmail/pref-enigmail.xul (content/pref-enigmail.xul) content/enigmail/pref-enigmail.js (content/pref-enigmail.js) content/enigmail/pref-pep.xul (content/pref-pep.xul) content/enigmail/pref-pep.js (content/pref-pep.js) content/enigmail/am-enigprefs.xul (content/am-enigprefs.xul) content/enigmail/am-enigprefs.js (content/am-enigprefs.js) content/enigmail/am-enigprefs-edit.xul (content/am-enigprefs-edit.xul) content/enigmail/enigmailKeygen.xul (content/enigmailKeygen.xul) content/enigmail/enigmailKeygen.js (content/enigmailKeygen.js) content/enigmail/enigmailKeygenConsole.htm (content/enigmailKeygenConsole.htm) content/enigmail/enigmailKeyserverDlg.xul (content/enigmailKeyserverDlg.xul) content/enigmail/enigmailKeyserverDlg.js (content/enigmailKeyserverDlg.js) content/enigmail/enigmailKeySelection.xul (content/enigmailKeySelection.xul) content/enigmail/enigmailKeySelection.js (content/enigmailKeySelection.js) content/enigmail/enigmailMsgComposeOverlay.xul (content/enigmailMsgComposeOverlay.xul) content/enigmail/enigmailMsgComposeOverlay.js (content/enigmailMsgComposeOverlay.js) content/enigmail/enigmailMsgComposeHelper.js (content/enigmailMsgComposeHelper.js) content/enigmail/messengerOverlay-tbird.xul (content/messengerOverlay-tbird.xul) content/enigmail/messengerOverlay-sm.xul (content/messengerOverlay-sm.xul) content/enigmail/enigmailMessengerOverlay.xul (content/enigmailMessengerOverlay.xul) content/enigmail/enigmailMessengerOverlay.js (content/enigmailMessengerOverlay.js) content/enigmail/enigmailMsgHdrViewOverlay.xul (content/enigmailMsgHdrViewOverlay.xul) content/enigmail/enigmailMsgHdrViewOverlay.js (content/enigmailMsgHdrViewOverlay.js) content/enigmail/enigmailFilterEditorOverlay.xul (content/enigmailFilterEditorOverlay.xul) content/enigmail/enigmailFilterEditorOverlay.js (content/enigmailFilterEditorOverlay.js) content/enigmail/enigmailFilterListOverlay.xul (content/enigmailFilterListOverlay.xul) content/enigmail/enigmailFilterListOverlay.js (content/enigmailFilterListOverlay.js) content/enigmail/enigmailMsgPrintOverlay.xul (content/enigmailMsgPrintOverlay.xul) content/enigmail/enigmailMsgPrintOverlay.js (content/enigmailMsgPrintOverlay.js) content/enigmail/enigmailPrivacyOverlay.js (content/enigmailPrivacyOverlay.js) content/enigmail/enigmailPrivacyOverlay.xul (content/enigmailPrivacyOverlay.xul) content/enigmail/enigmailSetupWizard.js (content/enigmailSetupWizard.js) content/enigmail/enigmailSetupWizard.xul (content/enigmailSetupWizard.xul) content/enigmail/enigmailWrapSelection.xul (content/enigmailWrapSelection.xul) content/enigmail/enigmailWrapSelection.js (content/enigmailWrapSelection.js) content/enigmail/enigmailViewFile.js (content/enigmailViewFile.js) content/enigmail/enigmailViewFile.xul (content/enigmailViewFile.xul) content/enigmail/enigRetrieveProgress.xul (content/enigRetrieveProgress.xul) content/enigmail/enigRetrieveProgress.js (content/enigRetrieveProgress.js) content/enigmail/exportSettingsWizard.js (content/exportSettingsWizard.js) content/enigmail/exportSettingsWizard.xul (content/exportSettingsWizard.xul) content/enigmail/pepHandshake.xul (content/pepHandshake.xul) content/enigmail/pepHandshake.js (content/pepHandshake.js) content/enigmail/pepPrepHandshake.xul (content/pepPrepHandshake.xul) content/enigmail/pepPrepHandshake.js (content/pepPrepHandshake.js) content/enigmail/pepTrustWords.xul (content/pepTrustWords.xul) content/enigmail/pepTrustWords.js (content/pepTrustWords.js) content/enigmail/check0.png (skin/images/check0.png) content/enigmail/check1.png (skin/images/check1.png) content/enigmail/check2.png (skin/images/check2.png) locale/en-US/enigmail.dtd (locale/en-US/enigmail.dtd) locale/en-US/enigmail.properties (locale/en-US/enigmail.properties) locale/en-US/am-enigprefs.properties (locale/en-US/am-enigprefs.properties) locale/en-US/help/compose.html (locale/en-US/help/compose.html) locale/en-US/help/editRcptRule.html (locale/en-US/help/editRcptRule.html) locale/en-US/help/initError.html (locale/en-US/help/initError.html) locale/en-US/help/messenger.html (locale/en-US/help/messenger.html) locale/en-US/help/rulesEditor.html (locale/en-US/help/rulesEditor.html) locale/en-US/help/sendingPrefs.html (locale/en-US/help/sendingPrefs.html) skin/tb-win-xp/enigmail/enigmail.css (skin/tb-windows/enigmail.css) skin/tb-win-xp/enigmail/enigmail-common.css (skin/common/enigmail-common.css) skin/tb-win-xp/enigmail/enigmail-pEp.css (skin/common/enigmail-pEp.css) skin/tb-win-xp/enigmail/enigmail-about.png (skin/images/enigmail-about.png) skin/tb-win-xp/enigmail/enigmail-logo.png (skin/images/enigmail-logo.png) skin/tb-win-xp/enigmail/enigmail-toolbar.png (skin/tb-windows/images/enigmail-toolbar.png) skin/tb-win-xp/enigmail/enigmail-toolbar-small.png (skin/tb-windows/images/enigmail-toolbar-small.png) skin/tb-win-xp/enigmail/enigmail-settings.png (skin/tb-windows/images/enigmail-settings.png) skin/tb-win-xp/enigmail/enigmail-settings-small.png (skin/tb-windows/images/enigmail-settings-small.png) skin/tb-win-xp/enigmail/enigEncInactive.png (skin/tb-windows/images/enigEncInactive.png) skin/tb-win-xp/enigmail/enigEncNotOk.png (skin/tb-windows/images/enigEncNotOk.png) skin/tb-win-xp/enigmail/enigEncOk.png (skin/tb-windows/images/enigEncOk.png) skin/tb-win-xp/enigmail/enigSignInactive.png (skin/tb-windows/images/enigSignInactive.png) skin/tb-win-xp/enigmail/enigSignNotOk.png (skin/tb-windows/images/enigSignNotOk.png) skin/tb-win-xp/enigmail/enigSignOk.png (skin/tb-windows/images/enigSignOk.png) skin/tb-win-xp/enigmail/enigSignUnkown.png (skin/tb-windows/images/enigSignUnkown.png) skin/tb-win-xp/enigmail/twisty-open.png (skin/images/twisty-open.png) skin/tb-win-xp/enigmail/twisty-clsd.png (skin/images/twisty-clsd.png) skin/tb-xp-win/enigmail/spinning-wheel.png (skin/images/spinning-wheel.png) skin/tb-win-xp/enigmail/col-encrypted-signed.png (skin/tb-windows/images/col-encrypted-signed.png) skin/tb-win-xp/enigmail/enigSignActiveNone.png (skin/tb-windows/images/enigSignActiveNone.png) skin/tb-win-xp/enigmail/enigSignActivePlus.png (skin/tb-windows/images/enigSignActivePlus.png) skin/tb-win-xp/enigmail/enigSignActiveMinus.png (skin/tb-windows/images/enigSignActiveMinus.png) skin/tb-win-xp/enigmail/enigSignActiveConflict.png (skin/tb-windows/images/enigSignActiveConflict.png) skin/tb-win-xp/enigmail/enigSignInactiveNone.png (skin/tb-windows/images/enigSignInactiveNone.png) skin/tb-win-xp/enigmail/enigSignInactivePlus.png (skin/tb-windows/images/enigSignInactivePlus.png) skin/tb-win-xp/enigmail/enigSignInactiveMinus.png (skin/tb-windows/images/enigSignInactiveMinus.png) skin/tb-win-xp/enigmail/enigSignInactiveConflict.png (skin/tb-windows/images/enigSignInactiveConflict.png) skin/tb-win-xp/enigmail/enigSignForceYes.png (skin/tb-windows/images/enigSignForceYes.png) skin/tb-win-xp/enigmail/enigSignForceNo.png (skin/tb-windows/images/enigSignForceNo.png) skin/tb-win-xp/enigmail/enigEncActiveNone.png (skin/tb-windows/images/enigEncActiveNone.png) skin/tb-win-xp/enigmail/enigEncActivePlus.png (skin/tb-windows/images/enigEncActivePlus.png) skin/tb-win-xp/enigmail/enigEncActiveMinus.png (skin/tb-windows/images/enigEncActiveMinus.png) skin/tb-win-xp/enigmail/enigEncActiveConflict.png (skin/tb-windows/images/enigEncActiveConflict.png) skin/tb-win-xp/enigmail/enigEncInactiveNone.png (skin/tb-windows/images/enigEncInactiveNone.png) skin/tb-win-xp/enigmail/enigEncInactivePlus.png (skin/tb-windows/images/enigEncInactivePlus.png) skin/tb-win-xp/enigmail/enigEncInactiveMinus.png (skin/tb-windows/images/enigEncInactiveMinus.png) skin/tb-win-xp/enigmail/enigEncInactiveConflict.png (skin/tb-windows/images/enigEncInactiveConflict.png) skin/tb-win-xp/enigmail/enigEncForceYes.png (skin/tb-windows/images/enigEncForceYes.png) skin/tb-win-xp/enigmail/enigEncForceNo.png (skin/tb-windows/images/enigEncForceNo.png) skin/tb-win-xp/enigmail/encrypt-active-16.png (skin/images/encrypt-active-16.png) skin/tb-win-xp/enigmail/encrypt-active-force-16.png (skin/images/encrypt-active-force-16.png) skin/tb-win-xp/enigmail/encrypt-disabled-16.png (skin/images/encrypt-disabled-16.png) skin/tb-win-xp/enigmail/encrypt-inactive-16.png (skin/images/encrypt-inactive-16.png) skin/tb-win-xp/enigmail/encrypt-inactive-force-16.png (skin/images/encrypt-inactive-force-16.png) skin/tb-win-xp/enigmail/encrypt-active-30.png (skin/images/encrypt-active-30.png) skin/tb-win-xp/enigmail/encrypt-active-force-30.png (skin/images/encrypt-active-force-30.png) skin/tb-win-xp/enigmail/encrypt-disabled-30.png (skin/images/encrypt-disabled-30.png) skin/tb-win-xp/enigmail/encrypt-inactive-30.png (skin/images/encrypt-inactive-30.png) skin/tb-win-xp/enigmail/encrypt-inactive-force-30.png (skin/images/encrypt-inactive-force-30.png) skin/tb-win-xp/enigmail/sign-active-16.png (skin/images/sign-active-16.png) skin/tb-win-xp/enigmail/sign-active-force-16.png (skin/images/sign-active-force-16.png) skin/tb-win-xp/enigmail/sign-disabled-16.png (skin/images/sign-disabled-16.png) skin/tb-win-xp/enigmail/sign-inactive-16.png (skin/images/sign-inactive-16.png) skin/tb-win-xp/enigmail/sign-inactive-force-16.png (skin/images/sign-inactive-force-16.png) skin/tb-win-xp/enigmail/sign-active-30.png (skin/images/sign-active-30.png) skin/tb-win-xp/enigmail/sign-active-force-30.png (skin/images/sign-active-force-30.png) skin/tb-win-xp/enigmail/sign-disabled-30.png (skin/images/sign-disabled-30.png) skin/tb-win-xp/enigmail/sign-inactive-30.png (skin/images/sign-inactive-30.png) skin/tb-win-xp/enigmail/sign-inactive-force-30.png (skin/images/sign-inactive-force-30.png) skin/tb-win-xp/enigmail/attach-active-16.png (skin/images/attach-active-16.png) skin/tb-win-xp/enigmail/attach-disabled-16.png (skin/images/attach-disabled-16.png) skin/tb-win-xp/enigmail/attach-inactive-16.png (skin/images/attach-inactive-16.png) skin/tb-win-xp/enigmail/warning-16.png (skin/images/warning-16.png) skin/tb-win-xp/enigmail/password-error.png (skin/images/password-error.png) skin/tb-win-xp/enigmail/col-pEpGreen.svg (skin/images/col-pEpGreen.svg) skin/tb-win-xp/enigmail/col-pEpYellow.svg (skin/images/col-pEpYellow.svg) skin/tb-win-xp/enigmail/col-pEpRed.svg (skin/images/col-pEpRed.svg) skin/tb-win-xp/enigmail/pEpGreen.svg (skin/images/pEpGreen.svg) skin/tb-win-xp/enigmail/pEpYellow.svg (skin/images/pEpYellow.svg) skin/tb-win-xp/enigmail/pEpRed.svg (skin/images/pEpRed.svg) skin/tb-win-xp/enigmail/pEpEncryptActive.svg (skin/images/pEpEncryptActive.svg) skin/tb-win-xp/enigmail/pEpEncryptInactive.svg (skin/images/pEpEncryptInactive.svg) skin/tb-win-xp/enigmail/pEpLogo.svg (skin/images/pEpLogo.svg) skin/aero/enigmail/enigmail.css (skin/tb-windows/enigmail-aero.css) skin/aero/enigmail/enigmail-common.css (skin/common/enigmail-common.css) skin/aero/enigmail/enigmail-pEp.css (skin/common/enigmail-pEp.css) skin/aero/enigmail/enigmail-about.png (skin/images/enigmail-about.png) skin/aero/enigmail/enigmail-logo.png (skin/images/enigmail-logo.png) skin/aero/enigmail/enigmail-toolbar.png (skin/tb-windows/images/enigmail-toolbar-aero.png) skin/aero/enigmail/enigmail-toolbar-small.png (skin/tb-windows/images/enigmail-toolbar-small-aero.png) skin/aero/enigmail/enigmail-settings.png (skin/tb-windows/images/enigmail-settings-aero.png) skin/aero/enigmail/enigmail-settings-small.png (skin/tb-windows/images/enigmail-settings-small-aero.png) skin/aero/enigmail/enigEncInactive.png (skin/tb-windows/images/enigEncInactive.png) skin/aero/enigmail/enigEncNotOk.png (skin/tb-windows/images/enigEncNotOk.png) skin/aero/enigmail/enigEncOk.png (skin/tb-windows/images/enigEncOk.png) skin/aero/enigmail/enigSignInactive.png (skin/tb-windows/images/enigSignInactive.png) skin/aero/enigmail/enigSignNotOk.png (skin/tb-windows/images/enigSignNotOk.png) skin/aero/enigmail/enigSignOk.png (skin/tb-windows/images/enigSignOk.png) skin/aero/enigmail/enigSignUnkown.png (skin/tb-windows/images/enigSignUnkown.png) skin/aero/enigmail/twisty-open.png (skin/images/twisty-open.png) skin/aero/enigmail/twisty-clsd.png (skin/images/twisty-clsd.png) skin/aero/enigmail/spinning-wheel.png (skin/images/spinning-wheel.png) skin/aero/enigmail/col-encrypted-signed.png (skin/tb-windows/images/col-encrypted-signed.png) skin/aero/enigmail/enigSignActiveNone.png (skin/tb-windows/images/enigSignActiveNone.png) skin/aero/enigmail/enigSignActivePlus.png (skin/tb-windows/images/enigSignActivePlus.png) skin/aero/enigmail/enigSignActiveMinus.png (skin/tb-windows/images/enigSignActiveMinus.png) skin/aero/enigmail/enigSignActiveConflict.png (skin/tb-windows/images/enigSignActiveConflict.png) skin/aero/enigmail/enigSignInactiveNone.png (skin/tb-windows/images/enigSignInactiveNone.png) skin/aero/enigmail/enigSignInactivePlus.png (skin/tb-windows/images/enigSignInactivePlus.png) skin/aero/enigmail/enigSignInactiveMinus.png (skin/tb-windows/images/enigSignInactiveMinus.png) skin/aero/enigmail/enigSignInactiveConflict.png (skin/tb-windows/images/enigSignInactiveConflict.png) skin/aero/enigmail/enigSignForceYes.png (skin/tb-windows/images/enigSignForceYes.png) skin/aero/enigmail/enigSignForceNo.png (skin/tb-windows/images/enigSignForceNo.png) skin/aero/enigmail/enigEncActiveNone.png (skin/tb-windows/images/enigEncActiveNone.png) skin/aero/enigmail/enigEncActivePlus.png (skin/tb-windows/images/enigEncActivePlus.png) skin/aero/enigmail/enigEncActiveMinus.png (skin/tb-windows/images/enigEncActiveMinus.png) skin/aero/enigmail/enigEncActiveConflict.png (skin/tb-windows/images/enigEncActiveConflict.png) skin/aero/enigmail/enigEncInactiveNone.png (skin/tb-windows/images/enigEncInactiveNone.png) skin/aero/enigmail/enigEncInactivePlus.png (skin/tb-windows/images/enigEncInactivePlus.png) skin/aero/enigmail/enigEncInactiveMinus.png (skin/tb-windows/images/enigEncInactiveMinus.png) skin/aero/enigmail/enigEncInactiveConflict.png (skin/tb-windows/images/enigEncInactiveConflict.png) skin/aero/enigmail/enigEncForceYes.png (skin/tb-windows/images/enigEncForceYes.png) skin/aero/enigmail/enigEncForceNo.png (skin/tb-windows/images/enigEncForceNo.png) skin/aero/enigmail/encrypt-active-16.png (skin/images/encrypt-active-16.png) skin/aero/enigmail/encrypt-active-force-16.png (skin/images/encrypt-active-force-16.png) skin/aero/enigmail/encrypt-disabled-16.png (skin/images/encrypt-disabled-16.png) skin/aero/enigmail/encrypt-inactive-16.png (skin/images/encrypt-inactive-16.png) skin/aero/enigmail/encrypt-inactive-force-16.png (skin/images/encrypt-inactive-force-16.png) skin/aero/enigmail/encrypt-active-30.png (skin/images/encrypt-active-30.png) skin/aero/enigmail/encrypt-active-force-30.png (skin/images/encrypt-active-force-30.png) skin/aero/enigmail/encrypt-disabled-30.png (skin/images/encrypt-disabled-30.png) skin/aero/enigmail/encrypt-inactive-30.png (skin/images/encrypt-inactive-30.png) skin/aero/enigmail/encrypt-inactive-force-30.png (skin/images/encrypt-inactive-force-30.png) skin/aero/enigmail/sign-active-16.png (skin/images/sign-active-16.png) skin/aero/enigmail/sign-active-force-16.png (skin/images/sign-active-force-16.png) skin/aero/enigmail/sign-disabled-16.png (skin/images/sign-disabled-16.png) skin/aero/enigmail/sign-inactive-16.png (skin/images/sign-inactive-16.png) skin/aero/enigmail/sign-inactive-force-16.png (skin/images/sign-inactive-force-16.png) skin/aero/enigmail/sign-active-30.png (skin/images/sign-active-30.png) skin/aero/enigmail/sign-active-force-30.png (skin/images/sign-active-force-30.png) skin/aero/enigmail/sign-disabled-30.png (skin/images/sign-disabled-30.png) skin/aero/enigmail/sign-inactive-30.png (skin/images/sign-inactive-30.png) skin/aero/enigmail/sign-inactive-force-30.png (skin/images/sign-inactive-force-30.png) skin/aero/enigmail/attach-active-16.png (skin/images/attach-active-16.png) skin/aero/enigmail/attach-disabled-16.png (skin/images/attach-disabled-16.png) skin/aero/enigmail/attach-inactive-16.png (skin/images/attach-inactive-16.png) skin/aero/enigmail/password-error.png (skin/images/password-error.png) skin/aero/enigmail/warning-16.png (skin/images/warning-16.png) skin/aero/enigmail/col-pEpGreen.svg (skin/images/col-pEpGreen.svg) skin/aero/enigmail/col-pEpYellow.svg (skin/images/col-pEpYellow.svg) skin/aero/enigmail/col-pEpRed.svg (skin/images/col-pEpRed.svg) skin/aero/enigmail/pEpGreen.svg (skin/images/pEpGreen.svg) skin/aero/enigmail/pEpYellow.svg (skin/images/pEpYellow.svg) skin/aero/enigmail/pEpRed.svg (skin/images/pEpRed.svg) skin/aero/enigmail/pEpEncryptActive.svg (skin/images/pEpEncryptActive.svg) skin/aero/enigmail/pEpEncryptInactive.svg (skin/images/pEpEncryptInactive.svg) skin/aero/enigmail/pEpLogo.svg (skin/images/pEpLogo.svg) skin/tb-mac/enigmail/enigmail.css (skin/tb-mac/enigmail.css) skin/tb-mac/enigmail/enigmail-common.css (skin/common/enigmail-common.css) skin/tb-mac/enigmail/enigmail-pEp.css (skin/common/enigmail-pEp.css) skin/tb-mac/enigmail/enigmail-about.png (skin/images/enigmail-about.png) skin/tb-mac/enigmail/enigmail-logo.png (skin/images/enigmail-logo.png) skin/tb-mac/enigmail/enigmail-decrypt.png (skin/tb-mac/images/enigmail-decrypt.png) skin/tb-mac/enigmail/enigmail-decrypt-inactive.png (skin/tb-mac/images/enigmail-decrypt-inactive.png) skin/tb-mac/enigmail/enigmail-decrypt-small.png (skin/tb-mac/images/enigmail-decrypt-small.png) skin/tb-mac/enigmail/enigmail-decrypt-small-inactive.png (skin/tb-mac/images/enigmail-decrypt-small-inactive.png) skin/tb-mac/enigmail/enigEncInactive.png (skin/tb-mac/images/enigEncInactive.png) skin/tb-mac/enigmail/enigEncNotOk.png (skin/tb-mac/images/enigEncNotOk.png) skin/tb-mac/enigmail/enigEncOk.png (skin/tb-mac/images/enigEncOk.png) skin/tb-mac/enigmail/enigSignInactive.png (skin/tb-mac/images/enigSignInactive.png) skin/tb-mac/enigmail/enigSignNotOk.png (skin/tb-mac/images/enigSignNotOk.png) skin/tb-mac/enigmail/enigSignOk.png (skin/tb-mac/images/enigSignOk.png) skin/tb-mac/enigmail/enigSignUnkown.png (skin/tb-mac/images/enigSignUnkown.png) skin/tb-mac/enigmail/twisty-open.png (skin/images/twisty-open.png) skin/tb-mac/enigmail/twisty-clsd.png (skin/images/twisty-clsd.png) skin/tb-mac/enigmail/spinning-wheel.png (skin/images/spinning-wheel.png) skin/tb-mac/enigmail/col-encrypted-signed.png (skin/tb-mac/images/col-encrypted-signed.png) skin/tb-mac/enigmail/enigSignActiveNone.png (skin/tb-windows/images/enigSignActiveNone.png) skin/tb-mac/enigmail/enigSignActivePlus.png (skin/tb-windows/images/enigSignActivePlus.png) skin/tb-mac/enigmail/enigSignActiveMinus.png (skin/tb-windows/images/enigSignActiveMinus.png) skin/tb-mac/enigmail/enigSignActiveConflict.png (skin/tb-windows/images/enigSignActiveConflict.png) skin/tb-mac/enigmail/enigSignInactiveNone.png (skin/tb-windows/images/enigSignInactiveNone.png) skin/tb-mac/enigmail/enigSignInactivePlus.png (skin/tb-windows/images/enigSignInactivePlus.png) skin/tb-mac/enigmail/enigSignInactiveMinus.png (skin/tb-windows/images/enigSignInactiveMinus.png) skin/tb-mac/enigmail/enigSignInactiveConflict.png (skin/tb-windows/images/enigSignInactiveConflict.png) skin/tb-mac/enigmail/enigSignForceYes.png (skin/tb-windows/images/enigSignForceYes.png) skin/tb-mac/enigmail/enigSignForceNo.png (skin/tb-windows/images/enigSignForceNo.png) skin/tb-mac/enigmail/enigEncActiveNone.png (skin/tb-windows/images/enigEncActiveNone.png) skin/tb-mac/enigmail/enigEncActivePlus.png (skin/tb-windows/images/enigEncActivePlus.png) skin/tb-mac/enigmail/enigEncActiveMinus.png (skin/tb-windows/images/enigEncActiveMinus.png) skin/tb-mac/enigmail/enigEncActiveConflict.png (skin/tb-windows/images/enigEncActiveConflict.png) skin/tb-mac/enigmail/enigEncInactiveNone.png (skin/tb-windows/images/enigEncInactiveNone.png) skin/tb-mac/enigmail/enigEncInactivePlus.png (skin/tb-windows/images/enigEncInactivePlus.png) skin/tb-mac/enigmail/enigEncInactiveMinus.png (skin/tb-windows/images/enigEncInactiveMinus.png) skin/tb-mac/enigmail/enigEncInactiveConflict.png (skin/tb-windows/images/enigEncInactiveConflict.png) skin/tb-mac/enigmail/enigEncForceYes.png (skin/tb-windows/images/enigEncForceYes.png) skin/tb-mac/enigmail/enigEncForceNo.png (skin/tb-windows/images/enigEncForceNo.png) skin/tb-mac/enigmail/encrypt-active-18.png (skin/images/encrypt-active-18.png) skin/tb-mac/enigmail/encrypt-active-force-18.png (skin/images/encrypt-active-force-18.png) skin/tb-mac/enigmail/encrypt-disabled-18.png (skin/images/encrypt-disabled-18.png) skin/tb-mac/enigmail/encrypt-inactive-18.png (skin/images/encrypt-inactive-18.png) skin/tb-mac/enigmail/encrypt-inactive-force-18.png (skin/images/encrypt-inactive-force-18.png) skin/tb-mac/enigmail/encrypt-active-30.png (skin/images/encrypt-active-30.png) skin/tb-mac/enigmail/encrypt-active-force-30.png (skin/images/encrypt-active-force-30.png) skin/tb-mac/enigmail/encrypt-disabled-30.png (skin/images/encrypt-disabled-30.png) skin/tb-mac/enigmail/encrypt-inactive-30.png (skin/images/encrypt-inactive-30.png) skin/tb-mac/enigmail/encrypt-inactive-force-30.png (skin/images/encrypt-inactive-force-30.png) skin/tb-mac/enigmail/attach-active-24.png (skin/images/attach-active-24.png) skin/tb-mac/enigmail/attach-inactive-24.png (skin/images/attach-inactive-24.png) skin/tb-mac/enigmail/attach-disabled-24.png (skin/images/attach-disabled-24.png) skin/tb-mac/enigmail/attach-active-30.png (skin/images/attach-active-30.png) skin/tb-mac/enigmail/attach-inactive-30.png (skin/images/attach-inactive-30.png) skin/tb-mac/enigmail/attach-disabled-30.png (skin/images/attach-disabled-30.png) skin/tb-mac/enigmail/sign-active-18.png (skin/images/sign-active-18.png) skin/tb-mac/enigmail/sign-active-force-18.png (skin/images/sign-active-force-18.png) skin/tb-mac/enigmail/sign-disabled-18.png (skin/images/sign-disabled-18.png) skin/tb-mac/enigmail/sign-inactive-18.png (skin/images/sign-inactive-18.png) skin/tb-mac/enigmail/sign-inactive-force-18.png (skin/images/sign-inactive-force-18.png) skin/tb-mac/enigmail/sign-active-30.png (skin/images/sign-active-30.png) skin/tb-mac/enigmail/sign-active-force-30.png (skin/images/sign-active-force-30.png) skin/tb-mac/enigmail/sign-disabled-30.png (skin/images/sign-disabled-30.png) skin/tb-mac/enigmail/sign-inactive-30.png (skin/images/sign-inactive-30.png) skin/tb-mac/enigmail/sign-inactive-force-30.png (skin/images/sign-inactive-force-30.png) skin/tb-mac/enigmail/warning-16.png (skin/images/warning-16.png) skin/tb-mac/enigmail/password-error.png (skin/images/password-error.png) skin/tb-mac/enigmail/col-pEpGreen.svg (skin/images/col-pEpGreen.svg) skin/tb-mac/enigmail/col-pEpYellow.svg (skin/images/col-pEpYellow.svg) skin/tb-mac/enigmail/col-pEpRed.svg (skin/images/col-pEpRed.svg) skin/tb-mac/enigmail/pEpGreen.svg (skin/images/pEpGreen.svg) skin/tb-mac/enigmail/pEpGrey.svg (skin/images/pEpGrey.svg) skin/tb-mac/enigmail/pEpYellow.svg (skin/images/pEpYellow.svg) skin/tb-mac/enigmail/pEpRed.svg (skin/images/pEpRed.svg) skin/tb-mac/enigmail/pEpEncryptActive.svg (skin/images/pEpEncryptActive.svg) skin/tb-mac/enigmail/pEpEncryptInactive.svg (skin/images/pEpEncryptInactive.svg) skin/tb-mac/enigmail/pEpLogo.svg (skin/images/pEpLogo.svg) skin/tb-linux/enigmail/enigmail.css (skin/tb-linux/enigmail.css) skin/tb-linux/enigmail/enigmail-common.css (skin/common/enigmail-common.css) skin/tb-linux/enigmail/enigmail-pEp.css (skin/common/enigmail-pEp.css) skin/tb-linux/enigmail/enigmail-about.png (skin/images/enigmail-about.png) skin/tb-linux/enigmail/enigmail-logo.png (skin/images/enigmail-logo.png) skin/tb-linux/enigmail/enigmail-toolbar.png (skin/tb-linux/images/enigmail-toolbar.png) skin/tb-linux/enigmail/enigmail-toolbar-small.png (skin/tb-linux/images/enigmail-toolbar-small.png) skin/tb-linux/enigmail/enigmail-settings.png (skin/tb-linux/images/enigmail-settings.png) skin/tb-linux/enigmail/enigmail-settings-small.png (skin/tb-linux/images/enigmail-settings-small.png) skin/tb-linux/enigmail/enigEncInactive.png (skin/tb-linux/images/enigEncInactive.png) skin/tb-linux/enigmail/enigEncNotOk.png (skin/tb-linux/images/enigEncNotOk.png) skin/tb-linux/enigmail/enigEncOk.png (skin/tb-linux/images/enigEncOk.png) skin/tb-linux/enigmail/enigSignInactive.png (skin/tb-linux/images/enigSignInactive.png) skin/tb-linux/enigmail/enigSignNotOk.png (skin/tb-linux/images/enigSignNotOk.png) skin/tb-linux/enigmail/enigSignOk.png (skin/tb-linux/images/enigSignOk.png) skin/tb-linux/enigmail/enigSignUnkown.png (skin/tb-linux/images/enigSignUnkown.png) skin/tb-linux/enigmail/twisty-open.png (skin/images/twisty-open.png) skin/tb-linux/enigmail/twisty-clsd.png (skin/images/twisty-clsd.png) skin/tb-linux/enigmail/spinning-wheel.png (skin/images/spinning-wheel.png) skin/tb-linux/enigmail/col-encrypted-signed.png (skin/tb-linux/images/col-encrypted-signed.png) skin/tb-linux/enigmail/enigSignActiveNone.png (skin/tb-windows/images/enigSignActiveNone.png) skin/tb-linux/enigmail/enigSignActivePlus.png (skin/tb-windows/images/enigSignActivePlus.png) skin/tb-linux/enigmail/enigSignActiveMinus.png (skin/tb-windows/images/enigSignActiveMinus.png) skin/tb-linux/enigmail/enigSignActiveConflict.png (skin/tb-windows/images/enigSignActiveConflict.png) skin/tb-linux/enigmail/enigSignInactiveNone.png (skin/tb-windows/images/enigSignInactiveNone.png) skin/tb-linux/enigmail/enigSignInactivePlus.png (skin/tb-windows/images/enigSignInactivePlus.png) skin/tb-linux/enigmail/enigSignInactiveMinus.png (skin/tb-windows/images/enigSignInactiveMinus.png) skin/tb-linux/enigmail/enigSignInactiveConflict.png (skin/tb-windows/images/enigSignInactiveConflict.png) skin/tb-linux/enigmail/enigSignForceNo.png (skin/tb-windows/images/enigSignForceNo.png) skin/tb-linux/enigmail/enigSignForceYes.png (skin/tb-windows/images/enigSignForceYes.png) skin/tb-linux/enigmail/enigEncActiveNone.png (skin/tb-windows/images/enigEncActiveNone.png) skin/tb-linux/enigmail/enigEncActivePlus.png (skin/tb-windows/images/enigEncActivePlus.png) skin/tb-linux/enigmail/enigEncActiveMinus.png (skin/tb-windows/images/enigEncActiveMinus.png) skin/tb-linux/enigmail/enigEncActiveConflict.png (skin/tb-windows/images/enigEncActiveConflict.png) skin/tb-linux/enigmail/enigEncInactiveNone.png (skin/tb-windows/images/enigEncInactiveNone.png) skin/tb-linux/enigmail/enigEncInactivePlus.png (skin/tb-windows/images/enigEncInactivePlus.png) skin/tb-linux/enigmail/enigEncInactiveMinus.png (skin/tb-windows/images/enigEncInactiveMinus.png) skin/tb-linux/enigmail/enigEncInactiveConflict.png (skin/tb-windows/images/enigEncInactiveConflict.png) skin/tb-linux/enigmail/enigEncForceNo.png (skin/tb-windows/images/enigEncForceNo.png) skin/tb-linux/enigmail/enigEncForceYes.png (skin/tb-windows/images/enigEncForceYes.png) skin/tb-linux/enigmail/encrypt-active-24.png (skin/images/encrypt-active-24.png) skin/tb-linux/enigmail/encrypt-active-force-24.png (skin/images/encrypt-active-force-24.png) skin/tb-linux/enigmail/encrypt-disabled-24.png (skin/images/encrypt-disabled-24.png) skin/tb-linux/enigmail/encrypt-inactive-24.png (skin/images/encrypt-inactive-24.png) skin/tb-linux/enigmail/encrypt-inactive-force-24.png (skin/images/encrypt-inactive-force-24.png) skin/tb-linux/enigmail/encrypt-active-30.png (skin/images/encrypt-active-30.png) skin/tb-linux/enigmail/encrypt-active-force-30.png (skin/images/encrypt-active-force-30.png) skin/tb-linux/enigmail/encrypt-disabled-30.png (skin/images/encrypt-disabled-30.png) skin/tb-linux/enigmail/encrypt-inactive-30.png (skin/images/encrypt-inactive-30.png) skin/tb-linux/enigmail/encrypt-inactive-force-30.png (skin/images/encrypt-inactive-force-30.png) skin/tb-linux/enigmail/sign-active-24.png (skin/images/sign-active-24.png) skin/tb-linux/enigmail/sign-active-force-24.png (skin/images/sign-active-force-24.png) skin/tb-linux/enigmail/sign-disabled-24.png (skin/images/sign-disabled-24.png) skin/tb-linux/enigmail/sign-inactive-24.png (skin/images/sign-inactive-24.png) skin/tb-linux/enigmail/sign-inactive-force-24.png (skin/images/sign-inactive-force-24.png) skin/tb-linux/enigmail/sign-active-30.png (skin/images/sign-active-30.png) skin/tb-linux/enigmail/sign-active-force-30.png (skin/images/sign-active-force-30.png) skin/tb-linux/enigmail/sign-disabled-30.png (skin/images/sign-disabled-30.png) skin/tb-linux/enigmail/sign-inactive-30.png (skin/images/sign-inactive-30.png) skin/tb-linux/enigmail/sign-inactive-force-30.png (skin/images/sign-inactive-force-30.png) skin/tb-linux/enigmail/attach-active-24.png (skin/images/attach-active-24.png) skin/tb-linux/enigmail/attach-inactive-24.png (skin/images/attach-inactive-24.png) skin/tb-linux/enigmail/attach-disabled-24.png (skin/images/attach-disabled-24.png) skin/tb-linux/enigmail/attach-active-30.png (skin/images/attach-active-30.png) skin/tb-linux/enigmail/attach-inactive-30.png (skin/images/attach-inactive-30.png) skin/tb-linux/enigmail/attach-disabled-30.png (skin/images/attach-disabled-30.png) skin/tb-linux/enigmail/warning-16.png (skin/images/warning-16.png) skin/tb-linux/enigmail/password-error.png (skin/images/password-error.png) skin/tb-linux/enigmail/col-pEpGreen.svg (skin/images/col-pEpGreen.svg) skin/tb-linux/enigmail/col-pEpYellow.svg (skin/images/col-pEpYellow.svg) skin/tb-linux/enigmail/col-pEpRed.svg (skin/images/col-pEpRed.svg) skin/tb-linux/enigmail/pEpGreen.svg (skin/images/pEpGreen.svg) skin/tb-linux/enigmail/pEpYellow.svg (skin/images/pEpYellow.svg) skin/tb-linux/enigmail/pEpRed.svg (skin/images/pEpRed.svg) skin/tb-linux/enigmail/pEpEncryptActive.svg (skin/images/pEpEncryptActive.svg) skin/tb-linux/enigmail/pEpEncryptInactive.svg (skin/images/pEpEncryptInactive.svg) skin/tb-linux/enigmail/pEpLogo.svg (skin/images/pEpLogo.svg) skin/classic-seamonkey/enigmail/enigmail.css (skin/classic-seamonkey/enigmail.css) skin/classic-seamonkey/enigmail/enigmail-common.css (skin/common/enigmail-common.css) skin/classic-seamonkey/enigmail/enigmail-pEp.css (skin/common/enigmail-pEp.css) skin/classic-seamonkey/enigmail/enigmail-about.png (skin/images/enigmail-about.png) skin/classic-seamonkey/enigmail/enigmail-logo.png (skin/images/enigmail-logo.png) skin/classic-seamonkey/enigmail/enigmail-toolbar.png (skin/classic-seamonkey/images/enigmail-toolbar.png) skin/classic-seamonkey/enigmail/enigmail-toolbar-small.png (skin/classic-seamonkey/images/enigmail-toolbar-small.png) skin/classic-seamonkey/enigmail/enigmail-send.png (skin/classic-seamonkey/images/enigmail-send.png) skin/classic-seamonkey/enigmail/enigmail-send-small.png (skin/classic-seamonkey/images/enigmail-send-small.png) skin/classic-seamonkey/enigmail/enigEncInactive.png (skin/classic-seamonkey/images/enigEncInactive.png) skin/classic-seamonkey/enigmail/enigEncNotOk.png (skin/classic-seamonkey/images/enigEncNotOk.png) skin/classic-seamonkey/enigmail/enigEncOk.png (skin/classic-seamonkey/images/enigEncOk.png) skin/classic-seamonkey/enigmail/enigSignInactive.png (skin/classic-seamonkey/images/enigSignInactive.png) skin/classic-seamonkey/enigmail/enigSignNotOk.png (skin/classic-seamonkey/images/enigSignNotOk.png) skin/classic-seamonkey/enigmail/enigSignOk.png (skin/classic-seamonkey/images/enigSignOk.png) skin/classic-seamonkey/enigmail/enigSignUnkown.png (skin/classic-seamonkey/images/enigSignUnkown.png) skin/classic-seamonkey/enigmail/twisty-open.png (skin/images/twisty-open.png) skin/classic-seamonkey/enigmail/twisty-clsd.png (skin/images/twisty-clsd.png) skin/classic-seamonkey/enigmail/spinning-wheel.png (skin/images/spinning-wheel.png) skin/classic-seamonkey/enigmail/col-encrypted-signed.png (skin/classic-seamonkey/images/col-encrypted-signed.png) skin/classic-seamonkey/enigmail/enigSignActiveNone.png (skin/tb-windows/images/enigSignActiveNone.png) skin/classic-seamonkey/enigmail/enigSignActivePlus.png (skin/tb-windows/images/enigSignActivePlus.png) skin/classic-seamonkey/enigmail/enigSignActiveMinus.png (skin/tb-windows/images/enigSignActiveMinus.png) skin/classic-seamonkey/enigmail/enigSignActiveConflict.png (skin/tb-windows/images/enigSignActiveConflict.png) skin/classic-seamonkey/enigmail/enigSignInactiveNone.png (skin/tb-windows/images/enigSignInactiveNone.png) skin/classic-seamonkey/enigmail/enigSignInactivePlus.png (skin/tb-windows/images/enigSignInactivePlus.png) skin/classic-seamonkey/enigmail/enigSignInactiveMinus.png (skin/tb-windows/images/enigSignInactiveMinus.png) skin/classic-seamonkey/enigmail/enigSignInactiveConflict.png (skin/tb-windows/images/enigSignInactiveConflict.png) skin/classic-seamonkey/enigmail/enigSignForceYes.png (skin/tb-windows/images/enigSignForceYes.png) skin/classic-seamonkey/enigmail/enigSignForceNo.png (skin/tb-windows/images/enigSignForceNo.png) skin/classic-seamonkey/enigmail/enigEncActiveNone.png (skin/tb-windows/images/enigEncActiveNone.png) skin/classic-seamonkey/enigmail/enigEncActivePlus.png (skin/tb-windows/images/enigEncActivePlus.png) skin/classic-seamonkey/enigmail/enigEncActiveMinus.png (skin/tb-windows/images/enigEncActiveMinus.png) skin/classic-seamonkey/enigmail/enigEncActiveConflict.png (skin/tb-windows/images/enigEncActiveConflict.png) skin/classic-seamonkey/enigmail/enigEncInactiveNone.png (skin/tb-windows/images/enigEncInactiveNone.png) skin/classic-seamonkey/enigmail/enigEncInactivePlus.png (skin/tb-windows/images/enigEncInactivePlus.png) skin/classic-seamonkey/enigmail/enigEncInactiveMinus.png (skin/tb-windows/images/enigEncInactiveMinus.png) skin/classic-seamonkey/enigmail/enigEncInactiveConflict.png (skin/tb-windows/images/enigEncInactiveConflict.png) skin/classic-seamonkey/enigmail/enigEncForceYes.png (skin/tb-windows/images/enigEncForceYes.png) skin/classic-seamonkey/enigmail/enigEncForceNo.png (skin/tb-windows/images/enigEncForceNo.png) skin/classic-seamonkey/enigmail/encrypt-active-24.png (skin/images/encrypt-active-24.png) skin/classic-seamonkey/enigmail/encrypt-active-force-24.png (skin/images/encrypt-active-force-24.png) skin/classic-seamonkey/enigmail/encrypt-disabled-24.png (skin/images/encrypt-disabled-24.png) skin/classic-seamonkey/enigmail/encrypt-inactive-24.png (skin/images/encrypt-inactive-24.png) skin/classic-seamonkey/enigmail/encrypt-inactive-force-24.png (skin/images/encrypt-inactive-force-24.png) skin/classic-seamonkey/enigmail/encrypt-active-30.png (skin/images/encrypt-active-30.png) skin/classic-seamonkey/enigmail/encrypt-active-force-30.png (skin/images/encrypt-active-force-30.png) skin/classic-seamonkey/enigmail/encrypt-disabled-30.png (skin/images/encrypt-disabled-30.png) skin/classic-seamonkey/enigmail/encrypt-inactive-30.png (skin/images/encrypt-inactive-30.png) skin/classic-seamonkey/enigmail/encrypt-inactive-force-30.png (skin/images/encrypt-inactive-force-30.png) skin/classic-seamonkey/enigmail/sign-active-24.png (skin/images/sign-active-24.png) skin/classic-seamonkey/enigmail/sign-active-force-24.png (skin/images/sign-active-force-24.png) skin/classic-seamonkey/enigmail/sign-disabled-24.png (skin/images/sign-disabled-24.png) skin/classic-seamonkey/enigmail/sign-inactive-24.png (skin/images/sign-inactive-24.png) skin/classic-seamonkey/enigmail/sign-inactive-force-24.png (skin/images/sign-inactive-force-24.png) skin/classic-seamonkey/enigmail/sign-active-30.png (skin/images/sign-active-30.png) skin/classic-seamonkey/enigmail/sign-active-force-30.png (skin/images/sign-active-force-30.png) skin/classic-seamonkey/enigmail/sign-disabled-30.png (skin/images/sign-disabled-30.png) skin/classic-seamonkey/enigmail/sign-inactive-30.png (skin/images/sign-inactive-30.png) skin/classic-seamonkey/enigmail/sign-inactive-force-30.png (skin/images/sign-inactive-force-30.png) skin/classic-seamonkey/enigmail/attach-active-24.png (skin/images/attach-active-24.png) skin/classic-seamonkey/enigmail/attach-inactive-24.png (skin/images/attach-inactive-24.png) skin/classic-seamonkey/enigmail/attach-disabled-24.png (skin/images/attach-disabled-24.png) skin/classic-seamonkey/enigmail/attach-active-30.png (skin/images/attach-active-30.png) skin/classic-seamonkey/enigmail/attach-inactive-30.png (skin/images/attach-inactive-30.png) skin/classic-seamonkey/enigmail/attach-disabled-30.png (skin/images/attach-disabled-30.png) skin/classic-seamonkey/enigmail/warning-16.png (skin/images/warning-16.png) skin/classic-seamonkey/enigmail/password-error.png (skin/images/password-error.png) skin/classic-seamonkey/enigmail/col-pEpGreen.svg (skin/images/col-pEpGreen.svg) skin/classic-seamonkey/enigmail/col-pEpYellow.svg (skin/images/col-pEpYellow.svg) skin/classic-seamonkey/enigmail/col-pEpRed.svg (skin/images/col-pEpRed.svg) skin/classic-seamonkey/enigmail/pEpGreen.svg (skin/images/pEpGreen.svg) skin/classic-seamonkey/enigmail/pEpYellow.svg (skin/images/pEpYellow.svg) skin/classic-seamonkey/enigmail/pEpRed.svg (skin/images/pEpRed.svg) skin/classic-seamonkey/enigmail/pEpEncryptActive.svg (skin/images/pEpEncryptActive.svg) skin/classic-seamonkey/enigmail/pEpEncryptInactive.svg (skin/images/pEpEncryptInactive.svg) skin/classic-seamonkey/enigmail/pEpLogo.svg (skin/images/pEpLogo.svg) skin/modern/enigmail/enigmail.css (skin/modern/enigmail.css) skin/modern/enigmail/enigmail-common.css (skin/common/enigmail-common.css) skin/modern/enigmail/enigmail-pEp.css (skin/common/enigmail-pEp.css) skin/modern/enigmail/enigmail-about.png (skin/images/enigmail-about.png) skin/modern/enigmail/enigmail-logo.png (skin/images/enigmail-logo.png) skin/modern/enigmail/enigdecrypt-act.png (skin/images/enigdecrypt-act.png) skin/modern/enigmail/enigdecrypt-dis.png (skin/images/enigdecrypt-dis.png) skin/modern/enigmail/enigdecrypt-hov.png (skin/images/enigdecrypt-hov.png) skin/modern/enigmail/enigdecrypt.png (skin/images/enigdecrypt.png) skin/modern/enigmail/enigEncInactive.png (skin/tb-windows/images/enigEncInactive.png) skin/modern/enigmail/enigEncNotOk.png (skin/tb-windows/images/enigEncNotOk.png) skin/modern/enigmail/enigEncOk.png (skin/tb-windows/images/enigEncOk.png) skin/modern/enigmail/enigSignInactive.png (skin/tb-windows/images/enigSignInactive.png) skin/modern/enigmail/enigSignNotOk.png (skin/tb-windows/images/enigSignNotOk.png) skin/modern/enigmail/enigSignOk.png (skin/tb-windows/images/enigSignOk.png) skin/modern/enigmail/enigSignUnkown.png (skin/images/enigSignUnkown.png) skin/modern/enigmail/modern-encrypt-active-force.png (skin/images/modern-encrypt-active-force.png) skin/modern/enigmail/modern-encrypt-active.png (skin/images/modern-encrypt-active.png) skin/modern/enigmail/modern-encrypt-inactive-force.png (skin/images/modern-encrypt-inactive-force.png) skin/modern/enigmail/modern-encrypt-inactive.png (skin/images/modern-encrypt-inactive.png) skin/modern/enigmail/modern-sign-active-force.png (skin/images/modern-sign-active-force.png) skin/modern/enigmail/modern-sign-active.png (skin/images/modern-sign-active.png) skin/modern/enigmail/modern-sign-inactive-force.png (skin/images/modern-sign-inactive-force.png) skin/modern/enigmail/modern-sign-inactive.png (skin/images/modern-sign-inactive.png) skin/modern/enigmail/modern-attach-active.png (skin/images/modern-attach-active.png) skin/modern/enigmail/modern-attach-disabled.png (skin/images/modern-attach-disabled.png) skin/modern/enigmail/modern-attach-inactive.png (skin/images/modern-attach-inactive.png) skin/modern/enigmail/twisty-open.png (skin/images/twisty-open.png) skin/modern/enigmail/twisty-clsd.png (skin/images/twisty-clsd.png) skin/modern/enigmail/spinning-wheel.png (skin/images/spinning-wheel.png) skin/modern/enigmail/col-encrypted-signed.png (skin/images/col-encrypted-signed.png) skin/modern/enigmail/enigSignActiveNone.png (skin/tb-windows/images/enigSignActiveNone.png) skin/modern/enigmail/enigSignActivePlus.png (skin/tb-windows/images/enigSignActivePlus.png) skin/modern/enigmail/enigSignActiveMinus.png (skin/tb-windows/images/enigSignActiveMinus.png) skin/modern/enigmail/enigSignActiveConflict.png (skin/tb-windows/images/enigSignActiveConflict.png) skin/modern/enigmail/enigSignInactiveNone.png (skin/tb-windows/images/enigSignInactiveNone.png) skin/modern/enigmail/enigSignInactivePlus.png (skin/tb-windows/images/enigSignInactivePlus.png) skin/modern/enigmail/enigSignInactiveMinus.png (skin/tb-windows/images/enigSignInactiveMinus.png) skin/modern/enigmail/enigSignInactiveConflict.png (skin/tb-windows/images/enigSignInactiveConflict.png) skin/modern/enigmail/enigSignForceYes.png (skin/tb-windows/images/enigSignForceYes.png) skin/modern/enigmail/enigSignForceNo.png (skin/tb-windows/images/enigSignForceNo.png) skin/modern/enigmail/enigEncActiveNone.png (skin/tb-windows/images/enigEncActiveNone.png) skin/modern/enigmail/enigEncActivePlus.png (skin/tb-windows/images/enigEncActivePlus.png) skin/modern/enigmail/enigEncActiveMinus.png (skin/tb-windows/images/enigEncActiveMinus.png) skin/modern/enigmail/enigEncActiveConflict.png (skin/tb-windows/images/enigEncActiveConflict.png) skin/modern/enigmail/enigEncInactiveNone.png (skin/tb-windows/images/enigEncInactiveNone.png) skin/modern/enigmail/enigEncInactivePlus.png (skin/tb-windows/images/enigEncInactivePlus.png) skin/modern/enigmail/enigEncInactiveMinus.png (skin/tb-windows/images/enigEncInactiveMinus.png) skin/modern/enigmail/enigEncInactiveConflict.png (skin/tb-windows/images/enigEncInactiveConflict.png) skin/modern/enigmail/enigEncForceYes.png (skin/tb-windows/images/enigEncForceYes.png) skin/modern/enigmail/enigEncForceNo.png (skin/tb-windows/images/enigEncForceNo.png) skin/modern/enigmail/modern-toolbar-background.png (skin/images/modern-toolbar-background.png) skin/modern/enigmail/warning-16.png (skin/images/warning-16.png) skin/modern/enigmail/password-error.png (skin/images/password-error.png) skin/modern/enigmail/col-pEpGreen.svg (skin/images/col-pEpGreen.svg) skin/modern/enigmail/col-pEpYellow.svg (skin/images/col-pEpYellow.svg) skin/modern/enigmail/col-pEpRed.svg (skin/images/col-pEpRed.svg) skin/modern/enigmail/pEpGreen.svg (skin/images/pEpGreen.svg) skin/modern/enigmail/pEpYellow.svg (skin/images/pEpYellow.svg) skin/modern/enigmail/pEpRed.svg (skin/images/pEpRed.svg) skin/modern/enigmail/pEpEncryptActive.svg (skin/images/pEpEncryptActive.svg) skin/modern/enigmail/pEpEncryptInactive.svg (skin/images/pEpEncryptInactive.svg) skin/modern/enigmail/pEpLogo.svg (skin/images/pEpLogo.svg)