diff --git a/package/prefs/enigmail.js b/package/prefs/enigmail.js index abd95953..2794bdce 100755 --- a/package/prefs/enigmail.js +++ b/package/prefs/enigmail.js @@ -1,269 +1,269 @@ /* global pref: 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/. */ /** * Default pref values for Enigmail */ // use pEp or Enigmail engine for encryption/decryption // 0: force using Enigmail // 1: automatic mode (use pEp if Enigmail and S/MIME are not configured for any identity) // 2: force using pEp pref("extensions.enigmail.juniorMode", 1); // the last configured Enigmail version pref("extensions.enigmail.configuredVersion", ""); // Hide prefs and menu entries from non-advanced users pref("extensions.enigmail.advancedUser", false); // additional parameter(s) to pass to GnuPG pref("extensions.enigmail.agentAdditionalParam", ""); // path to gpg executable pref("extensions.enigmail.agentPath", ""); // allow empty subject line without asking for confirmation pref("extensions.enigmail.allowEmptySubject", false); // ** enigmail keySel preferences: // use rules to assign keys pref("extensions.enigmail.assignKeysByRules", true); // use email addresses to assign keys pref("extensions.enigmail.assignKeysByEmailAddr", true); // use manual dialog to assign missing keys pref("extensions.enigmail.assignKeysManuallyIfMissing", true); // always srats manual dialog for keys pref("extensions.enigmail.assignKeysManuallyAlways", false); // automatically download missing keys from keyserver pref("extensions.enigmail.autoKeyRetrieve", ""); // enable automatically decrypt/verify pref("extensions.enigmail.autoDecrypt", true); // enable X-Enigmail-xxx headers pref("extensions.enigmail.addHeaders", false); // countdown for alerts when composing inline PGP HTML msgs pref("extensions.enigmail.composeHtmlAlertCount", 3); // show warning message when clicking on sign icon pref("extensions.enigmail.displaySignWarn", true); // display warning as info for partially signed message pref("extensions.enigmail.displayPartiallySigned", true); // try to match secondary uid to from address pref("extensions.enigmail.displaySecondaryUid", true); // treat '-- ' as signature separator pref("extensions.enigmail.doubleDashSeparator", true); // last state of dialog to choose encryption method if there are attachments pref("extensions.enigmail.encryptAttachments", 1); // skip the attachments dialog pref("extensions.enigmail.encryptAttachmentsSkipDlg", 0); // Encrypt to self pref("extensions.enigmail.encryptToSelf", true); // enable 'Decrypt & open' for double click on attachment (if possible) pref("extensions.enigmail.handleDoubleClick", true); // disable '<' and '>' around email addresses pref("extensions.enigmail.hushMailSupport", false); // display alert for 'failed to initialize enigmime' pref("extensions.enigmail.initAlert", true); // use -a for encrypting attachments for inline PGP pref("extensions.enigmail.inlineAttachAsciiArmor", false); // extension to append for inline-encrypted attachments pref("extensions.enigmail.inlineAttachExt", ".pgp"); // extension to append for inline-signed attachments pref("extensions.enigmail.inlineSigAttachExt", ".sig"); // debug log directory (if set, also enabled debugging) pref("extensions.enigmail.logDirectory", ""); // display all or no keys by default in the key manager pref("extensions.enigmail.keyManShowAllKeys", true); // list of keyservers to use pref("extensions.enigmail.keyserver", "pool.sks-keyservers.net, keys.gnupg.net, pgp.mit.edu"); // auto select the first keyserver in the key server list pref("extensions.enigmail.autoKeyServerSelection", true); // keep passphrase for ... minutes pref("extensions.enigmail.maxIdleMinutes", 5); // GnuPG hash algorithm // 0: automatic seletion (i.e. let GnuPG choose) // 1: SHA1, 2: RIPEMD160, 3: SHA256, 4: SHA384, 5: SHA512, 6: SHA224 pref("extensions.enigmail.mimeHashAlgorithm", 0); // no passphrase for GnuPG key needed pref("extensions.enigmail.noPassphrase", false); // show quoted printable warning message (and remember selected state) pref("extensions.enigmail.quotedPrintableWarn", 0); // use http proxy settings as set in Mozilla/Thunderbird pref("extensions.enigmail.respectHttpProxy", true); // selection for which encryption model to prefer // 0: convenient encryption settings DEFAULT // 1: manual encryption settings pref("extensions.enigmail.encryptionModel", 0); // enable encryption for replies to encrypted mails pref("extensions.enigmail.keepSettingsForReply", true); // Warn if a key expires in less than N days. // 0 will disable the check pref("extensions.enigmail.warnKeyExpiryNumDays", 30); // holds the last result of the dayily key expiry check pref("extensions.enigmail.keyCheckResult", ""); // selection for which keys to accept // 0: accept valid/authenticated keys // 1: accept all keys (except disabled, ...) DEFAULT pref("extensions.enigmail.acceptedKeys", 1); // selection for automatic send encrypted if all keys valid // 0: never // 1: if all keys found and accepted DEFAULT pref("extensions.enigmail.autoSendEncrypted", 1); // enable Autocrypt (see www.autocrypt.org) // 0: no // 1: yes pref("extensions.enigmail.autocryptMode", 0); // ask to confirm before sending // 0: never DEFAULT // 1: always // 2: if send encrypted // 3: if send unencrypted // 4: if send (un)encrypted due to rules pref("extensions.enigmail.confirmBeforeSending", 0); // show "Missing Trust in own keys" message (and remember selected state) pref("extensions.enigmail.warnOnMissingOwnerTrust", true); // use GnuPG's default instead of Enigmail/Mozilla comment of for signed messages pref("extensions.enigmail.useDefaultComment", true); // allow encryption to newsgroups pref("extensions.enigmail.encryptToNews", false); pref("extensions.enigmail.warnOnSendingNewsgroups", true); // set locale for GnuPG calls to en-US (Windows only) pref("extensions.enigmail.gpgLocaleEn", true); // use PGP/MIME (0=never, 1=allow, 2=always) // pref("extensions.enigmail.usePGPMimeOption",1); -- OBSOLETE, see mail.identity.default.pgpMimeMode // Use gpg for keyserver operations (vs. Thunderbird) pref("extensions.enigmail.useGpgKeysTool", true); // show "conflicting rules" message (and remember selected state) pref("extensions.enigmail.warnOnRulesConflict", 0); // display a warning when the passphrase is cleared pref("extensions.enigmail.warnClearPassphrase", true); // display a warning if the GnuPG version is deprecated pref("extensions.enigmail.warnDeprecatedGnuPG", true); // warn if gpg-agent is found and "remember passphrase for X minutes is active" pref("extensions.enigmail.warnGpgAgentAndIdleTime", true); // display a warning when all keys are to be refreshed pref("extensions.enigmail.warnRefreshAll", true); // display a warning when the keys for all contacts are downloaded pref("extensions.enigmail.warnDownloadContactKeys", true); // wrap HTML messages before sending inline PGP messages pref("extensions.enigmail.wrapHtmlBeforeSend", true); // enable encryption/signing of headers like subject, from, to pref("extensions.enigmail.protectHeaders", true); pref("extensions.enigmail.protectedSubjectText", ""); // do reset the "references" and "in-reply-to" headers? pref("extensions.enigmail.protectReferencesHdr", false); // tor configuration pref("extensions.enigmail.torIpAddr", "127.0.0.1"); pref("extensions.enigmail.torServicePort", "9050"); pref("extensions.enigmail.torBrowserBundlePort", "9150"); // gpg tor actions pref("extensions.enigmail.downloadKeyWithTor", true); pref("extensions.enigmail.downloadKeyRequireTor", false); pref("extensions.enigmail.searchKeyWithTor", true); pref("extensions.enigmail.searchKeyRequireTor", false); pref("extensions.enigmail.uploadKeyWithTor", true); pref("extensions.enigmail.uploadKeyRequireTor", false); pref("extensions.enigmail.refreshAllKeysWithTor", true); pref("extensions.enigmail.refreshAllKeysRequireTor", false); // Hours per week that Enigmail is available for refreshing keys // The smaller the hours available, the more often the refresh // will happen to accommodate. pref("extensions.enigmail.hoursPerWeekEnigmailIsOn", 40); // Toggle to have user keys continuously refreshed pref("extensions.enigmail.keyRefreshOn", false); // enable experimental features. // WARNING: such features may unfinished functions or tests that can break // existing functionality in Enigmail and Thunderbird! pref("extensions.enigmail.enableExperiments", false); /* Default pref values for the enigmail per-identity settings */ pref("mail.identity.default.enablePgp", false); pref("mail.identity.default.pgpkeyId", ""); pref("mail.identity.default.pgpKeyMode", 0); pref("mail.identity.default.pgpSignPlain", false); pref("mail.identity.default.pgpSignEncrypted", false); pref("mail.identity.default.defaultSigningPolicy", 0); pref("mail.identity.default.defaultEncryptionPolicy", 0); pref("mail.identity.default.openPgpHeaderMode", 0); pref("mail.identity.default.openPgpUrlName", ""); pref("mail.identity.default.pgpMimeMode", true); pref("mail.identity.default.attachPgpKey", true); pref("mail.identity.default.autoEncryptDrafts", true); pref("mail.identity.default.protectSubject", true); -pref("mail.identity.default.warnWeakReply", true); +pref("mail.identity.default.warnWeakReply", false); pref("mail.identity.default.enablePEP", true); // prefer S/MIME or PGP/MIME (0: S/MIME, 1: PGP/MIME) pref("mail.identity.default.mimePreferOpenPGP", 1); /* Other settings (change Mozilla behaviour) */ // disable flowed text by default pref("mailnews.send_plaintext_flowed", false); diff --git a/ui/content/columnOverlay.js b/ui/content/columnOverlay.js index d4bd5cc5..e666ccf1 100644 --- a/ui/content/columnOverlay.js +++ b/ui/content/columnOverlay.js @@ -1,122 +1,122 @@ /* * 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"; /* global Components: false, gDBView: false */ Components.utils.import("resource://enigmail/pEpAdapter.jsm"); /*global EnigmailPEPAdapter: false */ if (!Enigmail) var Enigmail = {}; Enigmail.columnHandler = { nsIEnigmail: Components.interfaces.nsIEnigmail, _usingPep: null, resetUsingPep: function() { this._usingPep = null; }, isUsingPep: function() { if (this._usingPep === null) { this._usingPep = EnigmailPEPAdapter.usingPep(); } return this._usingPep; }, getCellText: function(row, col) { return null; }, getSortStringForRow: function(hdr) { return ""; }, isString: function() { return false; }, getCellProperties: function(row, col, props) { let key = gDBView.getKeyAt(row); let hdr = gDBView.db.GetMsgHdrForKey(key); let newProp = null; if (this.isUsingPep()) { - let rating = hdr.getUint32Property("enigmailPep"); + let rating = hdr.getUint32Property("enigmailPep") & 0xFF; switch (rating) { case 1: newProp = "enigmailPepMistrust"; break; case 2: newProp = "enigmailPepReliable"; break; case 3: newProp = "enigmailPepTrusted"; break; } } else { let statusFlags = hdr.getUint32Property("enigmail"); if ((statusFlags & this.nsIEnigmail.GOOD_SIGNATURE) && (statusFlags & this.nsIEnigmail.DECRYPTION_OKAY)) newProp = "enigSignedEncrypted"; else if (statusFlags & this.nsIEnigmail.GOOD_SIGNATURE) newProp = "enigSigned"; else if (statusFlags & this.nsIEnigmail.DECRYPTION_OKAY) newProp = "enigEncrypted"; } if (newProp) { let atomService = Components.classes["@mozilla.org/atom-service;1"]. getService(Components.interfaces.nsIAtomService); var atom = atomService.getAtom(newProp); return newProp; } return null; }, getRowProperties: function(row, props) {}, getImageSrc: function(row, col) {}, getSortLongForRow: function(hdr) { if (this.isUsingPep()) { return hdr.getUint32Property("enigmailPep"); } var statusFlags = hdr.getUint32Property("enigmail"); if ((statusFlags & this.nsIEnigmail.GOOD_SIGNATURE) && (statusFlags & this.nsIEnigmail.DECRYPTION_OKAY)) return 3; else if (statusFlags & this.nsIEnigmail.GOOD_SIGNATURE) return 2; else if (statusFlags & this.nsIEnigmail.DECRYPTION_OKAY) return 1; return 0; }, createDbObserver: { // Components.interfaces.nsIObserver observe: function(aMsgFolder, aTopic, aData) { try { gDBView.addColumnHandler("enigmailStatusCol", Enigmail.columnHandler); } catch (ex) {} } } }; window.addEventListener("load", function() { var ObserverService = Components.classes["@mozilla.org/observer-service;1"]. getService(Components.interfaces.nsIObserverService); ObserverService.addObserver(Enigmail.columnHandler.createDbObserver, "MsgCreateDBView", false); let folderTree = document.getElementById("folderTree"); folderTree.addEventListener("select", function _f() { Enigmail.columnHandler.resetUsingPep(); }); }, false ); diff --git a/ui/content/enigmailMsgComposeOverlay.js b/ui/content/enigmailMsgComposeOverlay.js index 8644d889..de8f9121 100644 --- a/ui/content/enigmailMsgComposeOverlay.js +++ b/ui/content/enigmailMsgComposeOverlay.js @@ -1,5143 +1,5170 @@ /*global Components: false, EnigmailLocale: false, EnigmailApp: false, Dialog: false, EnigmailTimer: 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"; /*globally available Thunderbird variables/object/functions: */ /*global MimeBody: false, MimeUnknown: false, MimeMessageAttachment: false, gMsgCompose: false, getCurrentIdentity: false */ /*global msgHdrToMimeMessage: false, MimeMessage: false, MimeContainer: false, UpdateAttachmentBucket: false, gContentChanged: true */ /*global AddAttachments: false, AddAttachment: false, ChangeAttachmentBucketVisibility: false, GetResourceFromUri: false */ /*global Recipients2CompFields: false, Attachments2CompFields: false, DetermineConvertibility: false, gWindowLocked: false */ /*global CommandUpdate_MsgCompose: false, gSMFields: false, setSecuritySettings: false */ /*global Sendlater3Composing: false */ Components.utils.import("resource://enigmail/glodaMime.jsm"); 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/log.jsm"); /*global EnigmailLog: false */ Components.utils.import("resource://enigmail/prefs.jsm"); /*global EnigmailPrefs: false */ Components.utils.import("resource://enigmail/os.jsm"); /*global EnigmailOS: false */ Components.utils.import("resource://enigmail/armor.jsm"); /*global EnigmailArmor: false */ Components.utils.import("resource://enigmail/locale.jsm"); /*global EnigmailLocale: false */ Components.utils.import("resource://enigmail/files.jsm"); /*global EnigmailFiles: false */ Components.utils.import("resource://enigmail/data.jsm"); /*global EnigmailData: false */ Components.utils.import("resource://enigmail/app.jsm"); /*global EnigmailApp: false */ Components.utils.import("resource://enigmail/dialog.jsm"); /*global EnigmailDialog: false */ Components.utils.import("resource://enigmail/timer.jsm"); /*global EnigmailTimer: false */ Components.utils.import("resource://enigmail/windows.jsm"); /* global EnigmailWindows: 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/uris.jsm"); /*global EnigmailURIs: 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/rules.jsm"); /*global EnigmailRules: false */ Components.utils.import("resource://enigmail/clipboard.jsm"); /*global EnigmailClipboard: 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://gre/modules/jsmime.jsm"); /*global jsmime: false*/ try { Components.utils.import("resource:///modules/MailUtils.js"); /*global MailUtils: false */ } catch (ex) {} if (!Enigmail) var Enigmail = {}; const IOSERVICE_CONTRACTID = "@mozilla.org/network/io-service;1"; const LOCAL_FILE_CONTRACTID = "@mozilla.org/file/local;1"; Enigmail.msg = { editor: null, dirty: null, processed: null, timeoutId: null, sendPgpMime: false, sendMode: null, // the current default for sending a message (0, SIGN, ENCRYPT, or SIGN|ENCRYPT) sendModeDirty: false, // send mode or final send options changed? // processed reasons for encryption: reasonEncrypted: "", reasonSigned: "", // encrypt/sign/pgpmime according to rules? // (1:ENIG_UNDEF(undef/maybe), 0:ENIG_NEVER(never/forceNo), 2:ENIG_ALWAYS(always/forceYes), // 22:ENIG_AUTO_ALWAYS, 99:ENIG_CONFLICT(conflict)) encryptByRules: EnigmailConstants.ENIG_UNDEF, signByRules: EnigmailConstants.ENIG_UNDEF, pgpmimeByRules: EnigmailConstants.ENIG_UNDEF, // forced to encrypt/sign/pgpmime? // (1:ENIG_UNDEF(undef/maybe), 0:ENIG_NEVER(never/forceNo), 2:ENIG_ALWAYS(always/forceYes)) encryptForced: EnigmailConstants.ENIG_UNDEF, signForced: EnigmailConstants.ENIG_UNDEF, pgpmimeForced: EnigmailConstants.ENIG_UNDEF, finalSignDependsOnEncrypt: false, // does signing finally depends on encryption mode? // resulting final encrypt/sign/pgpmime mode: // (-1:ENIG_FINAL_UNDEF, 0:ENIG_FINAL_NO, 1:ENIG_FINAL_YES, 10:ENIG_FINAL_FORCENO, 11:ENIG_FINAL_FORCEYES, 99:ENIG_FINAL_CONFLICT) statusEncrypted: EnigmailConstants.ENIG_FINAL_UNDEF, statusSigned: EnigmailConstants.ENIG_FINAL_UNDEF, statusPGPMime: EnigmailConstants.ENIG_FINAL_UNDEF, statusEncryptedInStatusBar: null, // last statusEncyrpted when processing status buttons // to find possible broken promise of encryption // is OpenPGP encryption possible without displaying the key selection dialog? autoPgpEncryption: false, // processed strings to signal final encrypt/sign/pgpmime state: statusEncryptedStr: "???", statusSignedStr: "???", statusPGPMimeStr: "???", statusSMimeStr: "???", statusInlinePGPStr: "???", statusAttachOwnKey: "???", juniorMode: false, + origPepRating: null, sendProcess: false, composeBodyReady: false, identity: null, enableRules: null, modifiedAttach: null, lastFocusedWindow: null, determineSendFlagId: null, trustAllKeys: false, protectHeaders: false, attachOwnKeyObj: { appendAttachment: false, attachedObj: null, attachedKey: null }, compFieldsEnig_CID: "@mozdev.org/enigmail/composefields;1", saveDraftError: 0, composeStartup: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.composeStartup\n"); function delayedProcessFinalState() { EnigmailTimer.setTimeout(function _f() { Enigmail.msg.processFinalState(); Enigmail.msg.updateStatusBar(); }, 50); } function addSecurityListener(itemId, func) { let s = document.getElementById(itemId); if (s) { s.addEventListener("command", func); } else { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: addSecurityListener - cannot find element " + itemId + "\n"); } } // Relabel SMIME button and menu item var smimeButton = document.getElementById("button-security"); if (smimeButton) { smimeButton.setAttribute("label", "S/MIME"); } var msgId = document.getElementById("msgIdentityPopup"); if (msgId) { msgId.addEventListener("command", Enigmail.msg.setIdentityCallback); } var subj = document.getElementById("msgSubject"); subj.addEventListener('focus', Enigmail.msg.fireSendFlags); // listen to S/MIME changes to potentially display "conflict" message addSecurityListener("menu_securitySign1", delayedProcessFinalState); addSecurityListener("menu_securitySign2", delayedProcessFinalState); addSecurityListener("menu_securityEncryptRequire1", delayedProcessFinalState); addSecurityListener("menu_securityEncryptRequire2", delayedProcessFinalState); this.msgComposeReset(false); // false => not closing => call setIdentityDefaults() this.composeOpen(); this.processFinalState(); this.updateStatusBar(); }, composeUnload: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.composeUnload\n"); //if (gMsgCompose) // gMsgCompose.UnregisterStateListener(Enigmail.composeStateListener); }, handleClick: function(event, modifyType) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.handleClick\n"); switch (event.button) { case 2: // do not process the event any futher // needed on Windows to prevent displaying the context menu event.preventDefault(); this.doPgpButton(); break; case 0: this.doPgpButton(modifyType); break; } }, setIdentityCallback: function(elementId) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.setIdentityCallback: elementId=" + elementId + "\n"); EnigmailTimer.setTimeout(function _f() { Enigmail.msg.setIdentityDefaults(); }, 50); }, /* return whether the account specific setting key is enabled or disabled */ getAccDefault: function(key) { //EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.getAccDefault: identity="+this.identity.key+"("+this.identity.email+") key="+key+"\n"); if (this.isEnigmailEnabled()) { var res = null; switch (key) { case 'sign': res = (this.identity.getIntAttribute("defaultSigningPolicy") > 0); // converts int property to bool property break; case 'encrypt': res = (this.identity.getIntAttribute("defaultEncryptionPolicy") > 0); // converts int property to bool property break; case 'pgpMimeMode': res = this.identity.getBoolAttribute(key); break; case 'signIfNotEnc': res = this.identity.getBoolAttribute("pgpSignPlain"); break; case 'signIfEnc': res = this.identity.getBoolAttribute("pgpSignEncrypted"); break; case 'attachPgpKey': res = this.identity.getBoolAttribute(key); break; } //EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.getAccDefault: "+key+"="+res+"\n"); return res; } else { // every detail is disabled if OpenPGP in general is disabled: switch (key) { case 'sign': case 'encrypt': case 'signIfNotEnc': case 'signIfEnc': case 'pgpMimeMode': case 'attachPgpKey': return false; } } // should not be reached EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.getAccDefault: internal error: invalid key '" + key + "'\n"); return null; }, /** * Determine if any of Enigmail (OpenPGP) or S/MIME encryption is enabled for the account */ getEncryptionEnabled: function() { if (this.juniorMode) return false; let id = getCurrentIdentity(); return ((id.getUnicharAttribute("encryption_cert_name") !== "") || this.isEnigmailEnabled()); }, /** * Determine if any of Enigmail (OpenPGP) or S/MIME signing is enabled for the account */ getSigningEnabled: function() { if (this.juniorMode) return false; let id = getCurrentIdentity(); return ((id.getUnicharAttribute("signing_cert_name") !== "") || this.isEnigmailEnabled()); }, getSmimeSigningEnabled: function() { if (this.juniorMode) return false; let id = getCurrentIdentity(); if (!id.getUnicharAttribute("signing_cert_name")) return false; return id.getBoolPref("sign_mail"); }, setIdentityDefaults: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.setIdentityDefaults\n"); this.identity = getCurrentIdentity(); if (this.isEnigmailEnabled()) { EnigmailFuncs.getSignMsg(this.identity); // convert old acc specific to new acc specific options } else { // reset status strings in menu to useful defaults this.statusEncryptedStr = EnigmailLocale.getString("encryptNo"); this.statusSignedStr = EnigmailLocale.getString("signNo", [""]); this.statusPGPMimeStr = EnigmailLocale.getString("pgpmimeNormal"); this.statusInlinePGPStr = EnigmailLocale.getString("inlinePGPNormal"); this.statusSMimeStr = EnigmailLocale.getString("smimeNormal"); this.statusAttachOwnKey = EnigmailLocale.getString("attachOwnKeyNo"); } if (this.juniorMode) { let pepBc = document.getElementById("enigmail-bc-pepEncrypt"); pepBc.setAttribute("encrypt", this.pepEnabled() ? "true" : "false"); } // reset default send settings, unless we have changed them already if (!this.sendModeDirty) { this.mimePreferOpenPGP = this.identity.getIntAttribute("mimePreferOpenPGP"); this.processAccountSpecificDefaultOptions(); this.determineSendFlags(); // important to use identity specific settings this.processFinalState(); this.updateStatusBar(); } }, // set the current default for sending a message // depending on the identity processAccountSpecificDefaultOptions: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.processAccountSpecificDefaultOptions\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; this.sendMode = 0; if (!this.isEnigmailEnabled()) { return; } if (this.getAccDefault("encrypt")) { this.sendMode |= ENCRYPT; this.reasonEncrypted = EnigmailLocale.getString("reasonEnabledByDefault"); } if (this.getAccDefault("sign")) { this.sendMode |= SIGN; this.reasonSigned = EnigmailLocale.getString("reasonEnabledByDefault"); } this.sendPgpMime = this.getAccDefault("pgpMimeMode"); this.attachOwnKeyObj.appendAttachment = this.getAccDefault("attachPgpKey"); this.setOwnKeyStatus(); this.attachOwnKeyObj.attachedObj = null; this.attachOwnKeyObj.attachedKey = null; this.finalSignDependsOnEncrypt = (this.getAccDefault("signIfEnc") || this.getAccDefault("signIfNotEnc")); }, getOriginalMsgUri: function() { let draftId = gMsgCompose.compFields.draftId; let msgUri = null; if (typeof(draftId) == "string" && draftId.length > 0) { // original message is draft msgUri = draftId.replace(/\?.*$/, ""); } else if (typeof(gMsgCompose.originalMsgURI) == "string" && gMsgCompose.originalMsgURI.length > 0) { // original message is a "true" mail msgUri = gMsgCompose.originalMsgURI; } return msgUri; }, getMsgHdr: function(msgUri) { if (!msgUri) { msgUri = this.getOriginalMsgUri(); } let messenger = Components.classes["@mozilla.org/messenger;1"].getService(Components.interfaces.nsIMessenger); return messenger.messageServiceFromURI(msgUri).messageURIToMsgHdr(msgUri); }, getMsgProperties: function(draft) { EnigmailLog.DEBUG("enigmailMessengerOverlay.js: Enigmail.msg.getMsgProperties:\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; let msgUri = this.getOriginalMsgUri(); let properties = 0; try { let msgHdr = this.getMsgHdr(msgUri); if (msgHdr) { this.setOriginalSubject(msgHdr.subject); properties = msgHdr.getUint32Property("enigmail"); if (draft) { try { msgHdrToMimeMessage(msgHdr, null, this.getMsgPropertiesCb, true, { examineEncryptedParts: true }); } catch (ex) { EnigmailLog.DEBUG("enigmailMessengerOverlay.js: Enigmail.msg.getMsgProperties: cannot use msgHdrToMimeMessage\n"); } } } } catch (ex) { EnigmailLog.DEBUG("enigmailMessengerOverlay.js: Enigmail.msg.getMsgProperties: got exception '" + ex.toString() + "'\n"); } if (EnigmailURIs.isEncryptedUri(msgUri)) { properties |= nsIEnigmail.DECRYPTION_OKAY; } return properties; }, getMsgPropertiesCb: function(msg, mimeMsg) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.getMsgPropertiesCb\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; var stat = ""; if (mimeMsg && mimeMsg.headers["x-enigmail-draft-status"]) { stat = String(mimeMsg.headers["x-enigmail-draft-status"]); } else { return; } EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.getMsgPropertiesCb: draftStatus: " + stat + "\n"); if (stat.substr(0, 1) == "N") { // new style drafts (Enigmail 1.7) var enc = "final-encryptDefault"; switch (Number(stat.substr(1, 1))) { case EnigmailConstants.ENIG_NEVER: enc = "final-encryptNo"; break; case EnigmailConstants.ENIG_ALWAYS: enc = "final-encryptYes"; } var sig = "final-signDefault"; switch (Number(stat.substr(2, 1))) { case EnigmailConstants.ENIG_NEVER: sig = "final-signNo"; break; case EnigmailConstants.ENIG_ALWAYS: sig = "final-signYes"; } var pgpMime = "final-pgpmimeDefault"; switch (Number(stat.substr(3, 1))) { case EnigmailConstants.ENIG_NEVER: pgpMime = "final-pgpmimeNo"; break; case EnigmailConstants.ENIG_ALWAYS: pgpMime = "final-pgpmimeYes"; } Enigmail.msg.setFinalSendMode(enc); Enigmail.msg.setFinalSendMode(sig); Enigmail.msg.setFinalSendMode(pgpMime); if (stat.substr(4, 1) == "1") Enigmail.msg.attachOwnKeyObj.appendAttachment = true; } else { // drafts from older versions of Enigmail var flags = Number(stat); if (flags & nsIEnigmail.SEND_SIGNED) Enigmail.msg.setFinalSendMode('final-signYes'); if (flags & nsIEnigmail.SEND_ENCRYPTED) Enigmail.msg.setFinalSendMode('final-encryptYes'); if (flags & nsIEnigmail.SEND_ATTACHMENT) Enigmail.msg.attachOwnKeyObj.appendAttachment = true; } Enigmail.msg.setOwnKeyStatus(); }, setOriginalSubject: function(subject) { const CT = Components.interfaces.nsIMsgCompType; let subjElem = document.getElementById("msgSubject"); let prefix = ""; if (!subjElem) return; switch (gMsgCompose.type) { case CT.ForwardInline: case CT.ForwardAsAttachment: prefix = this.getMailPref("mail.forward_subject_prefix") + ": "; } subject = jsmime.headerparser.decodeRFC2047Words(subject, "utf-8"); switch (gMsgCompose.type) { case CT.Draft: case CT.Template: case CT.ForwardInline: case CT.ForwardAsAttachment: gMsgCompose.compFields.subject = prefix + subject; subjElem.value = prefix + subject; break; } }, setupMenuAndToolbar: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.setupMenuAndToolbar\n"); let toolbarTxt = document.getElementById("enigmail-toolbar-text"); let encBroadcaster = document.getElementById("enigmail-bc-encrypt"); let signBroadcaster = document.getElementById("enigmail-bc-sign"); let attachBroadcaster = document.getElementById("enigmail-bc-attach"); let enigmailMenu = document.getElementById("menu_Enigmail"); let pepBroadcaster = document.getElementById("enigmail-bc-pepEncrypt"); let pepMenu = document.getElementById("menu_EnigmailPep"); let pepStatusbar = document.getElementById("enigmail-pep-statusbar"); if (this.juniorMode) { encBroadcaster.setAttribute("hidden", "true"); signBroadcaster.setAttribute("hidden", "true"); attachBroadcaster.setAttribute("hidden", "true"); if (toolbarTxt) { toolbarTxt.setAttribute("hidden", "true"); } enigmailMenu.setAttribute("hidden", "true"); pepBroadcaster.removeAttribute("hidden"); pepMenu.removeAttribute("hidden"); pepStatusbar.removeAttribute("hidden"); this.setFinalSendMode("final-encryptNo"); this.setFinalSendMode("final-signNo"); this.setFinalSendMode("final-pgpmimeNo"); this.updateStatusBar(); } else { encBroadcaster.removeAttribute("hidden"); signBroadcaster.removeAttribute("hidden"); attachBroadcaster.removeAttribute("hidden"); if (toolbarTxt) { toolbarTxt.removeAttribute("hidden"); } enigmailMenu.removeAttribute("hidden"); pepBroadcaster.setAttribute("hidden", "true"); pepMenu.setAttribute("hidden", "true"); pepStatusbar.setAttribute("hidden", "true"); } }, composeOpen: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.composeOpen\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; var msgFlags; var msgUri = null; var msgIsDraft = false; this.juniorMode = EnigmailPEPAdapter.getPepJuniorMode(); this.setupMenuAndToolbar(); this.determineSendFlagId = null; this.disableSmime = false; this.saveDraftError = 0; this.protectHeaders = EnigmailPrefs.getPref("protectHeaders"); this.enableUndoEncryption(false); this.displayProtectHeadersStatus(); + if (this.juniorMode) { + this.getOriginalPepMsgRating(); + } var toobarElem = document.getElementById("composeToolbar2"); if (toobarElem && (EnigmailOS.getOS() == "Darwin")) { toobarElem.setAttribute("platform", "macos"); } // check rules for status bar icons on each change of the recipients var adrCol = document.getElementById("addressCol2#1"); // recipients field if (adrCol) { let attr = adrCol.getAttribute("oninput"); adrCol.setAttribute("oninput", attr + "; Enigmail.msg.addressOnChange(this);"); attr = adrCol.getAttribute("onchange"); adrCol.setAttribute("onchange", attr + "; Enigmail.msg.addressOnChange(this);"); adrCol.setAttribute("observes", "enigmail-bc-sendprocess"); } adrCol = document.getElementById("addressCol1#1"); // to/cc/bcc/... field if (adrCol) { let attr = adrCol.getAttribute("oncommand"); adrCol.setAttribute("oncommand", attr + "; Enigmail.msg.addressOnChange(this);"); adrCol.setAttribute("observes", "enigmail-bc-sendprocess"); } var draftId = gMsgCompose.compFields.draftId; if (EnigmailPrefs.getPref("keepSettingsForReply") && (!(this.sendMode & ENCRYPT)) || (typeof(draftId) == "string" && draftId.length > 0)) { msgUri = this.getOriginalMsgUri(); if (typeof(draftId) == "string" && draftId.length > 0) { // original message is draft msgIsDraft = true; } if (msgUri) { msgFlags = this.getMsgProperties(msgIsDraft); if (!msgIsDraft) { if (msgFlags & nsIEnigmail.DECRYPTION_OKAY) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.composeOpen: has encrypted originalMsgUri\n"); EnigmailLog.DEBUG("originalMsgURI=" + gMsgCompose.originalMsgURI + "\n"); this.setSendMode('encrypt'); this.disableSmime = true; } else if (msgFlags & (nsIEnigmail.GOOD_SIGNATURE | nsIEnigmail.BAD_SIGNATURE | nsIEnigmail.UNVERIFIED_SIGNATURE)) { this.setSendMode('sign'); } } this.removeAttachedKey(); } } // check for attached signature files and remove them var bucketList = document.getElementById("attachmentBucket"); if (bucketList.hasChildNodes()) { var node = bucketList.firstChild; let nodeNumber = 0; while (node) { if (node.attachment.contentType == "application/pgp-signature") { if (!this.findRelatedAttachment(bucketList, node)) { node = bucketList.removeItemAt(nodeNumber); // Let's release the attachment object held by the node else it won't go away until the window is destroyed node.attachment = null; } } else { ++nodeNumber; } node = node.nextSibling; } if (!bucketList.hasChildNodes()) { try { // TB only UpdateAttachmentBucket(false); } catch (ex) {} } } try { // TB only UpdateAttachmentBucket(bucketList.hasChildNodes()); } catch (ex) {} this.processFinalState(); this.updateStatusBar(); }, + getOriginalPepMsgRating: function() { + let msgUri = this.getOriginalMsgUri(); + + let msgHdr = this.getMsgHdr(msgUri); + if (msgHdr) { + let r = msgHdr.getUint32Property("enigmailPep"); + this.origPepRating = (r - (r & 0xFF)) >> 8; + } + }, // check if an signature is related to another attachment findRelatedAttachment: function(bucketList, node) { // check if filename ends with .sig if (node.attachment.name.search(/\.sig$/i) < 0) return null; var relatedNode = bucketList.firstChild; var findFile = node.attachment.name.toLowerCase(); var baseAttachment = null; while (relatedNode) { if (relatedNode.attachment.name.toLowerCase() + ".sig" == findFile) baseAttachment = relatedNode.attachment; relatedNode = relatedNode.nextSibling; } return baseAttachment; }, msgComposeReopen: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.msgComposeReopen\n"); this.msgComposeReset(false); // false => not closing => call setIdentityDefaults() this.composeOpen(); this.fireSendFlags(); EnigmailTimer.setTimeout(function _f() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay: re-determine send flags\n"); try { this.determineSendFlags(); this.processFinalState(); this.updateStatusBar(); } catch (ex) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay: re-determine send flags - ERROR: " + ex.toString() + "\n"); } }.bind(Enigmail.msg), 1000); }, msgComposeClose: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.msgComposeClose\n"); var ioServ; try { // we should delete the original temporary files of the encrypted or signed // inline PGP attachments (the rest is done automatically) if (this.modifiedAttach) { ioServ = Components.classes[IOSERVICE_CONTRACTID].getService(Components.interfaces.nsIIOService); if (!ioServ) return; for (var i in this.modifiedAttach) { if (this.modifiedAttach[i].origTemp) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.msgComposeClose: deleting " + this.modifiedAttach[i].origUrl + "\n"); var fileUri = ioServ.newURI(this.modifiedAttach[i].origUrl, null, null); var fileHandle = Components.classes[LOCAL_FILE_CONTRACTID].createInstance(Components.interfaces.nsIFile); fileHandle.initWithPath(fileUri.path); if (fileHandle.exists()) fileHandle.remove(false); } } this.modifiedAttach = null; } } catch (ex) { EnigmailLog.ERROR("enigmailMsgComposeOverlay.js: ECSL.ComposeProcessDone: could not delete all files:\n" + ex.toString() + "\n"); } this.msgComposeReset(true); // true => closing => don't call setIdentityDefaults() }, msgComposeReset: function(closing) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.msgComposeReset\n"); this.dirty = 0; this.processed = null; this.timeoutId = null; this.modifiedAttach = null; this.sendMode = 0; this.sendModeDirty = false; this.reasonEncrypted = ""; this.reasonSigned = ""; this.encryptByRules = EnigmailConstants.ENIG_UNDEF; this.signByRules = EnigmailConstants.ENIG_UNDEF; this.pgpmimeByRules = EnigmailConstants.ENIG_UNDEF; this.signForced = EnigmailConstants.ENIG_UNDEF; this.encryptForced = EnigmailConstants.ENIG_UNDEF; this.pgpmimeForced = EnigmailConstants.ENIG_UNDEF; this.finalSignDependsOnEncrypt = false; this.statusSigned = EnigmailConstants.ENIG_FINAL_UNDEF; this.statusEncrypted = EnigmailConstants.ENIG_FINAL_UNDEF; this.statusPGPMime = EnigmailConstants.ENIG_FINAL_UNDEF; this.statusEncryptedStr = "???"; this.statusSignedStr = "???"; this.statusPGPMimeStr = "???"; this.statusInlinePGPStr = "???"; this.statusAttachOwnKey = "???"; this.enableRules = true; this.identity = null; this.sendProcess = false; this.trustAllKeys = false; this.mimePreferOpenPGP = 0; + this.origPepRating = null; if (!closing) { this.setIdentityDefaults(); } }, initRadioMenu: function(prefName, optionIds) { EnigmailLog.DEBUG("enigmailMessengerOverlay.js: Enigmail.msg.initRadioMenu: " + prefName + "\n"); var encryptId; var prefValue = EnigmailPrefs.getPref(prefName); if (prefValue >= optionIds.length) return; var menuItem = document.getElementById("enigmail_" + optionIds[prefValue]); if (menuItem) menuItem.setAttribute("checked", "true"); }, usePpgMimeOption: function(value) { EnigmailLog.DEBUG("enigmailMessengerOverlay.js: Enigmail.msg.usePpgMimeOption: " + value + "\n"); EnigmailPrefs.setPref("usePGPMimeOption", value); return true; }, tempTrustAllKeys: function() { this.trustAllKeys = !this.trustAllKeys; }, toggleAttachOwnKey: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.toggleAttachOwnKey\n"); EnigmailCore.getService(window); // make sure Enigmail is loaded and working this.attachOwnKeyObj.appendAttachment = !this.attachOwnKeyObj.appendAttachment; this.setOwnKeyStatus(); }, toggleProtectHeaders: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.toggleProtectHeaders\n"); EnigmailCore.getService(window); // make sure Enigmail is loaded and working this.protectHeaders = !this.protectHeaders; this.displayProtectHeadersStatus(); }, displayProtectHeadersStatus: function() { let bc = document.getElementById("enigmail-bc-protectHdr"); if (this.protectHeaders) { bc.setAttribute("checked", "true"); } else { bc.removeAttribute("checked"); } }, /*** * set broadcaster to display whether the own key is attached or not */ setOwnKeyStatus: function() { let bc = document.getElementById("enigmail-bc-attach"); let attachIcon = document.getElementById("button-enigmail-attach"); if (this.allowAttachOwnKey() === 0) { this.statusAttachOwnKey = EnigmailLocale.getString("attachOwnKeyDisabled"); } else { if (this.attachOwnKeyObj.appendAttachment) { bc.setAttribute("addPubkey", "true"); bc.setAttribute("checked", "true"); this.statusAttachOwnKey = EnigmailLocale.getString("attachOwnKeyYes"); } else { bc.setAttribute("addPubkey", "false"); bc.removeAttribute("checked"); this.statusAttachOwnKey = EnigmailLocale.getString("attachOwnKeyNo"); } } if (attachIcon) attachIcon.setAttribute("tooltiptext", this.statusAttachOwnKey); }, attachOwnKey: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.attachOwnKey:\n"); var userIdValue; if (this.identity.getIntAttribute("pgpKeyMode") > 0) { userIdValue = this.identity.getCharAttribute("pgpkeyId"); if (this.attachOwnKeyObj.attachedKey && (this.attachOwnKeyObj.attachedKey != userIdValue)) { // remove attached key if user ID changed this.removeAttachedKey(); } if (!this.attachOwnKeyObj.attachedKey) { var attachedObj = this.extractAndAttachKey([userIdValue]); if (attachedObj) { this.attachOwnKeyObj.attachedObj = attachedObj; this.attachOwnKeyObj.attachedKey = userIdValue; } } } else { EnigmailLog.ERROR("enigmailMsgComposeOverlay.js: Enigmail.msg.attachOwnKey: trying to attach unknown own key!\n"); } }, attachKey: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.attachKey: \n"); var resultObj = {}; var inputObj = {}; inputObj.dialogHeader = EnigmailLocale.getString("keysToExport"); inputObj.options = "multisel,allowexpired,nosending"; if (this.trustAllKeys) { inputObj.options += ",trustallkeys"; } var userIdValue = ""; window.openDialog("chrome://enigmail/content/enigmailKeySelection.xul", "", "dialog,modal,centerscreen,resizable", inputObj, resultObj); try { if (resultObj.cancelled) return; this.extractAndAttachKey(resultObj.userList); } catch (ex) { // cancel pressed -> do nothing return; } }, extractAndAttachKey: function(uid) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.extractAndAttachKey: \n"); var enigmailSvc = EnigmailCore.getService(window); if (!enigmailSvc) return null; var tmpDir = EnigmailFiles.getTempDir(); var tmpFile; try { tmpFile = Components.classes[LOCAL_FILE_CONTRACTID].createInstance(Components.interfaces.nsIFile); tmpFile.initWithPath(tmpDir); if (!(tmpFile.isDirectory() && tmpFile.isWritable())) { EnigmailDialog.alert(window, EnigmailLocale.getString("noTempDir")); return null; } } catch (ex) { EnigmailLog.writeException("enigmailMsgComposeOverlay.js: Enigmail.msg.extractAndAttachKey", ex); } tmpFile.append("key.asc"); tmpFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0x180); // equal 0600 // save file var exitCodeObj = {}; var errorMsgObj = {}; EnigmailKeyRing.extractKey(false, uid.join(" "), tmpFile /*.path */ , exitCodeObj, errorMsgObj); if (exitCodeObj.value !== 0) { EnigmailDialog.alert(window, errorMsgObj.value); return null; } // create attachment var ioServ = Components.classes[IOSERVICE_CONTRACTID].getService(Components.interfaces.nsIIOService); var tmpFileURI = ioServ.newFileURI(tmpFile); var keyAttachment = Components.classes["@mozilla.org/messengercompose/attachment;1"].createInstance(Components.interfaces.nsIMsgAttachment); keyAttachment.url = tmpFileURI.spec; if ((uid.length == 1) && (uid[0].search(/^(0x)?[a-fA-F0-9]+$/) === 0)) { keyAttachment.name = uid[0].substr(-16, 16) + ".asc"; if (keyAttachment.name.search(/^0x/) < 0) keyAttachment.name = "0x" + keyAttachment.name; } else { keyAttachment.name = "pgpkeys.asc"; } keyAttachment.temporary = true; keyAttachment.contentType = "application/pgp-keys"; // add attachment to msg this.addAttachment(keyAttachment); try { // TB only ChangeAttachmentBucketVisibility(false); } catch (ex) {} gContentChanged = true; return keyAttachment; }, addAttachment: function(attachment) { if (typeof(AddAttachment) == "undefined") { // TB >= 24 AddAttachments([attachment]); } else { // SeaMonkey AddAttachment(attachment); } }, enableUndoEncryption: function(newStatus) { let eue = document.getElementById("enigmail_undo_encryption"); if (newStatus) { eue.removeAttribute("disabled"); } else eue.setAttribute("disabled", "true"); }, /** * undo the encryption or signing; get back the original (unsigned/unencrypted) text * * useEditorUndo |Number|: > 0 use undo function of editor |n| times * 0: replace text with original text */ undoEncryption: function(useEditorUndo) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.undoEncryption:\n"); if (this.processed) { if (useEditorUndo) { EnigmailTimer.setTimeout(function _f() { Enigmail.msg.editor.undo(useEditorUndo); }, 10); } else { this.replaceEditorText(this.processed.origText); this.enableUndoEncryption(false); } this.processed = null; } else { this.decryptQuote(true); } var node; var nodeNumber; var bucketList = document.getElementById("attachmentBucket"); if (this.modifiedAttach && bucketList && bucketList.hasChildNodes()) { // undo inline encryption of attachments for (var i = 0; i < this.modifiedAttach.length; i++) { node = bucketList.firstChild; nodeNumber = -1; while (node) { ++nodeNumber; if (node.attachment.url == this.modifiedAttach[i].newUrl) { if (this.modifiedAttach[i].encrypted) { node.attachment.url = this.modifiedAttach[i].origUrl; node.attachment.name = this.modifiedAttach[i].origName; node.attachment.temporary = this.modifiedAttach[i].origTemp; node.attachment.contentType = this.modifiedAttach[i].origCType; } else { node = bucketList.removeItemAt(nodeNumber); // Let's release the attachment object held by the node else it won't go away until the window is destroyed node.attachment = null; } // delete encrypted file try { this.modifiedAttach[i].newFile.remove(false); } catch (ex) {} node = null; // next attachment please } else { node = node.nextSibling; } } } } this.removeAttachedKey(); }, removeAttachedKey: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.removeAttachedKey: \n"); var bucketList = document.getElementById("attachmentBucket"); var node = bucketList.firstChild; if (bucketList && bucketList.hasChildNodes() && this.attachOwnKeyObj.attachedObj) { // undo attaching own key var nodeNumber = -1; while (node) { ++nodeNumber; if (node.attachment.url == this.attachOwnKeyObj.attachedObj.url) { node = bucketList.removeItemAt(nodeNumber); // Let's release the attachment object held by the node else it won't go away until the window is destroyed node.attachment = null; this.attachOwnKeyObj.attachedObj = null; this.attachOwnKeyObj.attachedKey = null; node = null; // exit loop } else { node = node.nextSibling; } } if (!bucketList.hasChildNodes()) { try { // TB only ChangeAttachmentBucketVisibility(true); } catch (ex) {} } } }, resetUpdatedFields: function() { this.removeAttachedKey(); // reset subject if (gMsgCompose.compFields.securityInfo instanceof Components.interfaces.nsIEnigMsgCompFields) { let si = gMsgCompose.compFields.securityInfo.QueryInterface(Components.interfaces.nsIEnigMsgCompFields); if (si.originalSubject) { gMsgCompose.compFields.subject = si.originalSubject; } } }, replaceEditorText: function(text) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.replaceEditorText:\n"); this.editorSelectAll(); // Overwrite text in clipboard for security // (Otherwise plaintext will be available in the clipbaord) if (this.editor.textLength > 0) { this.editorInsertText("Enigmail"); } else { this.editorInsertText(" "); } this.editorSelectAll(); this.editorInsertText(text); }, getMsgFolderFromUri: function(uri, checkFolderAttributes) { let msgfolder = null; if (typeof MailUtils != 'undefined') { return MailUtils.getFolderForURI(uri, checkFolderAttributes); } try { // Postbox, older versions of TB let resource = GetResourceFromUri(uri); msgfolder = resource.QueryInterface(Components.interfaces.nsIMsgFolder); if (checkFolderAttributes) { if (!(msgfolder && (msgfolder.parent || msgfolder.isServer))) { msgfolder = null; } } } catch (ex) { //EnigmailLog.DEBUG("failed to get the folder resource\n"); } return msgfolder; }, goAccountManager: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.goAccountManager:\n"); EnigmailCore.getService(window); var currentId = null; var server = null; try { currentId = getCurrentIdentity(); var amService = Components.classes["@mozilla.org/messenger/account-manager;1"].getService(); var servers, folderURI; try { // Gecko >= 20 servers = amService.getServersForIdentity(currentId); folderURI = servers.queryElementAt(0, Components.interfaces.nsIMsgIncomingServer).serverURI; } catch (ex) { servers = amService.GetServersForIdentity(currentId); folderURI = servers.GetElementAt(0).QueryInterface(Components.interfaces.nsIMsgIncomingServer).serverURI; } server = this.getMsgFolderFromUri(folderURI, true).server; } catch (ex) {} window.openDialog("chrome://enigmail/content/am-enigprefs-edit.xul", "", "dialog,modal,centerscreen", { identity: currentId, account: server }); this.setIdentityDefaults(); }, /** * Determine if Enigmail is enabled for the account */ isEnigmailEnabled: function() { if (this.juniorMode) return false; return this.identity.getBoolAttribute("enablePgp"); }, doPgpButton: function(what) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.doPgpButton: what=" + what + "\n"); if (this.isEnigmailEnabled()) { EnigmailCore.getService(window); // try to access Enigmail to launch the wizard if needed } // ignore settings for this account? try { if (!this.getEncryptionEnabled() && !this.getSigningEnabled()) { if (EnigmailDialog.confirmDlg(window, EnigmailLocale.getString("configureNow"), EnigmailLocale.getString("msgCompose.button.configure"))) { // configure account settings for the first time this.goAccountManager(); if (!this.isEnigmailEnabled()) { return; } } else { return; } } } catch (ex) {} switch (what) { case 'sign': case 'encrypt': this.setSendMode(what); break; // menu entries: case 'final-signDefault': case 'final-signYes': case 'final-signNo': case 'final-encryptDefault': case 'final-encryptYes': case 'final-encryptNo': case 'final-pgpmimeDefault': case 'final-pgpmimeYes': case 'final-pgpmimeNo': case 'final-useSmime': case 'toggle-final-sign': case 'toggle-final-encrypt': case 'toggle-final-mime': this.setFinalSendMode(what); break; case 'trustKeys': this.tempTrustAllKeys(); break; case 'nothing': break; case 'displaySecuritySettings': this.displaySecuritySettings(); break; default: this.displaySecuritySettings(); } }, // changes the DEFAULT sendMode // - also called internally for saved emails setSendMode: function(sendMode) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.setSendMode: sendMode=" + sendMode + "\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; var origSendMode = this.sendMode; switch (sendMode) { case 'sign': this.sendMode |= SIGN; break; case 'encrypt': this.sendMode |= ENCRYPT; break; default: EnigmailDialog.alert(window, "Enigmail.msg.setSendMode - unexpected value: " + sendMode); break; } // sendMode changed ? // - sign and send are internal initializations if (!this.sendModeDirty && (this.sendMode != origSendMode) && sendMode != 'sign' && sendMode != 'encrypt') { this.sendModeDirty = true; } this.processFinalState(); this.updateStatusBar(); }, // changes the FINAL sendMode // - triggered by the user interface setFinalSendMode: function(sendMode) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.setFinalSendMode: sendMode=" + sendMode + "\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; switch (sendMode) { // menu entries for final settings: case 'final-encryptDefault': // switch encryption to "use defaults & rules" if (this.encryptForced != EnigmailConstants.ENIG_UNDEF) { // if encrypt/noencrypt forced this.encryptForced = EnigmailConstants.ENIG_UNDEF; // back to defaults/rules } break; case 'final-encryptYes': // switch encryption to "force encryption" if (this.encryptForced != EnigmailConstants.ENIG_ALWAYS) { // if not forced to encrypt this.encryptForced = EnigmailConstants.ENIG_ALWAYS; // force to encrypt } break; case 'final-encryptNo': // switch encryption to "force no to encrypt" if (this.encryptForced != EnigmailConstants.ENIG_NEVER) { // if not forced not to encrypt this.encryptForced = EnigmailConstants.ENIG_NEVER; // force not to encrypt } break; case 'final-signDefault': // switch signing to "use defaults & rules" if (this.signForced != EnigmailConstants.ENIG_UNDEF) { // if sign/nosign forced // re-init if signing depends on encryption if this was broken before this.finalSignDependsOnEncrypt = (this.getAccDefault("signIfEnc") || this.getAccDefault("signIfNotEnc")); this.signForced = EnigmailConstants.ENIG_UNDEF; // back to defaults/rules } break; case 'final-signYes': if (this.signForced != EnigmailConstants.ENIG_ALWAYS) { // if not forced to sign this.signingNoLongerDependsOnEnc(); this.signForced = EnigmailConstants.ENIG_ALWAYS; // force to sign } break; case 'final-signNo': if (this.signForced != EnigmailConstants.ENIG_NEVER) { // if not forced not to sign this.signingNoLongerDependsOnEnc(); this.signForced = EnigmailConstants.ENIG_NEVER; // force not to sign } break; case 'final-pgpmimeDefault': if (this.pgpmimeForced != EnigmailConstants.ENIG_UNDEF) { // if any PGP mode forced this.pgpmimeForced = EnigmailConstants.ENIG_UNDEF; // back to defaults/rules } break; case 'final-pgpmimeYes': if (this.pgpmimeForced != EnigmailConstants.ENIG_ALWAYS) { // if not forced to PGP/Mime this.pgpmimeForced = EnigmailConstants.ENIG_ALWAYS; // force to PGP/Mime } break; case 'final-pgpmimeNo': if (this.pgpmimeForced != EnigmailConstants.ENIG_NEVER) { // if not forced not to PGP/Mime this.pgpmimeForced = EnigmailConstants.ENIG_NEVER; // force not to PGP/Mime } break; case 'final-useSmime': // this.pgpmimeForced = EnigmailConstants.ENIG_FORCE_SMIME; break; // status bar buttons: // - can only switch to force or not to force sign/enc case 'toggle-final-sign': this.signingNoLongerDependsOnEnc(); switch (this.statusSigned) { case EnigmailConstants.ENIG_FINAL_NO: case EnigmailConstants.ENIG_FINAL_FORCENO: this.signForced = EnigmailConstants.ENIG_ALWAYS; // force to sign break; case EnigmailConstants.ENIG_FINAL_YES: case EnigmailConstants.ENIG_FINAL_FORCEYES: this.signForced = EnigmailConstants.ENIG_NEVER; // force not to sign break; case EnigmailConstants.ENIG_FINAL_CONFLICT: this.signForced = EnigmailConstants.ENIG_NEVER; break; } break; case 'toggle-final-encrypt': if (this.juniorMode) { this.onPepEncryptButton(sendMode); return; } switch (this.statusEncrypted) { case EnigmailConstants.ENIG_FINAL_NO: case EnigmailConstants.ENIG_FINAL_FORCENO: this.encryptForced = EnigmailConstants.ENIG_ALWAYS; // force to encrypt break; case EnigmailConstants.ENIG_FINAL_YES: case EnigmailConstants.ENIG_FINAL_FORCEYES: this.encryptForced = EnigmailConstants.ENIG_NEVER; // force not to encrypt break; case EnigmailConstants.ENIG_FINAL_CONFLICT: this.encryptForced = EnigmailConstants.ENIG_NEVER; break; } break; case 'toggle-final-mime': switch (this.statusPGPMime) { case EnigmailConstants.ENIG_FINAL_NO: case EnigmailConstants.ENIG_FINAL_FORCENO: this.pgpmimeForced = EnigmailConstants.ENIG_ALWAYS; // force PGP/MIME break; case EnigmailConstants.ENIG_FINAL_YES: case EnigmailConstants.ENIG_FINAL_FORCEYES: this.pgpmimeForced = EnigmailConstants.ENIG_NEVER; // force Inline-PGP break; case EnigmailConstants.ENIG_FINAL_CONFLICT: this.pgpmimeForced = EnigmailConstants.ENIG_NEVER; break; } break; default: EnigmailDialog.alert(window, "Enigmail.msg.setFinalSendMode - unexpected value: " + sendMode); break; } // this is always a send mode change (only toggle effects) this.sendModeDirty = true; this.determineSendFlags(); //this.processFinalState(); //this.updateStatusBar(); }, /** key function to process the final encrypt/sign/pgpmime state from all settings @param sendFlags: contains the sendFlags if the message is really processed. Optional, can be null - uses as INPUT: - this.sendMode - this.encryptByRules, this.signByRules, pgpmimeByRules - this.encryptForced, this.encryptSigned - uses as OUTPUT: - this.statusEncrypt, this.statusSign, this.statusPGPMime no return value */ processFinalState: function(sendFlags) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.processFinalState()\n"); if (this.juniorMode) return; const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; let encFinally = null; let encReason = ""; let signFinally = null; let signReason = ""; let pgpmimeFinally = null; // ------ 1. process OpenPGP status ------ // process resulting encrypt mode if (this.encryptForced == EnigmailConstants.ENIG_NEVER) { // force not to encrypt? encFinally = EnigmailConstants.ENIG_FINAL_FORCENO; encReason = EnigmailLocale.getString("reasonManuallyForced"); } else if (this.encryptForced == EnigmailConstants.ENIG_ALWAYS) { // force to encrypt? encFinally = EnigmailConstants.ENIG_FINAL_FORCEYES; encReason = EnigmailLocale.getString("reasonManuallyForced"); } else switch (this.encryptByRules) { case EnigmailConstants.ENIG_NEVER: encFinally = EnigmailConstants.ENIG_FINAL_NO; encReason = EnigmailLocale.getString("reasonByRecipientRules"); break; case EnigmailConstants.ENIG_UNDEF: if (this.sendMode & ENCRYPT) { encFinally = EnigmailConstants.ENIG_FINAL_YES; if (this.getAccDefault("encrypt")) { encReason = EnigmailLocale.getString("reasonEnabledByDefault"); } } else { encFinally = EnigmailConstants.ENIG_FINAL_NO; } break; case EnigmailConstants.ENIG_ALWAYS: encFinally = EnigmailConstants.ENIG_FINAL_YES; encReason = EnigmailLocale.getString("reasonByRecipientRules"); break; case EnigmailConstants.ENIG_AUTO_ALWAYS: encFinally = EnigmailConstants.ENIG_FINAL_YES; encReason = EnigmailLocale.getString("reasonByAutoEncryption"); break; case EnigmailConstants.ENIG_CONFLICT: encFinally = EnigmailConstants.ENIG_FINAL_CONFLICT; encReason = EnigmailLocale.getString("reasonByConflict"); break; } EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: encrypt=" + ((this.sendMode & ENCRYPT) !== 0) + " encryptByRules=" + this.encryptByRules + " encFinally=" + encFinally + "\n"); EnigmailLog.DEBUG(" encReason=" + encReason + "\n"); // process resulting sign mode if (this.signForced == EnigmailConstants.ENIG_NEVER) { // force not to sign? signFinally = EnigmailConstants.ENIG_FINAL_FORCENO; signReason = EnigmailLocale.getString("reasonManuallyForced"); } else if (this.signForced == EnigmailConstants.ENIG_ALWAYS) { // force to sign? signFinally = EnigmailConstants.ENIG_FINAL_FORCEYES; signReason = EnigmailLocale.getString("reasonManuallyForced"); } else switch (this.signByRules) { case EnigmailConstants.ENIG_NEVER: signFinally = EnigmailConstants.ENIG_FINAL_NO; signReason = EnigmailLocale.getString("reasonByRecipientRules"); break; case EnigmailConstants.ENIG_UNDEF: if (this.sendMode & SIGN) { signFinally = EnigmailConstants.ENIG_FINAL_YES; if (this.getAccDefault("sign")) { signReason = EnigmailLocale.getString("reasonEnabledByDefault"); } } else { signFinally = EnigmailConstants.ENIG_FINAL_NO; } break; case EnigmailConstants.ENIG_ALWAYS: signFinally = EnigmailConstants.ENIG_FINAL_YES; signReason = EnigmailLocale.getString("reasonByRecipientRules"); break; case EnigmailConstants.ENIG_CONFLICT: signFinally = EnigmailConstants.ENIG_FINAL_CONFLICT; signReason = EnigmailLocale.getString("reasonByConflict"); break; } EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: signed=" + ((this.sendMode & SIGN) !== 0) + " signByRules=" + this.signByRules + " signFinally=" + signFinally + "\n"); EnigmailLog.DEBUG(" signReason=" + signReason + "\n"); // process option to finally sign if encrypted/unencrypted // (unless rules force not to sign) //var derivedFromEncMode = false; if (this.finalSignDependsOnEncrypt) { if (this.signByRules == EnigmailConstants.ENIG_UNDEF) { // if final sign mode not clear yet //derivedFromEncMode = true; switch (encFinally) { case EnigmailConstants.ENIG_FINAL_YES: case EnigmailConstants.ENIG_FINAL_FORCEYES: if (this.getAccDefault("signIfEnc")) { signFinally = EnigmailConstants.ENIG_FINAL_YES; signReason = EnigmailLocale.getString("reasonByEncryptionMode"); } break; case EnigmailConstants.ENIG_FINAL_NO: case EnigmailConstants.ENIG_FINAL_FORCENO: if (this.getAccDefault("signIfNotEnc")) { signFinally = EnigmailConstants.ENIG_FINAL_YES; signReason = EnigmailLocale.getString("reasonByEncryptionMode"); } break; case EnigmailConstants.ENIG_FINAL_CONFLICT: if (this.getAccDefault("signIfEnc") && this.getAccDefault("signIfNotEnc")) { signFinally = EnigmailConstants.ENIG_FINAL_YES; signReason = EnigmailLocale.getString("reasonByEncryptionMode"); } else { signFinally = EnigmailConstants.ENIG_FINAL_CONFLICT; } break; } EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: derived signFinally=" + signFinally + "\n"); EnigmailLog.DEBUG(" signReason=" + signReason + "\n"); } } this.statusPGPMime = EnigmailConstants.ENIG_FINAL_UNDEF; // ------ 2. Process S/MIME status ------ if (gSMFields) { let r = this.tryEnablingSMime(encFinally, signFinally); encFinally = r.encFinally; signFinally = r.signFinally; // update the S/MIME GUI elements try { setSecuritySettings("1"); } catch (ex) {} try { setSecuritySettings("2"); } catch (ex) {} } // ------ 3. process final resulting protocol mode (inline-PGP / PGP/MIME / S/MIME) ------ if (this.statusPGPMime !== EnigmailConstants.ENIG_FINAL_SMIME && this.statusPGPMime !== EnigmailConstants.ENIG_FINAL_FORCESMIME) { // process resulting PGP/MIME mode if (this.pgpmimeForced === EnigmailConstants.ENIG_NEVER) { // force not to PGP/Mime? pgpmimeFinally = EnigmailConstants.ENIG_FINAL_FORCENO; } else if (this.pgpmimeForced === EnigmailConstants.ENIG_ALWAYS) { // force to PGP/Mime? pgpmimeFinally = EnigmailConstants.ENIG_FINAL_FORCEYES; } else switch (this.pgpmimeByRules) { case EnigmailConstants.ENIG_NEVER: pgpmimeFinally = EnigmailConstants.ENIG_FINAL_NO; break; case EnigmailConstants.ENIG_UNDEF: pgpmimeFinally = ((this.sendPgpMime || (this.sendMode & nsIEnigmail.SEND_PGP_MIME)) ? EnigmailConstants.ENIG_FINAL_YES : EnigmailConstants.ENIG_FINAL_NO); break; case EnigmailConstants.ENIG_ALWAYS: pgpmimeFinally = EnigmailConstants.ENIG_FINAL_YES; break; case EnigmailConstants.ENIG_CONFLICT: pgpmimeFinally = EnigmailConstants.ENIG_FINAL_CONFLICT; break; } this.statusPGPMime = pgpmimeFinally; } EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: pgpmimeByRules=" + this.pgpmimeByRules + " pgpmimeFinally=" + pgpmimeFinally + "\n"); this.statusEncrypted = encFinally; this.statusSigned = signFinally; this.reasonEncrypted = encReason; this.reasonSigned = signReason; }, /** * Try to enable S/MIME, repsecting the various Enigmail rules * * @param encFinally: Number - "final" encryption status before applying S/MIME * @param signFinally: Number - "final" signing status before applying S/MIME * * @return Object: * - encFinally: Number - new encryption status after trying S/MIME * - signFinally: Number - new signing status after trying S/MIME */ tryEnablingSMime: function(encFinally, signFinally) { let encryptSmime = false; gSMFields.requireEncryptMessage = false; gSMFields.signMessage = false; // do not try S/MIME encryption if one of the following applies: // - OpenPGP is preferred over S/MIME, and OpenPGP is possible // - OpenPGP is preferred over S/MIME, and OpenPGP is enabled by rules // - encryption is disabled by rules and encryption is not manually enabled // - encryption is manually disabled if (this.pgpmimeForced === EnigmailConstants.ENIG_FORCE_SMIME) { encryptSmime = true; } else if ((this.mimePreferOpenPGP === 1 && (this.autoPgpEncryption || this.encryptByRules === EnigmailConstants.ENIG_ALWAYS)) || (this.encryptByRules === EnigmailConstants.ENIG_NEVER && encFinally !== EnigmailConstants.ENIG_FINAL_FORCEYES) || (this.pgpmimeForced === EnigmailConstants.ENIG_NEVER || this.pgpmimeForced === EnigmailConstants.ENIG_ALWAYS) || encFinally === EnigmailConstants.ENIG_FINAL_FORCENO) { return { encFinally: encFinally, signFinally: signFinally }; } if (!encryptSmime) { if (EnigmailPrefs.getPref("autoSendEncrypted") == 1) { if (this.isSmimeEncryptionPossible()) { if (this.mimePreferOpenPGP === 0) { // S/MIME is preferred and encryption is possible encryptSmime = true; encFinally = EnigmailConstants.ENIG_FINAL_YES; } else if (encFinally === EnigmailConstants.ENIG_FINAL_NO || encFinally === EnigmailConstants.ENIG_FINAL_CONFLICT || !this.autoPgpEncryption) { // Enigmail is preferred but not possible; S/MIME enc. is possible encryptSmime = true; encFinally = EnigmailConstants.ENIG_FINAL_YES; } } } else if (encFinally === EnigmailConstants.ENIG_FINAL_FORCEYES) { if (this.isSmimeEncryptionPossible()) { if (this.mimePreferOpenPGP === 0 || (!this.autoPgpEncryption)) { // S/MIME is preferred and encryption is possible // or PGP/MIME is preferred but impossible encryptSmime = true; } } } } if (encryptSmime) { if (this.pgpmimeForced === EnigmailConstants.ENIG_FORCE_SMIME) { this.statusPGPMime = EnigmailConstants.ENIG_FINAL_FORCESMIME; } else this.statusPGPMime = EnigmailConstants.ENIG_FINAL_SMIME; if (encFinally === EnigmailConstants.ENIG_FINAL_YES || encFinally === EnigmailConstants.ENIG_FINAL_FORCEYES) { gSMFields.requireEncryptMessage = true; } if (signFinally === EnigmailConstants.ENIG_FINAL_YES || signFinally === EnigmailConstants.ENIG_FINAL_FORCEYES) { gSMFields.signMessage = true; } } else { gSMFields.requireEncryptMessage = false; if ((encFinally === EnigmailConstants.ENIG_FINAL_NO || encFinally === EnigmailConstants.ENIG_FINAL_FORCENO) && this.mimePreferOpenPGP === 0 && !this.autoPgpEncryption && (signFinally === EnigmailConstants.ENIG_FINAL_YES || signFinally === EnigmailConstants.ENIG_FINAL_FORCEYES)) { // S/MIME is preferred this.statusPGPMime = EnigmailConstants.ENIG_FINAL_SMIME; gSMFields.signMessage = true; } else { gSMFields.signMessage = false; } } return { encFinally: encFinally, signFinally: signFinally }; }, // process icon/strings of status bar buttons and menu entries according to final encrypt/sign/pgpmime status // - uses as INPUT: // - this.statusEncrypt, this.statusSign, this.statusPGPMime // - uses as OUTPUT: // - resulting icon symbols // - this.statusEncryptStr, this.statusSignStr, this.statusPGPMimeStr, this.statusInlinePGPStr, this.statusAttachOwnKey // - this.statusSMimeStr updateStatusBar: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.updateStatusBar()\n"); this.statusEncryptedInStatusBar = this.statusEncrypted; // to double check broken promise for encryption if (!this.identity) { this.identity = getCurrentIdentity(); } var toolbarTxt = document.getElementById("enigmail-toolbar-text"); var encBroadcaster = document.getElementById("enigmail-bc-encrypt"); var signBroadcaster = document.getElementById("enigmail-bc-sign"); var attachBroadcaster = document.getElementById("enigmail-bc-attach"); let enc = this.getEncryptionEnabled(); let sign = this.getSigningEnabled(); // enigmail disabled for this identity?: if (!enc) { // hide icons if enigmail not enabled encBroadcaster.removeAttribute("encrypted"); encBroadcaster.setAttribute("disabled", "true"); } else { encBroadcaster.removeAttribute("disabled"); } if (!sign) { signBroadcaster.removeAttribute("signed"); signBroadcaster.setAttribute("disabled", "true"); attachBroadcaster.setAttribute("disabled", "true"); } else { signBroadcaster.removeAttribute("disabled"); attachBroadcaster.removeAttribute("disabled"); } if (!(enc || sign)) { if (toolbarTxt) { toolbarTxt.value = EnigmailLocale.getString("msgCompose.toolbarTxt.disabled"); toolbarTxt.removeAttribute("class"); } return; } // process resulting icon symbol and status strings for encrypt mode var encSymbol = null; var doEncrypt = false; var encStr = null; switch (this.statusEncrypted) { case EnigmailConstants.ENIG_FINAL_FORCENO: encSymbol = "forceNo"; encStr = EnigmailLocale.getString("encryptMessageNorm"); break; case EnigmailConstants.ENIG_FINAL_FORCEYES: doEncrypt = true; encSymbol = "forceYes"; encStr = EnigmailLocale.getString("encryptMessageNorm"); break; case EnigmailConstants.ENIG_FINAL_NO: encSymbol = "inactiveNone"; encStr = EnigmailLocale.getString("encryptMessageAuto"); break; case EnigmailConstants.ENIG_FINAL_YES: doEncrypt = true; encSymbol = "activeNone"; encStr = EnigmailLocale.getString("encryptMessageAuto"); break; case EnigmailConstants.ENIG_FINAL_CONFLICT: encSymbol = "inactiveConflict"; encStr = EnigmailLocale.getString("encryptMessageAuto"); break; } var encReasonStr = null; if (doEncrypt) { if (this.reasonEncrypted && this.reasonEncrypted !== "") { encReasonStr = EnigmailLocale.getString("encryptOnWithReason", [this.reasonEncrypted]); } else { encReasonStr = EnigmailLocale.getString("encryptOn"); } } else { if (this.reasonEncrypted && this.reasonEncrypted !== "") { encReasonStr = EnigmailLocale.getString("encryptOffWithReason", [this.reasonEncrypted]); } else { encReasonStr = EnigmailLocale.getString("encryptOff"); } } EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: encSymbol=" + encSymbol + " encReasonStr=" + encReasonStr + "\n"); // update encrypt icon and tooltip/menu-text encBroadcaster.setAttribute("encrypted", encSymbol); var encIcon = document.getElementById("button-enigmail-encrypt"); if (encIcon) { encIcon.setAttribute("tooltiptext", encReasonStr); } this.statusEncryptedStr = encStr; this.setChecked("enigmail-bc-encrypt", doEncrypt); // process resulting icon symbol for sign mode var signSymbol = null; var doSign = false; var signStr = ""; switch (this.statusSigned) { case EnigmailConstants.ENIG_FINAL_FORCENO: signSymbol = "forceNo"; signStr = EnigmailLocale.getString("signMessageNorm"); signReasonStr = EnigmailLocale.getString("signOffWithReason", [this.reasonSigned]); break; case EnigmailConstants.ENIG_FINAL_FORCEYES: doSign = true; signSymbol = "forceYes"; signStr = EnigmailLocale.getString("signMessageNorm"); signReasonStr = EnigmailLocale.getString("signOnWithReason", [this.reasonSigned]); break; case EnigmailConstants.ENIG_FINAL_NO: signSymbol = "inactiveNone"; signStr = EnigmailLocale.getString("signMessageAuto"); signReasonStr = EnigmailLocale.getString("signOffWithReason", [this.reasonSigned]); break; case EnigmailConstants.ENIG_FINAL_YES: doSign = true; signSymbol = "activeNone"; signStr = EnigmailLocale.getString("signMessageAuto"); signReasonStr = EnigmailLocale.getString("signOnWithReason", [this.reasonSigned]); break; case EnigmailConstants.ENIG_FINAL_CONFLICT: signSymbol = "inactiveConflict"; signStr = EnigmailLocale.getString("signMessageAuto"); signReasonStr = EnigmailLocale.getString("signOffWithReason", [this.reasonSigned]); break; } var signReasonStr = null; if (doSign) { if (this.reasonSigned && this.reasonSigned !== "") { signReasonStr = EnigmailLocale.getString("signOnWithReason", [this.reasonSigned]); } else { signReasonStr = signStr; } } else { if (this.reasonSigned && this.reasonSigned !== "") { signReasonStr = EnigmailLocale.getString("signOffWithReason", [this.reasonSigned]); } else { signReasonStr = signStr; } } EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: signSymbol=" + signSymbol + " signReasonStr=" + signReasonStr + "\n"); // update sign icon and tooltip/menu-text signBroadcaster.setAttribute("signed", signSymbol); var signIcon = document.getElementById("button-enigmail-sign"); if (signIcon) { signIcon.setAttribute("tooltiptext", signReasonStr); } this.statusSignedStr = signStr; this.setChecked("enigmail-bc-sign", doSign); // process resulting toolbar message var toolbarMsg = ""; if (doSign && doEncrypt) { toolbarMsg = EnigmailLocale.getString("msgCompose.toolbarTxt.signAndEncrypt"); } else if (doSign) { toolbarMsg = EnigmailLocale.getString("msgCompose.toolbarTxt.signOnly"); } else if (doEncrypt) { toolbarMsg = EnigmailLocale.getString("msgCompose.toolbarTxt.encryptOnly"); } else { toolbarMsg = EnigmailLocale.getString("msgCompose.toolbarTxt.noEncryption"); } if (toolbarTxt) { toolbarTxt.value = toolbarMsg; if (gMsgCompose.compFields.securityInfo) { let si = gMsgCompose.compFields.securityInfo.QueryInterface(Components.interfaces.nsIMsgSMIMECompFields); if (!doSign && !doEncrypt && !(gMsgCompose.compFields.securityInfo instanceof Components.interfaces.nsIMsgSMIMECompFields && (si.signMessage || si.requireEncryptMessage))) { toolbarTxt.setAttribute("class", "enigmailStrong"); } else { toolbarTxt.removeAttribute("class"); } } else { toolbarTxt.removeAttribute("class"); } } // update pgp mime/inline PGP menu-text if (this.statusPGPMime == EnigmailConstants.ENIG_FINAL_YES) { this.statusPGPMimeStr = EnigmailLocale.getString("pgpmimeAuto"); } else { this.statusPGPMimeStr = EnigmailLocale.getString("pgpmimeNormal"); } if (this.statusPGPMime == EnigmailConstants.ENIG_FINAL_NO) { this.statusInlinePGPStr = EnigmailLocale.getString("inlinePGPAuto"); } else { this.statusInlinePGPStr = EnigmailLocale.getString("inlinePGPNormal"); } if (this.statusPGPMime == EnigmailConstants.ENIG_FINAL_SMIME) { this.statusSMimeStr = EnigmailLocale.getString("smimeAuto"); } else { this.statusSMimeStr = EnigmailLocale.getString("smimeNormal"); } if (this.allowAttachOwnKey() === 1) { attachBroadcaster.removeAttribute("disabled"); } else { attachBroadcaster.setAttribute("disabled", "true"); } }, /** * determine if own key may be attached. * @result: Number: * -1: account not enabled for Enigmail * 0: account enabled but key mode set to "by Email address" * 1: account enabled; key specified */ allowAttachOwnKey: function() { let allow = -1; if (this.isEnigmailEnabled()) { allow = 0; if (this.identity.getIntAttribute("pgpKeyMode") > 0) { let keyIdValue = this.identity.getCharAttribute("pgpkeyId"); if (keyIdValue.search(/^ *(0x)?[0-9a-fA-F]* *$/) === 0) { allow = 1; } } } return allow; }, /* compute whether to sign/encrypt according to current rules and sendMode * - without any interaction, just to process resulting status bar icons */ determineSendFlags: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.focusChange: Enigmail.msg.determineSendFlags\n"); if (this.juniorMode) { this.getPepMessageRating(); return; } this.statusEncryptedInStatusBar = null; // to double check broken promise for encryption if (!this.identity) { this.identity = getCurrentIdentity(); } if (this.isEnigmailEnabled()) { var compFields = gMsgCompose.compFields; if (!Enigmail.msg.composeBodyReady) { compFields = Components.classes["@mozilla.org/messengercompose/composefields;1"].createInstance(Components.interfaces.nsIMsgCompFields); } Recipients2CompFields(compFields); gMsgCompose.expandMailingLists(); // process list of to/cc email addresses // - bcc email addresses are ignored, when processing whether to sign/encrypt var toAddrList = []; var arrLen = {}; var recList; if (compFields.to.length > 0) { recList = compFields.splitRecipients(compFields.to, true, arrLen); this.addRecipients(toAddrList, recList); } if (compFields.cc.length > 0) { recList = compFields.splitRecipients(compFields.cc, true, arrLen); this.addRecipients(toAddrList, recList); } this.encryptByRules = EnigmailConstants.ENIG_UNDEF; this.signByRules = EnigmailConstants.ENIG_UNDEF; this.pgpmimeByRules = EnigmailConstants.ENIG_UNDEF; // process rules if (toAddrList.length > 0 && EnigmailPrefs.getPref("assignKeysByRules")) { var matchedKeysObj = {}; var flagsObj = {}; if (EnigmailRules.mapAddrsToKeys(toAddrList.join(", "), false, // no interaction if not all addrs have a key window, matchedKeysObj, // resulting matching keys flagsObj)) { // resulting flags (0/1/2/3 for each type) this.encryptByRules = flagsObj.encrypt; this.signByRules = flagsObj.sign; this.pgpmimeByRules = flagsObj.pgpMime; if (matchedKeysObj.value && matchedKeysObj.value.length > 0) { // replace addresses with results from rules toAddrList = matchedKeysObj.value.split(", "); } } } let validKeyList = Enigmail.hlp.validKeysForAllRecipients(toAddrList.join(", ")); this.autoPgpEncryption = (validKeyList !== null); // if not clear whether to encrypt yet, check whether automatically-send-encrypted applies if (toAddrList.length > 0 && this.encryptByRules == EnigmailConstants.ENIG_UNDEF && EnigmailPrefs.getPref("autoSendEncrypted") == 1) { if (validKeyList) { this.encryptByRules = EnigmailConstants.ENIG_AUTO_ALWAYS; } } } else { this.encryptByRules = EnigmailConstants.ENIG_AUTO_NEVER; this.autoPgpEncryption = false; } // process and signal new resulting state this.processFinalState(); this.updateStatusBar(); this.determineSendFlagId = null; }, setChecked: function(elementId, checked) { let elem = document.getElementById(elementId); if (elem) { if (checked) { elem.setAttribute("checked", "true"); } else elem.removeAttribute("checked"); } }, setMenuSettings: function(postfix) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.setMenuSettings: postfix=" + postfix + "\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; var elem = document.getElementById("enigmail_compose_sign_item" + postfix); if (elem) { elem.setAttribute("label", this.statusSignedStr); switch (this.statusSigned) { case EnigmailConstants.ENIG_FINAL_YES: case EnigmailConstants.ENIG_FINAL_FORCEYES: elem.setAttribute("checked", "true"); break; default: elem.setAttribute("checked", "false"); } } elem = document.getElementById("enigmail_compose_encrypt_item" + postfix); if (elem) { elem.setAttribute("label", this.statusEncryptedStr); switch (this.statusEncrypted) { case EnigmailConstants.ENIG_FINAL_YES: case EnigmailConstants.ENIG_FINAL_FORCEYES: elem.setAttribute("checked", "true"); break; default: elem.setAttribute("checked", "false"); } } elem = document.getElementById("enigmail_compose_pgpmime_item" + postfix); if (elem) { elem.setAttribute("label", this.statusPGPMimeStr); switch (this.statusPGPMime) { case EnigmailConstants.ENIG_FINAL_YES: case EnigmailConstants.ENIG_FINAL_FORCEYES: elem.setAttribute("checked", "true"); break; default: elem.setAttribute("checked", "false"); } elem = document.getElementById("enigmail_compose_inline_item" + postfix); if (elem) { elem.setAttribute("label", this.statusInlinePGPStr); switch (this.statusPGPMime) { case EnigmailConstants.ENIG_FINAL_NO: case EnigmailConstants.ENIG_FINAL_FORCENO: case EnigmailConstants.ENIG_FINAL_CONFLICT: case EnigmailConstants.ENIG_FINAL_UNDEF: elem.setAttribute("checked", "true"); break; default: elem.setAttribute("checked", "false"); } } elem = document.getElementById("enigmail_compose_smime_item" + postfix); if (elem) { elem.setAttribute("label", this.statusSMimeStr); switch (this.statusPGPMime) { case EnigmailConstants.ENIG_FINAL_SMIME: case EnigmailConstants.ENIG_FINAL_FORCESMIME: elem.setAttribute("checked", "true"); break; default: elem.setAttribute("checked", "false"); } } let menuElement = document.getElementById("enigmail_insert_own_key"); if (menuElement) { if (this.identity.getIntAttribute("pgpKeyMode") > 0) { menuElement.setAttribute("checked", this.attachOwnKeyObj.appendAttachment.toString()); menuElement.removeAttribute("disabled"); } else { menuElement.setAttribute("disabled", "true"); } } } }, pepMenuPopup: function() { let encMenu = document.getElementById("enigmail_compose_pep_encrypt"); let hsMenu = document.getElementById("enigmail_composeMenu_pep_handshake"); let pepBc = document.getElementById("enigmail-bc-pepEncrypt"); if (this.pepEnabled()) { encMenu.setAttribute("checked", pepBc.getAttribute("encrypt")); encMenu.removeAttribute("disabled"); hsMenu.removeAttribute("disabled"); } else { encMenu.setAttribute("checked", "false"); encMenu.setAttribute("disabled", "true"); hsMenu.setAttribute("disabled", "true"); } }, /** * Determine if pEp was disabled by the user */ pepEnabled: function() { let id = getCurrentIdentity(); return id.getBoolAttribute("enablePEP"); }, pepDisabledError: function() { EnigmailDialog.alert(window, EnigmailLocale.getString("pep.alert.disabledForIdentity")); }, onPepEncryptMenu: function() { if (!this.pepEnabled()) { this.pepDisabledError(); return; } let pepBc = document.getElementById("enigmail-bc-pepEncrypt"); pepBc.setAttribute("encrypt", pepBc.getAttribute("encrypt") === "true" ? "false" : "true"); this.getPepMessageRating(); }, onPepEncryptButton: function() { this.onPepEncryptMenu(); }, onPepHandshakeButton: function(event) { if (!this.pepEnabled()) { this.pepDisabledError(); return; } event.stopPropagation(); EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.onPepHandshakeButton()\n"); let bc = document.getElementById("enigmail-bc-pepEncrypt"); if (bc.getAttribute("encrypt") === "false") { EnigmailDialog.info(window, EnigmailLocale.getString("handshakeDlg.error.noProtection")); return; } let o = this.compileFromAndTo(); let toAddr = EnigmailFuncs.stripEmail(o.toAddrList.join(",")).split(/,/); if (o.toAddrList.length === 0) { EnigmailDialog.info(window, EnigmailLocale.getString("handshakeDlg.error.noPeers")); return; } let myId = getCurrentIdentity(); let inputObj = { myself: myId.email, addresses: toAddr, direction: 1, parentWindow: window, onComplete: Enigmail.msg.getPepMessageRating.bind(Enigmail.msg) }; window.openDialog("chrome://enigmail/content/pepPrepHandshake.xul", "", "dialog,modal,centerscreen", inputObj); }, displaySecuritySettings: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.displaySecuritySettings\n"); var inputObj = { statusEncrypted: this.statusEncrypted, statusSigned: this.statusSigned, statusPGPMime: this.statusPGPMime, success: false, resetDefaults: false }; window.openDialog("chrome://enigmail/content/enigmailEncryptionDlg.xul", "", "dialog,modal,centerscreen", inputObj); if (!inputObj.success) return; // Cancel pressed if (inputObj.resetDefaults) { // reset everything to defaults this.encryptForced = EnigmailConstants.ENIG_UNDEF; this.signForced = EnigmailConstants.ENIG_UNDEF; this.pgpmimeForced = EnigmailConstants.ENIG_UNDEF; this.finalSignDependsOnEncrypt = true; } else { if (this.signForced != inputObj.sign) { this.dirty = 2; this.signForced = inputObj.sign; this.finalSignDependsOnEncrypt = false; } if (this.encryptForced != inputObj.encrypt || this.pgpmimeForced != inputObj.pgpmime) { this.dirty = 2; } this.encryptForced = inputObj.encrypt; this.pgpmimeForced = inputObj.pgpmime; } this.processFinalState(); this.updateStatusBar(); }, signingNoLongerDependsOnEnc: function() { if (this.finalSignDependsOnEncrypt && (!this.juniorMode)) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.signingNoLongerDependsOnEnc(): unbundle final signing\n"); this.finalSignDependsOnEncrypt = false; EnigmailDialog.alertPref(window, EnigmailLocale.getString("signIconClicked"), "displaySignWarn"); } }, confirmBeforeSend: function(toAddrStr, gpgKeys, sendFlags, isOffline) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.confirmBeforeSend: sendFlags=" + sendFlags + "\n"); // get confirmation before sending message const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; // get wording for message status (e.g. " SIGNED ENCRYPTED") var msgStatus = ""; if (sendFlags & (ENCRYPT | SIGN)) { if (this.statusPGPMime === EnigmailConstants.ENIG_FINAL_SMIME || this.statusPGPMime === EnigmailConstants.ENIG_FINAL_FORCESMIME) { msgStatus += " " + EnigmailLocale.getString("statSMIME"); } else if (sendFlags & nsIEnigmail.SEND_PGP_MIME) { msgStatus += " " + EnigmailLocale.getString("statPGPMIME"); } if (sendFlags & SIGN) { msgStatus += " " + EnigmailLocale.getString("statSigned"); } if (sendFlags & ENCRYPT) { msgStatus += " " + EnigmailLocale.getString("statEncrypted"); } } else { msgStatus += " " + EnigmailLocale.getString("statPlain"); } // create message var msgConfirm = ""; if (isOffline || sendFlags & nsIEnigmail.SEND_LATER) { msgConfirm = EnigmailLocale.getString("offlineSave", [msgStatus, EnigmailFuncs.stripEmail(toAddrStr).replace(/,/g, ", ")]); } else { msgConfirm = EnigmailLocale.getString("onlineSend", [msgStatus, EnigmailFuncs.stripEmail(toAddrStr).replace(/,/g, ", ")]); } // add list of keys if (sendFlags & ENCRYPT) { gpgKeys = gpgKeys.replace(/^, /, "").replace(/, $/, ""); // make gpg keys unique let keyList = gpgKeys.split(/[, ]+/).reduce(function _f(p, key) { if (p.indexOf(key) < 0) p.push(key); return p; }, []); if (this.statusPGPMime !== EnigmailConstants.ENIG_FINAL_SMIME && this.statusPGPMime !== EnigmailConstants.ENIG_FINAL_FORCESMIME) { msgConfirm += "\n\n" + EnigmailLocale.getString("encryptKeysNote", [keyList.join(", ")]); } } return EnigmailDialog.confirmDlg(window, msgConfirm, EnigmailLocale.getString((isOffline || sendFlags & nsIEnigmail.SEND_LATER) ? "msgCompose.button.save" : "msgCompose.button.send")); }, addRecipients: function(toAddrList, recList) { for (var i = 0; i < recList.length; i++) { toAddrList.push(EnigmailFuncs.stripEmail(recList[i].replace(/[\",]/g, ""))); } }, setDraftStatus: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.setDraftStatus - enabling draft mode\n"); // Draft Status: // N (for new style) plus String of 4 numbers: // 1: encryption // 2: signing // 3: PGP/MIME // 4: attach own key var draftStatus = "N" + this.encryptForced + this.signForced + this.pgpmimeForced + (this.attachOwnKeyObj.appendAttachment ? "1" : "0"); this.setAdditionalHeader("X-Enigmail-Draft-Status", draftStatus); }, getSenderUserId: function() { var userIdValue = null; if (this.identity.getIntAttribute("pgpKeyMode") > 0) { userIdValue = this.identity.getCharAttribute("pgpkeyId"); if (!userIdValue) { var mesg = EnigmailLocale.getString("composeSpecifyEmail"); var valueObj = { value: userIdValue }; if (EnigmailDialog.promptValue(window, mesg, valueObj)) { userIdValue = valueObj.value; } } if (userIdValue) { this.identity.setCharAttribute("pgpkeyId", userIdValue); } else { this.identity.setIntAttribute("pgpKeyMode", 0); } } if (typeof(userIdValue) != "string") { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.getSenderUserId: type of userIdValue=" + typeof(userIdValue) + "\n"); userIdValue = this.identity.email; } return userIdValue; }, /* process rules and find keys for passed email addresses * This is THE core method to prepare sending encryptes emails. * - it processes the recipient rules (if not disabled) * - it * * @sendFlags: Longint - all current combined/processed send flags (incl. optSendFlags) * @optSendFlags: Longint - may only be SEND_ALWAYS_TRUST or SEND_ENCRYPT_TO_SELF * @gotSendFlags: Longint - initial sendMode of encryptMsg() (0 or SIGN or ENCRYPT or SIGN|ENCRYPT) * @fromAddr: String - from email * @toAddrList: Array - both to and cc receivers * @bccAddrList: Array - bcc receivers * @return: Object: * - sendFlags (Longint) * - toAddrStr comma separated string of unprocessed to/cc emails * - bccAddrStr comma separated string of unprocessed to/cc emails * or null (cancel sending the email) */ keySelection: function(enigmailSvc, sendFlags, optSendFlags, gotSendFlags, fromAddr, toAddrList, bccAddrList) { EnigmailLog.DEBUG("=====> keySelection()\n"); EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.keySelection()\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; var toAddrStr = toAddrList.join(", "); var bccAddrStr = bccAddrList.join(", "); // NOTE: If we only have bcc addresses, we currently do NOT process rules and select keys at all // This is GOOD because sending keys for bcc addresses makes bcc addresses visible // (thus compromising the concept of bcc) // THUS, we disable encryption even though all bcc receivers might want to have it encrypted. if (toAddrStr.length === 0) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.keySelection(): skip key selection because we neither have \"to\" nor \"cc\" addresses\n"); if (this.statusPGPMime == EnigmailConstants.ENIG_FINAL_YES || this.statusPGPMime == EnigmailConstants.ENIG_FINAL_FORCEYES) { sendFlags |= nsIEnigmail.SEND_PGP_MIME; } else if (this.statusPGPMime == EnigmailConstants.ENIG_FINAL_NO || this.statusPGPMime == EnigmailConstants.ENIG_FINAL_FORCENO || this.statusPGPMime == EnigmailConstants.ENIG_FINAL_CONFLICT) { sendFlags &= ~nsIEnigmail.SEND_PGP_MIME; } return { sendFlags: sendFlags, toAddrStr: toAddrStr, bccAddrStr: bccAddrStr }; } EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.keySelection(): toAddrStr=\"" + toAddrStr + "\" bccAddrStr=\"" + bccAddrStr + "\"\n"); // force add-rule dialog for each missing key?: var forceRecipientSettings = false; // if keys are ONLY assigned by rules, force add-rule dialog for each missing key if (EnigmailPrefs.getPref("assignKeysByRules") && !EnigmailPrefs.getPref("assignKeysByEmailAddr") && !EnigmailPrefs.getPref("assignKeysManuallyIfMissing") && !EnigmailPrefs.getPref("assignKeysManuallyAlways")) { forceRecipientSettings = true; } // REPEAT 1 or 2 times: // NOTE: The only way to call this loop twice is to come to the "continue;" statement below, // which forces a second iteration (with forceRecipientSettings==true) var doRulesProcessingAgain; do { doRulesProcessingAgain = false; // process rules if not disabled // - enableRules: rules not temporarily disabled // REPLACES email addresses by keys in its result !!! var refreshKeyList = true; if (EnigmailPrefs.getPref("assignKeysByRules") && this.enableRules) { let result = this.processRules(forceRecipientSettings, sendFlags, optSendFlags, toAddrStr, bccAddrStr); if (!result) { return null; } sendFlags = result.sendFlags; optSendFlags = result.optSendFlags; toAddrStr = result.toAddr; // replace email addresses with rules by the corresponding keys bccAddrStr = result.bccAddr; // replace email addresses with rules by the corresponding keys refreshKeyList = !result.didRefreshKeyList; // if key list refreshed we don't have to do it again } // if encryption is requested for the email: // - encrypt test message for default encryption // - might trigger a second iteration through this loop // - if during its dialog for manual key selection "create per-recipient rules" is pressed // to force manual settings for missing keys // LEAVES remaining email addresses not covered by rules as they are if (sendFlags & ENCRYPT) { let result = this.encryptTestMessage(enigmailSvc, sendFlags, optSendFlags, fromAddr, toAddrStr, bccAddrStr, bccAddrList, refreshKeyList); if (!result) { return null; } sendFlags = result.sendFlags; toAddrStr = result.toAddrStr; bccAddrStr = result.bccAddrStr; if (result.doRulesProcessingAgain) { // start rule processing again ? doRulesProcessingAgain = true; if (result.createNewRule) { forceRecipientSettings = true; } } } } while (doRulesProcessingAgain); EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.keySelection(): return toAddrStr=\"" + toAddrStr + "\" bccAddrStr=\"" + bccAddrStr + "\"\n"); EnigmailLog.DEBUG(" <=== keySelection()\n"); return { sendFlags: sendFlags, toAddrStr: toAddrStr, bccAddrStr: bccAddrStr }; }, /** * Determine if S/MIME or OpenPGP should be used * * @param sendFlags: Number - input send flags. * * @return: Boolean: * 1: use OpenPGP * 0: use S/MIME */ preferPgpOverSmime: function(sendFlags) { const nsIEnigmail = Components.interfaces.nsIEnigmail; if (gMsgCompose.compFields.securityInfo instanceof Components.interfaces.nsIMsgSMIMECompFields && (sendFlags & (nsIEnigmail.SEND_SIGNED | nsIEnigmail.SEND_ENCRYPTED))) { let si = gMsgCompose.compFields.securityInfo.QueryInterface(Components.interfaces.nsIMsgSMIMECompFields); if (si.requireEncryptMessage || si.signMessage) { if (sendFlags & nsIEnigmail.SAVE_MESSAGE) { // use S/MIME if it's enabled for saving drafts return 0; } else { return this.mimePreferOpenPGP; } } } return 1; }, /** * check if S/MIME encryption can be enabled * * @return: Boolean - true: keys for all recipients are available */ isSmimeEncryptionPossible: function() { let ret = false; let id = getCurrentIdentity(); if (id.getUnicharAttribute("encryption_cert_name") === "") return false; // enable encryption if keys for all recipients are available let missingCount = {}; let emailAddresses = {}; try { Components.classes["@mozilla.org/messenger-smime/smimejshelper;1"] .createInstance(Components.interfaces.nsISMimeJSHelper) .getNoCertAddresses(gMsgCompose.compFields, missingCount, emailAddresses); } catch (e) { return false; } if (missingCount.value === 0) { return true; } return false; }, /** * try to apply the OpenPGP rules * * @forceRecipientSetting: Boolean - force manual selection for each missing key? * @sendFlags: Integer - all current combined/processed send flags (incl. optSendFlags) * @optSendFlags: Integer - may only be SEND_ALWAYS_TRUST or SEND_ENCRYPT_TO_SELF * @toAddrStr: String - comma separated string of keys and unprocessed to/cc emails * @bccAddrStr: String - comma separated string of keys and unprocessed bcc emails * @return: { sendFlags, toAddr, bccAddr } * or null (cancel sending the email) */ processRules: function(forceRecipientSettings, sendFlags, optSendFlags, toAddrStr, bccAddrStr) { EnigmailLog.DEBUG("=====> processRules()\n"); EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.processRules(): toAddrStr=\"" + toAddrStr + "\" bccAddrStr=\"" + bccAddrStr + "\" forceRecipientSettings=" + forceRecipientSettings + "\n"); // process defaults const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; var didRefreshKeyList = false; // return value to signal whether the key list was refreshed // get keys for to and cc addresses: // - matchedKeysObj will contain the keys and the remaining toAddrStr elements var matchedKeysObj = {}; // returned value for matched keys var flagsObj = {}; // returned value for flags if (!EnigmailRules.mapAddrsToKeys(toAddrStr, forceRecipientSettings, // true => start dialog for addrs without any key window, matchedKeysObj, flagsObj)) { return null; } if (matchedKeysObj.value) { toAddrStr = matchedKeysObj.value; EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.processRules(): after mapAddrsToKeys() toAddrStr=\"" + toAddrStr + "\"\n"); } this.encryptByRules = flagsObj.encrypt; this.signByRules = flagsObj.sign; this.pgpmimeByRules = flagsObj.pgpMime; // if not clear whether to encrypt yet, check whether automatically-send-encrypted applies // - check whether bcc is empty here? if (bccAddrStr.length === 0) if (toAddrStr.length > 0 && this.encryptByRules == EnigmailConstants.ENIG_UNDEF && EnigmailPrefs.getPref("autoSendEncrypted") == 1) { var validKeyList = Enigmail.hlp.validKeysForAllRecipients(toAddrStr); if (validKeyList) { this.encryptByRules = EnigmailConstants.ENIG_AUTO_ALWAYS; toAddrStr = validKeyList.join(", "); } } // process final state this.processFinalState(sendFlags); // final handling of conflicts: // - pgpMime conflicts always result into pgpMime = 0/'never' if (this.statusPGPMime == EnigmailConstants.ENIG_FINAL_CONFLICT) { this.statusPGPMime = EnigmailConstants.ENIG_FINAL_NO; } // - encrypt/sign conflicts result into result 0/'never' // with possible dialog to give a corresponding feedback var conflictFound = false; if (this.statusEncrypted == EnigmailConstants.ENIG_FINAL_CONFLICT) { this.statusEncrypted = EnigmailConstants.ENIG_FINAL_NO; conflictFound = true; } if (this.statusSigned == EnigmailConstants.ENIG_FINAL_CONFLICT) { this.statusSigned = EnigmailConstants.ENIG_FINAL_NO; conflictFound = true; } if (conflictFound) { if (!Enigmail.hlp.processConflicts(this.statusEncrypted == EnigmailConstants.ENIG_FINAL_YES || this.statusEncrypted == EnigmailConstants.ENIG_FINAL_FORCEYES, this.statusSigned == EnigmailConstants.ENIG_FINAL_YES || this.statusSigned == EnigmailConstants.ENIG_FINAL_FORCEYES)) { return null; } } // process final sendMode // ENIG_FINAL_CONFLICT no longer possible switch (this.statusEncrypted) { case EnigmailConstants.ENIG_FINAL_NO: case EnigmailConstants.ENIG_FINAL_FORCENO: sendFlags &= ~ENCRYPT; break; case EnigmailConstants.ENIG_FINAL_YES: case EnigmailConstants.ENIG_FINAL_FORCEYES: sendFlags |= ENCRYPT; break; } switch (this.statusSigned) { case EnigmailConstants.ENIG_FINAL_NO: case EnigmailConstants.ENIG_FINAL_FORCENO: sendFlags &= ~SIGN; break; case EnigmailConstants.ENIG_FINAL_YES: case EnigmailConstants.ENIG_FINAL_FORCEYES: sendFlags |= SIGN; break; } switch (this.statusPGPMime) { case EnigmailConstants.ENIG_FINAL_NO: case EnigmailConstants.ENIG_FINAL_FORCENO: sendFlags &= ~nsIEnigmail.SEND_PGP_MIME; break; case EnigmailConstants.ENIG_FINAL_YES: case EnigmailConstants.ENIG_FINAL_FORCEYES: sendFlags |= nsIEnigmail.SEND_PGP_MIME; break; } // get keys according to rules for bcc addresses: // - matchedKeysObj will contain the keys and the remaining bccAddrStr elements // - NOTE: bcc recipients are ignored when in general computing whether to sign or encrypt or pgpMime if (!EnigmailRules.mapAddrsToKeys(bccAddrStr, forceRecipientSettings, // true => start dialog for addrs without any key window, matchedKeysObj, flagsObj)) { return null; } if (matchedKeysObj.value) { bccAddrStr = matchedKeysObj.value; EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.processRules(): after mapAddrsToKeys() bccAddrStr=\"" + bccAddrStr + "\"\n"); } EnigmailLog.DEBUG(" <=== processRules()\n"); return { sendFlags: sendFlags, optSendFlags: optSendFlags, toAddr: toAddrStr, bccAddr: bccAddrStr, didRefreshKeyList: didRefreshKeyList }; }, /* encrypt a test message to see whether we have all necessary keys * * @sendFlags: all current combined/processed send flags (incl. optSendFlags) * @optSendFlags: may only be SEND_ALWAYS_TRUST or SEND_ENCRYPT_TO_SELF * @fromAddr: from email * @toAddrStr: comma separated string of keys and unprocessed to/cc emails * @bccAddrStr: comma separated string of keys and unprocessed bcc emails * @bccAddrList: bcc receivers * @return: doRulesProcessingAgain: start with rule processing once more * or null (cancel sending the email) */ encryptTestMessage: function(enigmailSvc, sendFlags, optSendFlags, fromAddr, toAddrStr, bccAddrStr, bccAddrList, refresh) { EnigmailLog.DEBUG("=====> encryptTestMessage()\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; var testCipher = null; var testExitCodeObj = {}; var testStatusFlagsObj = {}; var testErrorMsgObj = {}; // get keys for remaining email addresses // - NOTE: This should not be necessary; however, in GPG there is a problem: // Only the first key found for an email is used. // If this is invalid, no other keys are tested. // Thus, WE make it better here in enigmail until the bug is fixed. var details = {}; // will contain msgList[] afterwards if (EnigmailPrefs.getPref("assignKeysByEmailAddr")) { var validKeyList = Enigmail.hlp.validKeysForAllRecipients(toAddrStr, details); if (validKeyList) { toAddrStr = validKeyList.join(", "); } } // encrypt test message for test recipients var testPlain = "Test Message"; var testUiFlags = nsIEnigmail.UI_TEST; var testSendFlags = nsIEnigmail.SEND_TEST | ENCRYPT | optSendFlags; EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptTestMessage(): call encryptMessage() for fromAddr=\"" + fromAddr + "\" toAddrStr=\"" + toAddrStr + "\" bccAddrStr=\"" + bccAddrStr + "\"\n"); testCipher = enigmailSvc.encryptMessage(window, testUiFlags, testPlain, fromAddr, toAddrStr, bccAddrStr, testSendFlags, testExitCodeObj, testStatusFlagsObj, testErrorMsgObj); if (testStatusFlagsObj.value & (nsIEnigmail.INVALID_RECIPIENT | nsIEnigmail.NO_SECKEY)) { // check if own key is invalid EnigmailDialog.alert(window, testErrorMsgObj.value); return null; } // if // - "always ask/manually" (even if all keys were found) or // - unless "ask for missing keys": // - we have an invalid recipient or // - we could not resolve any/all keys // (due to disabled "assignKeysByEmailAddr"" or multiple keys with same trust for a recipient) // start the dialog for user selected keys if (EnigmailPrefs.getPref("assignKeysManuallyAlways") || (((testStatusFlagsObj.value & nsIEnigmail.INVALID_RECIPIENT) || toAddrStr.indexOf('@') >= 0) && EnigmailPrefs.getPref("assignKeysManuallyIfMissing")) || (details && details.errArray && details.errArray.length > 0) ) { // check for invalid recipient keys var resultObj = {}; var inputObj = {}; inputObj.toAddr = toAddrStr; inputObj.invalidAddr = Enigmail.hlp.getInvalidAddress(testErrorMsgObj.value); if (details && details.errArray && details.errArray.length > 0) { inputObj.errArray = details.errArray; } // prepare dialog options: inputObj.options = "multisel"; if (EnigmailPrefs.getPref("assignKeysByRules")) { inputObj.options += ",rulesOption"; // enable button to create per-recipient rule } if (EnigmailPrefs.getPref("assignKeysManuallyAlways")) { inputObj.options += ",noforcedisp"; } if (!(sendFlags & SIGN)) { inputObj.options += ",unsigned"; } if (this.trustAllKeys) { inputObj.options += ",trustallkeys"; } if (sendFlags & nsIEnigmail.SEND_LATER) { let sendLaterLabel = EnigmailLocale.getString("sendLaterCmd.label"); inputObj.options += ",sendlabel=" + sendLaterLabel; } inputObj.options += ","; inputObj.dialogHeader = EnigmailLocale.getString("recipientsSelectionHdr"); // perform key selection dialog: window.openDialog("chrome://enigmail/content/enigmailKeySelection.xul", "", "dialog,modal,centerscreen,resizable", inputObj, resultObj); // process result from key selection dialog: try { // CANCEL: if (resultObj.cancelled) { return null; } // repeat checking of rules etc. (e.g. after importing new key) if (resultObj.repeatEvaluation) { // THIS is the place that triggers a second iteration let returnObj = { doRulesProcessingAgain: true, createNewRule: false, sendFlags: sendFlags, toAddrStr: toAddrStr, bccAddrStr: bccAddrStr }; // "Create per recipient rule(s)": if (resultObj.perRecipientRules && this.enableRules) { // do an extra round because the user wants to set a PGP rule returnObj.createNewRule = true; } return returnObj; } // process OK button: if (resultObj.encrypt) { sendFlags |= ENCRYPT; // should anyway be set if (bccAddrList.length > 0) { toAddrStr = ""; bccAddrStr = resultObj.userList.join(", "); } else { toAddrStr = resultObj.userList.join(", "); bccAddrStr = ""; } } else { // encryption explicitely turned off sendFlags &= ~ENCRYPT; // counts as forced non-encryption // (no internal error if different state was processed before) this.statusEncrypted = EnigmailConstants.ENIG_FINAL_NO; this.statusEncryptedInStatusBar = EnigmailConstants.ENIG_FINAL_NO; } if (resultObj.sign) { sendFlags |= SIGN; } else { sendFlags &= ~SIGN; } testCipher = "ok"; testExitCodeObj.value = 0; } catch (ex) { // cancel pressed -> don't send mail return null; } } // If test encryption failed and never ask manually, turn off default encryption if ((!testCipher || (testExitCodeObj.value !== 0)) && !EnigmailPrefs.getPref("assignKeysManuallyIfMissing") && !EnigmailPrefs.getPref("assignKeysManuallyAlways")) { sendFlags &= ~ENCRYPT; this.statusEncrypted = EnigmailConstants.ENIG_FINAL_NO; this.statusEncryptedInStatusBar = EnigmailConstants.ENIG_FINAL_NO; EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptTestMessage: No default encryption because test failed\n"); } EnigmailLog.DEBUG(" <=== encryptTestMessage()\n"); return { doRulesProcessingAgain: false, createNewRule: false, sendFlags: sendFlags, toAddrStr: toAddrStr, bccAddrStr: bccAddrStr }; }, /* Manage the wrapping of inline signed mails * * @wrapresultObj: Result: * @wrapresultObj.cancelled, true if send operation is to be cancelled, else false * @wrapresultObj.usePpgMime, true if message send option was changed to PGP/MIME, else false */ wrapInLine: function(wrapresultObj) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: WrapInLine\n"); wrapresultObj.cancelled = false; wrapresultObj.usePpgMime = false; try { const dce = Components.interfaces.nsIDocumentEncoder; var wrapper = gMsgCompose.editor.QueryInterface(Components.interfaces.nsIEditorMailSupport); var editor = gMsgCompose.editor.QueryInterface(Components.interfaces.nsIPlaintextEditor); var encoderFlags = dce.OutputFormatted | dce.OutputLFLineBreak; var wrapWidth = this.getMailPref("mailnews.wraplength"); if (wrapWidth > 0 && wrapWidth < 68 && editor.wrapWidth > 0) { if (EnigmailDialog.confirmDlg(window, EnigmailLocale.getString("minimalLineWrapping", [wrapWidth]))) { wrapWidth = 68; EnigmailPrefs.getPrefRoot().setIntPref("mailnews.wraplength", wrapWidth); } } if (wrapWidth && editor.wrapWidth > 0) { // First use standard editor wrap mechanism: editor.wrapWidth = wrapWidth - 2; wrapper.rewrap(true); editor.wrapWidth = wrapWidth; // Now get plaintext from editor var wrapText = this.editorGetContentAs("text/plain", encoderFlags); // split the lines into an array wrapText = wrapText.split(/\r\n|\r|\n/g); var i = 0; var excess = 0; // inspect all lines of mail text to detect if we still have excessive lines which the "standard" editor wrapper leaves for (i = 0; i < wrapText.length; i++) { if (wrapText[i].length > wrapWidth) { excess = 1; } } if (excess) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Excess lines detected\n"); var resultObj = {}; window.openDialog("chrome://enigmail/content/enigmailWrapSelection.xul", "", "dialog,modal,centerscreen", resultObj); try { if (resultObj.cancelled) { // cancel pressed -> do not send, return instead. wrapresultObj.cancelled = true; return; } } catch (ex) { // cancel pressed -> do not send, return instead. wrapresultObj.cancelled = true; return; } var quote = ""; var limitedLine = ""; var restOfLine = ""; var WrapSelect = resultObj.Select; switch (WrapSelect) { case "0": // Selection: Force rewrap for (i = 0; i < wrapText.length; i++) { if (wrapText[i].length > wrapWidth) { // If the current line is too long, limit it hard to wrapWidth and insert the rest as the next line into wrapText array limitedLine = wrapText[i].slice(0, wrapWidth); restOfLine = wrapText[i].slice(wrapWidth); // We should add quotes at the beginning of "restOfLine", if limitedLine is a quoted line // However, this would be purely academic, because limitedLine will always be "standard"-wrapped // by the editor-rewrapper at the space between quote sign (>) and the quoted text. wrapText.splice(i, 1, limitedLine, restOfLine); } } break; case "1": // Selection: Send as is break; case "2": // Selection: Use MIME wrapresultObj.usePpgMime = true; break; case "3": // Selection: Edit manually -> do not send, return instead. wrapresultObj.cancelled = true; return; } //switch } // Now join all lines together again and feed it back into the compose editor. var newtext = wrapText.join("\n"); this.replaceEditorText(newtext); } } catch (ex) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Exception while wrapping=" + ex + "\n"); } }, // Save draft message. We do not want most of the other processing for encrypted mails here... saveDraftMessage: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: saveDraftMessage()\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; let doEncrypt = this.isEnigmailEnabled() && this.identity.getBoolAttribute("autoEncryptDrafts"); this.setDraftStatus(); if (!doEncrypt) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: drafts disabled\n"); try { if (gMsgCompose.compFields.securityInfo instanceof Components.interfaces.nsIEnigMsgCompFields) { gMsgCompose.compFields.securityInfo.sendFlags = 0; } } catch (ex) {} return true; } let sendFlags = nsIEnigmail.SEND_PGP_MIME | nsIEnigmail.SEND_ENCRYPTED | nsIEnigmail.SAVE_MESSAGE | nsIEnigmail.SEND_ALWAYS_TRUST; let fromAddr = this.identity.email; let userIdValue = this.getSenderUserId(); if (userIdValue) { fromAddr = userIdValue; } let enigmailSvc = EnigmailCore.getService(window); if (!enigmailSvc) return true; if (this.preferPgpOverSmime(sendFlags) === 0) return true; // use S/MIME // Try to save draft var testCipher = null; var testExitCodeObj = {}; var testStatusFlagsObj = {}; var testErrorMsgObj = {}; // encrypt test message for test recipients var testPlain = "Test Message"; var testUiFlags = nsIEnigmail.UI_TEST; EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.saveDraft(): call encryptMessage() for fromAddr=\"" + fromAddr + "\"\n"); testCipher = enigmailSvc.encryptMessage(null, testUiFlags, testPlain, fromAddr, fromAddr, "", sendFlags | nsIEnigmail.SEND_TEST, testExitCodeObj, testStatusFlagsObj, testErrorMsgObj); if (testStatusFlagsObj.value & (nsIEnigmail.INVALID_RECIPIENT | nsIEnigmail.NO_SECKEY)) { // check if own key is invalid if (testErrorMsgObj.value && testErrorMsgObj.value.length > 0) { ++this.saveDraftError; if (this.saveDraftError === 1) { this.notifyUser(3, EnigmailLocale.getString("msgCompose.cannotSaveDraft"), "saveDraftFailed", testErrorMsgObj.value); } return false; } } let newSecurityInfo; try { if (gMsgCompose.compFields.securityInfo instanceof Components.interfaces.nsIEnigMsgCompFields) { newSecurityInfo = gMsgCompose.compFields.securityInfo; } else { throw "dummy"; } } catch (ex) { try { newSecurityInfo = Components.classes[this.compFieldsEnig_CID].createInstance(Components.interfaces.nsIEnigMsgCompFields); if (newSecurityInfo) { let oldSecurityInfo = gMsgCompose.compFields.securityInfo; newSecurityInfo.init(oldSecurityInfo); gMsgCompose.compFields.securityInfo = newSecurityInfo; } } catch (ex2) { EnigmailLog.writeException("enigmailMsgComposeOverlay.js: Enigmail.msg.saveDraftMessage", ex); return false; } } newSecurityInfo.sendFlags = sendFlags; newSecurityInfo.UIFlags = 0; newSecurityInfo.senderEmailAddr = fromAddr; newSecurityInfo.recipients = fromAddr; newSecurityInfo.bccRecipients = ""; this.dirty = true; return true; }, createEnigmailSecurityFields: function(oldSecurityInfo) { let newSecurityInfo = Components.classes[this.compFieldsEnig_CID].createInstance(Components.interfaces.nsIEnigMsgCompFields); if (!newSecurityInfo) throw Components.results.NS_ERROR_FAILURE; newSecurityInfo.init(oldSecurityInfo); gMsgCompose.compFields.securityInfo = newSecurityInfo; }, isSendConfirmationRequired: function(sendFlags) { // process whether final confirmation is necessary const SIGN = Components.interfaces.nsIEnigmail.SEND_SIGNED; const ENCRYPT = Components.interfaces.nsIEnigmail.SEND_ENCRYPTED; let confirm = false; let confPref = EnigmailPrefs.getPref("confirmBeforeSending"); switch (confPref) { case 0: // never confirm = false; break; case 1: // always confirm = true; break; case 2: // if send encrypted confirm = ((sendFlags & ENCRYPT) == ENCRYPT); break; case 3: // if send unencrypted confirm = ((sendFlags & ENCRYPT) === 0); break; case 4: // if encryption changed due to rules confirm = ((sendFlags & ENCRYPT) != (this.sendMode & ENCRYPT)); break; } // double check that no internal error did result in broken promise of encryption // - if NOT send encrypted // - although encryption was // - the recent processed resulting encryption status or // - was signaled in the status bar but is not the outcome now if ((sendFlags & ENCRYPT) === 0 && this.statusPGPMime !== EnigmailConstants.ENIG_FINAL_SMIME && this.statusPGPMime !== EnigmailConstants.ENIG_FINAL_FORCESMIME && (this.statusEncrypted == EnigmailConstants.ENIG_FINAL_YES || this.statusEncrypted == EnigmailConstants.ENIG_FINAL_FORCEYES || this.statusEncryptedInStatusBar == EnigmailConstants.ENIG_FINAL_YES || this.statusEncryptedInStatusBar == EnigmailConstants.ENIG_FINAL_FORCEYES)) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.isSendConfirmationRequired: promised encryption did not succeed\n"); if (!EnigmailDialog.confirmDlg(window, EnigmailLocale.getString("msgCompose.internalEncryptionError"), EnigmailLocale.getString("msgCompose.button.sendAnyway"))) { return null; // cancel sending } // without canceling sending, force firnal confirmation confirm = true; } return confirm; }, setPepPrivacyLabel: function(rating) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.setPepPrivacyLabel: " + rating + "\n"); let l = document.getElementById("enigmail-pep-privacy-status"); let bc = document.getElementById("enigmail-bc-pepEncrypt"); let color = EnigmailPEPAdapter.calculateColorFromRating(rating); if (bc.getAttribute("encrypt") === "false") { color = "grey"; } else if (rating === 0) { color = "?"; } switch (color) { case "?": l.setAttribute("value", EnigmailLocale.getString("msgCompose.pepSendUnknown")); l.setAttribute("class", "enigmail-statusbar-pep-unsecure"); break; case "green": l.setAttribute("value", EnigmailLocale.getString("msgCompose.pepSendTrusted")); l.setAttribute("class", "enigmail-statusbar-pep-trusted"); break; case "yellow": l.setAttribute("value", EnigmailLocale.getString("msgCompose.pepSendSecure")); l.setAttribute("class", "enigmail-statusbar-pep-secure"); break; default: l.setAttribute("value", EnigmailLocale.getString("msgCompose.pepSendUnsecure")); l.setAttribute("class", "enigmail-statusbar-pep-unsecure"); } }, getPepMessageRating: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.getPepMessageRating\n"); if (this.pepEnabled()) { let rating = 0; let o = this.compileFromAndTo(); if (o) { rating = EnigmailPEPAdapter.getOutgoingMessageRating(o.from, o.toAddrList); } this.setPepPrivacyLabel(rating); this.determineSendFlagId = null; } else { this.setPepPrivacyLabel(0); } }, compileFromAndTo: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.compileFromAndTo\n"); let compFields = gMsgCompose.compFields; let toAddrList = []; let recList; let arrLen = {}; if (!Enigmail.msg.composeBodyReady) { compFields = Components.classes["@mozilla.org/messengercompose/composefields;1"].createInstance(Components.interfaces.nsIMsgCompFields); } Recipients2CompFields(compFields); gMsgCompose.expandMailingLists(); EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: to='" + compFields.to + "'\n"); if (compFields.to.length > 0) { toAddrList = EnigmailFuncs.parseEmails(compFields.to, false); } if (compFields.cc.length > 0) { toAddrList = toAddrList.concat(EnigmailFuncs.parseEmails(compFields.cc, false)); } if (compFields.bcc.length > 0) { toAddrList = toAddrList.concat(EnigmailFuncs.parseEmails(compFields.bcc, false)); } for (let addr of toAddrList) { // determine incomplete addresses --> do not attempt pEp encryption if (addr.email.search(/.@./) < 0) return null; } this.identity = getCurrentIdentity(); let from = { email: this.identity.email, name: this.identity.fullName }; return { from: from, toAddrList: toAddrList }; }, attachPepKey: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.attachPepKey()\n"); if (this.identity.getBoolAttribute("attachPgpKey")) { let id = EnigmailPEPAdapter.getOwnIdentityForEmail(this.identity.email); if (id) { let userIdValue = "0x" + id.fpr; if (this.attachOwnKeyObj.attachedKey && (this.attachOwnKeyObj.attachedKey != userIdValue)) { // remove attached key if user ID changed this.removeAttachedKey(); } if (!this.attachOwnKeyObj.attachedKey) { let attachedObj = this.extractAndAttachKey([userIdValue]); if (attachedObj) { attachedObj.name = "pEpkey.asc"; this.attachOwnKeyObj.attachedObj = attachedObj; this.attachOwnKeyObj.attachedKey = userIdValue; gMsgCompose.compFields.addAttachment(attachedObj); } } } } }, encryptPepMessage: function(msgSendType) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptPepMessage()\n"); const CiMsgCompDeliverMode = Components.interfaces.nsIMsgCompDeliverMode; const nsIEnigmail = Components.interfaces.nsIEnigmail; let isDraft = false; let compFields = gMsgCompose.compFields; switch (msgSendType) { case CiMsgCompDeliverMode.SaveAsDraft: case CiMsgCompDeliverMode.SaveAsTemplate: case CiMsgCompDeliverMode.AutoSaveAsDraft: EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptPepMessage: detected save draft\n"); return true; } try { // autoEncryptDrafts equals "trusted server" in pEp mode if (this.identity.getBoolAttribute("autoEncryptDrafts")) { EnigmailPEPAdapter.filter.deleteDecryptedCopyFilter(this.identity); } else { EnigmailPEPAdapter.filter.ensureDecryptedCopyFilter(this.identity); } } catch (ex) {} let rating = 0; if (this.pepEnabled()) { let o = this.compileFromAndTo(); if (o) { rating = EnigmailPEPAdapter.getOutgoingMessageRating(o.from, o.toAddrList); + + if (this.origPepRating !== null && rating < this.origPepRating && this.identity.getBoolAttribute("warnWeakReply")) { + let msgInput = { + msgtext: EnigmailLocale.getString("pep.alert.weakReply"), + button1: EnigmailLocale.getString("dlg.button.continue"), + cancelButton: EnigmailLocale.getString("dlg.button.cancel"), + iconType: EnigmailConstants.ICONTYPE_ALERT, + dialogTitle: EnigmailLocale.getString("warning") + }; + + if (EnigmailDialog.msgBox(window, msgInput) !== 0) return false; + + } } } EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptPepMessage: rating=" + rating + "\n"); if (rating >= 6) { if (!(compFields.securityInfo instanceof Components.interfaces.nsIEnigMsgCompFields)) { this.createEnigmailSecurityFields(compFields.securityInfo); } let si = compFields.securityInfo.QueryInterface(Components.interfaces.nsIEnigMsgCompFields); if (this.identity.getBoolAttribute("protectSubject")) { si.originalSubject = compFields.subject; compFields.subject = ""; } else { si.originalSubject = null; } let encrypt = document.getElementById("enigmail-bc-pepEncrypt").getAttribute("encrypt"); si.sendFlags = (encrypt === "true" ? nsIEnigmail.SEND_ENCRYPTED : 0); } else { // attach own key this.attachPepKey(); } return true; }, encryptMsg: function(msgSendType) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: msgSendType=" + msgSendType + ", Enigmail.msg.sendMode=" + this.sendMode + ", Enigmail.msg.statusEncrypted=" + this.statusEncrypted + "\n"); if (this.juniorMode) return this.encryptPepMessage(msgSendType); const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; const CiMsgCompDeliverMode = Components.interfaces.nsIMsgCompDeliverMode; var promptSvc = EnigmailDialog.getPromptSvc(); var newSecurityInfo; let arrLen = {}; let toAddrList = []; let recList; let bccAddrList = []; let splitRecipients; var gotSendFlags = this.sendMode; // here we process the final state: if (this.statusEncrypted == EnigmailConstants.ENIG_FINAL_YES || this.statusEncrypted == EnigmailConstants.ENIG_FINAL_FORCEYES) { gotSendFlags |= ENCRYPT; } else if (this.statusEncrypted == EnigmailConstants.ENIG_FINAL_FORCENO) { gotSendFlags &= ~ENCRYPT; } if (this.statusSigned == EnigmailConstants.ENIG_FINAL_YES || this.statusSigned == EnigmailConstants.ENIG_FINAL_FORCEYES) { gotSendFlags |= SIGN; } else if (this.statusSigned == EnigmailConstants.ENIG_FINAL_FORCENO) { gotSendFlags &= ~SIGN; } var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); // EnigSend: Handle both plain and encrypted messages below var isOffline = (ioService && ioService.offline); var sendFlags = 0; if (gotSendFlags & SIGN) sendFlags |= SIGN; if (gotSendFlags & ENCRYPT) sendFlags |= ENCRYPT; if (msgSendType === CiMsgCompDeliverMode.Later) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: adding SEND_LATER\n"); sendFlags |= nsIEnigmail.SEND_LATER; } if (this.statusPGPMime == EnigmailConstants.ENIG_FINAL_SMIME || this.statusPGPMime == EnigmailConstants.ENIG_FINAL_FORCESMIME) { // use S/MIME and return let si = gMsgCompose.compFields.securityInfo.QueryInterface(Components.interfaces.nsIMsgSMIMECompFields); if (sendFlags & SIGN) si.signMessage = true; if (sendFlags & ENCRYPT) si.requireEncryptMessage = true; let conf = this.isSendConfirmationRequired(sendFlags); if (conf === null) return false; if (conf) { msgCompFields = gMsgCompose.compFields; splitRecipients = msgCompFields.splitRecipients; if (msgCompFields.to.length > 0) { recList = splitRecipients(msgCompFields.to, true, arrLen); this.addRecipients(toAddrList, recList); } if (msgCompFields.cc.length > 0) { recList = splitRecipients(msgCompFields.cc, true, arrLen); this.addRecipients(toAddrList, recList); } if (!this.confirmBeforeSend(toAddrList.join(", "), "", sendFlags, isOffline)) { return false; } } return true; } switch (msgSendType) { case CiMsgCompDeliverMode.SaveAsDraft: case CiMsgCompDeliverMode.SaveAsTemplate: case CiMsgCompDeliverMode.AutoSaveAsDraft: EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: detected save draft\n"); // saving drafts is simpler and works differently than the rest of Enigmail. // All rules except account-settings are ignored. return this.saveDraftMessage(); } this.unsetAdditionalHeader("x-enigmail-draft-status"); var msgCompFields = gMsgCompose.compFields; var newsgroups = msgCompFields.newsgroups; // Check if sending to any newsgroups if (msgCompFields.to === "" && msgCompFields.cc === "" && msgCompFields.bcc === "" && newsgroups === "") { // don't attempt to send message if no recipient specified var bundle = document.getElementById("bundle_composeMsgs"); EnigmailDialog.alert(window, bundle.getString("12511")); return false; } this.identity = getCurrentIdentity(); if (gWindowLocked) { EnigmailDialog.alert(window, EnigmailLocale.getString("windowLocked")); return false; } if (this.dirty) { // make sure the sendFlags are reset before the message is processed // (it may have been set by a previously cancelled send operation!) try { if (gMsgCompose.compFields.securityInfo instanceof Components.interfaces.nsIEnigMsgCompFields) { gMsgCompose.compFields.securityInfo.sendFlags = 0; gMsgCompose.compFields.securityInfo.originalSubject = gMsgCompose.compFields.subject; } else if (!gMsgCompose.compFields.securityInfo) { throw "dummy"; } } catch (ex) { try { newSecurityInfo = Components.classes[this.compFieldsEnig_CID].createInstance(Components.interfaces.nsIEnigMsgCompFields); if (newSecurityInfo) { newSecurityInfo.sendFlags = 0; newSecurityInfo.originalSubject = gMsgCompose.compFields.subject; gMsgCompose.compFields.securityInfo = newSecurityInfo; } } catch (ex2) { EnigmailLog.writeException("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg", ex2); } } } this.dirty = 1; var enigmailSvc = EnigmailCore.getService(window); if (!enigmailSvc) { var msg = EnigmailLocale.getString("sendUnencrypted"); if (EnigmailCore.getEnigmailService() && EnigmailCore.getEnigmailService().initializationError) { msg = EnigmailCore.getEnigmailService().initializationError + "\n\n" + msg; } return EnigmailDialog.confirmDlg(window, msg, EnigmailLocale.getString("msgCompose.button.send")); } try { this.modifiedAttach = null; EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: currentId=" + this.identity + ", " + this.identity.email + "\n"); var fromAddr = this.identity.email; if (!this.isEnigmailEnabled()) return true; var optSendFlags = 0; var inlineEncAttach = false; // request or preference to always accept (even non-authenticated) keys? if (this.trustAllKeys) { optSendFlags |= nsIEnigmail.SEND_ALWAYS_TRUST; } else { var acceptedKeys = EnigmailPrefs.getPref("acceptedKeys"); switch (acceptedKeys) { case 0: // accept valid/authenticated keys only break; case 1: // accept all but revoked/disabled/expired keys optSendFlags |= nsIEnigmail.SEND_ALWAYS_TRUST; break; default: EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: INVALID VALUE for acceptedKeys: \"" + acceptedKeys + "\"\n"); break; } } if (EnigmailPrefs.getPref("encryptToSelf")) { optSendFlags |= nsIEnigmail.SEND_ENCRYPT_TO_SELF; } sendFlags |= optSendFlags; var userIdValue = this.getSenderUserId(); if (userIdValue) { fromAddr = userIdValue; } EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg:gMsgCompose=" + gMsgCompose + "\n"); splitRecipients = msgCompFields.splitRecipients; if (msgCompFields.to.length > 0) { recList = splitRecipients(msgCompFields.to, true, arrLen); this.addRecipients(toAddrList, recList); } if (msgCompFields.cc.length > 0) { recList = splitRecipients(msgCompFields.cc, true, arrLen); this.addRecipients(toAddrList, recList); } // special handling of bcc: // - note: bcc and encryption is a problem // - but bcc to the sender is fine if (msgCompFields.bcc.length > 0) { recList = splitRecipients(msgCompFields.bcc, true, arrLen); var bccLC = EnigmailFuncs.stripEmail(msgCompFields.bcc).toLowerCase(); EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: BCC: " + bccLC + "\n"); var selfBCC = this.identity.email && (this.identity.email.toLowerCase() == bccLC); if (selfBCC) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: Self BCC\n"); this.addRecipients(toAddrList, recList); } else if (sendFlags & ENCRYPT) { // BCC and encryption var dummy = { value: null }; var hideBccUsers = promptSvc.confirmEx(window, EnigmailLocale.getString("enigConfirm"), EnigmailLocale.getString("sendingHiddenRcpt"), (promptSvc.BUTTON_TITLE_IS_STRING * promptSvc.BUTTON_POS_0) + (promptSvc.BUTTON_TITLE_CANCEL * promptSvc.BUTTON_POS_1) + (promptSvc.BUTTON_TITLE_IS_STRING * promptSvc.BUTTON_POS_2), EnigmailLocale.getString("sendWithShownBcc"), null, EnigmailLocale.getString("sendWithHiddenBcc"), null, dummy); switch (hideBccUsers) { case 2: this.addRecipients(bccAddrList, recList); this.addRecipients(toAddrList, recList); break; case 0: this.addRecipients(toAddrList, recList); break; case 1: return false; } } } if (newsgroups) { toAddrList.push(newsgroups); if (sendFlags & ENCRYPT) { if (!EnigmailPrefs.getPref("encryptToNews")) { EnigmailDialog.alert(window, EnigmailLocale.getString("sendingNews")); return false; } else if (!EnigmailDialog.confirmPref(window, EnigmailLocale.getString("sendToNewsWarning"), "warnOnSendingNewsgroups", EnigmailLocale.getString("msgCompose.button.send"))) { return false; } } } var usePGPMimeOption = EnigmailPrefs.getPref("usePGPMimeOption"); if (this.sendPgpMime) { // Use PGP/MIME sendFlags |= nsIEnigmail.SEND_PGP_MIME; } var result = this.keySelection(enigmailSvc, sendFlags, // all current combined/processed send flags (incl. optSendFlags) optSendFlags, // may only be SEND_ALWAYS_TRUST or SEND_ENCRYPT_TO_SELF gotSendFlags, // initial sendMode (0 or SIGN or ENCRYPT or SIGN|ENCRYPT) fromAddr, toAddrList, bccAddrList); if (!result) { return false; } var toAddrStr; var bccAddrStr; sendFlags = result.sendFlags; toAddrStr = result.toAddrStr; bccAddrStr = result.bccAddrStr; if (this.preferPgpOverSmime(sendFlags) === 0) { // use S/MIME sendFlags = 0; return true; } if (this.attachOwnKeyObj.appendAttachment) this.attachOwnKey(); var bucketList = document.getElementById("attachmentBucket"); var hasAttachments = ((bucketList && bucketList.hasChildNodes()) || gMsgCompose.compFields.attachVCard); EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: hasAttachments = " + hasAttachments + "\n"); if (hasAttachments && (sendFlags & (ENCRYPT | SIGN)) && !(sendFlags & nsIEnigmail.SEND_PGP_MIME)) { let inputObj = { pgpMimePossible: true, inlinePossible: true, restrictedScenario: false, reasonForCheck: "" }; // init reason for dialog to be able to use the right labels if (sendFlags & ENCRYPT) { if (sendFlags & SIGN) { inputObj.reasonForCheck = "encryptAndSign"; } else { inputObj.reasonForCheck = "encrypt"; } } else { if (sendFlags & SIGN) { inputObj.reasonForCheck = "sign"; } } // determine if attachments are all local files (currently the only // supported kind of attachments) var node = bucketList.firstChild; while (node) { if (node.attachment.url.substring(0, 7) != "file://") { inputObj.inlinePossible = false; } node = node.nextSibling; } if (inputObj.pgpMimePossible || inputObj.inlinePossible) { let resultObj = { selected: EnigmailPrefs.getPref("encryptAttachments") }; //skip or not var skipCheck = EnigmailPrefs.getPref("encryptAttachmentsSkipDlg"); if (skipCheck == 1) { if ((resultObj.selected == 2 && inputObj.pgpMimePossible === false) || (resultObj.selected == 1 && inputObj.inlinePossible === false)) { //add var to disable remember box since we're dealing with restricted scenarios... inputObj.restrictedScenario = true; resultObj.selected = -1; window.openDialog("chrome://enigmail/content/enigmailAttachmentsDialog.xul", "", "dialog,modal,centerscreen", inputObj, resultObj); } } else { resultObj.selected = -1; window.openDialog("chrome://enigmail/content/enigmailAttachmentsDialog.xul", "", "dialog,modal,centerscreen", inputObj, resultObj); } if (resultObj.selected < 0) { // dialog cancelled return false; } else if (resultObj.selected == 1) { // encrypt attachments inlineEncAttach = true; } else if (resultObj.selected == 2) { // send as PGP/MIME sendFlags |= nsIEnigmail.SEND_PGP_MIME; } else if (resultObj.selected == 3) { // cancel the encryption/signing for the whole message sendFlags &= ~ENCRYPT; sendFlags &= ~SIGN; } } else { if (sendFlags & ENCRYPT) { if (!EnigmailDialog.confirmDlg(window, EnigmailLocale.getString("attachWarning"), EnigmailLocale.getString("msgCompose.button.send"))) return false; } } } var usingPGPMime = (sendFlags & nsIEnigmail.SEND_PGP_MIME) && (sendFlags & (ENCRYPT | SIGN)); // ----------------------- Rewrapping code, taken from function "encryptInline" // Check wrapping, if sign only and inline and plaintext if ((sendFlags & SIGN) && !(sendFlags & ENCRYPT) && !(usingPGPMime) && !(gMsgCompose.composeHTML)) { var wrapresultObj = {}; this.wrapInLine(wrapresultObj); if (wrapresultObj.usePpgMime) { sendFlags |= nsIEnigmail.SEND_PGP_MIME; usingPGPMime = nsIEnigmail.SEND_PGP_MIME; } if (wrapresultObj.cancelled) { return false; } } var uiFlags = nsIEnigmail.UI_INTERACTIVE; if (usingPGPMime) uiFlags |= nsIEnigmail.UI_PGP_MIME; if ((sendFlags & (ENCRYPT | SIGN)) && usingPGPMime) { // Use PGP/MIME EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: Using PGP/MIME, flags=" + sendFlags + "\n"); var oldSecurityInfo = gMsgCompose.compFields.securityInfo; EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: oldSecurityInfo = " + oldSecurityInfo + "\n"); if (!oldSecurityInfo) { try { newSecurityInfo = oldSecurityInfo.QueryInterface(Components.interfaces.nsIEnigMsgCompFields); } catch (ex) {} } if (!newSecurityInfo) { this.createEnigmailSecurityFields(oldSecurityInfo); newSecurityInfo = gMsgCompose.compFields.securityInfo.QueryInterface(Components.interfaces.nsIEnigMsgCompFields); } newSecurityInfo.originalSubject = gMsgCompose.compFields.subject; newSecurityInfo.originalReferences = gMsgCompose.compFields.references; if (this.protectHeaders) { sendFlags |= nsIEnigmail.ENCRYPT_HEADERS; if (sendFlags & ENCRYPT) { gMsgCompose.compFields.subject = ""; if (EnigmailPrefs.getPref("protectReferencesHdr")) { gMsgCompose.compFields.references = ""; } } } newSecurityInfo.sendFlags = sendFlags; newSecurityInfo.UIFlags = uiFlags; newSecurityInfo.senderEmailAddr = fromAddr; newSecurityInfo.recipients = toAddrStr; newSecurityInfo.bccRecipients = bccAddrStr; EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: securityInfo = " + newSecurityInfo + "\n"); } else if (!this.processed && (sendFlags & (ENCRYPT | SIGN))) { // use inline PGP var sendInfo = { sendFlags: sendFlags, inlineEncAttach: inlineEncAttach, fromAddr: fromAddr, toAddr: toAddrStr, bccAddr: bccAddrStr, uiFlags: uiFlags, bucketList: bucketList }; if (!this.encryptInline(sendInfo)) { return false; } } // update the list of attachments Attachments2CompFields(msgCompFields); let confirm = this.isSendConfirmationRequired(sendFlags); if (confirm === null) return false; // perform confirmation dialog if necessary/requested if (confirm) { if (!this.confirmBeforeSend(toAddrList.join(", "), toAddrStr + ", " + bccAddrStr, sendFlags, isOffline)) { if (this.processed) { this.undoEncryption(0); } else { this.removeAttachedKey(); } return false; } } else if ((sendFlags & nsIEnigmail.SEND_WITH_CHECK) && !this.messageSendCheck()) { // Abort send if (this.processed) { this.undoEncryption(0); } else { this.removeAttachedKey(); } return false; } if (msgCompFields.characterSet != "ISO-2022-JP") { if ((usingPGPMime && ((sendFlags & (ENCRYPT | SIGN)))) || ((!usingPGPMime) && (sendFlags & ENCRYPT))) { try { // make sure plaintext is not changed to 7bit if (typeof(msgCompFields.forceMsgEncoding) == "boolean") { msgCompFields.forceMsgEncoding = true; EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: enabled forceMsgEncoding\n"); } } catch (ex) {} } } } catch (ex) { EnigmailLog.writeException("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg", ex); let msg = EnigmailLocale.getString("signFailed"); if (EnigmailCore.getEnigmailService() && EnigmailCore.getEnigmailService().initializationError) { msg += "\n" + EnigmailCore.getEnigmailService().initializationError; } return EnigmailDialog.confirmDlg(window, msg, EnigmailLocale.getString("msgCompose.button.sendUnencrypted")); } // The encryption process for PGP/MIME messages follows "here". It's // called automatically from nsMsgCompose->sendMsg(). // registration for this is dome in chrome.manifest return true; }, encryptInline: function(sendInfo) { // sign/encrpyt message using inline-PGP const dce = Components.interfaces.nsIDocumentEncoder; const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; var enigmailSvc = EnigmailCore.getService(window); if (!enigmailSvc) return false; if (gMsgCompose.composeHTML) { var errMsg = EnigmailLocale.getString("hasHTML"); EnigmailDialog.alertCount(window, "composeHtmlAlertCount", errMsg); } try { var convert = DetermineConvertibility(); if (convert == Components.interfaces.nsIMsgCompConvertible.No) { if (!EnigmailDialog.confirmDlg(window, EnigmailLocale.getString("strippingHTML"), EnigmailLocale.getString("msgCompose.button.sendAnyway"))) { return false; } } } catch (ex) { EnigmailLog.writeException("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptInline", ex); } try { if (this.getMailPref("mail.strictly_mime")) { if (EnigmailDialog.confirmPref(window, EnigmailLocale.getString("quotedPrintableWarn"), "quotedPrintableWarn")) { EnigmailPrefs.getPrefRoot().setBoolPref("mail.strictly_mime", false); } } } catch (ex) {} var sendFlowed; try { sendFlowed = this.getMailPref("mailnews.send_plaintext_flowed"); } catch (ex) { sendFlowed = true; } var encoderFlags = dce.OutputFormatted | dce.OutputLFLineBreak; var wrapper = gMsgCompose.editor.QueryInterface(Components.interfaces.nsIEditorMailSupport); var editor = gMsgCompose.editor.QueryInterface(Components.interfaces.nsIPlaintextEditor); var wrapWidth = 72; if (!(sendInfo.sendFlags & ENCRYPT)) { // signed messages only if (gMsgCompose.composeHTML) { // enforce line wrapping here // otherwise the message isn't signed correctly try { wrapWidth = this.getMailPref("editor.htmlWrapColumn"); if (wrapWidth > 0 && wrapWidth < 68 && gMsgCompose.wrapLength > 0) { if (EnigmailDialog.confirmDlg(window, EnigmailLocale.getString("minimalLineWrapping", [wrapWidth]))) { EnigmailPrefs.getPrefRoot().setIntPref("editor.htmlWrapColumn", 68); } } if (EnigmailPrefs.getPref("wrapHtmlBeforeSend")) { if (wrapWidth) { editor.wrapWidth = wrapWidth - 2; // prepare for the worst case: a 72 char's long line starting with '-' wrapper.rewrap(false); } } } catch (ex) {} } else { // plaintext: Wrapping code has been moved to superordinate function encryptMsg to enable interactive format switch } } var exitCodeObj = {}; var statusFlagsObj = {}; var errorMsgObj = {}; var exitCode; // Get plain text // (Do we need to set the nsIDocumentEncoder.* flags?) var origText = this.editorGetContentAs("text/plain", encoderFlags); if (!origText) origText = ""; if (origText.length > 0) { // Sign/encrypt body text var escText = origText; // Copy plain text for possible escaping if (sendFlowed && !(sendInfo.sendFlags & ENCRYPT)) { // Prevent space stuffing a la RFC 2646 (format=flowed). //EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: escText["+encoderFlags+"] = '"+escText+"'\n"); escText = escText.replace(/^From /gm, "~From "); escText = escText.replace(/^>/gm, "|"); escText = escText.replace(/^[ \t]+$/gm, ""); escText = escText.replace(/^ /gm, "~ "); //EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: escText = '"+escText+"'\n"); // Replace plain text and get it again this.replaceEditorText(escText); escText = this.editorGetContentAs("text/plain", encoderFlags); } // Replace plain text and get it again (to avoid linewrapping problems) this.replaceEditorText(escText); escText = this.editorGetContentAs("text/plain", encoderFlags); //EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: escText["+encoderFlags+"] = '"+escText+"'\n"); // Encrypt plaintext var charset = this.editorGetCharset(); EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptMsg: charset=" + charset + "\n"); // Encode plaintext to charset from unicode var plainText = (sendInfo.sendFlags & ENCRYPT) ? EnigmailData.convertFromUnicode(origText, charset) : EnigmailData.convertFromUnicode(escText, charset); var cipherText = enigmailSvc.encryptMessage(window, sendInfo.uiFlags, plainText, sendInfo.fromAddr, sendInfo.toAddr, sendInfo.bccAddr, sendInfo.sendFlags, exitCodeObj, statusFlagsObj, errorMsgObj); exitCode = exitCodeObj.value; //EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: cipherText = '"+cipherText+"'\n"); if (cipherText && (exitCode === 0)) { // Encryption/signing succeeded; overwrite plaintext if (gMsgCompose.composeHTML) { // workaround for Thunderbird bug (TB adds an extra space in front of the text) cipherText = "\n" + cipherText; } else cipherText = cipherText.replace(/\r\n/g, "\n"); if ((sendInfo.sendFlags & ENCRYPT) && charset && (charset.search(/^us-ascii$/i) !== 0)) { // Add Charset armor header for encrypted blocks cipherText = cipherText.replace(/(-----BEGIN PGP MESSAGE----- *)(\r?\n)/, "$1$2Charset: " + charset + "$2"); } // Decode ciphertext from charset to unicode and overwrite this.replaceEditorText(EnigmailData.convertToUnicode(cipherText, charset)); this.enableUndoEncryption(true); // Save original text (for undo) this.processed = { "origText": origText, "charset": charset }; } else { // Restore original text this.replaceEditorText(origText); this.enableUndoEncryption(false); if (sendInfo.sendFlags & (ENCRYPT | SIGN)) { // Encryption/signing failed /*if (statusFlagsObj.statusMsg) { // check if own key is invalid let s = new RegExp("^(\\[GNUPG:\\] )?INV_(RECP|SGNR) [0-9]+ \\?", "m"); if (statusFlagsObj.statusMsg.search(s) >= 0) { errorMsgObj.value += "\n\n" + EnigmailLocale.getString("keyError.resolutionAction"); } }*/ this.sendAborted(window, errorMsgObj); return false; } } } if (sendInfo.inlineEncAttach) { // encrypt attachments this.modifiedAttach = []; exitCode = this.encryptAttachments(sendInfo.bucketList, this.modifiedAttach, window, sendInfo.uiFlags, sendInfo.fromAddr, sendInfo.toAddr, sendInfo.bccAddr, sendInfo.sendFlags, errorMsgObj); if (exitCode !== 0) { this.modifiedAttach = null; this.sendAborted(window, errorMsgObj); if (this.processed) { this.undoEncryption(0); } else { this.removeAttachedKey(); } return false; } } return true; }, sendAborted: function(window, errorMsgObj) { if (errorMsgObj && errorMsgObj.value) { var txt = errorMsgObj.value; var txtLines = txt.split(/\r?\n/); var errorMsg = ""; for (var i = 0; i < txtLines.length; ++i) { var line = txtLines[i]; var tokens = line.split(/ /); // process most important business reasons for invalid recipient (and sender) errors: if (tokens.length == 3 && (tokens[0] == "INV_RECP" || tokens[0] == "INV_SGNR")) { var reason = tokens[1]; var key = tokens[2]; if (reason == "10") { errorMsg += EnigmailLocale.getString("keyNotTrusted", [key]) + "\n"; } else if (reason == "1") { errorMsg += EnigmailLocale.getString("keyNotFound", [key]) + "\n"; } else if (reason == "4") { errorMsg += EnigmailLocale.getString("keyRevoked", [key]) + "\n"; } else if (reason == "5") { errorMsg += EnigmailLocale.getString("keyExpired", [key]) + "\n"; } } } if (errorMsg !== "") { txt = errorMsg + "\n" + txt; } EnigmailDialog.info(window, EnigmailLocale.getString("sendAborted") + txt); } else { EnigmailDialog.info(window, EnigmailLocale.getString("sendAborted") + "\n" + EnigmailLocale.getString("msgCompose.internalError")); } }, getMailPref: function(prefName) { let prefRoot = EnigmailPrefs.getPrefRoot(); var prefValue = null; try { var prefType = prefRoot.getPrefType(prefName); // Get pref value switch (prefType) { case prefRoot.PREF_BOOL: prefValue = prefRoot.getBoolPref(prefName); break; case prefRoot.PREF_INT: prefValue = prefRoot.getIntPref(prefName); break; case prefRoot.PREF_STRING: prefValue = prefRoot.getCharPref(prefName); break; default: prefValue = undefined; break; } } catch (ex) { // Failed to get pref value EnigmailLog.ERROR("enigmailMsgComposeOverlay.js: Enigmail.msg.getMailPref: unknown prefName:" + prefName + " \n"); } return prefValue; }, messageSendCheck: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.messageSendCheck\n"); try { var warn = this.getMailPref("mail.warn_on_send_accel_key"); if (warn) { var checkValue = { value: false }; var bundle = document.getElementById("bundle_composeMsgs"); var buttonPressed = EnigmailDialog.getPromptSvc().confirmEx(window, bundle.getString('sendMessageCheckWindowTitle'), bundle.getString('sendMessageCheckLabel'), (EnigmailDialog.getPromptSvc().BUTTON_TITLE_IS_STRING * EnigmailDialog.getPromptSvc().BUTTON_POS_0) + (EnigmailDialog.getPromptSvc().BUTTON_TITLE_CANCEL * EnigmailDialog.getPromptSvc().BUTTON_POS_1), bundle.getString('sendMessageCheckSendButtonLabel'), null, null, bundle.getString('CheckMsg'), checkValue); if (buttonPressed !== 0) { return false; } if (checkValue.value) { EnigmailPrefs.getPrefRoot().setBoolPref("mail.warn_on_send_accel_key", false); } } } catch (ex) {} return true; }, /** * set non-standard message Header * (depending on TB version) * * hdr: String: header type (e.g. X-Enigmail-Version) * val: String: header data (e.g. 1.2.3.4) */ setAdditionalHeader: function(hdr, val) { if ("otherRandomHeaders" in gMsgCompose.compFields) { // TB <= 36 gMsgCompose.compFields.otherRandomHeaders += hdr + ": " + val + "\r\n"; } else { gMsgCompose.compFields.setHeader(hdr, val); } }, unsetAdditionalHeader: function(hdr) { if ("otherRandomHeaders" in gMsgCompose.compFields) { // TB <= 36 let h = gMsgCompose.compFields.otherRandomHeaders; let r = new RegExp("^(" + hdr + ":)(.*)$", "im"); let m = h.replace(r, "").replace(/(\r\n)+/, "\r\n"); gMsgCompose.compFields.otherRandomHeaders = m; } else { gMsgCompose.compFields.deleteHeader(hdr); } }, modifyCompFields: function() { const HEADERMODE_KEYID = 0x01; const HEADERMODE_URL = 0x10; try { if (!this.identity) { this.identity = getCurrentIdentity(); } if (this.isEnigmailEnabled()) { if (EnigmailPrefs.getPref("addHeaders")) { this.setAdditionalHeader("X-Enigmail-Version", EnigmailApp.getVersion()); } var pgpHeader = ""; var openPgpHeaderMode = this.identity.getIntAttribute("openPgpHeaderMode"); if (openPgpHeaderMode & HEADERMODE_KEYID) { let key = EnigmailKeyRing.getKeyById(this.identity.getCharAttribute("pgpkeyId")); if (key && key.fpr && key.fpr.length > 0) { pgpHeader += "id=" + key.fpr; } } if (openPgpHeaderMode & HEADERMODE_URL) { if (pgpHeader.indexOf("=") > 0) pgpHeader += ";\r\n\t"; pgpHeader += "url=" + this.identity.getCharAttribute("openPgpUrlName"); } if (openPgpHeaderMode === 0) { pgpHeader = "preference=signencrypt"; } if (pgpHeader.length > 0) { this.setAdditionalHeader("OpenPGP", pgpHeader); } this.setAutocryptHeader(); } } catch (ex) { EnigmailLog.writeException("enigmailMsgComposeOverlay.js: Enigmail.msg.modifyCompFields", ex); } }, setAutocryptHeader: function() { if (EnigmailPEPAdapter.usingPep() || EnigmailPrefs.getPref("autocryptMode") === 0) { return; } if (!this.identity) { this.identity = getCurrentIdentity(); } let key; if (this.identity.getIntAttribute("pgpKeyMode") > 0) { key = EnigmailKeyRing.getKeyById(this.identity.getCharAttribute("pgpkeyId")); } else { key = EnigmailKeyRing.getSecretKeyByUserId(this.identity.email); } if (key) { let k = key.getMinimalPubKey(); if (k.exitCode === 0) { let keyData = k.keyData.replace(/(.{72})/g, " $1\r\n"); this.setAdditionalHeader('Autocrypt', 'to=' + this.identity.email + '; key=\r\n' + keyData); } } }, /** * Handle the 'compose-send-message' event from TB */ sendMessageListener: function(event) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.sendMessageListener\n"); // Do nothing if a compatible version of the "SendLater" addon is installed. // SendLater will call handleSendMessageEvent when needed. try { if (typeof(Sendlater3Composing.callEnigmail) === "function") { return; } } catch (ex) {} Enigmail.msg.handleSendMessageEvent(event); }, /** * Perform handling of the compose-send-message' event from TB (or SendLater) */ handleSendMessageEvent: function(event) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.handleSendMessageEvent\n"); let msgcomposeWindow = document.getElementById("msgcomposeWindow"); let sendMsgType = Number(msgcomposeWindow.getAttribute("msgtype")); if (!(this.sendProcess && sendMsgType == Components.interfaces.nsIMsgCompDeliverMode.AutoSaveAsDraft)) { this.sendProcess = true; let bc = document.getElementById("enigmail-bc-sendprocess"); try { this.modifyCompFields(); bc.setAttribute("disabled", "true"); if (!this.encryptMsg(sendMsgType)) { this.resetUpdatedFields(); event.preventDefault(); event.stopPropagation(); } } catch (ex) {} bc.removeAttribute("disabled"); } else { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.sendMessageListener: sending in progress - autosave aborted\n"); event.preventDefault(); event.stopPropagation(); } this.sendProcess = false; }, // encrypt attachments when sending inline PGP mails // It's quite a hack: the attachments are stored locally // and the attachments list is modified to pick up the // encrypted file(s) instead of the original ones. encryptAttachments: function(bucketList, newAttachments, window, uiFlags, fromAddr, toAddr, bccAddr, sendFlags, errorMsgObj) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptAttachments\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; const SIGN = nsIEnigmail.SEND_SIGNED; const ENCRYPT = nsIEnigmail.SEND_ENCRYPTED; var ioServ; var fileTemplate; errorMsgObj.value = ""; try { ioServ = Components.classes[IOSERVICE_CONTRACTID].getService(Components.interfaces.nsIIOService); if (!ioServ) return -1; } catch (ex) { return -1; } var tmpDir = EnigmailFiles.getTempDir(); var extAppLauncher = Components.classes["@mozilla.org/mime;1"]. getService(Components.interfaces.nsPIExternalAppLauncher); try { fileTemplate = Components.classes[LOCAL_FILE_CONTRACTID].createInstance(Components.interfaces.nsIFile); fileTemplate.initWithPath(tmpDir); if (!(fileTemplate.isDirectory() && fileTemplate.isWritable())) { errorMsgObj.value = EnigmailLocale.getString("noTempDir"); return -1; } fileTemplate.append("encfile"); } catch (ex) { errorMsgObj.value = EnigmailLocale.getString("noTempDir"); return -1; } EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.encryptAttachments tmpDir=" + tmpDir + "\n"); var enigmailSvc = EnigmailCore.getService(window); if (!enigmailSvc) return null; var exitCodeObj = {}; var statusFlagsObj = {}; var node = bucketList.firstChild; while (node) { var origUrl = node.attachment.url; if (origUrl.substring(0, 7) != "file://") { // this should actually never happen since it is pre-checked! errorMsgObj.value = "The attachment '" + node.attachment.name + "' is not a local file"; return -1; } // transform attachment URL to platform-specific file name var origUri = ioServ.newURI(origUrl, null, null); var origFile = origUri.QueryInterface(Components.interfaces.nsIFileURL); if (node.attachment.temporary) { try { var origLocalFile = Components.classes[LOCAL_FILE_CONTRACTID].createInstance(Components.interfaces.nsIFile); origLocalFile.initWithPath(origFile.file.path); extAppLauncher.deleteTemporaryFileOnExit(origLocalFile); } catch (ex) {} } var newFile = fileTemplate.clone(); var txtMessage; try { newFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0x180); txtMessage = enigmailSvc.encryptAttachment(window, fromAddr, toAddr, bccAddr, sendFlags, origFile.file, newFile, exitCodeObj, statusFlagsObj, errorMsgObj); } catch (ex) {} if (exitCodeObj.value !== 0) { return exitCodeObj.value; } var fileInfo = { origFile: origFile, origUrl: node.attachment.url, origName: node.attachment.name, origTemp: node.attachment.temporary, origCType: node.attachment.contentType }; // transform platform specific new file name to file:// URL var newUri = ioServ.newFileURI(newFile); fileInfo.newUrl = newUri.asciiSpec; fileInfo.newFile = newFile; fileInfo.encrypted = (sendFlags & ENCRYPT); newAttachments.push(fileInfo); node = node.nextSibling; } var i = 0; if (sendFlags & ENCRYPT) { // if we got here, all attachments were encrpted successfully, // so we replace their names & urls node = bucketList.firstChild; while (node) { node.attachment.url = newAttachments[i].newUrl; node.attachment.name += EnigmailPrefs.getPref("inlineAttachExt"); node.attachment.contentType = "application/octet-stream"; node.attachment.temporary = true; ++i; node = node.nextSibling; } } else { // for inline signing we need to add new attachments for every // signed file for (i = 0; i < newAttachments.length; i++) { // create new attachment var fileAttachment = Components.classes["@mozilla.org/messengercompose/attachment;1"].createInstance(Components.interfaces.nsIMsgAttachment); fileAttachment.temporary = true; fileAttachment.url = newAttachments[i].newUrl; fileAttachment.name = newAttachments[i].origName + EnigmailPrefs.getPref("inlineSigAttachExt"); // add attachment to msg this.addAttachment(fileAttachment); } } return 0; }, toggleAttribute: function(attrName) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.toggleAttribute('" + attrName + "')\n"); var menuElement = document.getElementById("enigmail_" + attrName); var oldValue = EnigmailPrefs.getPref(attrName); EnigmailPrefs.setPref(attrName, !oldValue); }, toggleAccountAttr: function(attrName) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.toggleAccountAttr('" + attrName + "')\n"); var oldValue = this.identity.getBoolAttribute(attrName); this.identity.setBoolAttribute(attrName, !oldValue); }, decryptQuote: function(interactive) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.decryptQuote: " + interactive + "\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; if (gWindowLocked || this.processed) return; var enigmailSvc = EnigmailCore.getService(window); if (!enigmailSvc) return; const dce = Components.interfaces.nsIDocumentEncoder; var encoderFlags = dce.OutputFormatted | dce.OutputLFLineBreak; var docText = this.editorGetContentAs("text/plain", encoderFlags); var blockBegin = docText.indexOf("-----BEGIN PGP "); if (blockBegin < 0) return; // Determine indentation string var indentBegin = docText.substr(0, blockBegin).lastIndexOf("\n"); var indentStr = docText.substring(indentBegin + 1, blockBegin); EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.decryptQuote: indentStr='" + indentStr + "'\n"); var beginIndexObj = {}; var endIndexObj = {}; var indentStrObj = {}; var blockType = EnigmailArmor.locateArmoredBlock(docText, 0, indentStr, beginIndexObj, endIndexObj, indentStrObj); if ((blockType != "MESSAGE") && (blockType != "SIGNED MESSAGE")) return; var beginIndex = beginIndexObj.value; var endIndex = endIndexObj.value; var head = docText.substr(0, beginIndex); var tail = docText.substr(endIndex + 1); var pgpBlock = docText.substr(beginIndex, endIndex - beginIndex + 1); var indentRegexp; if (indentStr) { if (indentStr == "> ") { // replace ">> " with "> > " to allow correct quoting pgpBlock = pgpBlock.replace(/^>>/gm, "> >"); } // Delete indentation indentRegexp = new RegExp("^" + indentStr, "gm"); pgpBlock = pgpBlock.replace(indentRegexp, ""); //tail = tail.replace(indentRegexp, ""); if (indentStr.match(/[ \t]*$/)) { indentStr = indentStr.replace(/[ \t]*$/gm, ""); indentRegexp = new RegExp("^" + indentStr + "$", "gm"); pgpBlock = pgpBlock.replace(indentRegexp, ""); } // Handle blank indented lines pgpBlock = pgpBlock.replace(/^[ \t]*>[ \t]*$/gm, ""); //tail = tail.replace(/^[ \t]*>[ \t]*$/g, ""); // Trim leading space in tail tail = tail.replace(/^\s*\n/m, "\n"); } if (tail.search(/\S/) < 0) { // No non-space characters in tail; delete it tail = ""; } //EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.decryptQuote: pgpBlock='"+pgpBlock+"'\n"); var charset = this.editorGetCharset(); EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.decryptQuote: charset=" + charset + "\n"); // Encode ciphertext from unicode to charset var cipherText = EnigmailData.convertFromUnicode(pgpBlock, charset); if ((!this.getMailPref("mailnews.reply_in_default_charset")) && (blockType == "MESSAGE")) { // set charset according to PGP block, if available (encrypted messages only) cipherText = cipherText.replace(/\r\n/g, "\n"); cipherText = cipherText.replace(/\r/g, "\n"); let cPos = cipherText.search(/\nCharset: .+\n/i); if (cPos < cipherText.search(/\n\n/)) { var charMatch = cipherText.match(/\n(Charset: )(.+)\n/i); if (charMatch && charMatch.length > 2) { charset = charMatch[2]; gMsgCompose.SetDocumentCharset(charset); } } } // Decrypt message var signatureObj = {}; signatureObj.value = ""; var exitCodeObj = {}; var statusFlagsObj = {}; var userIdObj = {}; var keyIdObj = {}; var sigDetailsObj = {}; var errorMsgObj = {}; var blockSeparationObj = {}; var encToDetailsObj = {}; var uiFlags = nsIEnigmail.UI_UNVERIFIED_ENC_OK; var plainText = ""; if (EnigmailPEPAdapter.usingPep()) { let msgHdr = this.getMsgHdr(); let addresses = { from: null, to: EnigmailFuncs.parseEmails(msgHdr.recipients), cc: EnigmailFuncs.parseEmails(msgHdr.ccList) }; let fromAddr = EnigmailFuncs.parseEmails(msgHdr.author); if (fromAddr.length > 0) addresses.from = fromAddr[0]; let pEpResult = EnigmailPEPDecrypt.decryptMessageData(false, cipherText, addresses); if (pEpResult && pEpResult.longmsg.length > 0) { plainText = pEpResult.longmsg; exitCodeObj.value = 0; errorMsgObj.value = ""; } } else { plainText = enigmailSvc.decryptMessage(window, uiFlags, cipherText, signatureObj, exitCodeObj, statusFlagsObj, keyIdObj, userIdObj, sigDetailsObj, errorMsgObj, blockSeparationObj, encToDetailsObj); } // Decode plaintext from charset to unicode plainText = EnigmailData.convertToUnicode(plainText, charset).replace(/\r\n/g, "\n"); if (EnigmailPrefs.getPref("keepSettingsForReply")) { if (statusFlagsObj.value & nsIEnigmail.DECRYPTION_OKAY) this.setSendMode('encrypt'); } var exitCode = exitCodeObj.value; if (exitCode !== 0) { // Error processing var errorMsg = errorMsgObj.value; var statusLines = errorMsg.split(/\r?\n/); var displayMsg; if (statusLines && statusLines.length) { // Display only first ten lines of error message while (statusLines.length > 10) statusLines.pop(); displayMsg = statusLines.join("\n"); if (interactive) EnigmailDialog.info(window, displayMsg); } } if (blockType == "MESSAGE" && exitCode === 0 && plainText.length === 0) { plainText = " "; } if (!plainText) { if (blockType != "SIGNED MESSAGE") return; // Extract text portion of clearsign block plainText = EnigmailArmor.extractSignaturePart(pgpBlock, nsIEnigmail.SIGNATURE_TEXT); } const nsIMsgCompType = Components.interfaces.nsIMsgCompType; var doubleDashSeparator = EnigmailPrefs.getPref("doubleDashSeparator"); if (gMsgCompose.type != nsIMsgCompType.Template && gMsgCompose.type != nsIMsgCompType.Draft && doubleDashSeparator) { var signOffset = plainText.search(/[\r\n]-- +[\r\n]/); if (signOffset < 0 && blockType == "SIGNED MESSAGE") { signOffset = plainText.search(/[\r\n]--[\r\n]/); } if (signOffset > 0) { // Strip signature portion of quoted message plainText = plainText.substr(0, signOffset + 1); } } var clipBoard = Components.classes["@mozilla.org/widget/clipboard;1"]. getService(Components.interfaces.nsIClipboard); var data; if (clipBoard.supportsSelectionClipboard()) { // get the clipboard contents for selected text (X11) data = EnigmailClipboard.getClipboardContent(window, Components.interfaces.nsIClipboard.kSelectionClipboard); } // Replace encrypted quote with decrypted quote (destroys selection clipboard on X11) this.editorSelectAll(); //EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.decryptQuote: plainText='"+plainText+"'\n"); if (head) this.editorInsertText(head); var quoteElement; if (indentStr) { quoteElement = this.editorInsertAsQuotation(plainText); } else { this.editorInsertText(plainText); } if (tail) this.editorInsertText(tail); if (clipBoard.supportsSelectionClipboard()) { // restore the clipboard contents for selected text (X11) EnigmailClipboard.setClipboardContent(data, clipBoard.kSelectionClipboard); } if (interactive) return; // Position cursor var replyOnTop = 1; try { replyOnTop = this.identity.replyOnTop; } catch (ex) {} if (!indentStr || !quoteElement) replyOnTop = 1; EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.decryptQuote: replyOnTop=" + replyOnTop + ", quoteElement=" + quoteElement + "\n"); var nsISelectionController = Components.interfaces.nsISelectionController; if (this.editor.selectionController) { var selection = this.editor.selectionController; selection.completeMove(false, false); // go to start; switch (replyOnTop) { case 0: // Position after quote this.editor.endOfDocument(); if (tail) { for (let cPos = 0; cPos < tail.length; cPos++) { selection.characterMove(false, false); // move backwards } } break; case 2: // Select quote if (head) { for (let cPos = 0; cPos < head.length; cPos++) { selection.characterMove(true, false); } } selection.completeMove(true, true); if (tail) { for (let cPos = 0; cPos < tail.length; cPos++) { selection.characterMove(false, true); // move backwards } } break; default: // Position at beginning of document if (this.editor) { this.editor.beginningOfDocument(); } } this.editor.selectionController.scrollSelectionIntoView(nsISelectionController.SELECTION_NORMAL, nsISelectionController.SELECTION_ANCHOR_REGION, true); } this.processFinalState(); this.updateStatusBar(); }, editorInsertText: function(plainText) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.editorInsertText\n"); if (this.editor) { var mailEditor; try { mailEditor = this.editor.QueryInterface(Components.interfaces.nsIEditorMailSupport); mailEditor.insertTextWithQuotations(plainText); } catch (ex) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.editorInsertText: no mail editor\n"); this.editor.insertText(plainText); } } }, editorInsertAsQuotation: function(plainText) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.editorInsertAsQuotation\n"); if (this.editor) { var mailEditor; try { mailEditor = this.editor.QueryInterface(Components.interfaces.nsIEditorMailSupport); } catch (ex) {} if (!mailEditor) return 0; EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.editorInsertAsQuotation: mailEditor=" + mailEditor + "\n"); mailEditor.insertAsQuotation(plainText); return 1; } return 0; }, /** * Display a notification to the user at the bottom of the window * * @param priority: Number - Priority of the message [1 = high (error) ... 3 = low (info)] * @param msgText: String - Text to be displayed in notification bar * @param messageId: String - Unique message type identification * @param detailsText: String - optional text to be displayed by clicking on "Details" button. * if null or "", then the Detail button will no be displayed. */ notifyUser: function(priority, msgText, messageId, detailsText) { let notif = document.getElementById("attachmentNotificationBox"); let prio; switch (priority) { case 1: prio = notif.PRIORITY_CRITICAL_MEDIUM; break; case 3: prio = notif.PRIORITY_INFO_MEDIUM; break; default: prio = notif.PRIORITY_WARNING_MEDIUM; } let buttonArr = []; if (detailsText && detailsText.length > 0) { buttonArr.push({ accessKey: EnigmailLocale.getString("msgCompose.detailsButton.accessKey"), label: EnigmailLocale.getString("msgCompose.detailsButton.label"), callback: function(aNotificationBar, aButton) { EnigmailDialog.info(window, detailsText); } }); } notif.appendNotification(msgText, messageId, null, prio, buttonArr); }, editorSelectAll: function() { if (this.editor) { this.editor.selectAll(); } }, editorGetCharset: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.editorGetCharset\n"); return this.editor.documentCharacterSet; }, editorGetContentAs: function(mimeType, flags) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.editorGetContentAs\n"); if (this.editor) { return this.editor.outputToString(mimeType, flags); } return null; }, addrOnChangeTimer: null, addressOnChange: function(element) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.addressOnChange\n"); if (!this.addrOnChangeTimer) { var self = this; this.addrOnChangeTimer = EnigmailTimer.setTimeout(function _f() { self.fireSendFlags(); self.addrOnChangeTimer = null; }, 250); } }, focusChange: function() { // call original TB function CommandUpdate_MsgCompose(); var focusedWindow = top.document.commandDispatcher.focusedWindow; // we're just setting focus to where it was before if (focusedWindow == Enigmail.msg.lastFocusedWindow) { // skip return; } Enigmail.msg.lastFocusedWindow = focusedWindow; Enigmail.msg.fireSendFlags(); }, fireSendFlags: function() { try { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: Enigmail.msg.fireSendFlags\n"); if (!this.determineSendFlagId) { this.determineSendFlagId = EnigmailEvents.dispatchEvent( function _sendFlagWrapper() { Enigmail.msg.determineSendFlags(); }, 0); } } catch (ex) {} }, /** * Merge multiple Re: Re: into one Re: in message subject */ fixMessageSubject: function() { let subjElem = document.getElementById("msgSubject"); if (subjElem) { let r = subjElem.value.replace(/^(Re: )+(.*)/, "Re: $2"); if (r !== subjElem.value) { subjElem.value = r; if (typeof subjElem.oninput === "function") subjElem.oninput(); } } } }; Enigmail.composeStateListener = { NotifyComposeFieldsReady: function() { // Note: NotifyComposeFieldsReady is only called when a new window is created (i.e. not in case a window object is reused). EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: ECSL.NotifyComposeFieldsReady\n"); try { Enigmail.msg.editor = gMsgCompose.editor.QueryInterface(Components.interfaces.nsIEditor); } catch (ex) {} if (!Enigmail.msg.editor) return; Enigmail.msg.fixMessageSubject(); function enigDocStateListener() {} enigDocStateListener.prototype = { QueryInterface: function(iid) { if (!iid.equals(Components.interfaces.nsIDocumentStateListener) && !iid.equals(Components.interfaces.nsISupports)) throw Components.results.NS_ERROR_NO_INTERFACE; return this; }, NotifyDocumentCreated: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: EDSL.NotifyDocumentCreated\n"); }, NotifyDocumentWillBeDestroyed: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: EDSL.enigDocStateListener.NotifyDocumentWillBeDestroyed\n"); }, NotifyDocumentStateChanged: function(nowDirty) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: EDSL.enigDocStateListener.NotifyDocumentStateChanged\n"); } }; var docStateListener = new enigDocStateListener(); Enigmail.msg.editor.addDocumentStateListener(docStateListener); }, ComposeProcessDone: function(aResult) { // Note: called after a mail was sent (or saved) EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: ECSL.ComposeProcessDone: " + aResult + "\n"); if (aResult != Components.results.NS_OK) { if (Enigmail.msg.processed) { Enigmail.msg.undoEncryption(4); } Enigmail.msg.removeAttachedKey(); } // ensure that securityInfo is set back to S/MIME flags (especially required if draft was saved) if (gSMFields) gMsgCompose.compFields.securityInfo = gSMFields; }, NotifyComposeBodyReady: function() { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: ECSL.ComposeBodyReady\n"); var isEmpty, isEditable; isEmpty = Enigmail.msg.editor.documentIsEmpty; isEditable = Enigmail.msg.editor.isDocumentEditable; Enigmail.msg.composeBodyReady = true; EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: EDSL.ComposeBodyReady: isEmpty=" + isEmpty + ", isEditable=" + isEditable + "\n"); //FIXME EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: EDSL.ComposeBodyReady: disableSmime=" + Enigmail.msg.disableSmime + "\n"); if (Enigmail.msg.disableSmime) { if (gMsgCompose && gMsgCompose.compFields && gMsgCompose.compFields.securityInfo) { let si = gMsgCompose.compFields.securityInfo.QueryInterface(Components.interfaces.nsIMsgSMIMECompFields); si.signMessage = false; si.requireEncryptMessage = false; } else { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: EDSL.ComposeBodyReady: could not disable S/MIME\n"); } } if (!isEditable || isEmpty) return; // Required for TB < 48 (with window recycling) Enigmail.msg.fixMessageSubject(); if (!Enigmail.msg.timeoutId && !Enigmail.msg.dirty) { Enigmail.msg.timeoutId = EnigmailTimer.setTimeout(function() { Enigmail.msg.decryptQuote(false); }, 0); } }, SaveInFolderDone: function(folderURI) { //EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: ECSL.SaveInFolderDone\n"); } }; window.addEventListener("load", function _enigmail_composeStartup(event) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: got load event\n"); Enigmail.msg.composeStartup(event); }, false); window.addEventListener("unload", function _enigmail_composeUnload(event) { Enigmail.msg.composeUnload(event); }, false); // Handle recycled windows // TB < 47 window.addEventListener('compose-window-close', function _enigmail_msgComposeClose(event) { Enigmail.msg.msgComposeClose(event); }, true); // TB >= 48 window.addEventListener('compose-window-unload', function _enigmail_msgComposeDestory(event) { Enigmail.msg.msgComposeClose(event); }, true); // TB < 47 only window.addEventListener('compose-window-reopen', function _enigmail_msgComposeReopen(event) { Enigmail.msg.msgComposeReopen(event); }, true); // Listen to message sending event window.addEventListener('compose-send-message', function _enigmail_sendMessageListener(event) { Enigmail.msg.sendMessageListener(event); }, true); window.addEventListener('compose-window-init', function _enigmail_composeWindowInit(event) { EnigmailLog.DEBUG("enigmailMsgComposeOverlay.js: _enigmail_composeWindowInit\n"); gMsgCompose.RegisterStateListener(Enigmail.composeStateListener); Enigmail.msg.composeBodyReady = false; }, true); diff --git a/ui/content/enigmailMsgHdrViewOverlay.js b/ui/content/enigmailMsgHdrViewOverlay.js index c22fb1be..4ee80bfc 100644 --- a/ui/content/enigmailMsgHdrViewOverlay.js +++ b/ui/content/enigmailMsgHdrViewOverlay.js @@ -1,1585 +1,1593 @@ /*global Components: false, EnigmailWindows: false, EnigmailLocale: false, EnigmailPrefs: false, EnigmailTime: 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"; /* globals from Thunderbird: */ /* global gFolderDisplay: false, currentAttachments: false, gSMIMEContainer: false, gSignedUINode: false, gEncryptedUINode: false */ /* global gDBView: false, msgWindow: false, messageHeaderSink: false: gMessageListeners: false, findEmailNodeFromPopupNode: true */ /* global gExpandedHeaderView: false, gMessageListeners: false, onShowAttachmentItemContextMenu: false, onShowAttachmentContextMenu: false */ /* global attachmentList: false, MailOfflineMgr: false, currentHeaderData: false, ContentTypeIsSMIME: 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/log.jsm"); /*global EnigmailLog: false */ Components.utils.import("resource://enigmail/prefs.jsm"); /*global EnigmailPrefs: 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/dialog.jsm"); /*global EnigmailDialog: false */ Components.utils.import("resource://enigmail/time.jsm"); /*global EnigmailTime: false */ Components.utils.import("resource://enigmail/gpg.jsm"); /*global EnigmailGpg: false */ Components.utils.import("resource://enigmail/key.jsm"); /*global EnigmailKey: false */ Components.utils.import("resource://enigmail/keyRing.jsm"); /*global EnigmailKeyRing: false */ Components.utils.import("resource://enigmail/uris.jsm"); /*global EnigmailURIs: false */ Components.utils.import("resource://enigmail/constants.jsm"); /*global EnigmailConstants: false */ Components.utils.import("resource://enigmail/data.jsm"); /*global EnigmailData: false */ Components.utils.import("resource://enigmail/clipboard.jsm"); /*global EnigmailClipboard: false */ Components.utils.import("resource://enigmail/pEpAdapter.jsm"); /*global EnigmailPEPAdapter: false */ Components.utils.import("resource://enigmail/stdlib.jsm"); /* global EnigmailStdlib: false */ Components.utils.import("resource://enigmail/webKey.jsm"); /* global EnigmailWks: false */ if (!Enigmail) var Enigmail = {}; const EC = EnigmailCore; Enigmail.hdrView = { statusBar: null, enigmailBox: null, lastEncryptedMsgKey: null, pEpStatus: null, hdrViewLoad: function() { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.hdrViewLoad\n"); // Override SMIME ui var signedHdrElement = document.getElementById("signedHdrIcon"); if (signedHdrElement) { signedHdrElement.setAttribute("onclick", "Enigmail.msg.viewSecurityInfo(event, true);"); } var encryptedHdrElement = document.getElementById("encryptedHdrIcon"); if (encryptedHdrElement) { encryptedHdrElement.setAttribute("onclick", "Enigmail.msg.viewSecurityInfo(event, true);"); } this.statusBar = document.getElementById("enigmail-status-bar"); this.enigmailBox = document.getElementById("enigmailBox"); this.pEpBox = document.getElementById("enigmail-pEp-bc"); var addrPopup = document.getElementById("emailAddressPopup"); if (addrPopup) { var attr = addrPopup.getAttribute("onpopupshowing"); attr = "Enigmail.hdrView.displayAddressPopup(this); " + attr; addrPopup.setAttribute("onpopupshowing", attr); } }, displayAddressPopup: function(target) { if (EnigmailPEPAdapter.usingPep()) { let adr = findEmailNodeFromPopupNode(document.popupNode, 'emailAddressPopup'); if (adr) { Enigmail.hdrView.setPepVerifyFunction(adr); } } EnigmailFuncs.collapseAdvanced(target, 'hidden'); }, statusBarHide: function() { function resetPepColors(textNode) { let nodes = textNode.getElementsByTagName("mail-emailaddress"); for (let i = 0; i < nodes.length; i++) { nodes[i].setAttribute("class", ""); } } try { this.statusBar.removeAttribute("signed"); this.statusBar.removeAttribute("encrypted"); this.enigmailBox.setAttribute("collapsed", "true"); this.pEpBox.setAttribute("collapsed", "true"); resetPepColors(gExpandedHeaderView.from.textNode); resetPepColors(gExpandedHeaderView.to.textNode); resetPepColors(gExpandedHeaderView.cc.textNode); resetPepColors(gExpandedHeaderView["reply-to"].textNode); Enigmail.msg.setAttachmentReveal(null); if (Enigmail.msg.securityInfo) { Enigmail.msg.securityInfo.statusFlags = 0; Enigmail.msg.securityInfo.msgSigned = 0; Enigmail.msg.securityInfo.msgEncrypted = 0; } } catch (ex) {} }, // Match the userId from gpg to the sender's from address matchUidToSender: function(userId) { if (!gFolderDisplay.selectedMessage) { return userId; } var fromAddr = gFolderDisplay.selectedMessage.author; try { fromAddr = EnigmailFuncs.stripEmail(fromAddr); } catch (ex) {} var userIdList = userId.split(/\n/); try { let i; for (i = 0; i < userIdList.length; i++) { if (fromAddr.toLowerCase() == EnigmailFuncs.stripEmail(userIdList[i]).toLowerCase()) { userId = userIdList[i]; break; } } if (i >= userIdList.length) userId = userIdList[0]; } catch (ex) { userId = userIdList[0]; } return userId; }, setStatusText: function(txt) { let s = document.getElementById("enigmailStatusText"); s.firstChild.data = txt; }, updateHdrIcons: function(exitCode, statusFlags, keyId, userId, sigDetails, errorMsg, blockSeparation, encToDetails, xtraStatus, encMimePartNumber) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.updateHdrIcons: exitCode=" + exitCode + ", statusFlags=" + statusFlags + ", keyId=" + keyId + ", userId=" + userId + ", " + errorMsg + "\n"); if (EnigmailPEPAdapter.usingPep()) return; if (Enigmail.msg.securityInfo && Enigmail.msg.securityInfo.xtraStatus && Enigmail.msg.securityInfo.xtraStatus === "wks-request") { return; } const nsIEnigmail = Components.interfaces.nsIEnigmail; this.statusBar = document.getElementById("enigmail-status-bar"); this.enigmailBox = document.getElementById("enigmailBox"); if (gFolderDisplay.selectedMessageUris && gFolderDisplay.selectedMessageUris.length > 0) { this.lastEncryptedMsgKey = gFolderDisplay.selectedMessageUris[0]; } if (!errorMsg) errorMsg = ""; var replaceUid = null; if (userId && (userId.indexOf("\n") >= 0)) { replaceUid = this.matchUidToSender(userId); } else { replaceUid = userId; } if (Enigmail.msg.savedHeaders && (Enigmail.msg.savedHeaders["x-pgp-encoding-format"].search(/partitioned/i) === 0)) { if (currentAttachments && currentAttachments.length) { Enigmail.msg.setAttachmentReveal(currentAttachments); } } if (userId && replaceUid) { // no EnigConvertGpgToUnicode() here; strings are already UTF-8 replaceUid = replaceUid.replace(/\\[xe]3a/gi, ":"); errorMsg = errorMsg.replace(userId, replaceUid); } var errorLines = ""; var fullStatusInfo = ""; if (exitCode == EnigmailConstants.POSSIBLE_PGPMIME) { exitCode = 0; } else { if (errorMsg) { // no EnigConvertGpgToUnicode() here; strings are already UTF-8 errorLines = errorMsg.split(/\r?\n/); fullStatusInfo = errorMsg; } } if (errorLines && (errorLines.length > 22)) { // Retain only first twenty lines and last two lines of error message var lastLines = errorLines[errorLines.length - 2] + "\n" + errorLines[errorLines.length - 1] + "\n"; while (errorLines.length > 20) errorLines.pop(); errorMsg = errorLines.join("\n") + "\n...\n" + lastLines; } var statusInfo = ""; var statusLine = ""; var statusArr = []; if (statusFlags & nsIEnigmail.NODATA) { if (statusFlags & nsIEnigmail.PGP_MIME_SIGNED) statusFlags |= nsIEnigmail.UNVERIFIED_SIGNATURE; if (statusFlags & nsIEnigmail.PGP_MIME_ENCRYPTED) statusFlags |= nsIEnigmail.DECRYPTION_INCOMPLETE; } if (!(statusFlags & nsIEnigmail.PGP_MIME_ENCRYPTED)) { encMimePartNumber = ""; } if (!EnigmailPrefs.getPref("displayPartiallySigned")) { if ((statusFlags & (nsIEnigmail.PARTIALLY_PGP)) && (statusFlags & (nsIEnigmail.BAD_SIGNATURE))) { statusFlags &= ~(nsIEnigmail.BAD_SIGNATURE | nsIEnigmail.PARTIALLY_PGP); if (statusFlags === 0) { errorMsg = ""; fullStatusInfo = ""; } } } var msgSigned = (statusFlags & (nsIEnigmail.BAD_SIGNATURE | nsIEnigmail.GOOD_SIGNATURE | nsIEnigmail.EXPIRED_KEY_SIGNATURE | nsIEnigmail.EXPIRED_SIGNATURE | nsIEnigmail.UNVERIFIED_SIGNATURE | nsIEnigmail.REVOKED_KEY | nsIEnigmail.EXPIRED_KEY_SIGNATURE | nsIEnigmail.EXPIRED_SIGNATURE)); var msgEncrypted = (statusFlags & (nsIEnigmail.DECRYPTION_OKAY | nsIEnigmail.DECRYPTION_INCOMPLETE | nsIEnigmail.DECRYPTION_FAILED)); if (msgSigned && (statusFlags & nsIEnigmail.IMPORTED_KEY)) { statusFlags &= (~nsIEnigmail.IMPORTED_KEY); } if (!(statusFlags & nsIEnigmail.DECRYPTION_FAILED) && ((!(statusFlags & (nsIEnigmail.DECRYPTION_INCOMPLETE | nsIEnigmail.UNVERIFIED_SIGNATURE | nsIEnigmail.DECRYPTION_FAILED | nsIEnigmail.BAD_SIGNATURE))) || (statusFlags & nsIEnigmail.DISPLAY_MESSAGE) && !(statusFlags & nsIEnigmail.UNVERIFIED_SIGNATURE)) && !(statusFlags & nsIEnigmail.IMPORTED_KEY)) { // normal exit / display message statusLine = errorMsg; statusInfo = statusLine; if (sigDetails) { var detailArr = sigDetails.split(/ /); let dateTime = EnigmailTime.getDateTime(detailArr[2], true, true); var txt = EnigmailLocale.getString("keyAndSigDate", [keyId, dateTime]); statusArr.push(txt); statusInfo += "\n" + txt; var fpr = ""; if (detailArr.length >= 10) { fpr = EnigmailKey.formatFpr(detailArr[9]); } else { fpr = EnigmailKey.formatFpr(detailArr[0]); } if (fpr) { statusInfo += "\n" + EnigmailLocale.getString("keyFpr", [fpr]); } if (detailArr.length > 7) { var signingAlg = EnigmailGpg.signingAlgIdToString(detailArr[6]); var hashAlg = EnigmailGpg.hashAlgIdToString(detailArr[7]); statusInfo += "\n\n" + EnigmailLocale.getString("usedAlgorithms", [signingAlg, hashAlg]); } } fullStatusInfo = statusInfo; } else { // no normal exit / don't display message // - process failed decryptions first because they imply bad signature handling if (statusFlags & nsIEnigmail.BAD_PASSPHRASE) { statusInfo = EnigmailLocale.getString("badPhrase"); statusLine = statusInfo + EnigmailLocale.getString("clickDecryptRetry"); } else if (statusFlags & nsIEnigmail.DECRYPTION_FAILED) { if (statusFlags & nsIEnigmail.MISSING_PASSPHRASE) { statusInfo = EnigmailLocale.getString("missingPassphrase"); statusLine = statusInfo + EnigmailLocale.getString("clickDecryptRetry"); } else if (statusFlags & nsIEnigmail.NO_SECKEY) { statusInfo = EnigmailLocale.getString("needKey"); } else { statusInfo = EnigmailLocale.getString("failedDecrypt"); } statusLine = statusInfo + EnigmailLocale.getString("clickDetailsButton"); } else if (statusFlags & nsIEnigmail.UNVERIFIED_SIGNATURE) { statusInfo = EnigmailLocale.getString("unverifiedSig"); if (keyId) { statusLine = statusInfo + EnigmailLocale.getString("clickImportButton"); } else { statusLine = statusInfo + EnigmailLocale.getString("keyTypeUnsupported"); } } else if (statusFlags & (nsIEnigmail.BAD_SIGNATURE | nsIEnigmail.EXPIRED_SIGNATURE | nsIEnigmail.EXPIRED_KEY_SIGNATURE)) { statusInfo = EnigmailLocale.getString("unverifiedSig"); statusLine = statusInfo + EnigmailLocale.getString("clickDetailsButton"); } else if (statusFlags & nsIEnigmail.DECRYPTION_INCOMPLETE) { statusInfo = EnigmailLocale.getString("incompleteDecrypt"); statusLine = statusInfo + EnigmailLocale.getString("clickDetailsButton"); } else if (statusFlags & nsIEnigmail.IMPORTED_KEY) { statusLine = ""; statusInfo = ""; EnigmailDialog.info(window, errorMsg); } else { statusInfo = EnigmailLocale.getString("failedDecryptVerify"); statusLine = statusInfo + EnigmailLocale.getString("viewInfo"); } // add key infos if available if (keyId) { var si = EnigmailLocale.getString("unverifiedSig"); // "Unverified signature" if (statusInfo === "") { statusInfo += si; statusLine = si + EnigmailLocale.getString("clickDetailsButton"); } if (statusFlags & nsIEnigmail.UNVERIFIED_SIGNATURE) { statusInfo += "\n" + EnigmailLocale.getString("keyNeeded", [keyId]); // "public key ... needed" } else { statusInfo += "\n" + EnigmailLocale.getString("keyUsed", [keyId]); // "public key ... used" } } statusInfo += "\n\n" + errorMsg; } if (statusFlags & nsIEnigmail.DECRYPTION_OKAY || (this.statusBar.getAttribute("encrypted") == "ok")) { var statusMsg; if (xtraStatus && xtraStatus == "buggyMailFormat") { statusMsg = EnigmailLocale.getString("decryptedMsgWithFormatError"); } else { statusMsg = EnigmailLocale.getString("decryptedMsg"); } if (!statusInfo) { statusInfo = statusMsg; } else { statusInfo = statusMsg + "\n" + statusInfo; } if (!statusLine) { statusLine = statusInfo; } else { statusLine = statusMsg + "; " + statusLine; } } if (EnigmailPrefs.getPref("displayPartiallySigned")) { if (statusFlags & nsIEnigmail.PARTIALLY_PGP) { if (msgSigned && msgEncrypted) { statusLine = EnigmailLocale.getString("msgPart", [EnigmailLocale.getString("msgSignedAndEnc")]); statusLine += EnigmailLocale.getString("clickDetailsButton"); statusInfo = EnigmailLocale.getString("msgPart", [EnigmailLocale.getString("msgSigned")]) + "\n" + statusInfo; } else if (msgEncrypted) { statusLine = EnigmailLocale.getString("msgPart", [EnigmailLocale.getString("msgEncrypted")]); statusLine += EnigmailLocale.getString("clickDetailsButton"); statusInfo = EnigmailLocale.getString("msgPart", [EnigmailLocale.getString("msgEncrypted")]) + "\n" + statusInfo; } else if (msgSigned) { if (statusFlags & nsIEnigmail.UNVERIFIED_SIGNATURE) { statusLine = EnigmailLocale.getString("msgPart", [EnigmailLocale.getString("msgSignedUnkownKey")]); if (keyId) { statusLine += EnigmailLocale.getString("clickImportButton"); } else { statusLine += EnigmailLocale.getString("keyTypeUnsupported"); } } else { statusLine = EnigmailLocale.getString("msgPart", [EnigmailLocale.getString("msgSigned")]); statusLine += EnigmailLocale.getString("clickDetailsButton"); } statusInfo = EnigmailLocale.getString("msgPart", [EnigmailLocale.getString("msgSigned")]) + "\n" + statusInfo; } } } // if we have parsed ENC_TO entries, add them as status info if (encToDetails && encToDetails.length > 0) { statusInfo += "\n\n" + EnigmailLocale.getString("encryptKeysNote", [encToDetails]); } if (!statusLine) { return; } Enigmail.msg.securityInfo = { statusFlags: statusFlags, keyId: keyId, userId: userId, statusLine: statusLine, msgSigned: msgSigned, statusArr: statusArr, statusInfo: statusInfo, fullStatusInfo: fullStatusInfo, blockSeparation: blockSeparation, xtraStatus: xtraStatus, encryptedMimePart: encMimePartNumber }; Enigmail.msg.createArtificialAutocryptHeader(); this.displayStatusBar(); this.updateMsgDb(); }, /** * Check whether we got a WKS request */ checkWksConfirmRequest: function(jsonStr) { let requestObj; try { requestObj = JSON.parse(jsonStr); } catch (ex) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: checkWksConfirmRequest parsing JSON failed\n"); return; } if ("type" in requestObj && requestObj.type.toLowerCase() === "confirmation-request") { let view = Enigmail.hdrView; EnigmailWks.getWksClientPathAsync(window, function _res(wksClientPath) { if (!wksClientPath) return; view.setStatusText(EnigmailLocale.getString("wksConfirmationReq")); view.enigmailBox.removeAttribute("collapsed"); document.getElementById("enigmail_confirmKey").removeAttribute("hidden"); document.getElementById("enigmail_importKey").setAttribute("hidden", "true"); view.enigmailBox.setAttribute("class", "expandedEnigmailBox enigmailHeaderBoxLabelSignatureUnknown"); if (!Enigmail.msg.securityInfo) { Enigmail.msg.securityInfo = {}; } Enigmail.msg.securityInfo.xtraStatus = "wks-request"; }); } else { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: checkWksConfirmRequest failed condition\n"); } }, displayStatusBar: function() { const nsIEnigmail = EnigmailConstants.nsIEnigmail; let statusText = document.getElementById("enigmailStatusText"); let expStatusText = document.getElementById("expandedEnigmailStatusText"); let icon = document.getElementById("enigToggleHeaderView2"); let bodyElement = document.getElementById("messagepanebox"); let secInfo = Enigmail.msg.securityInfo; let statusFlags = secInfo.statusFlags; if (secInfo.statusArr.length > 0) { expStatusText.value = secInfo.statusArr[0]; expStatusText.setAttribute("state", "true"); icon.removeAttribute("collapsed"); } else { expStatusText.value = ""; expStatusText.setAttribute("state", "false"); icon.setAttribute("collapsed", "true"); } if (secInfo.statusLine) { this.setStatusText(secInfo.statusLine + " "); this.enigmailBox.removeAttribute("collapsed"); this.displayExtendedStatus(true); if ((secInfo.keyId && (statusFlags & nsIEnigmail.UNVERIFIED_SIGNATURE)) || (statusFlags & nsIEnigmail.INLINE_KEY)) { document.getElementById("enigmail_importKey").removeAttribute("hidden"); } else { document.getElementById("enigmail_importKey").setAttribute("hidden", "true"); } document.getElementById("enigmail_confirmKey").setAttribute("hidden", "true"); } else { this.setStatusText(""); this.enigmailBox.setAttribute("collapsed", "true"); this.displayExtendedStatus(false); } if (!gSMIMEContainer) return; // Update icons and header-box css-class try { gSMIMEContainer.collapsed = false; gSignedUINode.collapsed = false; gEncryptedUINode.collapsed = false; if ((statusFlags & nsIEnigmail.BAD_SIGNATURE) && !(statusFlags & nsIEnigmail.GOOD_SIGNATURE)) { // Display untrusted/bad signature icon gSignedUINode.setAttribute("signed", "unknown"); this.enigmailBox.setAttribute("class", "expandedEnigmailBox enigmailHeaderBoxLabelSignatureUnknown"); this.statusBar.setAttribute("signed", "unknown"); } else if ((statusFlags & nsIEnigmail.GOOD_SIGNATURE) && (statusFlags & nsIEnigmail.TRUSTED_IDENTITY) && !(statusFlags & (nsIEnigmail.REVOKED_KEY | nsIEnigmail.EXPIRED_KEY_SIGNATURE | nsIEnigmail.EXPIRED_SIGNATURE))) { // Display trusted good signature icon gSignedUINode.setAttribute("signed", "ok"); this.enigmailBox.setAttribute("class", "expandedEnigmailBox enigmailHeaderBoxLabelSignatureOk"); this.statusBar.setAttribute("signed", "ok"); bodyElement.setAttribute("enigSigned", "ok"); } else if (statusFlags & nsIEnigmail.UNVERIFIED_SIGNATURE) { // Display unverified signature icon gSignedUINode.setAttribute("signed", "unknown"); this.enigmailBox.setAttribute("class", "expandedEnigmailBox enigmailHeaderBoxLabelSignatureUnknown"); this.statusBar.setAttribute("signed", "unknown"); } else if (statusFlags & (nsIEnigmail.REVOKED_KEY | nsIEnigmail.EXPIRED_KEY_SIGNATURE | nsIEnigmail.EXPIRED_SIGNATURE | nsIEnigmail.GOOD_SIGNATURE)) { // Display unverified signature icon gSignedUINode.setAttribute("signed", "unknown"); this.enigmailBox.setAttribute("class", "expandedEnigmailBox enigmailHeaderBoxLabelSignatureVerified"); this.statusBar.setAttribute("signed", "unknown"); } else if (statusFlags & nsIEnigmail.INLINE_KEY) { this.enigmailBox.setAttribute("class", "expandedEnigmailBox enigmailHeaderBoxLabelSignatureUnknown"); } else { this.enigmailBox.setAttribute("class", "expandedEnigmailBox enigmailHeaderBoxLabelNoSignature"); } if (statusFlags & nsIEnigmail.DECRYPTION_OKAY) { EnigmailURIs.rememberEncryptedUri(this.lastEncryptedMsgKey); // Display encrypted icon gEncryptedUINode.setAttribute("encrypted", "ok"); this.statusBar.setAttribute("encrypted", "ok"); } else if (statusFlags & (nsIEnigmail.DECRYPTION_INCOMPLETE | nsIEnigmail.DECRYPTION_FAILED)) { // Display un-encrypted icon gEncryptedUINode.setAttribute("encrypted", "notok"); this.statusBar.setAttribute("encrypted", "notok"); this.enigmailBox.setAttribute("class", "expandedEnigmailBox enigmailHeaderBoxLabelSignatureNotOk"); } // special handling after trying to fix buggy mail format (see buggyExchangeEmailContent in code) if (secInfo.xtraStatus && secInfo.xtraStatus == "buggyMailFormat") { this.enigmailBox.setAttribute("class", "expandedEnigmailBox enigmailHeaderBoxLabelBuggyMailFormat"); } } catch (ex) { EnigmailLog.writeException("displayStatusBar", ex); } }, dispSecurityContext: function() { const nsIEnigmail = Components.interfaces.nsIEnigmail; try { if (Enigmail.msg.securityInfo) { if ((Enigmail.msg.securityInfo.statusFlags & nsIEnigmail.NODATA) && (Enigmail.msg.securityInfo.statusFlags & (nsIEnigmail.PGP_MIME_SIGNED | nsIEnigmail.PGP_MIME_ENCRYPTED))) { document.getElementById("enigmail_reloadMessage").removeAttribute("hidden"); } else { document.getElementById("enigmail_reloadMessage").setAttribute("hidden", "true"); } } var optList = ["pgpSecurityInfo", "copySecurityInfo"]; for (var j = 0; j < optList.length; j++) { var menuElement = document.getElementById("enigmail_" + optList[j]); if (Enigmail.msg.securityInfo) { menuElement.removeAttribute("disabled"); } else { menuElement.setAttribute("disabled", "true"); } } this.setSenderStatus("signSenderKey", "editSenderKeyTrust", "showPhoto", "dispKeyDetails"); } catch (ex) { EnigmailLog.ERROR("error on displaying Security menu:\n" + ex.toString() + "\n"); } }, updateSendersKeyMenu: function() { this.setSenderStatus("keyMgmtSignKey", "keyMgmtKeyTrust", "keyMgmtShowPhoto", "keyMgmtDispKeyDetails", "importpublickey"); }, setSenderStatus: function(elemSign, elemTrust, elemPhoto, elemKeyProps, elemImportKey) { function setElemStatus(elemName, disabledValue) { document.getElementById("enigmail_" + elemName).setAttribute("disabled", !disabledValue); let secondElem = document.getElementById("enigmail_" + elemName + "2"); if (secondElem) secondElem.setAttribute("disabled", !disabledValue); } const nsIEnigmail = Components.interfaces.nsIEnigmail; var photo = false; var sign = false; var trust = false; var unknown = false; var signedMsg = false; if (Enigmail.msg.securityInfo) { if (Enigmail.msg.securityInfo.statusFlags & nsIEnigmail.PHOTO_AVAILABLE) { photo = true; } if (Enigmail.msg.securityInfo.msgSigned) { signedMsg = true; if (!(Enigmail.msg.securityInfo.statusFlags & (nsIEnigmail.REVOKED_KEY | nsIEnigmail.EXPIRED_KEY_SIGNATURE | nsIEnigmail.UNVERIFIED_SIGNATURE))) { sign = true; } if (!(Enigmail.msg.securityInfo.statusFlags & nsIEnigmail.UNVERIFIED_SIGNATURE)) { trust = true; } if (Enigmail.msg.securityInfo.statusFlags & nsIEnigmail.UNVERIFIED_SIGNATURE) { unknown = true; } } } if (elemTrust) setElemStatus(elemTrust, trust); if (elemSign) setElemStatus(elemSign, sign); if (elemPhoto) setElemStatus(elemPhoto, photo); if (elemKeyProps) setElemStatus(elemKeyProps, (signedMsg && !unknown)); if (elemImportKey) setElemStatus(elemImportKey, unknown); }, editKeyExpiry: function() { EnigmailWindows.editKeyExpiry(window, [Enigmail.msg.securityInfo.userId], [Enigmail.msg.securityInfo.keyId]); gDBView.reloadMessageWithAllParts(); }, editKeyTrust: function() { let enigmailSvc = EnigmailCore.getService(); let key = EnigmailKeyRing.getKeyById(Enigmail.msg.securityInfo.keyId); EnigmailWindows.editKeyTrust(window, [Enigmail.msg.securityInfo.userId], [key.keyId]); gDBView.reloadMessageWithAllParts(); }, signKey: function() { let enigmailSvc = EnigmailCore.getService(); let key = EnigmailKeyRing.getKeyById(Enigmail.msg.securityInfo.keyId); EnigmailWindows.signKey(window, Enigmail.msg.securityInfo.userId, key.keyId, null); gDBView.reloadMessageWithAllParts(); }, msgHdrViewLoad: function(event) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.msgHdrViewLoad\n"); var listener = { enigmailBox: document.getElementById("enigmailBox"), onStartHeaders: function _listener_onStartHeaders() { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: _listener_onStartHeaders\n"); try { Enigmail.hdrView.statusBarHide(); EnigmailVerify.setMsgWindow(msgWindow, Enigmail.msg.getCurrentMsgUriSpec()); Enigmail.hdrView.setStatusText(""); this.enigmailBox.setAttribute("class", "expandedEnigmailBox enigmailHeaderBoxLabelSignatureOk"); var msgFrame = EnigmailWindows.getFrame(window, "messagepane"); if (msgFrame) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: msgFrame=" + msgFrame + "\n"); msgFrame.addEventListener("unload", Enigmail.hdrView.messageUnload.bind(Enigmail.hdrView), true); msgFrame.addEventListener("load", function _f() { Enigmail.hdrView.enablePepMenus(); Enigmail.msg.messageAutoDecrypt(); Enigmail.msg.handleAttchmentEvent(); }, false); } Enigmail.hdrView.forgetEncryptedMsgKey(); if (messageHeaderSink) { try { messageHeaderSink.enigmailPrepSecurityInfo(); } catch (ex) {} } } catch (ex) {} }, onEndHeaders: function _listener_onEndHeaders() { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: _listener_onEndHeaders\n"); try { Enigmail.hdrView.statusBarHide(); this.enigmailBox.setAttribute("class", "expandedEnigmailBox enigmailHeaderBoxLabelSignatureOk"); } catch (ex) {} }, beforeStartHeaders: function _listener_beforeStartHeaders() { return true; } }; gMessageListeners.push(listener); }, messageUnload: function() { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.messageUnload\n"); if (Enigmail.msg.securityInfo && Enigmail.msg.securityInfo.xtraStatus) { Enigmail.msg.securityInfo.xtraStatus = ""; } }, hdrViewUnload: function() { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.hdrViewUnLoad\n"); this.forgetEncryptedMsgKey(); }, copyStatusInfo: function() { if (Enigmail.msg.securityInfo) { EnigmailClipboard.setClipboardContent(Enigmail.msg.securityInfo.statusInfo); } }, showPhoto: function() { if (!Enigmail.msg.securityInfo) return; let enigmailSvc = EnigmailCore.getService(); let key = EnigmailKeyRing.getKeyById(Enigmail.msg.securityInfo.keyId); EnigmailWindows.showPhoto(window, key.keyId, Enigmail.msg.securityInfo.userId); }, dispKeyDetails: function() { if (!Enigmail.msg.securityInfo) return; let enigmailSvc = EnigmailCore.getService(); let key = EnigmailKeyRing.getKeyById(Enigmail.msg.securityInfo.keyId); EnigmailWindows.openKeyDetails(window, key.keyId, false); }, createRuleFromAddress: function(emailAddressNode) { if (emailAddressNode) { if (typeof(findEmailNodeFromPopupNode) == "function") { emailAddressNode = findEmailNodeFromPopupNode(emailAddressNode, 'emailAddressPopup'); } EnigmailWindows.createNewRule(window, emailAddressNode.getAttribute("emailAddress")); } }, forgetEncryptedMsgKey: function() { if (Enigmail.hdrView.lastEncryptedMsgKey) { EnigmailURIs.forgetEncryptedUri(Enigmail.hdrView.lastEncryptedMsgKey); Enigmail.hdrView.lastEncryptedMsgKey = null; } }, msgHdrViewHide: function() { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.msgHdrViewHide\n"); this.enigmailBox.setAttribute("collapsed", true); Enigmail.msg.securityInfo = { statusFlags: 0, keyId: "", userId: "", statusLine: "", statusInfo: "", fullStatusInfo: "", encryptedMimePart: "" }; }, msgHdrViewUnhide: function(event) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.msgHdrViewUnhide:\n"); if (Enigmail.msg.securityInfo && Enigmail.msg.securityInfo.statusFlags !== 0) { this.enigmailBox.removeAttribute("collapsed"); } }, displayExtendedStatus: function(displayOn) { var expStatusText = document.getElementById("expandedEnigmailStatusText"); if (displayOn && expStatusText.getAttribute("state") == "true") { if (expStatusText.getAttribute("display") == "true") { expStatusText.removeAttribute("collapsed"); } else { expStatusText.setAttribute("collapsed", "true"); } } else { expStatusText.setAttribute("collapsed", "true"); } }, toggleHeaderView: function() { var viewToggle = document.getElementById("enigToggleHeaderView2"); var expandedText = document.getElementById("expandedEnigmailStatusText"); var state = viewToggle.getAttribute("state"); if (state == "true") { viewToggle.setAttribute("state", "false"); viewToggle.setAttribute("class", "enigmailExpandViewButton"); expandedText.setAttribute("display", "false"); this.displayExtendedStatus(false); } else { viewToggle.setAttribute("state", "true"); viewToggle.setAttribute("class", "enigmailCollapseViewButton"); expandedText.setAttribute("display", "true"); this.displayExtendedStatus(true); } }, enigOnShowAttachmentContextMenu: function() { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.enigOnShowAttachmentContextMenu\n"); // first, call the original function ... try { // Thunderbird onShowAttachmentItemContextMenu(); } catch (ex) { // SeaMonkey onShowAttachmentContextMenu(); } // then, do our own additional stuff ... // Thunderbird var contextMenu = document.getElementById('attachmentItemContext'); var selectedAttachments = contextMenu.attachments; if (!contextMenu) { // SeaMonkey contextMenu = document.getElementById('attachmentListContext'); selectedAttachments = attachmentList.selectedItems; } var decryptOpenMenu = document.getElementById('enigmail_ctxDecryptOpen'); var decryptSaveMenu = document.getElementById('enigmail_ctxDecryptSave'); var importMenu = document.getElementById('enigmail_ctxImportKey'); var verifyMenu = document.getElementById('enigmail_ctxVerifyAtt'); if (selectedAttachments.length > 0) { if (selectedAttachments[0].contentType.search(/^application\/pgp-keys/i) === 0) { importMenu.removeAttribute('disabled'); decryptOpenMenu.setAttribute('disabled', true); decryptSaveMenu.setAttribute('disabled', true); verifyMenu.setAttribute('disabled', true); } else if (Enigmail.msg.checkSignedAttachment(selectedAttachments[0], null)) { importMenu.setAttribute('disabled', true); decryptOpenMenu.setAttribute('disabled', true); decryptSaveMenu.setAttribute('disabled', true); verifyMenu.removeAttribute('disabled'); } else if (Enigmail.msg.checkEncryptedAttach(selectedAttachments[0])) { importMenu.setAttribute('disabled', true); decryptOpenMenu.removeAttribute('disabled'); decryptSaveMenu.removeAttribute('disabled'); verifyMenu.setAttribute('disabled', true); if (typeof(selectedAttachments[0].displayName) == "undefined") { if (!selectedAttachments[0].name) { selectedAttachments[0].name = "message.pgp"; } } else if (!selectedAttachments[0].displayName) { selectedAttachments[0].displayName = "message.pgp"; } } else { importMenu.setAttribute('disabled', true); decryptOpenMenu.setAttribute('disabled', true); decryptSaveMenu.setAttribute('disabled', true); verifyMenu.setAttribute('disabled', true); } } else { openMenu.setAttribute('disabled', true); /* global openMenu: false */ saveMenu.setAttribute('disabled', true); /* global saveMenu: false */ decryptOpenMenu.setAttribute('disabled', true); decryptSaveMenu.setAttribute('disabled', true); importMenu.setAttribute('disabled', true); verifyMenu.setAttribute('disabled', true); } }, updateMsgDb: function() { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.updateMsgDb\n"); var msg = gFolderDisplay.selectedMessage; if (!msg || !msg.folder) return; var msgHdr = msg.folder.GetMessageHeader(msg.messageKey); if (EnigmailPEPAdapter.usingPep()) { + let rating = 0; + if (this.pEpStatus.rating !== null) { + rating = this.pEpStatus.rating; + } + + rating = (rating + 0xFF) << 8; + let pepColor = 0; switch (this.pEpStatus.messageColor) { case "red": pepColor = 1; break; case "yellow": pepColor = 2; break; case "green": pepColor = 3; break; } - msgHdr.setUint32Property("enigmailPep", pepColor); + + msgHdr.setUint32Property("enigmailPep", rating + pepColor); } else { if (this.statusBar.getAttribute("encrypted") == "ok") Enigmail.msg.securityInfo.statusFlags |= Components.interfaces.nsIEnigmail.DECRYPTION_OKAY; msgHdr.setUint32Property("enigmail", Enigmail.msg.securityInfo.statusFlags); } }, enigCanDetachAttachments: function() { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: this.enigCanDetachAttachments\n"); const nsIEnigmail = Components.interfaces.nsIEnigmail; var canDetach = true; if (Enigmail.msg.securityInfo && (typeof(Enigmail.msg.securityInfo.statusFlags) != "undefined")) { canDetach = ((Enigmail.msg.securityInfo.statusFlags & (nsIEnigmail.PGP_MIME_SIGNED | nsIEnigmail.PGP_MIME_ENCRYPTED)) ? false : true); } return canDetach; }, fillAttachmentListPopup: function(item) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: Enigmail.hdrView.fillAttachmentListPopup\n"); FillAttachmentListPopup(item); /* global FillAttachmentListPopup: false */ if (!this.enigCanDetachAttachments()) { for (var i = 0; i < item.childNodes.length; i++) { if (item.childNodes[i].className == "menu-iconic") { var mnu = item.childNodes[i].firstChild.firstChild; while (mnu) { if (mnu.getAttribute("oncommand").search(/(detachAttachment|deleteAttachment)/) >= 0) { mnu.setAttribute("disabled", true); } mnu = mnu.nextSibling; } } } } }, setSubject: function(subject) { if (gFolderDisplay.selectedMessages.length === 1 && gFolderDisplay.selectedMessage) { gFolderDisplay.selectedMessage.subject = EnigmailData.convertFromUnicode(subject, "utf-8"); this.updateHdrBox("subject", subject); } }, updateHdrBox: function(header, value) { let e = document.getElementById("expanded" + header + "Box"); if (e) { e.headerValue = value; } }, displayPepStatus: function(rating, keyIDs, uri, persons) { if (typeof(keyIDs) === "string") { keyIDs = keyIDs.split(/,/); } this.pEpStatus = { rating: rating, messageColor: "grey", emailRatings: [], keyIDs: keyIDs }; this.displayPepMessageRating(rating); this.displayPepIdentities(persons); }, displayPepMessageRating: function(rating) { this.pEpBox.removeAttribute("collapsed"); if (rating === -2 || rating === 2) { this.pEpStatus.messageColor = "grey"; this.pEpBox.setAttribute("ratingcode", "unknown"); } else if (rating < 0) { this.pEpStatus.messageColor = "red"; this.pEpBox.setAttribute("ratingcode", "mistrust"); } else if (rating < 6) { this.pEpStatus.messageColor = "grey"; this.pEpBox.setAttribute("ratingcode", "unknown"); } else if (rating >= 7) { this.pEpStatus.messageColor = "green"; this.pEpBox.setAttribute("ratingcode", "trusted"); } else { this.pEpStatus.messageColor = "yellow"; this.pEpBox.setAttribute("ratingcode", "reliable"); } this.updateMsgDb(); }, displayPepEmailRating: function(textNode, person) { let nodes = textNode.getElementsByTagName("mail-emailaddress"); let emailAddress = person.address.toLowerCase(); for (let i = 0; i < nodes.length; i++) { if (nodes[i].getAttribute("hidden") !== "true" && nodes[i].getAttribute("emailAddress").toLowerCase() === emailAddress) { EnigmailPEPAdapter.pep.getIdentityRating(person). then( function _gotRating(cbObj) { if ("result" in cbObj && Array.isArray(cbObj.result) && typeof(cbObj.result.outParams[0]) === "object") { if ("rating" in cbObj.result.outParams[0]) { let rating = EnigmailPEPAdapter.calculateColorFromRating(cbObj.result.outParams[0].rating); let setClass = EnigmailPEPAdapter.getRatingClass(cbObj.result.outParams[0].rating); nodes[i].setAttribute("class", setClass); Enigmail.hdrView.pEpStatus.emailRatings[emailAddress] = rating; } } }). catch(function _err() {}); } } }, displayPepIdentities: function(persons) { if ("from" in persons && persons.from) { this.displayPepEmailRating(gExpandedHeaderView.from.textNode, persons.from); } if ("to" in persons && persons.to) { for (let p of persons.to) { this.displayPepEmailRating(gExpandedHeaderView.to.textNode, p); } } if ("cc" in persons && persons.cc) { for (let p of persons.cc) { this.displayPepEmailRating(gExpandedHeaderView.cc.textNode, p); } } if ("reply_to" in persons && persons.reply_to) { for (let p of persons.reply_to) { this.displayPepEmailRating(gExpandedHeaderView["reply-to"].textNode, p); } } }, pEpIconPopup: function() { // let rating = this.pEpStatus.rating; let addrs = ""; if ("from" in currentHeaderData) { addrs = currentHeaderData.from.headerValue; } if ("to" in currentHeaderData) { addrs += "," + currentHeaderData.to.headerValue; } if ("cc" in currentHeaderData) { addrs += "," + currentHeaderData.cc.headerValue; } if ("bcc" in currentHeaderData) { addrs += "," + currentHeaderData.bcc.headerValue; } let emailsInMessage = EnigmailFuncs.stripEmail(addrs).toLowerCase().split(/,/); if (emailsInMessage.length === 0) { EnigmailDialog.info(window, EnigmailLocale.getString("handshakeDlg.error.noPeers")); return; } EnigmailPEPAdapter.pep.getOwnIdentities().then(function _gotOwnIds(data) { if (("result" in data) && typeof data.result.outParams[0] === "object" && Array.isArray(data.result.outParams[0])) { let ownIds = data.result.outParams[0]; let myEmail = ""; for (let i = 0; i < ownIds.length; i++) { for (let j = 0; j < emailsInMessage.length; j++) { if (ownIds[i].address.toLowerCase() === emailsInMessage[j]) { myEmail = ownIds[i].address; break; } } } let inputObj = { myself: myEmail, addresses: emailsInMessage, direction: 0, parentWindow: window, onComplete: Enigmail.msg.reloadCompleteMsg.bind(Enigmail.msg) }; window.openDialog("chrome://enigmail/content/pepPrepHandshake.xul", "", "dialog,modal,centerscreen", inputObj); } }); }, enablePepMenus: function() { if (EnigmailPEPAdapter.usingPep()) { document.getElementById("enigmailCreateRuleFromAddr").setAttribute("collapsed", "true"); } else { document.getElementById("enigmailCreateRuleFromAddr").removeAttribute("collapsed"); document.getElementById("enigmailVerifyPepStatus").setAttribute("collapsed", "true"); document.getElementById("enigmailRevokePepStatus").setAttribute("collapsed", "true"); } }, setPepVerifyFunction: function(addressNode) { let emailAddress = addressNode.getAttribute("emailAddress").toLowerCase(); if (Enigmail.hdrView.pEpStatus.emailRatings[emailAddress]) { let idColor = Enigmail.hdrView.pEpStatus.emailRatings[emailAddress]; if (idColor === "green") { document.getElementById("enigmailRevokePepStatus").removeAttribute("collapsed"); document.getElementById("enigmailVerifyPepStatus").setAttribute("collapsed", "true"); } else { document.getElementById("enigmailVerifyPepStatus").removeAttribute("collapsed"); document.getElementById("enigmailRevokePepStatus").setAttribute("collapsed", "true"); } } else { document.getElementById("enigmailVerifyPepStatus").setAttribute("collapsed", "true"); document.getElementById("enigmailRevokePepStatus").setAttribute("collapsed", "true"); } }, verifyPepTrustWords: function(emailAddressNode) { if (emailAddressNode) { if (typeof(findEmailNodeFromPopupNode) == "function") { emailAddressNode = findEmailNodeFromPopupNode(emailAddressNode, 'emailAddressPopup'); } let emailAddr = emailAddressNode.getAttribute("emailAddress"); EnigmailWindows.verifyPepTrustWords(window, emailAddr, currentHeaderData). then(function _done() { gDBView.reloadMessageWithAllParts(); }). catch(function _err() {}); } }, revokePepTrust: function(emailAddressNode) { if (emailAddressNode) { if (typeof(findEmailNodeFromPopupNode) == "function") { emailAddressNode = findEmailNodeFromPopupNode(emailAddressNode, 'emailAddressPopup'); } let emailAddr = emailAddressNode.getAttribute("emailAddress"); if (EnigmailDialog.confirmDlg(window, EnigmailLocale.getString("pepRevokeTrust.question", emailAddr), EnigmailLocale.getString("pepRevokeTrust.doRevoke"), EnigmailLocale.getString("dlg.button.close"))) { EnigmailPEPAdapter.resetTrustForEmail(emailAddr). then(function _done() { gDBView.reloadMessageWithAllParts(); }). catch(function _err() {}); } } } }; window.addEventListener("load", Enigmail.hdrView.hdrViewLoad.bind(Enigmail.hdrView), false); addEventListener('messagepane-loaded', Enigmail.hdrView.msgHdrViewLoad.bind(Enigmail.hdrView), true); addEventListener('messagepane-unloaded', Enigmail.hdrView.hdrViewUnload.bind(Enigmail.hdrView), true); addEventListener('messagepane-hide', Enigmail.hdrView.msgHdrViewHide.bind(Enigmail.hdrView), true); addEventListener('messagepane-unhide', Enigmail.hdrView.msgHdrViewUnhide.bind(Enigmail.hdrView), true); //////////////////////////////////////////////////////////////////////////////// // THE FOLLOWING OVERRIDES CODE IN msgHdrViewOverlay.js //////////////////////////////////////////////////////////////////////////////// // there is unfortunately no other way to add Enigmail to the validator than this function CanDetachAttachments() { var canDetach = !gFolderDisplay.selectedMessageIsNews && (!gFolderDisplay.selectedMessageIsImap || MailOfflineMgr.isOnline()); if (canDetach && ("content-type" in currentHeaderData)) { var contentType = currentHeaderData["content-type"].headerValue; canDetach = !ContentTypeIsSMIME(currentHeaderData["content-type"].headerValue); } return canDetach && Enigmail.hdrView.enigCanDetachAttachments(); } //////////////////////////////////////////////////////////////////////////////// // THE FOLLOWING EXTENDS CODE IN msgHdrViewOverlay.js //////////////////////////////////////////////////////////////////////////////// if (messageHeaderSink) { messageHeaderSink.enigmailPrepSecurityInfo = function() { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: enigmailPrepSecurityInfo\n"); /// BEGIN EnigMimeHeaderSink definition function EnigMimeHeaderSink(innerSMIMEHeaderSink) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: EnigMimeHeaderSink.innerSMIMEHeaderSink=" + innerSMIMEHeaderSink + "\n"); this._smimeHeaderSink = innerSMIMEHeaderSink; } EnigMimeHeaderSink.prototype = { _smimeHeaderSink: null, QueryInterface: function(iid) { //EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: EnigMimeHeaderSink.QI: "+iid+"\n"); if (iid.equals(Components.interfaces.nsIMsgSMIMEHeaderSink) && this._smimeHeaderSink) return this; if (iid.equals(Components.interfaces.nsIEnigMimeHeaderSink) || iid.equals(Components.interfaces.nsISupports)) return this; throw Components.results.NS_NOINTERFACE; }, /** * Determine message number and folder from mailnews URI * * @param url - nsIURI object * * @return Object: * - msgNum: String - the message number, or "" if no URI Scheme fits * - folder: String - the folder (or newsgroup) name */ msgIdentificationFromUrl: function(url) { // sample URLs in Thunderbird // Local folder: mailbox:///some/path/to/folder?number=359360 // IMAP: imap://user@host:port/fetch>some>path>111 // NNTP: news://some.host/some.service.com?group=some.group.name&key=3510 // also seen: e.g. mailbox:///som/path/to/folder?number=4455522&part=1.1.2&filename=test.eml // mailbox:///...?number=4455522&part=1.1.2&filename=test.eml&type=application/x-message-display&filename=test.eml // imap://user@host:port>UID>some>path>10?header=filter&emitter=js&examineEncryptedParts=true EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: msgIdentificationFromUrl: url.path=" + url.path + "\n"); let msgNum = ""; let msgFolder = ""; if (url.schemeIs("mailbox")) { msgNum = url.path.replace(/(.*[?&]number=)([0-9]+)([^0-9].*)?/, "$2"); msgFolder = url.path.replace(/\?.*/, ""); } else if (url.schemeIs("imap")) { let p = unescape(url.path); msgNum = p.replace(/(.*>)([0-9]+)([^0-9].*)?/, "$2"); msgFolder = p.replace(/\?.*$/, "").replace(/>[^>]+$/, ""); } else if (url.schemeIs("news")) { msgNum = url.path.replace(/(.*[\?&]key=)([0-9]+)([^0-9].*)?/, "$2"); msgFolder = url.path.replace(/(.*[\?&]group=)([^&]+)(&.*)?/, "$2"); } EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: msgIdentificationFromUrl: msgNum=" + msgNum + " / folder=" + msgFolder + "\n"); return { msgNum: msgNum, folder: msgFolder.toLowerCase() }; }, isCurrentMessage: function(uri) { let uriSpec = (uri ? uri.spec : null); EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: EnigMimeHeaderSink.isCurrentMessage: uri.spec=" + uriSpec + "\n"); if (!uriSpec || uriSpec.search(/^enigmail:/) === 0) { // we cannot compare if no URI given or if URI is Enigmail-internal; // therefore assuming it's the current message return true; } let msgUriSpec = Enigmail.msg.getCurrentMsgUriSpec(); let currUrl = {}; try { let messenger = Components.classes["@mozilla.org/messenger;1"].getService(Components.interfaces.nsIMessenger); let msgSvc = messenger.messageServiceFromURI(msgUriSpec); msgSvc.GetUrlForUri(msgUriSpec, currUrl, null); } catch (ex) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: EnigMimeHeaderSink.isCurrentMessage: could not determine URL\n"); currUrl.value = { host: "invalid", path: "/message", scheme: "enigmail", spec: "enigmail://invalid/message", schemeIs: function(s) { return s === this.scheme; } }; } let currMsgId = this.msgIdentificationFromUrl(currUrl.value); let gotMsgId = this.msgIdentificationFromUrl(uri); EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: EnigMimeHeaderSink.isCurrentMessage: url=" + currUrl.value.spec + "\n"); if (uri.host == currUrl.value.host && currMsgId.folder === gotMsgId.folder && currMsgId.msgNum === gotMsgId.msgNum) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: EnigMimeHeaderSink.isCurrentMessage: true\n"); return true; } EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: EnigMimeHeaderSink.isCurrentMessage: false\n"); return false; }, /** * Determine if a given mime part number should be displayed. * Returns true if one of these conditions is true: * - this is the 1st crypto-mime part * - the mime part is earlier in the mime tree * - the mime part is the 1st child of an already displayed mime part */ displaySubPart: function(mimePartNumber) { if (!mimePartNumber) return true; let securityInfo = Enigmail.msg.securityInfo; if (mimePartNumber.length > 0 && securityInfo && securityInfo.encryptedMimePart && securityInfo.encryptedMimePart.length > 0) { let c = EnigmailFuncs.compareMimePartLevel(securityInfo.encryptedMimePart, mimePartNumber); if (c === -1) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: displaySubPart: MIME part after already processed part\n"); return false; } if (c === -2 && mimePartNumber !== securityInfo.encryptedMimePart + ".1") { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: displaySubPart: MIME part not 1st child of parent\n"); return false; } } return true; }, updateSecurityStatus: function(unusedUriSpec, exitCode, statusFlags, keyId, userId, sigDetails, errorMsg, blockSeparation, uri, extraDetails, mimePartNumber) { // uriSpec is not used for Enigmail anymore. It is here becaue other addons and pEp rely on it EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: updateSecurityStatus: mimePart=" + mimePartNumber + "\n"); let uriSpec = (uri ? uri.spec : null); if (this.isCurrentMessage(uri)) { if (!this.displaySubPart(mimePartNumber)) return; let encToDetails = ""; if (extraDetails && extraDetails.length > 0) { try { let o = JSON.parse(extraDetails); if ("encryptedTo" in o) { encToDetails = o.encryptedTo; } } catch (x) {} } Enigmail.hdrView.updateHdrIcons(exitCode, statusFlags, keyId, userId, sigDetails, errorMsg, blockSeparation, encToDetails, null, mimePartNumber); } if (uriSpec && uriSpec.search(/^enigmail:message\//) === 0) { // display header for broken MS-Exchange message let ebeb = document.getElementById("enigmailBrokenExchangeBox"); ebeb.removeAttribute("collapsed"); } return; }, processDecryptionResult: function(uri, actionType, processData, mimePartNumber) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: EnigMimeHeaderSink.processDecryptionResult:\n"); EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: actionType= " + actionType + ", mimePart=" + mimePartNumber + "\n"); let msg = gFolderDisplay.selectedMessage; if (!msg) return; if (!this.isCurrentMessage(uri) || gFolderDisplay.selectedMessages.length !== 1) return; switch (actionType) { case "modifyMessageHeaders": this.modifyMessageHeaders(uri, processData, mimePartNumber); return; case "wksConfirmRequest": Enigmail.hdrView.checkWksConfirmRequest(processData); return; case "displayPepStatus": try { let o = JSON.parse(processData); Enigmail.hdrView.displayPepStatus(o.rating, o.fpr, uri, o.persons); } catch (x) {} return; } }, modifyMessageHeaders: function(uri, headerData, mimePartNumber) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: EnigMimeHeaderSink.modifyMessageHeaders:\n"); let updateHdrBox = Enigmail.hdrView.updateHdrBox; let hdr; try { hdr = JSON.parse(headerData); } catch (ex) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: modifyMessageHeaders: - no headers to display\n"); return; } if (typeof(hdr) !== "object") return; if (!this.displaySubPart(mimePartNumber)) return; let msg = gFolderDisplay.selectedMessage; if ("subject" in hdr) { Enigmail.hdrView.setSubject(hdr.subject); } if ("date" in hdr) { msg.date = Date.parse(hdr.date) * 1000; } if ("newsgroups" in hdr) { updateHdrBox("newsgroups", hdr.newsgroups); } if ("followup-to" in hdr) { updateHdrBox("followup-to", hdr["followup-to"]); } if ("from" in hdr) { gExpandedHeaderView.from.outputFunction(gExpandedHeaderView.from, hdr.from); msg.setStringProperty("Enigmail-From", hdr.from); } if ("to" in hdr) { gExpandedHeaderView.to.outputFunction(gExpandedHeaderView.to, hdr.to); msg.setStringProperty("Enigmail-To", hdr.to); } if ("cc" in hdr) { gExpandedHeaderView.cc.outputFunction(gExpandedHeaderView.cc, hdr.cc); msg.setStringProperty("Enigmail-Cc", hdr.cc); } if ("reply-to" in hdr) { gExpandedHeaderView["reply-to"].outputFunction(gExpandedHeaderView["reply-to"], hdr["reply-to"]); msg.setStringProperty("Enigmail-ReplyTo", hdr["reply-to"]); } }, handleSMimeMessage: function(uri) { if (this.isCurrentMessage(uri)) { EnigmailVerify.unregisterContentTypeHandler(); Enigmail.msg.messageReload(false); } }, maxWantedNesting: function() { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: EnigMimeHeaderSink.maxWantedNesting:\n"); return this._smimeHeaderSink.maxWantedNesting(); }, signedStatus: function(aNestingLevel, aSignatureStatus, aSignerCert) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: EnigMimeHeaderSink.signedStatus:\n"); return this._smimeHeaderSink.signedStatus(aNestingLevel, aSignatureStatus, aSignerCert); }, encryptionStatus: function(aNestingLevel, aEncryptionStatus, aRecipientCert) { EnigmailLog.DEBUG("enigmailMsgHdrViewOverlay.js: EnigMimeHeaderSink.encryptionStatus:\n"); return this._smimeHeaderSink.encryptionStatus(aNestingLevel, aEncryptionStatus, aRecipientCert); } }; /// END EnigMimeHeaderSink definition var innerSMIMEHeaderSink = null; var enigmailHeaderSink = null; try { innerSMIMEHeaderSink = this.securityInfo.QueryInterface(Components.interfaces.nsIMsgSMIMEHeaderSink); try { enigmailHeaderSink = innerSMIMEHeaderSink.QueryInterface(Components.interfaces.nsIEnigMimeHeaderSink); } catch (ex) {} } catch (ex) {} if (!enigmailHeaderSink) { this.securityInfo = new EnigMimeHeaderSink(innerSMIMEHeaderSink); } }; } diff --git a/ui/locale/en-US/enigmail.properties b/ui/locale/en-US/enigmail.properties index 2fa878f1..d5e8fc90 100644 --- a/ui/locale/en-US/enigmail.properties +++ b/ui/locale/en-US/enigmail.properties @@ -1,749 +1,750 @@ Enigmail=Enigmail ##################################################################### # Strings used within enigmailCommon.js and enigmailCommon.jsm ##################################################################### enigAlert=Enigmail Alert enigConfirm=Enigmail Confirm enigInfo=Enigmail Information enigError=Enigmail Error enigPrompt=Enigmail Prompt dlgYes=&Yes dlgNo=&No dlgKeepSetting=Remember my answer and do not ask me again dlgNoPrompt=Do not show me this dialog again dlg.button.delete=&Delete dlg.button.cancel=&Cancel dlg.button.close=&Close dlg.button.continue=Con&tinue dlg.button.skip=&Skip dlg.button.overwrite=&Overwrite dlg.button.view=&View dlg.button.retry=&Retry dlg.button.ignore=&Ignore dlg.button.ok=&OK repeatPrefix=\n\nThis alert will repeat %S repeatSuffixSingular=more time. repeatSuffixPlural=more times. noRepeat=\n\nThis alert will not repeat until you upgrade Enigmail. pgpNotSupported=You seem to be using Enigmail together with PGP 6.x\n\nUnfortunately, PGP 6.x has a number of issues that prevent Enigmail from working correctly. Therefore, Enigmail does not support PGP 6.x anymore; please switch to GnuPG (GPG) instead.\n\nIf you need help on switching to GnuPG, check the Help section of the Enigmail homepage. initErr.howToFixIt=In order to use Enigmail, GnuPG is required. If you did not install GnuPG yet, the easiest way to do this is using the "Setup Wizard" button below. initErr.setupWizard.button=&Setup Wizard passphraseCleared=The passphrase has been cleared. cannotClearPassphrase=You are using a non-standard tool (such as gnome-keyring) for passphrase handling. Clearing the passphrase is therefore not possible from within Enigmail. noPhotoAvailable=No Photo available debugLog.title=Enigmail Debug Log error.photoPathNotReadable=Photo path '%S' is not readable generalError=Error: %S # Strings in configure.jsm enigmailCommon.versionSignificantlyChanged=This new version of Enigmail has significant changes in the handling of preferences and options. We tried to transfer the old settings to this new version. However, we cannot cover all cases automatically. Please double check the resulting new preferences and options. enigmailCommon.checkPreferences=Check Preferences ... preferences.defaultToPgpMime=We have changed the default message encoding in Enigmail from Inline-PGP to PGP/MIME. We recommend you keep this as default.\n\nIf you still wish to use Inline-PGP by default, you can do so in the Account Settings under OpenPGP Security. ##################################################################### # Strings in enigmailAbout.js ##################################################################### usingVersion=Running Enigmail version %S enigmailPepVersion=Enigmail/p≡p version %S usingAgent=Using %1$S executable %2$S to encrypt and decrypt agentError=ERROR: Failed to access Enigmail core service! ##################################################################### # Strings in enigmailKeygen.js ##################################################################### accessError=Error in accessing Enigmail service onlyGPG=Key generation only works with GnuPG (not with PGP)! keygenComplete=Key generation completed! Identity <%S> will be used for signing. revokeCertRecommended=We highly recommend to create a revocation certificate for your key. This certificate can be used to invalidate your key, e.g. in case your secret key gets lost or compromised. Do you want to create such a revocation certificate now? keyMan.button.generateCert=&Generate Certificate genCompleteNoSign=Key generation completed! genGoing=Key generation already in progress! passNoMatch=Passphrase entries do not match; please re-enter passCheckBox=Please check box if specifying no passphrase for key passUserName=Please specify user name for this identity keygen.missingUserName=There is no name specified for the selected account/identity. Please enter a value in the field "Your name" in the account settings. keygen.passCharProblem=You are using special characters in your passphrase. Unfortunately, this can cause troubles for other applications. We recommend you choose a passphrase consisting only of any of these characters:\na-z A-Z 0-9 /.;:-,!?(){}[]%* passSpaceProblem=Due to technical reasons, your passphrase may not start or end with a space character. changePassFailed=Changing the passphrase failed. keyConfirm=Generate public and private keys for '%S'? keyMan.button.generateKey=&Generate Key keyAbort=Abort key generation? keyMan.button.generateKeyAbort=&Abort Key Generation keyMan.button.generateKeyContinue=&Continue Key Generation expiryTooLong=You cannot create a key that expires in more than 100 years. expiryTooLongShorter=You cannot create a key that expires in more than 90 years. expiryTooShort=Your key must be valid for at least one day. dsaSizeLimit=DSA signing keys are limited to 3072 bits. The key size will be reduced accordingly. keyGenFailed=The key generation failed. Please check the Enigmail console (Menu Enigmail > Debugging Enigmail) for details. setKeyExpirationDateFailed=The expiration date could not be changed # Strings in enigmailMessengerOverlay.js securityInfo=Enigmail Security Info\n\n enigHeader=Enigmail: enigContentNote=Enigmail: *Attachments to this message have not been signed or encrypted*\r\n\r\n possiblyPgpMime=Possibly PGP/MIME encrypted or signed message; use 'Decrypt/Verify' function to verify noDecrypted=No decrypted message to save!\nUse Save command from File menu noMessage=No message to save! useButton=Please use 'Decrypt/Verify' function to decrypt message saveHeader=Enigmail: Save decrypted message saveAttachmentHeader=Enigmail: Save decrypted attachment noTempDir=Could not find a temporary directory to write to\nPlease set the TEMP environment variable attachmentPgpKey=The attachment '%S' you are opening appears to be an OpenPGP key file.\n\nClick 'Import' to import the keys contained or 'View' to view the file contents in a browser window beginPgpPart=********* *BEGIN ENCRYPTED or SIGNED PART* ********* endPgpPart=********** *END ENCRYPTED or SIGNED PART* ********** notePartEncrypted=Enigmail: *Parts of the message have NOT been signed or encrypted* noteCutMessage=Enigmail: *Multiple message blocks found -- decryption/verification aborted* decryptOkNoSig=Warning\n\nDecryption was successful, but the signature could not be verified correctly msgOvl.button.contAnyway=&Continue Anyway signature.verifiedOK=The signature for attachment %S was successfully verified signature.verifyFailed=The signature for attachment %S could not be verified attachment.noMatchToSignature=Could not match attachment '%S' to a signature file attachment.noMatchFromSignature=Could not match signature file '%S' to an attachment fixBrokenExchangeMsg.failed=Did not succeed to repair message. enigmail.msgViewColumn.label=Enigmail enigmailPep.msgViewColumn.label=Enigmail/p≡p wksNoIdentity=This key is not linked to any of your email accounts. Please add an account for at least one of the following email addresse(s):\n\n%S wksConfirmSuccess=Confirmation email sent. wksConfirmFailure=Sending the confirmation email failed. fileSaveError=Error in saving to file %S ##################################################################### # Strings in enigmailMsgComposeOverlay.js ##################################################################### keysToExport=Select OpenPGP Keys to Insert keysToUse=Select OpenPGP Key(s) to use for %S pubKey=Public key for %S\n windowLocked=Compose window is locked; send cancelled sendUnencrypted=Failed to initialize Enigmail.\nSend unencrypted message? composeSpecifyEmail=Please specify your primary email address, which will be used to choose the signing key for outgoing messages.\n If you leave it blank, the FROM address of the message will be used to choose the signing key. sendingHiddenRcpt=This message has BCC (blind copy) recipients. If this message is encrypted, it is possible to hide the BCC recipients but users of some products (e.g. PGP Corp.) will not be able to decrypt the message. Given this, we recommend to avoid BCC-emails with encrypted messages. sendWithHiddenBcc=Hide BCC recipients sendWithShownBcc=Encrypt normally sendingNews=Encrypted send operation aborted.\n\nThis message cannot be encrypted because there are newsgroup recipients. Please re-send the message without encryption. sendToNewsWarning=Warning: you are about to send an encrypted email to a newsgroup.\n\nThis is discouraged because it only makes sense if all members of the group can decrypt the message, i.e. the message needs to be encrypted with the keys of all group participants. Please send this message only if you know exactly what you are doing.\n\nContinue? hasHTML=HTML mail warning:\nThis message may contain HTML, which could cause signing/encryption to fail. To avoid this in the future, you should press the SHIFT key when clicking on the Compose/Reply button to send signed mail.\nIf you sign mail by default, you should uncheck the 'Compose Messages in HTML' preference box to permanently disable HTML mail for this mail account. strippingHTML=Message contains HTML formatting information that will be lost when converting to plain text for signing/encryption. Do you wish to proceed? msgCompose.button.sendAnyway=&Send Message Anyway attachWarning=Attachments to this message are not local, they cannot be encrypted. In order to encrypt the attachments, store them as local files first and attach these files. Do you wish to send the message anyway? quotedPrintableWarn=You have enabled 'quoted-printable' encoding for sending messages. This may result in incorrect decryption and/or verification of your message.\nDo you wish to turn off sending 'quoted-printable' messages now? minimalLineWrapping=You have set line wrapping to %S characters. For correct encryption and/or signing, this value needs to be at least 68.\nDo you wish to change line wrapping to 68 characters now? warning=Warning signIconClicked=You have manually modified signing. Therefore, while you are composing this message, (de)activating signing does not depend anymore on (de)activating encryption. errorOwnKeyUnusable=The key ID '%S' configured for the current identity does not yield a usable OpenPGP key.\n\nPlease ensure that you have a valid, not expired OpenPGP key and that your account settings point to that key.\nIf your key is not expired, then check if you did set Owner trust to full or ultimate. msgCompose.cannotSaveDraft=Error while saving draft msgCompose.internalEncryptionError=Internal Error: promised encryption disabled msgCompose.internalError=An internal error has occurred. msgCompose.toolbarTxt.signAndEncrypt=This message will be signed and encrypted msgCompose.toolbarTxt.signOnly=This message will be signed msgCompose.toolbarTxt.encryptOnly=This message will be encrypted msgCompose.toolbarTxt.noEncryption=This message will be unsigned and unencrypted msgCompose.toolbarTxt.disabled=Enigmail is disabled for the selected identity msgCompose.encryptedSubjectStub=Encrypted Message msgCompose.detailsButton.label=Details ... msgCompose.detailsButton.accessKey=D msgCompose.pepSendUnknown=Unknown msgCompose.pepSendUnsecure=Unsecure msgCompose.pepSendSecure=Secure msgCompose.pepSendTrusted=Secure & Trusted pep.alert.disabledForIdentity=p≡p is disabled for the current identity. Please enable p≡p via the Enigmail/p≡p preferences. +pep.alert.weakReply=Sending this mail will recude the security compared to when it was sent to you. # note: should end with double newline: sendAborted=Send operation aborted.\n\n # details: keyNotTrusted=Not enough trust for key '%S' keyNotFound=Key '%S' not found keyRevoked=Key '%S' revoked keyExpired=Key '%S' expired statPGPMIME=PGP/MIME statSMIME=S/MIME statSigned=SIGNED statEncrypted=ENCRYPTED statPlain=UNSIGNED and UNENCRYPTED offlineSave=Save %1$S message to %2$S in Unsent Messages folder? onlineSend=Send %1$S message to %2$S? encryptKeysNote=Note: The message is encrypted for the following User ID's / Keys: %S hiddenKey= signFailed=Error in Enigmail; Encryption/signing failed; send unencrypted message? msgCompose.button.sendUnencrypted=&Send Unencrypted Message recipientsSelectionHdr=Select Recipients for Encryption configureNow=You did not yet configure Enigmail security for the selected identity. Do you want to do this now? # encryption/signing status and associated reasons: encryptMessageAuto=Encrypt Message (auto) encryptMessageNorm=Encrypt Message signMessageAuto=Sign Message (auto) signMessageNorm=Sign Message encryptOff=Encryption: OFF encryptOnWithReason=Encryption: ON (%S) encryptOffWithReason=Encryption: OFF (%S) encryptOn=Encryption: ON signOn=Signing: ON signOff=Signing: OFF signOnWithReason=Signing: ON (%S) signOffWithReason=Signing: OFF (%S) reasonEnabledByDefault=enabled by default reasonManuallyForced=manually forced reasonByRecipientRules=forced by recipient rules reasonByAutoEncryption=forced by auto encryption reasonByConflict=due to conflict in recipient rules reasonByEncryptionMode=due to encryption mode # should not be used anymore: encryptYes=Message will be encrypted encryptNo=Message will not be encrypted # should not be used anymore: signYes=Message will be signed signNo=Message will not be signed # PGP/MIME status: pgpmimeNormal=Protocol: PGP/MIME inlinePGPNormal=Protocol: Inline PGP smimeNormal=Protocol: S/MIME pgpmimeAuto=Protocol: PGP/MIME (auto) inlinePGPAuto=Protocol: Inline PGP (auto) smimeAuto=Protocol: S/MIME (auto) # should not be used anymore pgpmimeYes=PGP/MIME will be used pgpmimeNo=Inline PGP will be used # Attach own key status (tooltip strings): attachOwnKeyNo=Your own key will not be attached attachOwnKeyYes=Your own key will be attached attachOwnKeyDisabled=Your own key cannot be attached. You have to select a specific key\nin the OpenPGP section of the Account Settings to enable this feature. rulesConflict=Conflicting per-recipient rules detected\n%S\n\nSend message with these settings? msgCompose.button.configure=&Configure msgCompose.button.send=&Send Message msgCompose.button.save=&Save Message # Strings in enigmailMsgHdrViewOverlay.js keyNeeded=Public key %S needed to verify signature keyUsed=Public key %S used to verify signature clickDecrypt=; use 'Decrypt/Verify' function clickDecryptRetry=; use 'Decrypt/Verify' function to retry clickDetailsButton=; click on 'Details' button for more information clickImportButton=; click on the 'Import Key' button to import the key keyTypeUnsupported=; the key type is not supported by your version of GnuPG msgPart=Part of the message %S msgSigned=signed msgSignedUnkownKey=signed with unknown key msgEncrypted=encrypted msgSignedAndEnc=signed and encrypted unverifiedSig=Unverified signature incompleteDecrypt=Decryption incomplete needKey=Error - no matching private/secret key found to decrypt message failedDecrypt=Error - decryption failed badPhrase=Error - bad passphrase failedDecryptVerify=Error - decryption/verification failed viewInfo=; View > Message security info for details decryptedMsg=Decrypted message decryptedMsgWithFormatError=Decrypted message (restored broken PGP email format probably caused by an old Exchange server, so that the result might not be perfect to read) usedAlgorithms=Used Algorithms: %1$S and %2$S pepStatusInfo.text=p≡p Message Status. pepStatusInfo.title.m3=Under Attack pepStatusInfo.info.m3=This message is not secure and has been tampered with. pepStatusInfo.title.m1=Mistrusted pepStatusInfo.info.m1=This message has a communication partner that has previously been marked as mistrusted pepStatusInfo.title.r0=Unknown pepStatusInfo.info.r0=This message does not contain enough information to determine if it is secure. pepStatusInfo.title.r1=Cannot Decrypt pepStatusInfo.info.r1=This message cannot be decrypted because the key is not available. pepStatusInfo.title.r2=Cannot Decrypt pepStatusInfo.info.r2=This message cannot be decrypted because the key is not available. pepStatusInfo.title.r3=Unsecure pepStatusInfo.info.r3=This message is unsecure. pepStatusInfo.title.r4=Unsecure for Some pepStatusInfo.info.r4=This message is unsecure for some communication partners. pepStatusInfo.title.r5=Unreliable Security pepStatusInfo.info.r5=This message has unreliable protection. pepStatusInfo.title.r6=Secure... pepStatusInfo.info.r6=This message is secure but you still need to verify the identity of your communication partner. pepStatusInfo.title.r7=Secure & Trusted pepStatusInfo.info.r7=This message is secure and trusted. pepStatusInfo.color.green=Green pepStatusInfo.color.yellow=Yellow pepStatusInfo.color.red=Red pepRevokeTrust.question=Do you really want to cancel the trust for %S? pepRevokeMistrust.question=Do you really want to re-trust the key for %S? pepRevokeTrust.doRevoke=Cancel &trust wksConfirmationReq=Webkey Directory Confirmation Request # strings in pref-enigmail.js oldGpgVersion20=Enigmail initialization failed.\n\nYou are using GnuPG version %1$S, which is not supported anymore. Enigmail requires GnuPG version %2$S or newer. Please upgrade your GnuPG installation, or Enigmail will not work. locateGpg=Locate GnuPG program invalidGpgPath=GnuPG cannot be executed with the path provided. Enigmail is therefore deactivated until you change the path to GnuPG again or until you restart the application. warningsAreReset=All warnings have been reset. prefs.gpgFound=GnuPG was found in %S prefs.gpgNotFound=Could not find GnuPG prefs.warnAskNever=Warning: activating this option will result in unencrypted emails without any further information if there is no key for one of the recipients -- Enigmail will not inform you if this happens! prefs.warnIdleTimeForUnknownAgent=Cannot connect to gpg-agent. Maybe your system uses a specialized tool for passphrase handling (e.g. gnome-keyring, seahorse-agent, KDE wallet manager, ...). Unfortunately Enigmail cannot control the passphrase timeout for the tool you are using. Therefore the respective timeout settings in Enigmail are disregarded. prefEnigmail.oneKeyserverOnly=Error - you can only specify one keyserver for automatic downloading of missing OpenPGP keys. # Strings used in components/enigmail.js # (said file also re-uses some strings from above) enterAdminPin=Please type in the ADMIN PIN of your SmartCard enterCardPin=Please type your SmartCard PIN notInit=Error - Enigmail service not yet initialized badCommand=Error - encryption command failed cmdLine=command line and output: notRequired=Error - no encryption required notComplete=Error - key generation not yet completed invalidEmail=Error - invalid email address(es) noPassphrase=Error - no passphrase supplied noPGPblock=Error - No valid armored OpenPGP data block found unverifiedReply=Indented message part (reply) was probably modified keyInMessageBody=Key in message body found. Click 'Import Key' to import the key sigMismatch=Error - Signature mismatch cantImport=Error in importing public key\n\n doImportOne=Import %1$S (%2$S)? doImportMultiple=Import the following keys?\n\n%S previewFailed=Can't read public key file. # Strings used in errorHandling.jsm sc.wrongCardAvailable=The SmartCard %1$S found in your reader cannot be used to process the message.\nPlease insert your SmartCard %2$S and repeat the operation. sc.insertCard=The operation requires your SmartCard %S.\nPlease insert the required SmartCard and repeat the operation. sc.removeCard=The operation requires no SmartCard to be in the reader.\nPlease remove your SmartCard and repeat the operation. sc.noCardAvailable=No SmartCard could be found in your reader\nPlease insert your SmartCard and repeat the operation. sc.noReaderAvailable=Your SmartCard reader could not be accessed\nPlease attach your SmartCard reader, insert your card, and repeat the operation. keyError.keySpecNotFound=The email address "%S" cannot be matched to a key on your keyring. keyError.keyIdNotFound=The configured key ID "%S" cannot be found on your keyring. keyError.resolutionAction=Please select a valid key in the OpenPGP section of your Account Settings. missingPassphrase=Missing passphrase errorHandling.gpgAgentInvalid=Your system is running a version of gpg-agent that is not suitable for your GnuPG version. errorHandling.gpgAgentError=GnuPG reported an error in the communication with gpg-agent (a component of GnuPG). errorHandling.dirmngrError=GnuPG reported an error in the communication with dirmngr (a component of GnuPG). errorHandling.pinentryError=GnuPG cannot query your passphrase via pinentry. errorHandling.readFaq=This is a system setup or configuration error that prevents Enigmail from working properly and cannot be fixed automatically.\n\nWe strongly recommend that you consult our support web site at https://enigmail.net/faq. gpgNotFound=Unable to locate GnuPG program '%S'.\nMake sure you have set the GnuPG executable path correctly in the Enigmail Preferences. gpgNotInPath=Unable to locate GnuPG executable in the PATH.\nMake sure you have set the GnuPG executable path correctly in the Enigmail Preferences. enigmailNotAvailable=Enigmail core Service not available gpgAgentNotStarted=Could not start the gpg-agent program which is needed for your GnuPG version %S. prefUntrusted=UNTRUSTED prefRevoked=REVOKED KEY prefExpiredKey=EXPIRED KEY prefExpired=EXPIRED prefGood=Good signature from %S prefBad=BAD signature from %S failCancel=Error - Key receive cancelled by user failNoServer=Error - No keyserver specified to receive key from failNoID=Error - No key ID specified to receive key for failKeyExtract=Error - key extraction command failed notFirstBlock=Error - First OpenPGP block not public key block importKeyConfirm=Import public key(s) embedded in message? failKeyImport=Error - key importing failed fileWriteFailed=Failed to write to file %S importKey=Import public key %S from keyserver: uploadKey=Send public key %S to keyserver: keyId=Key ID keyAndSigDate=Key ID: 0x%1$S / Signed on: %2$S keyFpr=Key fingerprint: %S noEmailProvided=You did not provide an email address! keyAlreadySigned=The key is already signed, you cannot sign it twice. ##################################################################### # Strings used in enigmailKeySelection.js ##################################################################### selKeyExpired=expired %S createdHeader=Created atLeastOneKey=No key selected! You have to select at least one key to accept this dialog fewerKeysThanRecipients=You have selected a smaller number of keys than recipients. Are you sure that the list of keys to encrypt is complete? userSel.button.goBack=Select more Keys userSel.secretKeySel.title=Select a Secret OpenPGP Key to Sign Your Messages userSel.problemNoKey=No valid key userSel.problemMultipleKeys=Multiple keys # should be same as thunderbird ENTITY sendLaterCmd.label: sendLaterCmd.label=Send Later # Strings used in enigmailAttachmentDialog.js pgpMimeNote=NOTE: PGP/MIME is only supported by a limited number of mail clients! On Windows only Mozilla/Thunderbird, Sylpheed, Pegasus and Mulberry are known to support this standard; on Linux/UNIX and Mac OS X most popular mail clients support it. If you are unsure, select the %S option. first=first second=second # Strings used in am-enigprefs.js encryptKeyHeader=Select OpenPGP Key for Encryption identityName=Identity: %S # Strings used in enigmailSingleRcptSettings.js noEncryption=You have activated encryption, but you did not select a key. In order to encrypt mails sent to %1$S, you need to specify one or several valid key(s) from your key list. Do you want to disable encryption for %2$S? noKeyToUse=(none - no encryption) noEmptyRule=The Rule may not be empty! Please set an email address in the Rule field. invalidAddress=The email address(es) you have entered are not valid. You should not set the names of the recipients, just the email addresses. E.g.:\nInvalid: Some Name \nValid: some.name@address.net noCurlyBrackets=The curly brackets {} have a special meaning and should not be used in the email addresses. If you want to modify the matching behavior for this rule, use the 'Apply rule if recipient ...' option.\nMore information is available from the Help button. # Strings used in enigmailRulesEditor.js never=Never always=Always possible=Possible deleteRule=Really delete the selected rule? nextRcpt=(Next recipient) negateRule=Not addKeyToRule=Add key %1$S (%2$S) to per-recipient rule # Strings used in enigmailSearchKey.js needOnline=The function you have selected is not available in offline mode. Please go online and try again. protocolNotSupported=The protocol '%S://' that you have selected is not supported for downloading OpenPGP keys. gpgkeysDisabled=It might help to enable the option 'extensions.enigmail.useGpgKeysTool'. noKeyserverConn=Could not connect to keyserver at %S. keyDownloadFailed=Failed to download key from keyserver. Status message is:\n%S internalError=An internal error occurred. The keys could not be downloaded or imported. noKeyFound=We are sorry, could not find any key that would match the specified search criteria. # gpgkeys_%S is one of the gpg command line tools gpgkeys_hkp, gpgkeys_ldap, etc. gpgKeysFailed=Failed to search or download key from keyserver: gpgkeys_%S could not be executed. # Strings in enigmailEditKeyTrustDlg.xul setKeyTrustFailed=Setting owner trust failed # Strings in enigmailSignKeyDlg.js signKeyFailed=Key signing failed alreadySigned.label=Note: the key %S is already signed with the selected private key. alreadySignedexportable.label=Note: the key %S is already signed exportable with the selected private key. A local signature does not make sense. partlySigned.label=Note: some user IDs of key %S are already signed with the selected private key. noTrustedOwnKeys=No eligible key found for signing! You need at least one fully trusted private key in order to sign keys. # Strings in enigmailKeyManager.js keyMan.loadingKeys=Loading keys, please wait ... keyValid.unknown=unknown keyValid.invalid=invalid keyValid.disabled=disabled keyValid.revoked=revoked keyValid.expired=expired keyValid.noSubkey=no valid subkey keyTrust.untrusted=untrusted keyTrust.marginal=marginal keyTrust.full=trusted keyTrust.ultimate=ultimate keyTrust.group=(group) keyType.public=pub keyType.publicAndSec=pub/sec keyMan.enableKey=Enable Key keyMan.disableKey=Disable Key userAtt.photo=User attribute (JPEG image) asciiArmorFile=ASCII Armored Files (*.asc) importKeyFile=Import OpenPGP Key File gnupgFile=GnuPG Files saveRevokeCertAs=Create & Save Revocation Certificate revokeCertOK=The revocation certificate has been successfully created. You can use it to invalidate your public key, e.g. in case you would lose your secret key.\n\nPlease transfer it to a medium which can be stored away safely such as a CD or USB stick. If somebody gains access to this certificate they can use it to render your key unusable. revokeCertFailed=The revocation certificate could not be created. addUidOK=User ID added successfully addUidFailed=Adding the User ID failed noKeySelected=You should select at least one key in order to perform the selected operation exportToFile=Export Public Key To File exportKeypairToFile=Export Secret and Public Key To File exportSecretKey=Do you want to include the secret key in the saved OpenPGP key file? saveKeysOK=The keys were successfully saved saveKeysFailed=Saving the keys failed importKeysFailed=Importing the keys failed enableKeyFailed=Enabling/disabling the keys failed specificPubKeyFilename=%1$S (0x%2$S) pub specificPubSecKeyFilename=%1$S (0x%2$S) pub-sec defaultPubKeyFilename=Exported-public-keys defaultPubSecKeyFilename=Exported-public-and-secret-keys noSecretKeys=No secret keys found.\n\nDo you want to generate your own key now? sendKeysOk=Key(s) sent successfully sendKeysFailed=Sending of keys failed receiveKeysOk=Key(s) updated successfully receiveKeysFailed=Downloading of keys failed importFromClip=Do you want to import some key(s) from clipboard? importFromUrl=Download public key from this URL: copyToClipbrdFailed=Could not copy the selected key(s) to the clipboard. copyToClipbrdOK=Key(s) copied to clipboard deleteSecretKey=WARNING: You are about to delete a secret key!\nIf you delete your secret key, you will no longer be able to decrypt any messages encrypted for that key, and you cannot revoke your key anymore.\n\nDo you really want to delete BOTH, the secret key and the public key\n'%S'? deleteMix=WARNING: You are about to delete secret keys!\nIf you delete your secret key, you will no longer be able to decrypt any messages encrypted for that key.\n\nDo you really want to delete BOTH, the selected secret and public keys? deletePubKey=Do you want to delete the public key\n'%S'? deleteSelectedPubKey=Do you want to delete the public keys? deleteKeyFailed=The key could not be deleted. revokeKeyQuestion=You are about to revoke the key '%S'.\n\nYou will no longer be able to sign with this key, and once distributed, others will no longer be able to encrypt with that key. You can still use the key to decrypt old messages.\n\nDo you want to proceed? revokeKeyOk=The key has been revoked. If your key is available on a key server, it is recommended to re-upload it, so that others can see the revocation. revokeKeyFailed=The key could not be revoked. revokeKeyNotPresent=You have no key (0x%S) which fits to this revocation certificate!\n\nIf you have lost your key, you must import it (e.g. from a keyserver) before the revocation certificate! revokeKeyAlreadyRevoked=The key 0x%S has already been revoked. refreshAllQuestion=You did not select any key. Would you like to refresh ALL keys? refreshKeyServiceOn.warn=Warning: Your keys are currently being refreshed in the background as safely as possible.\nRefreshing all your keys at once will unnecessarily reveal information about you.\nDo you really want to do this? refreshKey.warn=Warning: depending on the number of keys and the connection speed, refreshing all keys could be quite a lengthy process! downloadContactsKeys.warn=Warning: depending on the number of contacts and the connection speed, downloading all keys could be quite a lengthy process! downloadContactsKeys.importFrom=Import contacts from address book '%S'? keyMan.button.exportSecKey=Export &Secret Keys keyMan.button.exportPubKey=Export &Public Keys Only keyMan.button.import=&Import keyMan.button.refreshAll=&Refresh All Keys keyMan.button.revokeKey=&Revoke Key keyMan.button.skip=&Skip Key keylist.noOtherUids=Has no other identities keylist.hasOtherUids=Also known as keylist.noPhotos=No photograph available keylist.hasPhotos=Photographs keyMan.addphoto.filepicker.title=Select photo to add keyMan.addphoto.warnLargeFile=The file you have chosen is larger than 25 kB.\nIt is not recommended to add very large files because the keys get very large by this. keyMan.addphoto.noJpegFile=The selected file does not appear to be a JPEG file. Please choose a different file. keyMan.addphoto.failed=The photo could not be added. noWksIdentity=The key %S does not have a WKS identity. keyman.addBlacklistKey.msg=Do you really want to stop pEp using the key "%1$S (%2$S)" for encrypting messages? keyman.removeBlacklistKey.msg=Do you want allow pEp to use key "%1$S (%2$S)" for future messages? keyman.addBlacklistKey.button=&Blacklist the key keyman.removeBlacklistKey.button=&Remove key from Blacklist # Strings in enigmailManageUidDlg.xul changePrimUidFailed=Changing the primary User ID failed changePrimUidOK=The primary user ID was changed successfully deleteUidFailed=Deleting the user ID %S failed deleteUidOK=User ID %S was deleted successfully revokeUidFailed=Revoking the user ID %S failed revokeUidOK=User ID %S was revoked successfully. If your key is available on a key server, it is recommended to re-upload it, so that others can see the revocation. revokeUidQuestion=Do you really want to revoke the user ID %S? deleteUidQuestion=Do you really want to delete the user ID %S?\n\nPlease note: if you have submitted your public key to a key server, deleting a user ID will not change anything. In this case you should use 'Revoke user ID'. # Strings in enigmailKeyImportInfo.xul importInfoTitle=SUCCESS! Keys imported importInfoSuccess=\u2705 importInfoBits=Bits importInfoCreated=Created importInfoFpr=Fingerprint importInfoDetails=(Details) importInfoNoKeys=No keys imported. # Strings in enigmailKeyDetailsDlg.xul keyTypePublic=public key keyTypePrimary=primary key keyTypeSubkey=subkey keyTypePair=key pair keyExpiryNever=never keyAlgorithm_1=RSA keyAlgorithm_2=RSA keyAlgorithm_3=RSA keyAlgorithm_16=ELG keyAlgorithm_17=DSA keyAlgorithm_18=ECDH keyAlgorithm_19=ECDSA keyAlgorithm_20=ELG keyAlgorithm_22=EDDSA keyUsageEncrypt=Encrypt keyUsageSign=Sign keyUsageCertify=Certify keyUsageAuthentication=Authentication keyDoesNotExpire=Key does not expire # Strings in enigmailGenCardKey.xul keygen.started=Please wait while the key is being generated .... keygen.completed=Key Generated. The new Key ID is: 0x%S keygen.keyBackup=The key is backed up as %S keygen.passRequired=Please specify a passphrase if you want to create a backup copy of your key outside your SmartCard. # Strings in enigmailSetCardPin.xul cardPin.processFailed=Failed to change PIN # Strings in enigRetrieveProgres.xul keyserverProgress.refreshing=Refreshing keys, please wait ... keyserverProgress.uploading=Uploading keys, please wait ... keyserverProgress.wksCheck=Checking provider for Webkey Service support ... keyserverProgress.noWks=Your provider does not support the Webkey Service keyserverProgress.wksUploadFailed=Could not upload your key to the Webkey Service keyserverProgress.wksUploadCompleted=Your public key was successfully submitted to your provider. You will receive an email to confirm that you initiated the upload. keyserverTitle.refreshing=Refresh Keys keyserverTitle.uploading=Key Upload # Strings in enigmailSetupWizard passphrase.min8keys=Your passphrase should contain at least 8 characters! setupWizard.reallyCancel=Do you really want to close the Enigmail Setup Wizard? setupWizard.invalidGpg=The file you specified is not a GnuPG executable. Please specify a different file. setupWizard.specifyFile=You need to at least specify a public key file in order to proceed. setupWizard.installFailed=It seems that the installation was not successful. Please either retry the installation, or install GnuPG manually and locate it using the Browse button. setupWizard.downloadForbidden=For your own security, we will not download GnuPG. Please visit http://www.gnupg.org/ in order to download GnuPG. setupWizard.downloadImpossible=We cannot download GnuPG currently. Please try later or visit http://www.gnupg.org/ in order to download GnuPG. setupWizard.hashSumError=The wizard could not verify the integrity of the downloaded file. The file may be broken or manipulated. Do you want to continue the installation anyway? setupWizard.importSettingsFile=Specify backup file to load from setupWizard.invalidSettingsFile=The specified file is not a correct Enigmail Settings backup file. setupWizard.gpgConfExists=The GnuPG config file already exists. Do you want to overwrite it with the one from your old installation? setupWizard.noGpgHomeDir=It appears that you configured a specificy %S to use for GnuPG. However, this is not a directory - you cannot use it. setupWizard.unmachtedIds=The following identities of your old setup could not be matched:\n%S\nThe settings for these identities were skipped. # Strings in installGnuPG.jsm installGnuPG.downloadFailed=An error occurred while trying to download GnuPG. Please check the console log for further details. installGnuPG.installFailed=An error occurred while installing GnuPG. Please check the console log for further details. # Strings in enigmailAddUidDlg.xul addUidDlg.nameOrEmailError=You have to fill in a name and an email address addUidDlg.nameMinLengthError=The name must at least have 5 characters addUidDlg.invalidEmailError=You must specify a valid email address # Strings in enigmailCardDetails.js Carddetails.NoASCII=OpenPGP Smartcards only support ASCII characters in Firstname/Name. # network error types errorType.SecurityCertificate=The security certificate presented by the web service is not valid. errorType.SecurityProtocol=The security protocol used by the web service is unknown. errorType.Network=A network error has occurred. # filter stuff filter.folderRequired=You must select a target folder. filter.decryptMove.label=Decrypt permanently (Enigmail) filter.decryptCopy.label=Create decrypted Copy (Enigmail) filter.decryptMove.warnExperimental=Warning - the filter action "Decrypt permanently" may lead to destroyed messages.\n\nWe strongly recommend that you first try the "Create decrypted Copy" filter, test the result carefully, and only start using this filter once you are satisified with the result. filter.tempPepFilterDesc=Temporary filter to store sent message unencrypted # strings in enigmailConvert.jsm converter.decryptBody.failed=Could not decrypt message with subject\n"%S".\nDo you want to retry with a different passphrase or do you want to skip the message? converter.decryptAtt.failed=Could not decrypt attachment "%1$S"\nof message with subject\n"%2$S".\nDo you want to retry with a different passphrase or do you want to skip the message? saveLogFile.title=Save Log File # strings in gpg.jsm unknownSigningAlg=Unknown signing algorithm (ID: %S) unknownHashAlg=Unknown cryptographic hash (ID: %S) # strings in keyRing.jsm keyring.photo=Photo keyRing.pubKeyRevoked=The key %1$S (key ID %2$S) is revoked. keyRing.pubKeyExpired=The key %1$S (key ID %2$S) has expired. keyRing.pubKeyNotForSigning=The key %1$S (key ID %2$S) cannot be used for signing. keyRing.pubKeyNotForEncryption=The key %1$S (key ID %2$S) cannot be used for encryption. keyRing.keyDisabled=The key %1$S (key ID %2$S) is disabled; it cannot be used. keyRing.keyNotTrusted=The key %1$S (key ID %2$S) is not trusted enough. Please set the trust level of your key to "ultimate" to use it for signing. keyRing.keyInvalid=The key %1$S (key ID %2$S) is not valid. Please consider verifying it correctly. Alternatively use "Convenient encryption settings". keyRing.signSubKeysRevoked=All signing-subkeys of key %1$S (key ID %2$S) are revoked. keyRing.signSubKeysExpired=All signing-subkeys of key %1$S (key ID %2$S) have expired. keyRing.signSubKeysUnusable=All signing-subkeys of key %1$S (key ID %2$S) are revoked, expired or otherwise unusable. keyRing.encSubKeysRevoked=All encryption subkeys of key %1$S (key ID %2$S) are revoked. keyRing.encSubKeysExpired=All encryption subkeys of key %1$S (key ID %2$S) have expired. keyRing.noSecretKey=You do not seem to have the secret key for %1$S (key ID %2$S) on your keyring; you cannot use the key for signing. keyRing.encSubKeysUnusable=All encryption subkeys of key %1$S (key ID %2$S) are revoked, expired or otherwise unusable. #strings in exportSettingsWizard.js cannotWriteToFile=Cannot save to file '%S'. Please select a different file. dataExportError=An error occurred during exporting your data. enigmailSettings=EnigmailSettings defaultBackupFileName=Enigmail-export specifyExportFile=Specify file name for exporting homedirParamNotSUpported=Additional params that configure paths such as --homedir and --keyring are not supported for exporting/restoring your settings. Please use alternative methods such as setting the environment variable GNUPGHOME. #strings in expiry.jsm expiry.keyExpiresSoon=Your key %1$S will expire in less than %2$S days.\n\nWe recommend that you create a new key pair and configure the corresponding accounts to use the new key. expiry.keysExpireSoon=The following of your keys will expire in less than %1$S days:\n%2$S. We recommend that you create new keys and configure your accounts to use the new keys. expiry.keyMissingOwnerTrust=Your secret key %S has missing trust.\n\nWe recommend that you set "You rely on certifications" to ultimate in key properties. expiry.keysMissingOwnerTrust=The following of your secret keys have missing trust.\n%S.\nWe recommend that you set "You rely on certifications" to ultimate in key properties. expiry.OpenKeyManager=Open Enigmail Key Management expiry.OpenKeyProperties=Open Key Properties #strings in pEpDecrypt.jsm pEpDecrypt.cannotDecrypt=This is an encrypted message. Unfortunately you don't have the private key to decrypt the message. #strings in gpgAgent.jsm gpghomedir.notexists=The directory '%S' containing your OpenPGP keys does not exist and cannot be created. gpghomedir.notwritable=The directory '%S' containing your OpenPGP keys is not writable. gpghomedir.notdirectory=The directory '%S' containing your OpenPGP keys is a file instead of a directory. gpghomedir.notusable=Please fix the directory permissions or change the location of your GnuPG "home" directory. GnuPG cannot work corretly otherwise. #strings in pepTrustWords.js pepTrustWords.cannotVerifyOwnId=Cannot verify p≡p Trustwords for own account. pepTrustWords.cannotFindKey=Cannot find key for %S. pepTrustWords.cannotStoreChange=Could not change trust for %S. pepTrustWords.generalFailure=Cannot obtain trustwords for %S. pepTrustWords.partnerFingerprint=Fingerprint for %S: #strings in mimeWkdHandler.jsm wkdMessage.body.req=Your email provider processed your request to upload your public key to the OpenPGP Web Key Directory.\n\nPlease click the confirmation button in the Enigmail header to complete the publishing of your public key. wkdMessage.body.process=This is an email related to the automatic processing to upload your public key to the OpenPGP Web Key Directory.\n\nYou do not need to take any manual action at this point. #strings in pepHandshake.js pepPrivacyStatus.RatingBrokenSuggestion=Either you or the sender should resend the message. pepPrivacyStatus.RatingHaveNoKeySuggestionOutgoing=If you composed this message, your key is not available. pepPrivacyStatus.RatingMistrustSuggestion=Re-establish the connection with your communication partner and try to complete another handshake. pepPrivacyStatus.RatingReliableSuggestion=Complete a handshake with your communication partner by exchanging trustwords in person or over the phone. A handshake is needed only once per partner and will ensure secure and trusted communication. pepPrivacyStatus.RatingTrustedSuggestion=No action needed! pepPrivacyStatus.RatingUndefinedSuggestionIncoming=Be aware this message may not be secure. pepPrivacyStatus.RatingUndefinedSuggestionOutgoing=Please add the necessary information. pepPrivacyStatus.RatingUnderAttackSuggestion=Separately verify the content of this message with your communication partner. pepPrivacyStatus.RatingUnencryptedForSomeSuggestion=Make sure the privacy status for each communication partner listed is at least secure. pepPrivacyStatus.RatingUnencryptedSuggestion=Please ask your communication partner to use an encryption solution or install p≡p. pepPrivacyStatus.RatingUnreliableSuggestion=This message has no reliable encryption or no signature. Ask your communication partner to upgrade their encryption solution or install p≡p. pepPrivacyStatus.RatingBrokenExplanation=This message has broken encryption or formatting. pepPrivacyStatus.RatingHaveNoKeyExplanation=This message cannot be decrypted because the key is not available. pepPrivacyStatus.RatingMistrustExplanation=This message has a communication partner that has previously been marked as mistrusted. pepPrivacyStatus.RatingReliableExplanation=This message is secure but you still need to verify the identity of your communication partner. pepPrivacyStatus.RatingTrustedExplanation=This message is secure and trusted. pepPrivacyStatus.RatingUndefinedExplanation=This message does not contain enough information to determine if it is secure. pepPrivacyStatus.RatingUnderAttackExplanation=This message is not secure and has been tampered with. pepPrivacyStatus.RatingUnencryptedExplanation=This message is unsecure. pepPrivacyStatus.RatingUnencryptedForSomeExplanation=This message is unsecure for some communication partners. pepPrivacyStatus.RatingUnreliableExplanation=This message has unreliable protection. pepPrivacyStatus.RatingBrokenText=Broken pepPrivacyStatus.RatingHaveNoKeyText=Cannot Decrypt pepPrivacyStatus.RatingMistrustText=Mistrusted pepPrivacyStatus.RatingReliableText=Secure pepPrivacyStatus.RatingTrustedText=Secure & Trusted pepPrivacyStatus.RatingUndefinedText=Unknown pepPrivacyStatus.RatingUnderAttackText=Under Attack pepPrivacyStatus.RatingUnencryptedForSomeText=Unsecure for Some pepPrivacyStatus.RatingUnencryptedText=Unsecure pepPrivacyStatus.RatingUnreliableText=Unreliable Security handshakeDlg.button.initHandshake=Handshake... handshakeDlg.button.stopTrust=Stop Trusting handshakeDlg.button.reTrust=Stop Mistrusting handshakeDlg.label.outgoingMessage=Outgoing message handshakeDlg.label.incomingMessage=Incoming message handshakeDlg.error.noPeers=Cannot handshake without any correspondents. handshakeDlg.error.noProtection=Please enable protection in order to use the Handshake function.