Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1

This commit is contained in:
Matt A. Tobin 2019-11-03 00:17:46 -04:00 • committed by Roy Tam
commit e400f4130a
1564 changed files with 510348 additions and 0 deletions

View file

@ -0,0 +1,478 @@
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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/. */
Components.utils.import("resource://gre/modules/Services.jsm");
var nsIX509CertDB = Components.interfaces.nsIX509CertDB;
var nsX509CertDBContractID = "@mozilla.org/security/x509certdb;1";
var nsIX509Cert = Components.interfaces.nsIX509Cert;
var email_recipient_cert_usage = 5;
var email_signing_cert_usage = 4;
var gIdentity;
var gPref = null;
var gEncryptionCertName = null;
var gHiddenEncryptionPolicy = null;
var gEncryptionChoices = null;
var gSignCertName = null;
var gSignMessages = null;
var gEncryptAlways = null;
var gNeverEncrypt = null;
var gBundle = null;
var gBrandBundle;
var gSmimePrefbranch;
var gEncryptionChoicesLocked;
var gSigningChoicesLocked;
var kEncryptionCertPref = "identity.encryption_cert_name";
var kSigningCertPref = "identity.signing_cert_name";
function onInit()
{
smimeInitializeFields();
}
function smimeInitializeFields()
{
// initialize all of our elements based on the current identity values....
gEncryptionCertName = document.getElementById(kEncryptionCertPref);
gHiddenEncryptionPolicy = document.getElementById("identity.encryptionpolicy");
gEncryptionChoices = document.getElementById("encryptionChoices");
gSignCertName = document.getElementById(kSigningCertPref);
gSignMessages = document.getElementById("identity.sign_mail");
gEncryptAlways = document.getElementById("encrypt_mail_always");
gNeverEncrypt = document.getElementById("encrypt_mail_never");
gBundle = document.getElementById("bundle_smime");
gBrandBundle = document.getElementById("bundle_brand");
gEncryptionChoicesLocked = false;
gSigningChoicesLocked = false;
if (!gIdentity) {
// The user is going to create a new identity.
// Set everything to default values.
// Do not take over the values from gAccount.defaultIdentity
// as the new identity is going to have a different mail address.
gEncryptionCertName.value = "";
gEncryptionCertName.nickname = "";
gEncryptionCertName.dbKey = "";
gSignCertName.value = "";
gSignCertName.nickname = "";
gSignCertName.dbKey = "";
gEncryptAlways.setAttribute("disabled", true);
gNeverEncrypt.setAttribute("disabled", true);
gSignMessages.setAttribute("disabled", true);
gSignMessages.checked = false;
gEncryptionChoices.value = 0;
}
else {
var certdb = Components.classes[nsX509CertDBContractID].getService(nsIX509CertDB);
var x509cert = null;
gEncryptionCertName.value = gIdentity.getUnicharAttribute("encryption_cert_name");
gEncryptionCertName.dbKey = gIdentity.getCharAttribute("encryption_cert_dbkey");
// If we succeed in looking up the certificate by the dbkey pref, then
// append the serial number " [...]" to the display value, and remember the
// nickname in a separate property.
try {
if (certdb && gEncryptionCertName.dbKey &&
(x509cert = certdb.findCertByDBKey(gEncryptionCertName.dbKey))) {
gEncryptionCertName.value = x509cert.nickname + " [" + x509cert.serialNumber + "]";
gEncryptionCertName.nickname = x509cert.nickname;
}
} catch(e) {}
gEncryptionChoices.value = gIdentity.getIntAttribute("encryptionpolicy");
if (!gEncryptionCertName.value) {
gEncryptAlways.setAttribute("disabled", true);
gNeverEncrypt.setAttribute("disabled", true);
}
else {
enableEncryptionControls(true);
}
gSignCertName.value = gIdentity.getUnicharAttribute("signing_cert_name");
gSignCertName.dbKey = gIdentity.getCharAttribute("signing_cert_dbkey");
x509cert = null;
// same procedure as with gEncryptionCertName (see above)
try {
if (certdb && gSignCertName.dbKey &&
(x509cert = certdb.findCertByDBKey(gSignCertName.dbKey))) {
gSignCertName.value = x509cert.nickname + " [" + x509cert.serialNumber + "]";
gSignCertName.nickname = x509cert.nickname;
}
} catch(e) {}
gSignMessages.checked = gIdentity.getBoolAttribute("sign_mail");
if (!gSignCertName.value)
{
gSignMessages.setAttribute("disabled", true);
}
else {
enableSigningControls(true);
}
}
// Always start with enabling signing and encryption cert select buttons.
// This will keep the visibility of buttons in a sane state as user
// jumps from security panel of one account to another.
enableCertSelectButtons();
// Disable all locked elements on the panel
if (gIdentity)
onLockPreference();
}
function onPreInit(account, accountValues)
{
gIdentity = account.defaultIdentity;
}
function onSave()
{
smimeSave();
}
function smimeSave()
{
// find out which radio for the encryption radio group is selected and set that on our hidden encryptionChoice pref....
var newValue = gEncryptionChoices.value;
gHiddenEncryptionPolicy.setAttribute('value', newValue);
gIdentity.setIntAttribute("encryptionpolicy", newValue);
gIdentity.setUnicharAttribute("encryption_cert_name",
gEncryptionCertName.nickname || gEncryptionCertName.value);
gIdentity.setCharAttribute("encryption_cert_dbkey", gEncryptionCertName.dbKey);
gIdentity.setBoolAttribute("sign_mail", gSignMessages.checked);
gIdentity.setUnicharAttribute("signing_cert_name",
gSignCertName.nickname || gSignCertName.value);
gIdentity.setCharAttribute("signing_cert_dbkey", gSignCertName.dbKey);
}
function smimeOnAcceptEditor()
{
try {
if (!onOk())
return false;
}
catch (ex) {}
smimeSave();
return true;
}
function onLockPreference()
{
var initPrefString = "mail.identity";
var finalPrefString;
var allPrefElements = [
{ prefstring:"signingCertSelectButton", id:"signingCertSelectButton"},
{ prefstring:"encryptionCertSelectButton", id:"encryptionCertSelectButton"},
{ prefstring:"sign_mail", id:"identity.sign_mail"},
{ prefstring:"encryptionpolicy", id:"encryptionChoices"}
];
finalPrefString = initPrefString + "." + gIdentity.key + ".";
gSmimePrefbranch = Services.prefs.getBranch(finalPrefString);
disableIfLocked( allPrefElements );
}
// Does the work of disabling an element given the array which contains xul id/prefstring pairs.
// Also saves the id/locked state in an array so that other areas of the code can avoid
// stomping on the disabled state indiscriminately.
function disableIfLocked( prefstrArray )
{
var i;
for (i=0; i<prefstrArray.length; i++) {
var id = prefstrArray[i].id;
var element = document.getElementById(id);
if (gSmimePrefbranch.prefIsLocked(prefstrArray[i].prefstring)) {
// If encryption choices radio group is locked, make sure the individual
// choices in the group are locked. Set a global (gEncryptionChoicesLocked)
// indicating the status so that locking can be maintained further.
if (id == "encryptionChoices") {
document.getElementById("encrypt_mail_never").setAttribute("disabled", "true");
document.getElementById("encrypt_mail_always").setAttribute("disabled", "true");
gEncryptionChoicesLocked = true;
}
// If option to sign mail is locked (with true/false set in config file), disable
// the corresponding checkbox and set a global (gSigningChoicesLocked) in order to
// honor the locking as user changes other elements on the panel.
if (id == "identity.sign_mail") {
document.getElementById("identity.sign_mail").setAttribute("disabled", "true");
gSigningChoicesLocked = true;
}
else {
element.setAttribute("disabled", "true");
if (id == "signingCertSelectButton") {
document.getElementById("signingCertClearButton").setAttribute("disabled", "true");
}
else if (id == "encryptionCertSelectButton") {
document.getElementById("encryptionCertClearButton").setAttribute("disabled", "true");
}
}
}
}
}
function alertUser(message)
{
Services.prompt.alert(window,
gBrandBundle.getString("brandShortName"),
message);
}
function askUser(message)
{
let button = Services.prompt.confirmEx(
window,
gBrandBundle.getString("brandShortName"),
message,
Services.prompt.STD_YES_NO_BUTTONS,
null,
null,
null,
null,
{});
// confirmEx returns button index:
return (button == 0);
}
function checkOtherCert(cert, pref, usage, msgNeedCertWantSame, msgWantSame, msgNeedCertWantToSelect, enabler)
{
var otherCertInfo = document.getElementById(pref);
if (!otherCertInfo)
return;
if (otherCertInfo.dbKey == cert.dbKey)
// all is fine, same cert is now selected for both purposes
return;
var certdb = Components.classes[nsX509CertDBContractID].getService(nsIX509CertDB);
if (!certdb)
return;
if (email_recipient_cert_usage == usage) {
matchingOtherCert = certdb.findEmailEncryptionCert(cert.nickname);
}
else if (email_signing_cert_usage == usage) {
matchingOtherCert = certdb.findEmailSigningCert(cert.nickname);
}
else
return;
var userWantsSameCert = false;
if (!otherCertInfo.value.length) {
if (matchingOtherCert && (matchingOtherCert.dbKey == cert.dbKey)) {
userWantsSameCert = askUser(gBundle.getString(msgNeedCertWantSame));
}
else {
if (askUser(gBundle.getString(msgNeedCertWantToSelect))) {
smimeSelectCert(pref);
}
}
}
else {
if (matchingOtherCert && (matchingOtherCert.dbKey == cert.dbKey)) {
userWantsSameCert = askUser(gBundle.getString(msgWantSame));
}
}
if (userWantsSameCert) {
otherCertInfo.value = cert.nickname + " [" + cert.serialNumber + "]";
otherCertInfo.nickname = cert.nickname;
otherCertInfo.dbKey = cert.dbKey;
enabler(true);
}
}
function smimeSelectCert(smime_cert)
{
var certInfo = document.getElementById(smime_cert);
if (!certInfo)
return;
var picker = Components.classes["@mozilla.org/user_cert_picker;1"]
.createInstance(Components.interfaces.nsIUserCertPicker);
var canceled = new Object;
var x509cert = 0;
var certUsage;
var selectEncryptionCert;
if (smime_cert == kEncryptionCertPref) {
selectEncryptionCert = true;
certUsage = email_recipient_cert_usage;
} else if (smime_cert == kSigningCertPref) {
selectEncryptionCert = false;
certUsage = email_signing_cert_usage;
}
try {
x509cert = picker.pickByUsage(window,
certInfo.value,
certUsage, // this is from enum SECCertUsage
false, true,
gIdentity.email,
canceled);
} catch(e) {
canceled.value = false;
x509cert = null;
}
if (!canceled.value) {
if (!x509cert) {
if (gIdentity.email) {
alertUser(gBundle.getFormattedString(selectEncryptionCert ?
"NoEncryptionCertForThisAddress" :
"NoSigningCertForThisAddress",
[ gIdentity.email ]));
} else {
alertUser(gBundle.getString(selectEncryptionCert ?
"NoEncryptionCert" : "NoSigningCert"));
}
}
else {
certInfo.removeAttribute("disabled");
certInfo.value = x509cert.nickname + " [" + x509cert.serialNumber + "]";
certInfo.nickname = x509cert.nickname;
certInfo.dbKey = x509cert.dbKey;
if (selectEncryptionCert) {
enableEncryptionControls(true);
checkOtherCert(x509cert,
kSigningCertPref, email_signing_cert_usage,
"signing_needCertWantSame",
"signing_wantSame",
"signing_needCertWantToSelect",
enableSigningControls);
} else {
enableSigningControls(true);
checkOtherCert(x509cert,
kEncryptionCertPref, email_recipient_cert_usage,
"encryption_needCertWantSame",
"encryption_wantSame",
"encryption_needCertWantToSelect",
enableEncryptionControls);
}
}
}
enableCertSelectButtons();
}
function enableEncryptionControls(do_enable)
{
if (gEncryptionChoicesLocked)
return;
if (do_enable) {
gEncryptAlways.removeAttribute("disabled");
gNeverEncrypt.removeAttribute("disabled");
gEncryptionCertName.removeAttribute("disabled");
}
else {
gEncryptAlways.setAttribute("disabled", "true");
gNeverEncrypt.setAttribute("disabled", "true");
gEncryptionCertName.setAttribute("disabled", "true");
gEncryptionChoices.value = 0;
}
}
function enableSigningControls(do_enable)
{
if (gSigningChoicesLocked)
return;
if (do_enable) {
gSignMessages.removeAttribute("disabled");
gSignCertName.removeAttribute("disabled");
}
else {
gSignMessages.setAttribute("disabled", "true");
gSignCertName.setAttribute("disabled", "true");
gSignMessages.checked = false;
}
}
function enableCertSelectButtons()
{
document.getElementById("signingCertSelectButton").removeAttribute("disabled");
if (document.getElementById('identity.signing_cert_name').value.length)
document.getElementById("signingCertClearButton").removeAttribute("disabled");
else
document.getElementById("signingCertClearButton").setAttribute("disabled", "true");
document.getElementById("encryptionCertSelectButton").removeAttribute("disabled");
if (document.getElementById('identity.encryption_cert_name').value.length)
document.getElementById("encryptionCertClearButton").removeAttribute("disabled");
else
document.getElementById("encryptionCertClearButton").setAttribute("disabled", "true");
}
function smimeClearCert(smime_cert)
{
var certInfo = document.getElementById(smime_cert);
if (!certInfo)
return;
certInfo.setAttribute("disabled", "true");
certInfo.value = "";
certInfo.nickname = "";
certInfo.dbKey = "";
if (smime_cert == kEncryptionCertPref) {
enableEncryptionControls(false);
} else if (smime_cert == kSigningCertPref) {
enableSigningControls(false);
}
enableCertSelectButtons();
}
function openCertManager()
{
// Check for an existing certManager window and focus it; it's not
// application modal.
let lastCertManager = Services.wm.getMostRecentWindow("mozilla:certmanager");
if (lastCertManager)
lastCertManager.focus();
else
window.openDialog("chrome://pippki/content/certManager.xul", "",
"centerscreen,resizable=yes,dialog=no");
}
function openDeviceManager()
{
// Check for an existing deviceManager window and focus it; it's not
// application modal.
let lastCertManager = Services.wm.getMostRecentWindow("mozilla:devicemanager");
if (lastCertManager)
lastCertManager.focus();
else
window.openDialog("chrome://pippki/content/device_manager.xul", "",
"centerscreen,resizable=yes,dialog=no");
}
function smimeOnLoadEditor()
{
smimeInitializeFields();
document.documentElement.setAttribute("ondialogaccept",
"return smimeOnAcceptEditor();");
}

View file

@ -0,0 +1,26 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css" type="text/css"?>
<?xul-overlay href="chrome://messenger/content/am-smimeOverlay.xul"?>
<!DOCTYPE page SYSTEM "chrome://messenger/locale/am-smime.dtd">
<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
class="color-dialog"
onload="parent.onPanelLoaded('am-smime.xul');"
ondialogaccept="smimeOnAcceptEditor();">
<vbox flex="1" style="overflow: auto;">
<script type="application/javascript" src="chrome://messenger/content/AccountManager.js"/>
<script type="application/javascript" src="chrome://messenger/content/am-smime.js"/>
<dialogheader title="&securityTitle.label;"/>
<vbox flex="1" id="smimeEditing"/>
</vbox>
</page>

View file

@ -0,0 +1,39 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css"
type="text/css"?>
<?xul-overlay href="chrome://messenger/content/am-smimeOverlay.xul"?>
<!DOCTYPE overlay SYSTEM "chrome://messenger/locale/am-smime.dtd">
<!--
This is the overlay that adds the SMIME configurator
to the identity editor of the account manager
-->
<overlay id="smimeAmIdEditOverlay"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://messenger/content/AccountManager.js"/>
<script type="application/javascript"
src="chrome://messenger/content/am-smime.js"/>
<tabs id="identitySettings">
<tab label="&securityTab.label;"/>
</tabs>
<tabpanels id="identityTabsPanels">
<vbox flex="1" name="smimeEditingContent" id="smimeEditing"/>
</tabpanels>
<script type="application/javascript">
<![CDATA[
window.addEventListener("load", smimeOnLoadEditor, false);
]]>
</script>
</overlay>

View file

@ -0,0 +1,102 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://messenger/skin/accountManage.css"
type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://messenger/locale/am-smime.dtd">
<overlay xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<vbox id="smimeEditing">
<stringbundleset>
<stringbundle id="bundle_smime" src="chrome://messenger/locale/am-smime.properties"/>
<stringbundle id="bundle_brand" src="chrome://branding/locale/brand.properties"/>
</stringbundleset>
<label hidden="true" wsm_persist="true" id="identity.encryptionpolicy"/>
<description>&securityHeading.label;</description>
<groupbox id="signing.titlebox">
<caption label="&signingGroupTitle.label;"/>
<label value="&signingCert.message;" control="identity.signing_cert_name"
prefstring="mail.identity.%identitykey%.encryptionpolicy"/>
<hbox align="center">
<textbox id="identity.signing_cert_name" wsm_persist="true" flex="1"
prefstring="mail.identity.%identitykey%.signing_cert_name"
readonly="true" disabled="true"/>
<button id="signingCertSelectButton"
label="&digitalSign.certificate.button;"
accesskey="&digitalSign.certificate.accesskey;"
oncommand="smimeSelectCert('identity.signing_cert_name')"/>
<button id="signingCertClearButton"
label="&digitalSign.certificate_clear.button;"
accesskey="&digitalSign.certificate_clear.accesskey;"
oncommand="smimeClearCert('identity.signing_cert_name')"/>
</hbox>
<separator class="thin"/>
<checkbox id="identity.sign_mail" wsm_persist="true"
prefstring="mail.identity.%identitykey%.sign_mail"
label="&signMessage.label;" accesskey="&signMessage.accesskey;"/>
</groupbox>
<groupbox id="encryption.titlebox">
<caption label="&encryptionGroupTitle.label;"/>
<label value="&encryptionCert.message;"
control="identity.encryption_cert_name"/>
<hbox align="center">
<textbox id="identity.encryption_cert_name" wsm_persist="true" flex="1"
prefstring="mail.identity.%identitykey%.encryption_cert_name"
readonly="true" disabled="true"/>
<button id="encryptionCertSelectButton"
label="&encryption.certificate.button;"
accesskey="&encryption.certificate.accesskey;"
oncommand="smimeSelectCert('identity.encryption_cert_name')"/>
<button id="encryptionCertClearButton"
label="&encryption.certificate_clear.button;"
accesskey="&encryption.certificate_clear.accesskey;"
oncommand="smimeClearCert('identity.encryption_cert_name')"/>
</hbox>
<separator class="thin"/>
<label value="&encryptionChoiceLabel.label;" control="encryptionChoices"/>
<radiogroup id="encryptionChoices">
<radio id="encrypt_mail_never" wsm_persist="true" value="0"
label="&neverEncrypt.label;"
accesskey="&neverEncrypt.accesskey;"/>
<radio id="encrypt_mail_always" wsm_persist="true" value="2"
label="&alwaysEncryptMessage.label;"
accesskey="&alwaysEncryptMessage.accesskey;"/>
</radiogroup>
</groupbox>
<!-- Certificate manager -->
<groupbox id="smimeCertificateManager" orient="horizontal">
<caption label="&certificates.label;"/>
<button id="openCertManagerButton" oncommand="openCertManager();"
label="&manageCerts2.label;" accesskey="&manageCerts2.accesskey;"
prefstring="security.disable_button.openCertManager"/>
<button id="openDeviceManagerButton" oncommand="openDeviceManager();"
label="&manageDevices.label;" accesskey="&manageDevices.accesskey;"
prefstring="security.disable_button.openDeviceManager"/>
</groupbox>
</vbox>
</overlay>

View file

@ -0,0 +1,265 @@
/* 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/. */
/* We expect the following arguments:
- pref name of LDAP directory to fetch from
- array with email addresses
Display modal dialog with message and stop button.
In onload, kick off binding to LDAP.
When bound, kick off the searches.
On finding certificates, import into permanent cert database.
When all searches are finished, close the dialog.
*/
Components.utils.import("resource://gre/modules/Services.jsm");
var nsIX509CertDB = Components.interfaces.nsIX509CertDB;
var nsX509CertDB = "@mozilla.org/security/x509certdb;1";
var CertAttribute = "usercertificate;binary";
var gEmailAddresses;
var gDirectoryPref;
var gLdapServerURL;
var gLdapConnection;
var gCertDB;
var gLdapOperation;
var gLogin;
function onLoad()
{
gDirectoryPref = window.arguments[0];
gEmailAddresses = window.arguments[1];
if (!gEmailAddresses.length)
{
window.close();
return;
}
setTimeout(search, 1);
}
function search()
{
// get the login to authenticate as, if there is one
try {
gLogin = Services.prefs.getComplexValue(gDirectoryPref + ".auth.dn", Components.interfaces.nsISupportsString).data;
} catch (ex) {
// if we don't have this pref, no big deal
}
try {
let url = Services.prefs.getCharPref(gDirectoryPref + ".uri");
gLdapServerURL = Services.io
.newURI(url, null, null).QueryInterface(Components.interfaces.nsILDAPURL);
gLdapConnection = Components.classes["@mozilla.org/network/ldap-connection;1"]
.createInstance().QueryInterface(Components.interfaces.nsILDAPConnection);
gLdapConnection.init(gLdapServerURL, gLogin, new boundListener(),
null, Components.interfaces.nsILDAPConnection.VERSION3);
} catch (ex) {
dump(ex);
dump(" exception creating ldap connection\n");
window.close();
}
}
function stopFetching()
{
if (gLdapOperation) {
try {
gLdapOperation.abandon();
}
catch (e) {
}
}
return true;
}
function importCert(ber_value)
{
if (!gCertDB) {
gCertDB = Components.classes[nsX509CertDB].getService(nsIX509CertDB);
}
var cert_length = new Object();
var cert_bytes = ber_value.get(cert_length);
if (cert_bytes) {
gCertDB.importEmailCertificate(cert_bytes, cert_length.value, null);
}
}
function getLDAPOperation()
{
gLdapOperation = Components.classes["@mozilla.org/network/ldap-operation;1"]
.createInstance().QueryInterface(Components.interfaces.nsILDAPOperation);
gLdapOperation.init(gLdapConnection,
new ldapMessageListener(),
null);
}
function getPassword()
{
// we only need a password if we are using credentials
if (gLogin)
{
let authPrompter = Services.ww.getNewAuthPrompter(window.QueryInterface(Components.interfaces.nsIDOMWindow));
let strBundle = document.getElementById('bundle_ldap');
let password = { value: "" };
// nsLDAPAutocompleteSession uses asciiHost instead of host for the prompt text, I think we should be
// consistent.
if (authPrompter.promptPassword(strBundle.getString("authPromptTitle"),
strBundle.getFormattedString("authPromptText", [gLdapServerURL.asciiHost]),
gLdapServerURL.spec,
authPrompter.SAVE_PASSWORD_PERMANENTLY,
password))
return password.value;
}
return null;
}
function kickOffBind()
{
try {
getLDAPOperation();
gLdapOperation.simpleBind(getPassword());
}
catch (e) {
window.close();
}
}
function kickOffSearch()
{
try {
var prefix1 = "";
var suffix1 = "";
var urlFilter = gLdapServerURL.filter;
if (urlFilter != null && urlFilter.length > 0 && urlFilter != "(objectclass=*)") {
if (urlFilter.startsWith('(')) {
prefix1 = "(&" + urlFilter;
}
else {
prefix1 = "(&(" + urlFilter + ")";
}
suffix1 = ")";
}
var prefix2 = "";
var suffix2 = "";
if (gEmailAddresses.length > 1) {
prefix2 = "(|";
suffix2 = ")";
}
var mailFilter = "";
for (var i = 0; i < gEmailAddresses.length; ++i) {
mailFilter += "(mail=" + gEmailAddresses[i] + ")";
}
var filter = prefix1 + prefix2 + mailFilter + suffix2 + suffix1;
var wanted_attributes = CertAttribute;
// Max search results =>
// Double number of email addresses, because each person might have
// multiple certificates listed. We expect at most two certificates,
// one for signing, one for encrypting.
// Maybe that number should be larger, to allow for deployments,
// where even more certs can be stored per user???
var maxEntriesWanted = gEmailAddresses.length * 2;
getLDAPOperation();
gLdapOperation.searchExt(gLdapServerURL.dn, gLdapServerURL.scope,
filter, wanted_attributes, 0, maxEntriesWanted);
}
catch (e) {
window.close();
}
}
function boundListener() {
}
boundListener.prototype.QueryInterface =
function(iid) {
if (iid.equals(Components.interfaces.nsISupports) ||
iid.equals(Components.interfaces.nsILDAPMessageListener))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
}
boundListener.prototype.onLDAPMessage =
function(aMessage) {
}
boundListener.prototype.onLDAPInit =
function(aConn, aStatus) {
kickOffBind();
}
function ldapMessageListener() {
}
ldapMessageListener.prototype.QueryInterface =
function(iid) {
if (iid.equals(Components.interfaces.nsISupports) ||
iid.equals(Components.interfaces.nsILDAPMessageListener))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
}
ldapMessageListener.prototype.onLDAPMessage =
function(aMessage) {
if (Components.interfaces.nsILDAPMessage.RES_SEARCH_RESULT == aMessage.type) {
window.close();
return;
}
if (Components.interfaces.nsILDAPMessage.RES_BIND == aMessage.type) {
if (Components.interfaces.nsILDAPErrors.SUCCESS != aMessage.errorCode) {
window.close();
}
else {
kickOffSearch();
}
return;
}
if (Components.interfaces.nsILDAPMessage.RES_SEARCH_ENTRY == aMessage.type) {
var outSize = new Object();
try {
var outBinValues = aMessage.getBinaryValues(CertAttribute, outSize);
var i;
for (i=0; i < outSize.value; ++i) {
importCert(outBinValues[i]);
}
}
catch (e) {
}
return;
}
}
ldapMessageListener.prototype.onLDAPInit =
function(aConn, aStatus) {
}

View file

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://messenger/skin/smime/certFetchingStatus.css" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://messenger-smime/locale/certFetchingStatus.dtd">
<dialog id="certFetchingStatus" title="&title.label;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
style="width: 50em;"
buttons="cancel"
buttonlabelcancel="&stop.label;"
ondialogcancel="return stopFetching();"
onload="onLoad();">
<stringbundle id="bundle_ldap" src="chrome://mozldap/locale/ldap.properties"/>
<script type="application/javascript" src="chrome://messenger-smime/content/certFetchingStatus.js"/>
<description>&info.message;</description>
</dialog>

View file

@ -0,0 +1,73 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* 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";
const nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
var dialogParams;
var itemCount = 0;
function onLoad()
{
dialogParams = window.arguments[0].QueryInterface(nsIDialogParamBlock);
var selectElement = document.getElementById("nicknames");
itemCount = dialogParams.GetInt(0);
var selIndex = dialogParams.GetInt(1);
if (selIndex < 0) {
selIndex = 0;
}
for (let i = 0; i < itemCount; i++) {
let menuItemNode = document.createElement("menuitem");
let nick = dialogParams.GetString(i);
menuItemNode.setAttribute("value", i);
menuItemNode.setAttribute("label", nick); // This is displayed.
selectElement.firstChild.appendChild(menuItemNode);
if (selIndex == i) {
selectElement.selectedItem = menuItemNode;
}
}
dialogParams.SetInt(0, 0); // Set cancel return value.
setDetails();
}
function setDetails()
{
let selItem = document.getElementById("nicknames").value;
if (selItem.length == 0) {
return;
}
let index = parseInt(selItem);
let details = dialogParams.GetString(index + itemCount);
document.getElementById("details").value = details;
}
function onCertSelected()
{
setDetails();
}
function doOK()
{
// Signal that the user accepted.
dialogParams.SetInt(0, 1);
// Signal the index of the selected cert in the list of cert nicknames
// provided.
let index = parseInt(document.getElementById("nicknames").value);
dialogParams.SetInt(1, index);
return true;
}
function doCancel()
{
dialogParams.SetInt(0, 0); // Signal that the user cancelled.
return true;
}

View file

@ -0,0 +1,38 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog [
<!ENTITY % amSMIMEDTD SYSTEM "chrome://messenger/locale/am-smime.dtd" >
%amSMIMEDTD;
]>
<dialog id="certPicker" title="&certPicker.title;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
style="width: 50em;"
buttons="accept,cancel"
ondialogaccept="return doOK();"
ondialogcancel="return doCancel();"
onload="onLoad();">
<script type="application/javascript"
src="chrome://messenger/content/certpicker.js"/>
<hbox align="center">
<broadcaster id="certSelected" oncommand="onCertSelected();"/>
<label id="pickerInfo" value="&certPicker.info;"/>
<!-- The items in this menulist must never be sorted,
but remain in the order filled by the application
-->
<menulist id="nicknames" observes="certSelected">
<menupopup/>
</menulist>
</hbox>
<separator class="thin"/>
<label value="&certPicker.detailsLabel;"/>
<textbox readonly="true" id="details" multiline="true"
style="height: 12em;" flex="1"/>
</dialog>

View file

@ -0,0 +1,357 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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/. */
Components.utils.import("resource://gre/modules/Services.jsm");
// Account encryption policy values:
// const kEncryptionPolicy_Never = 0;
// 'IfPossible' was used by ns4.
// const kEncryptionPolicy_IfPossible = 1;
var kEncryptionPolicy_Always = 2;
var gEncryptedURIService =
Components.classes["@mozilla.org/messenger-smime/smime-encrypted-uris-service;1"]
.getService(Components.interfaces.nsIEncryptedSMIMEURIsService);
var gNextSecurityButtonCommand = "";
var gSMFields = null;
var gEncryptOptionChanged;
var gSignOptionChanged;
function onComposerLoad()
{
// Are we already set up ? Or are the required fields missing ?
if (gSMFields || !gMsgCompose || !gMsgCompose.compFields)
return;
gMsgCompose.compFields.securityInfo = null;
gSMFields = Components.classes["@mozilla.org/messenger-smime/composefields;1"]
.createInstance(Components.interfaces.nsIMsgSMIMECompFields);
if (!gSMFields)
return;
gMsgCompose.compFields.securityInfo = gSMFields;
// Set up the intial security state.
gSMFields.requireEncryptMessage =
gCurrentIdentity.getIntAttribute("encryptionpolicy") == kEncryptionPolicy_Always;
if (!gSMFields.requireEncryptMessage &&
gEncryptedURIService &&
gEncryptedURIService.isEncrypted(gMsgCompose.originalMsgURI))
{
// Override encryption setting if original is known as encrypted.
gSMFields.requireEncryptMessage = true;
}
if (gSMFields.requireEncryptMessage)
setEncryptionUI();
else
setNoEncryptionUI();
gSMFields.signMessage = gCurrentIdentity.getBoolAttribute("sign_mail");
if (gSMFields.signMessage)
setSignatureUI();
else
setNoSignatureUI();
}
addEventListener("load", smimeComposeOnLoad, {capture: false, once: true});
// this function gets called multiple times
function smimeComposeOnLoad()
{
onComposerLoad();
top.controllers.appendController(SecurityController);
addEventListener("compose-from-changed", onComposerFromChanged, true);
addEventListener("compose-send-message", onComposerSendMessage, true);
addEventListener("unload", smimeComposeOnUnload, {capture: false, once: true});
}
function smimeComposeOnUnload()
{
removeEventListener("compose-from-changed", onComposerFromChanged, true);
removeEventListener("compose-send-message", onComposerSendMessage, true);
top.controllers.removeController(SecurityController);
}
function showNeedSetupInfo()
{
let compSmimeBundle = document.getElementById("bundle_comp_smime");
let brandBundle = document.getElementById("bundle_brand");
if (!compSmimeBundle || !brandBundle)
return;
let buttonPressed = Services.prompt.confirmEx(window,
brandBundle.getString("brandShortName"),
compSmimeBundle.getString("NeedSetup"),
Services.prompt.STD_YES_NO_BUTTONS, 0, 0, 0, null, {});
if (buttonPressed == 0)
openHelp("sign-encrypt", "chrome://communicator/locale/help/suitehelp.rdf");
}
function toggleEncryptMessage()
{
if (!gSMFields)
return;
gSMFields.requireEncryptMessage = !gSMFields.requireEncryptMessage;
if (gSMFields.requireEncryptMessage)
{
// Make sure we have a cert.
if (!gCurrentIdentity.getUnicharAttribute("encryption_cert_name"))
{
gSMFields.requireEncryptMessage = false;
showNeedSetupInfo();
return;
}
setEncryptionUI();
}
else
{
setNoEncryptionUI();
}
gEncryptOptionChanged = true;
}
function toggleSignMessage()
{
if (!gSMFields)
return;
gSMFields.signMessage = !gSMFields.signMessage;
if (gSMFields.signMessage) // make sure we have a cert name...
{
if (!gCurrentIdentity.getUnicharAttribute("signing_cert_name"))
{
gSMFields.signMessage = false;
showNeedSetupInfo();
return;
}
setSignatureUI();
}
else
{
setNoSignatureUI();
}
gSignOptionChanged = true;
}
function setSecuritySettings(menu_id)
{
if (!gSMFields)
return;
document.getElementById("menu_securityEncryptRequire" + menu_id)
.setAttribute("checked", gSMFields.requireEncryptMessage);
document.getElementById("menu_securitySign" + menu_id)
.setAttribute("checked", gSMFields.signMessage);
}
function setNextCommand(what)
{
gNextSecurityButtonCommand = what;
}
function doSecurityButton()
{
var what = gNextSecurityButtonCommand;
gNextSecurityButtonCommand = "";
switch (what)
{
case "encryptMessage":
toggleEncryptMessage();
break;
case "signMessage":
toggleSignMessage();
break;
case "show":
default:
showMessageComposeSecurityStatus();
}
}
function setNoSignatureUI()
{
top.document.getElementById("securityStatus").removeAttribute("signing");
top.document.getElementById("signing-status").collapsed = true;
}
function setSignatureUI()
{
top.document.getElementById("securityStatus").setAttribute("signing", "ok");
top.document.getElementById("signing-status").collapsed = false;
}
function setNoEncryptionUI()
{
top.document.getElementById("securityStatus").removeAttribute("crypto");
top.document.getElementById("encryption-status").collapsed = true;
}
function setEncryptionUI()
{
top.document.getElementById("securityStatus").setAttribute("crypto", "ok");
top.document.getElementById("encryption-status").collapsed = false;
}
function showMessageComposeSecurityStatus()
{
Recipients2CompFields(gMsgCompose.compFields);
window.openDialog(
"chrome://messenger-smime/content/msgCompSecurityInfo.xul",
"",
"chrome,modal,resizable,centerscreen",
{
compFields : gMsgCompose.compFields,
subject : GetMsgSubjectElement().value,
smFields : gSMFields,
isSigningCertAvailable :
gCurrentIdentity.getUnicharAttribute("signing_cert_name") != "",
isEncryptionCertAvailable :
gCurrentIdentity.getUnicharAttribute("encryption_cert_name") != "",
currentIdentity : gCurrentIdentity
}
);
}
var SecurityController =
{
supportsCommand: function(command)
{
switch (command)
{
case "cmd_viewSecurityStatus":
return true;
default:
return false;
}
},
isCommandEnabled: function(command)
{
switch (command)
{
case "cmd_viewSecurityStatus":
return true;
default:
return false;
}
}
};
function onComposerSendMessage()
{
let missingCount = new Object();
let emailAddresses = new Object();
try
{
if (!gMsgCompose.compFields.securityInfo.requireEncryptMessage)
return;
Components.classes["@mozilla.org/messenger-smime/smimejshelper;1"]
.createInstance(Components.interfaces.nsISMimeJSHelper)
.getNoCertAddresses(gMsgCompose.compFields,
missingCount,
emailAddresses);
}
catch (e)
{
return;
}
if (missingCount.value > 0)
{
// The rules here: If the current identity has a directoryServer set, then
// use that, otherwise, try the global preference instead.
let autocompleteDirectory;
// Does the current identity override the global preference?
if (gCurrentIdentity.overrideGlobalPref)
{
autocompleteDirectory = gCurrentIdentity.directoryServer;
}
else
{
// Try the global one
if (Services.prefs.getBoolPref("ldap_2.autoComplete.useDirectory"))
autocompleteDirectory =
Services.prefs.getCharPref("ldap_2.autoComplete.directoryServer");
}
if (autocompleteDirectory)
window.openDialog("chrome://messenger-smime/content/certFetchingStatus.xul",
"",
"chrome,modal,resizable,centerscreen",
autocompleteDirectory,
emailAddresses.value);
}
}
function onComposerFromChanged()
{
if (!gSMFields)
return;
var encryptionPolicy = gCurrentIdentity.getIntAttribute("encryptionpolicy");
var useEncryption = false;
if (!gEncryptOptionChanged)
{
// Encryption wasn't manually checked.
// Set up the encryption policy from the setting of the new identity.
// 0 == never, 1 == if possible (ns4), 2 == always encrypt.
useEncryption = (encryptionPolicy == kEncryptionPolicy_Always);
}
else
{
useEncryption = !!gCurrentIdentity.getUnicharAttribute("encryption_cert_name");
}
gSMFields.requireEncryptMessage = useEncryption;
if (useEncryption)
setEncryptionUI();
else
setNoEncryptionUI();
// - If signing is disabled, we will not turn it on automatically.
// - If signing is enabled, but the new account defaults to not sign, we will turn signing off.
var signMessage = gCurrentIdentity.getBoolAttribute("sign_mail");
var useSigning = false;
if (!gSignOptionChanged)
{
// Signing wasn't manually checked.
// Set up the signing policy from the setting of the new identity.
useSigning = signMessage;
}
else
{
useSigning = !!gCurrentIdentity.getUnicharAttribute("signing_cert_name");
}
gSMFields.signMessage = useSigning;
if (useSigning)
setSignatureUI();
else
setNoSignatureUI();
}

View file

@ -0,0 +1,85 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://messenger/skin/smime/msgCompSMIMEOverlay.css" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://messenger-smime/locale/msgCompSMIMEOverlay.dtd">
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://messenger-smime/content/msgCompSMIMEOverlay.js"/>
<window id="msgcomposeWindow">
<broadcaster id="securityStatus" crypto="" signing=""/>
<observes element="securityStatus" attribute="crypto" />
<observes element="securityStatus" attribute="signing" />
<stringbundle id="bundle_comp_smime" src="chrome://messenger-smime/locale/msgCompSMIMEOverlay.properties"/>
<stringbundle id="bundle_brand" src="chrome://branding/locale/brand.properties"/>
</window>
<menupopup id="optionsMenuPopup"
onpopupshowing="setSecuritySettings(1);">
<menuseparator id="smimeOptionsSeparator"/>
<menuitem id="menu_securityEncryptRequire1"
type="checkbox"
label="&menu_securityEncryptRequire.label;"
accesskey="&menu_securityEncryptRequire.accesskey;"
oncommand="toggleEncryptMessage();"/>
<menuitem id="menu_securitySign1"
type="checkbox"
label="&menu_securitySign.label;"
accesskey="&menu_securitySign.accesskey;"
oncommand="toggleSignMessage();"/>
</menupopup>
<toolbarpalette id="MsgComposeToolbarPalette">
<toolbarbutton id="button-security"
type="menu-button"
class="toolbarbutton-1"
label="&securityButton.label;"
tooltiptext="&securityButton.tooltip;"
oncommand="doSecurityButton();">
<menupopup onpopupshowing="setSecuritySettings(2);">
<menuitem id="menu_securityEncryptRequire2"
type="checkbox"
label="&menu_securityEncryptRequire.label;"
accesskey="&menu_securityEncryptRequire.accesskey;"
oncommand="setNextCommand('encryptMessage');"/>
<menuitem id="menu_securitySign2"
type="checkbox"
label="&menu_securitySign.label;"
accesskey="&menu_securitySign.accesskey;"
oncommand="setNextCommand('signMessage');"/>
<menuseparator id="smimeToolbarButtonSeparator"/>
<menuitem id="menu_securityStatus2"
label="&menu_securityStatus.label;"
accesskey="&menu_securityStatus.accesskey;"
oncommand="setNextCommand('show');"/>
</menupopup>
</toolbarbutton>
</toolbarpalette>
<statusbar id="status-bar">
<statusbarpanel insertbefore="offline-status" class="statusbarpanel-iconic" collapsed="true"
id="signing-status" oncommand="showMessageComposeSecurityStatus();"/>
<statusbarpanel insertbefore="offline-status" class="statusbarpanel-iconic" collapsed="true"
id="encryption-status" oncommand="showMessageComposeSecurityStatus();"/>
</statusbar>
<commandset id="composeCommands">
<command id="cmd_viewSecurityStatus" oncommand="showMessageComposeSecurityStatus();"/>
</commandset>
<menupopup id="menu_View_Popup">
<menuseparator id="viewMenuBeforeSecurityStatusSeparator"/>
<menuitem id="menu_viewSecurityStatus"
label="&menu_viewSecurityStatus.label;"
accesskey="&menu_viewSecurityStatus.accesskey;"
command="cmd_viewSecurityStatus"/>
</menupopup>
</overlay>

View file

@ -0,0 +1,244 @@
/* 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/. */
Components.utils.import("resource://gre/modules/Services.jsm");
var gListBox;
var gViewButton;
var gBundle;
var gEmailAddresses;
var gCertStatusSummaries;
var gCertIssuedInfos;
var gCertExpiresInfos;
var gCerts;
var gCount;
var gSMimeContractID = "@mozilla.org/messenger-smime/smimejshelper;1";
var gISMimeJSHelper = Components.interfaces.nsISMimeJSHelper;
var gIX509Cert = Components.interfaces.nsIX509Cert;
var nsICertificateDialogs = Components.interfaces.nsICertificateDialogs;
var nsCertificateDialogs = "@mozilla.org/nsCertificateDialogs;1"
function getStatusExplanation(value)
{
switch (value)
{
case gIX509Cert.VERIFIED_OK:
return gBundle.getString("StatusValid");
case gIX509Cert.NOT_VERIFIED_UNKNOWN:
case gIX509Cert.INVALID_CA:
case gIX509Cert.USAGE_NOT_ALLOWED:
return gBundle.getString("StatusInvalid");
case gIX509Cert.CERT_REVOKED:
return gBundle.getString("StatusRevoked");
case gIX509Cert.CERT_EXPIRED:
return gBundle.getString("StatusExpired");
case gIX509Cert.CERT_NOT_TRUSTED:
case gIX509Cert.ISSUER_NOT_TRUSTED:
case gIX509Cert.ISSUER_UNKNOWN:
return gBundle.getString("StatusUntrusted");
}
return "";
}
function onLoad()
{
var params = window.arguments[0];
if (!params)
return;
var helper = Components.classes[gSMimeContractID].createInstance(gISMimeJSHelper);
if (!helper)
return;
gListBox = document.getElementById("infolist");
gViewButton = document.getElementById("viewCertButton");
gBundle = document.getElementById("bundle_smime_comp_info");
gEmailAddresses = new Object();
gCertStatusSummaries = new Object();
gCertIssuedInfos = new Object();
gCertExpiresInfos = new Object();
gCerts = new Object();
gCount = new Object();
var canEncrypt = new Object();
var allow_ldap_cert_fetching = false;
try {
if (params.compFields.securityInfo.requireEncryptMessage) {
allow_ldap_cert_fetching = true;
}
}
catch (e)
{
}
while (true)
{
try
{
helper.getRecipientCertsInfo(
params.compFields,
gCount,
gEmailAddresses,
gCertStatusSummaries,
gCertIssuedInfos,
gCertExpiresInfos,
gCerts,
canEncrypt);
}
catch (e)
{
dump(e);
return;
}
if (!allow_ldap_cert_fetching)
break;
allow_ldap_cert_fetching = false;
var missing = new Array();
for (var j = gCount.value - 1; j >= 0; --j)
{
if (!gCerts.value[j])
{
missing[missing.length] = gEmailAddresses.value[j];
}
}
if (missing.length > 0)
{
var autocompleteLdap = Services.prefs
.getBoolPref("ldap_2.autoComplete.useDirectory");
if (autocompleteLdap)
{
var autocompleteDirectory = null;
if (params.currentIdentity.overrideGlobalPref) {
autocompleteDirectory = params.currentIdentity.directoryServer;
} else {
autocompleteDirectory = Services.prefs
.getCharPref("ldap_2.autoComplete.directoryServer");
}
if (autocompleteDirectory)
{
window.openDialog('chrome://messenger-smime/content/certFetchingStatus.xul',
'',
'chrome,resizable=1,modal=1,dialog=1',
autocompleteDirectory,
missing
);
}
}
}
}
if (gBundle)
{
var yes_string = gBundle.getString("StatusYes");
var no_string = gBundle.getString("StatusNo");
var not_possible_string = gBundle.getString("StatusNotPossible");
var signed_element = document.getElementById("signed");
var encrypted_element = document.getElementById("encrypted");
if (params.smFields.requireEncryptMessage)
{
if (params.isEncryptionCertAvailable && canEncrypt.value)
{
encrypted_element.value = yes_string;
}
else
{
encrypted_element.value = not_possible_string;
}
}
else
{
encrypted_element.value = no_string;
}
if (params.smFields.signMessage)
{
if (params.isSigningCertAvailable)
{
signed_element.value = yes_string;
}
else
{
signed_element.value = not_possible_string;
}
}
else
{
signed_element.value = no_string;
}
}
var imax = gCount.value;
for (var i = 0; i < imax; ++i)
{
var listitem = document.createElement("listitem");
listitem.appendChild(createCell(gEmailAddresses.value[i]));
if (!gCerts.value[i])
{
listitem.appendChild(createCell(gBundle.getString("StatusNotFound")));
}
else
{
listitem.appendChild(createCell(getStatusExplanation(gCertStatusSummaries.value[i])));
listitem.appendChild(createCell(gCertIssuedInfos.value[i]));
listitem.appendChild(createCell(gCertExpiresInfos.value[i]));
}
gListBox.appendChild(listitem);
}
}
function onSelectionChange(event)
{
gViewButton.disabled = !(gListBox.selectedItems.length == 1 &&
certForRow(gListBox.selectedIndex));
}
function viewCertHelper(parent, cert) {
var cd = Components.classes[nsCertificateDialogs].getService(nsICertificateDialogs);
cd.viewCert(parent, cert);
}
function certForRow(aRowIndex) {
return gCerts.value[aRowIndex];
}
function viewSelectedCert()
{
if (!gViewButton.disabled)
viewCertHelper(window, certForRow(gListBox.selectedIndex));
}
function doHelpButton()
{
openHelp('compose_security', 'chrome://communicator/locale/help/suitehelp.rdf');
}
function createCell(label)
{
var cell = document.createElement("listcell");
cell.setAttribute("label", label)
return cell;
}

View file

@ -0,0 +1,68 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://messenger/skin/smime/msgCompSecurityInfo.css" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://messenger-smime/locale/msgCompSecurityInfo.dtd">
<dialog id="msgCompSecurityInfo" title="&title.label;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
style="width: 50em;"
persist="width height"
buttons="accept"
onload="onLoad();">
<script type="application/javascript" src="chrome://messenger-smime/content/msgCompSecurityInfo.js"/>
<stringbundle id="bundle_smime_comp_info" src="chrome://messenger-smime/locale/msgCompSecurityInfo.properties"/>
<description>&subject.plaintextWarning;</description>
<separator class="thin"/>
<description>&status.heading;</description>
<grid>
<columns>
<column/>
<column/>
</columns>
<rows>
<row>
<label value="&status.signed;"/>
<label id="signed"/>
</row>
<row>
<label value="&status.encrypted;"/>
<label id="encrypted"/>
</row>
</rows>
</grid>
<separator class="thin"/>
<label value="&status.certificates;" control="infolist"/>
<listbox id="infolist" flex="1"
onselect="onSelectionChange(event);">
<listcols>
<listcol flex="3" width="0"/>
<splitter class="tree-splitter"/>
<listcol flex="1" width="0"/>
<splitter class="tree-splitter"/>
<listcol flex="2" width="0"/>
<splitter class="tree-splitter"/>
<listcol flex="2" width="0"/>
</listcols>
<listhead>
<listheader label="&tree.recipient;"/>
<listheader label="&tree.status;"/>
<listheader label="&tree.issuedDate;"/>
<listheader label="&tree.expiresDate;"/>
</listhead>
</listbox>
<hbox pack="start">
<button id="viewCertButton" disabled="true"
label="&view.label;" accesskey="&view.accesskey;"
oncommand="viewSelectedCert();"/>
</hbox>
</dialog>

View file

@ -0,0 +1,264 @@
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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/. */
var gSignedUINode = null;
var gEncryptedUINode = null;
var gSMIMEContainer = null;
var gStatusBar = null;
var gSignedStatusPanel = null;
var gEncryptedStatusPanel = null;
var gEncryptedURIService = null;
var gMyLastEncryptedURI = null;
var gSMIMEBundle = null;
// var gBrandBundle; -- defined in mailWindow.js
// manipulates some globals from msgReadSMIMEOverlay.js
var nsICMSMessageErrors = Components.interfaces.nsICMSMessageErrors;
/// Get the necko URL for the message URI.
function neckoURLForMessageURI(aMessageURI)
{
let msgSvc = Components.classes["@mozilla.org/messenger;1"]
.createInstance(Components.interfaces.nsIMessenger)
.messageServiceFromURI(aMessageURI);
let neckoURI = {};
msgSvc.GetUrlForUri(aMessageURI, neckoURI, null);
return neckoURI.value.spec;
}
var smimeHeaderSink =
{
maxWantedNesting: function()
{
return 1;
},
signedStatus: function(aNestingLevel, aSignatureStatus, aSignerCert)
{
if (aNestingLevel > 1) {
// we are not interested
return;
}
gSignatureStatus = aSignatureStatus;
gSignerCert = aSignerCert;
gSMIMEContainer.collapsed = false;
gSignedUINode.collapsed = false;
gSignedStatusPanel.collapsed = false;
switch (aSignatureStatus) {
case nsICMSMessageErrors.SUCCESS:
gSignedUINode.setAttribute("signed", "ok");
gStatusBar.setAttribute("signed", "ok");
break;
case nsICMSMessageErrors.VERIFY_NOT_YET_ATTEMPTED:
gSignedUINode.setAttribute("signed", "unknown");
gStatusBar.setAttribute("signed", "unknown");
break;
case nsICMSMessageErrors.VERIFY_CERT_WITHOUT_ADDRESS:
case nsICMSMessageErrors.VERIFY_HEADER_MISMATCH:
gSignedUINode.setAttribute("signed", "mismatch");
gStatusBar.setAttribute("signed", "mismatch");
break;
default:
gSignedUINode.setAttribute("signed", "notok");
gStatusBar.setAttribute("signed", "notok");
break;
}
},
encryptionStatus: function(aNestingLevel, aEncryptionStatus, aRecipientCert)
{
if (aNestingLevel > 1) {
// we are not interested
return;
}
gEncryptionStatus = aEncryptionStatus;
gEncryptionCert = aRecipientCert;
gSMIMEContainer.collapsed = false;
gEncryptedUINode.collapsed = false;
gEncryptedStatusPanel.collapsed = false;
if (nsICMSMessageErrors.SUCCESS == aEncryptionStatus)
{
gEncryptedUINode.setAttribute("encrypted", "ok");
gStatusBar.setAttribute("encrypted", "ok");
}
else
{
gEncryptedUINode.setAttribute("encrypted", "notok");
gStatusBar.setAttribute("encrypted", "notok");
}
if (gEncryptedURIService)
{
// Remember the message URI and the corresponding necko URI.
gMyLastEncryptedURI = GetLoadedMessage();
gEncryptedURIService.rememberEncrypted(gMyLastEncryptedURI);
gEncryptedURIService.rememberEncrypted(
neckoURLForMessageURI(gMyLastEncryptedURI));
}
switch (aEncryptionStatus)
{
case nsICMSMessageErrors.SUCCESS:
case nsICMSMessageErrors.ENCRYPT_INCOMPLETE:
break;
default:
var brand = gBrandBundle.getString("brandShortName");
var title = gSMIMEBundle.getString("CantDecryptTitle").replace(/%brand%/g, brand);
var body = gSMIMEBundle.getString("CantDecryptBody").replace(/%brand%/g, brand);
// insert our message
msgWindow.displayHTMLInMessagePane(title,
"<html>\n" +
"<body bgcolor=\"#fafaee\">\n" +
"<center><br><br><br>\n" +
"<table>\n" +
"<tr><td>\n" +
"<center><strong><font size=\"+3\">\n" +
title+"</font></center><br>\n" +
body+"\n" +
"</td></tr></table></center></body></html>", false);
}
},
QueryInterface : function(iid)
{
if (iid.equals(Components.interfaces.nsIMsgSMIMEHeaderSink) || iid.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
}
};
function forgetEncryptedURI()
{
if (gMyLastEncryptedURI && gEncryptedURIService)
{
gEncryptedURIService.forgetEncrypted(gMyLastEncryptedURI);
gEncryptedURIService.forgetEncrypted(
neckoURLForMessageURI(gMyLastEncryptedURI));
gMyLastEncryptedURI = null;
}
}
function onSMIMEStartHeaders()
{
gEncryptionStatus = -1;
gSignatureStatus = -1;
gSignerCert = null;
gEncryptionCert = null;
gSMIMEContainer.collapsed = true;
gSignedUINode.collapsed = true;
gSignedUINode.removeAttribute("signed");
gSignedStatusPanel.collapsed = true;
gStatusBar.removeAttribute("signed");
gEncryptedUINode.collapsed = true;
gEncryptedUINode.removeAttribute("encrypted");
gEncryptedStatusPanel.collapsed = true;
gStatusBar.removeAttribute("encrypted");
forgetEncryptedURI();
}
function onSMIMEEndHeaders()
{}
function onSmartCardChange()
{
// only reload encrypted windows
if (gMyLastEncryptedURI && gEncryptionStatus != -1)
ReloadMessage();
}
function msgHdrViewSMIMEOnLoad(event)
{
window.crypto.enableSmartCardEvents = true;
document.addEventListener("smartcard-insert", onSmartCardChange, false);
document.addEventListener("smartcard-remove", onSmartCardChange, false);
if (!gSMIMEBundle)
gSMIMEBundle = document.getElementById("bundle_read_smime");
// we want to register our security header sink as an opaque nsISupports
// on the msgHdrSink used by mail.....
msgWindow.msgHeaderSink.securityInfo = smimeHeaderSink;
gSignedUINode = document.getElementById('signedHdrIcon');
gEncryptedUINode = document.getElementById('encryptedHdrIcon');
gSMIMEContainer = document.getElementById('smimeBox');
gStatusBar = document.getElementById('status-bar');
gSignedStatusPanel = document.getElementById('signed-status');
gEncryptedStatusPanel = document.getElementById('encrypted-status');
// add ourself to the list of message display listeners so we get notified when we are about to display a
// message.
var listener = {};
listener.onStartHeaders = onSMIMEStartHeaders;
listener.onEndHeaders = onSMIMEEndHeaders;
gMessageListeners.push(listener);
gEncryptedURIService =
Components.classes["@mozilla.org/messenger-smime/smime-encrypted-uris-service;1"]
.getService(Components.interfaces.nsIEncryptedSMIMEURIsService);
}
function msgHdrViewSMIMEOnUnload(event)
{
window.crypto.enableSmartCardEvents = false;
document.removeEventListener("smartcard-insert", onSmartCardChange, false);
document.removeEventListener("smartcard-remove", onSmartCardChange, false);
forgetEncryptedURI();
removeEventListener("messagepane-loaded", msgHdrViewSMIMEOnLoad, true);
removeEventListener("messagepane-unloaded", msgHdrViewSMIMEOnUnload, true);
removeEventListener("messagepane-hide", msgHdrViewSMIMEOnMessagePaneHide, true);
removeEventListener("messagepane-unhide", msgHdrViewSMIMEOnMessagePaneUnhide, true);
}
function msgHdrViewSMIMEOnMessagePaneHide()
{
gSMIMEContainer.collapsed = true;
gSignedUINode.collapsed = true;
gSignedStatusPanel.collapsed = true;
gEncryptedUINode.collapsed = true;
gEncryptedStatusPanel.collapsed = true;
}
function msgHdrViewSMIMEOnMessagePaneUnhide()
{
if (gEncryptionStatus != -1 || gSignatureStatus != -1)
{
gSMIMEContainer.collapsed = false;
if (gSignatureStatus != -1)
{
gSignedUINode.collapsed = false;
gSignedStatusPanel.collapsed = false;
}
if (gEncryptionStatus != -1)
{
gEncryptedUINode.collapsed = false;
gEncryptedStatusPanel.collapsed = false;
}
}
}
addEventListener('messagepane-loaded', msgHdrViewSMIMEOnLoad, true);
addEventListener('messagepane-unloaded', msgHdrViewSMIMEOnUnload, true);
addEventListener('messagepane-hide', msgHdrViewSMIMEOnMessagePaneHide, true);
addEventListener('messagepane-unhide', msgHdrViewSMIMEOnMessagePaneUnhide, true);

View file

@ -0,0 +1,29 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://messenger/skin/smime/msgHdrViewSMIMEOverlay.css" type="text/css"?>
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://messenger-smime/content/msgHdrViewSMIMEOverlay.js"/>
<!-- These stringbundles are already defined in msgReadSMIMEOverlay.xul!
<stringbundleset id="stringbundleset">
<stringbundle id="bundle_read_smime" src="chrome://messenger-smime/locale/msgReadSMIMEOverlay.properties"/>
<stringbundle id="bundle_brand" src="chrome://branding/locale/brand.properties"/>
</stringbundleset>
-->
<hbox id="expandedHeaderView">
<vbox id="smimeBox" insertafter="expandedHeaders" collapsed="true">
<spacer flex="1"/>
<image id="signedHdrIcon"
onclick="showMessageReadSecurityInfo();" collapsed="true"/>
<image id="encryptedHdrIcon"
onclick="showMessageReadSecurityInfo();" collapsed="true"/>
<spacer flex="1"/>
</vbox>
</hbox>
</overlay>

View file

@ -0,0 +1,102 @@
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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/. */
Components.utils.import("resource://gre/modules/Services.jsm");
var gEncryptionStatus = -1;
var gSignatureStatus = -1;
var gSignerCert = null;
var gEncryptionCert = null;
addEventListener("load", smimeReadOnLoad, {capture: false, once: true});
function smimeReadOnLoad()
{
top.controllers.appendController(SecurityController);
addEventListener("unload", smimeReadOnUnload, {capture: false, once: true});
}
function smimeReadOnUnload()
{
top.controllers.removeController(SecurityController);
}
function showImapSignatureUnknown()
{
let readSmimeBundle = document.getElementById("bundle_read_smime");
let brandBundle = document.getElementById("bundle_brand");
if (!readSmimeBundle || !brandBundle)
return;
if (Services.prompt.confirm(window, brandBundle.getString("brandShortName"),
readSmimeBundle.getString("ImapOnDemand")))
{
gDBView.reloadMessageWithAllParts();
}
}
function showMessageReadSecurityInfo()
{
let gSignedUINode = document.getElementById("signedHdrIcon");
if (gSignedUINode && gSignedUINode.getAttribute("signed") == "unknown")
{
showImapSignatureUnknown();
return;
}
let params = Components.classes["@mozilla.org/embedcomp/dialogparam;1"]
.createInstance(Components.interfaces.nsIDialogParamBlock);
params.objects = Components.classes["@mozilla.org/array;1"]
.createInstance(Components.interfaces.nsIMutableArray);
// Append even if null... the receiver must handle that.
params.objects.appendElement(gSignerCert, false);
params.objects.appendElement(gEncryptionCert, false);
// int array starts with index 0, but that is used for window exit status
params.SetInt(1, gSignatureStatus);
params.SetInt(2, gEncryptionStatus);
window.openDialog("chrome://messenger-smime/content/msgReadSecurityInfo.xul",
"", "chrome,resizable,modal,dialog,centerscreen", params);
}
var SecurityController =
{
supportsCommand: function(command)
{
switch (command)
{
case "cmd_viewSecurityStatus":
return true;
default:
return false;
}
},
isCommandEnabled: function(command)
{
switch (command)
{
case "cmd_viewSecurityStatus":
if (document.documentElement.getAttribute('windowtype') == "mail:messageWindow")
return GetNumSelectedMessages() > 0;
if (GetNumSelectedMessages() > 0 && gDBView)
{
let enabled = {value: false};
let checkStatus = {};
gDBView.getCommandStatus(nsMsgViewCommandType.cmdRequiringMsgBody,
enabled, checkStatus);
return enabled.value;
}
// else: fall through.
default:
return false;
}
}
};

View file

@ -0,0 +1,34 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://messenger/skin/smime/msgReadSMIMEOverlay.css" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://messenger-smime/locale/msgReadSMIMEOverlay.dtd">
<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://messenger-smime/content/msgReadSMIMEOverlay.js"/>
<commandset id="mailViewMenuItems">
<command id="cmd_viewSecurityStatus" oncommand="showMessageReadSecurityInfo();" disabled="true"/>
</commandset>
<menupopup id="menu_View_Popup">
<menuitem insertafter="pageSourceMenuItem" label="&menu_securityStatus.label;"
accesskey="&menu_securityStatus.accesskey;" command="cmd_viewSecurityStatus"/>
</menupopup>
<statusbar id="status-bar">
<statusbarpanel insertbefore="offline-status" class="statusbarpanel-iconic"
id="signed-status" collapsed="true" oncommand="showMessageReadSecurityInfo();"/>
<statusbarpanel insertbefore="offline-status" class="statusbarpanel-iconic"
id="encrypted-status" collapsed="true" oncommand="showMessageReadSecurityInfo();"/>
<stringbundle id="bundle_read_smime" src="chrome://messenger-smime/locale/msgReadSMIMEOverlay.properties"/>
<!-- This stringbundle is already defined on top window level!
<stringbundle id="bundle_brand" src="chrome://branding/locale/brand.properties"/>
-->
</statusbar>
</overlay>

View file

@ -0,0 +1,232 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
var nsIDialogParamBlock = Components.interfaces.nsIDialogParamBlock;
var nsIX509Cert = Components.interfaces.nsIX509Cert;
var nsICMSMessageErrors = Components.interfaces.nsICMSMessageErrors;
var nsICertificateDialogs = Components.interfaces.nsICertificateDialogs;
var nsCertificateDialogs = "@mozilla.org/nsCertificateDialogs;1"
var gSignerCert = null;
var gEncryptionCert = null;
var gSignatureStatus = -1;
var gEncryptionStatus = -1;
function setText(id, value) {
var element = document.getElementById(id);
if (!element)
return;
if (element.hasChildNodes())
element.firstChild.remove();
var textNode = document.createTextNode(value);
element.appendChild(textNode);
}
function onLoad()
{
var paramBlock = window.arguments[0].QueryInterface(nsIDialogParamBlock);
paramBlock.objects.QueryInterface(Components.interfaces.nsIMutableArray);
try {
gSignerCert = paramBlock.objects.queryElementAt(0, nsIX509Cert);
} catch(e) { } // maybe null
try {
gEncryptionCert = paramBlock.objects.queryElementAt(1, nsIX509Cert);
} catch(e) { } // maybe null
gSignatureStatus = paramBlock.GetInt(1);
gEncryptionStatus = paramBlock.GetInt(2);
var bundle = document.getElementById("bundle_smime_read_info");
if (bundle) {
var sigInfoLabel = null;
var sigInfoHeader = null;
var sigInfo = null;
var sigInfo_clueless = false;
switch (gSignatureStatus) {
case -1:
case nsICMSMessageErrors.VERIFY_NOT_SIGNED:
sigInfoLabel = "SINoneLabel";
sigInfo = "SINone";
break;
case nsICMSMessageErrors.SUCCESS:
sigInfoLabel = "SIValidLabel";
sigInfo = "SIValid";
break;
case nsICMSMessageErrors.VERIFY_BAD_SIGNATURE:
case nsICMSMessageErrors.VERIFY_DIGEST_MISMATCH:
sigInfoLabel = "SIInvalidLabel";
sigInfoHeader = "SIInvalidHeader";
sigInfo = "SIContentAltered";
break;
case nsICMSMessageErrors.VERIFY_UNKNOWN_ALGO:
case nsICMSMessageErrors.VERIFY_UNSUPPORTED_ALGO:
sigInfoLabel = "SIInvalidLabel";
sigInfoHeader = "SIInvalidHeader";
sigInfo = "SIInvalidCipher";
break;
case nsICMSMessageErrors.VERIFY_HEADER_MISMATCH:
sigInfoLabel = "SIPartiallyValidLabel";
sigInfoHeader = "SIPartiallyValidHeader";
sigInfo = "SIHeaderMismatch";
break;
case nsICMSMessageErrors.VERIFY_CERT_WITHOUT_ADDRESS:
sigInfoLabel = "SIPartiallyValidLabel";
sigInfoHeader = "SIPartiallyValidHeader";
sigInfo = "SICertWithoutAddress";
break;
case nsICMSMessageErrors.VERIFY_UNTRUSTED:
sigInfoLabel = "SIInvalidLabel";
sigInfoHeader = "SIInvalidHeader";
sigInfo = "SIUntrustedCA";
// XXX Need to extend to communicate better errors
// might also be:
// SIExpired SIRevoked SINotYetValid SIUnknownCA SIExpiredCA SIRevokedCA SINotYetValidCA
break;
case nsICMSMessageErrors.VERIFY_NOT_YET_ATTEMPTED:
case nsICMSMessageErrors.GENERAL_ERROR:
case nsICMSMessageErrors.VERIFY_NO_CONTENT_INFO:
case nsICMSMessageErrors.VERIFY_BAD_DIGEST:
case nsICMSMessageErrors.VERIFY_NOCERT:
case nsICMSMessageErrors.VERIFY_ERROR_UNVERIFIED:
case nsICMSMessageErrors.VERIFY_ERROR_PROCESSING:
case nsICMSMessageErrors.VERIFY_MALFORMED_SIGNATURE:
sigInfoLabel = "SIInvalidLabel";
sigInfoHeader = "SIInvalidHeader";
sigInfo_clueless = true;
break;
default:
Components.utils.reportError("Unexpected gSignatureStatus: " +
gSignatureStatus);
}
document.getElementById("signatureLabel").value =
bundle.getString(sigInfoLabel);
var label;
if (sigInfoHeader) {
label = document.getElementById("signatureHeader");
label.collapsed = false;
label.value = bundle.getString(sigInfoHeader);
}
var str;
if (sigInfo) {
str = bundle.getString(sigInfo);
}
else if (sigInfo_clueless) {
str = bundle.getString("SIClueless") + " (" + gSignatureStatus + ")";
}
setText("signatureExplanation", str);
var encInfoLabel = null;
var encInfoHeader = null;
var encInfo = null;
var encInfo_clueless = false;
switch (gEncryptionStatus) {
case -1:
encInfoLabel = "EINoneLabel2";
encInfo = "EINone";
break;
case nsICMSMessageErrors.SUCCESS:
encInfoLabel = "EIValidLabel";
encInfo = "EIValid";
break;
case nsICMSMessageErrors.ENCRYPT_INCOMPLETE:
encInfoLabel = "EIInvalidLabel";
encInfo = "EIContentAltered";
break;
case nsICMSMessageErrors.GENERAL_ERROR:
encInfoLabel = "EIInvalidLabel";
encInfoHeader = "EIInvalidHeader";
encInfo_clueless = 1;
break;
default:
Components.utils.reportError("Unexpected gEncryptionStatus: " +
gEncryptionStatus);
}
document.getElementById("encryptionLabel").value =
bundle.getString(encInfoLabel);
if (encInfoHeader) {
label = document.getElementById("encryptionHeader");
label.collapsed = false;
label.value = bundle.getString(encInfoHeader);
}
if (encInfo) {
str = bundle.getString(encInfo);
}
else if (encInfo_clueless) {
str = bundle.getString("EIClueless");
}
setText("encryptionExplanation", str);
}
if (gSignerCert) {
document.getElementById("signatureCert").collapsed = false;
if (gSignerCert.subjectName) {
document.getElementById("signedBy").value = gSignerCert.commonName;
}
if (gSignerCert.emailAddress) {
document.getElementById("signerEmail").value = gSignerCert.emailAddress;
}
if (gSignerCert.issuerName) {
document.getElementById("sigCertIssuedBy").value = gSignerCert.issuerCommonName;
}
}
if (gEncryptionCert) {
document.getElementById("encryptionCert").collapsed = false;
if (gEncryptionCert.subjectName) {
document.getElementById("encryptedFor").value = gEncryptionCert.commonName;
}
if (gEncryptionCert.emailAddress) {
document.getElementById("recipientEmail").value = gEncryptionCert.emailAddress;
}
if (gEncryptionCert.issuerName) {
document.getElementById("encCertIssuedBy").value = gEncryptionCert.issuerCommonName;
}
}
}
function viewCertHelper(parent, cert) {
var cd = Components.classes[nsCertificateDialogs].getService(nsICertificateDialogs);
cd.viewCert(parent, cert);
}
function viewSignatureCert()
{
if (gSignerCert) {
viewCertHelper(window, gSignerCert);
}
}
function viewEncryptionCert()
{
if (gEncryptionCert) {
viewCertHelper(window, gEncryptionCert);
}
}
function doHelpButton()
{
openHelp('received_security');
}

View file

@ -0,0 +1,68 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://messenger/skin/smime/msgReadSecurityInfo.css" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://messenger-smime/locale/msgReadSecurityInfo.dtd">
<dialog id="msgReadSecurityInfo" title="&status.label;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
style="width: 40em;"
buttons="accept"
onload="onLoad();">
<script type="application/javascript" src="chrome://messenger-smime/content/msgReadSecurityInfo.js"/>
<stringbundle id="bundle_smime_read_info" src="chrome://messenger-smime/locale/msgSecurityInfo.properties"/>
<vbox flex="1">
<label id="signatureLabel"/>
<label id="signatureHeader" collapsed="true"/>
<description id="signatureExplanation"/>
<vbox id="signatureCert" collapsed="true">
<hbox>
<label id="signedByLabel">&signer.name;</label>
<description id="signedBy"/>
</hbox>
<hbox>
<label id="signerEmailLabel">&email.address;</label>
<description id="signerEmail"/>
</hbox>
<hbox>
<label id="sigCertIssuedByLabel">&issuer.name;</label>
<description id="sigCertIssuedBy"/>
</hbox>
<hbox>
<button id="signatureCertView" label="&signatureCert.label;"
oncommand="viewSignatureCert()"/>
</hbox>
</vbox>
<separator/>
<label id="encryptionLabel"/>
<label id="encryptionHeader" collapsed="true"/>
<description id="encryptionExplanation"/>
<vbox id="encryptionCert" collapsed="true">
<hbox>
<label id="encryptedForLabel">&recipient.name;</label>
<description id="encryptedFor"/>
</hbox>
<hbox>
<label id="recipientEmailLabel">&email.address;</label>
<description id="recipientEmail"/>
</hbox>
<hbox>
<label id="encCertIssuedByLabel">&issuer.name;</label>
<description id="encCertIssuedBy"/>
</hbox>
<hbox>
<button id="encryptionCertView" label="&encryptionCert.label;"
oncommand="viewEncryptionCert()"/>
</hbox>
</vbox>
</vbox>
</dialog>

View file

@ -0,0 +1,14 @@
/* 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/. */
/*
Add any default pref values we want for smime
*/
pref("mail.identity.default.encryption_cert_name","");
pref("mail.identity.default.encryptionpolicy", 0);
pref("mail.identity.default.signing_cert_name", "");
pref("mail.identity.default.sign_mail", false);

View file

@ -0,0 +1,30 @@
# 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/.
#ifdef MOZ_SUITE
messenger.jar:
% content messenger-smime %content/messenger-smime/
% overlay chrome://messenger/content/messengercompose/messengercompose.xul chrome://messenger-smime/content/msgCompSMIMEOverlay.xul
% overlay chrome://messenger/content/msgHdrViewOverlay.xul chrome://messenger-smime/content/msgHdrViewSMIMEOverlay.xul
% overlay chrome://messenger/content/mailWindowOverlay.xul chrome://messenger-smime/content/msgReadSMIMEOverlay.xul
% overlay chrome://messenger/content/am-identity-edit.xul chrome://messenger/content/am-smimeIdentityEditOverlay.xul
content/messenger/am-smime.xul (content/am-smime.xul)
content/messenger/am-smime.js (content/am-smime.js)
content/messenger/am-smimeIdentityEditOverlay.xul (content/am-smimeIdentityEditOverlay.xul)
content/messenger/am-smimeOverlay.xul (content/am-smimeOverlay.xul)
content/messenger/certpicker.js (content/certpicker.js)
content/messenger/certpicker.xul (content/certpicker.xul)
content/messenger-smime/msgCompSMIMEOverlay.js (content/msgCompSMIMEOverlay.js)
content/messenger-smime/msgCompSMIMEOverlay.xul (content/msgCompSMIMEOverlay.xul)
content/messenger-smime/msgReadSMIMEOverlay.js (content/msgReadSMIMEOverlay.js)
content/messenger-smime/msgReadSMIMEOverlay.xul (content/msgReadSMIMEOverlay.xul)
content/messenger-smime/msgHdrViewSMIMEOverlay.xul (content/msgHdrViewSMIMEOverlay.xul)
content/messenger-smime/msgHdrViewSMIMEOverlay.js (content/msgHdrViewSMIMEOverlay.js)
content/messenger-smime/msgCompSecurityInfo.xul (content/msgCompSecurityInfo.xul)
content/messenger-smime/msgCompSecurityInfo.js (content/msgCompSecurityInfo.js)
content/messenger-smime/msgReadSecurityInfo.xul (content/msgReadSecurityInfo.xul)
content/messenger-smime/msgReadSecurityInfo.js (content/msgReadSecurityInfo.js)
content/messenger-smime/certFetchingStatus.xul (content/certFetchingStatus.xul)
content/messenger-smime/certFetchingStatus.js (content/certFetchingStatus.js)
#endif

View file

@ -0,0 +1,15 @@
# vim: set filetype=python:
# 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/.
DIRS += [
'public',
'src',
]
JAR_MANIFESTS += ['jar.mn']
JS_PREFERENCE_FILES += [
'content/smime.js',
]

View file

@ -0,0 +1,15 @@
# vim: set filetype=python:
# 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/.
XPIDL_SOURCES += [
'nsICertPickDialogs.idl',
'nsIEncryptedSMIMEURIsSrvc.idl',
'nsIMsgSMIMECompFields.idl',
'nsIMsgSMIMEHeaderSink.idl',
'nsISMimeJSHelper.idl',
'nsIUserCertPicker.idl',
]
XPIDL_MODULE = 'msgsmime'

View file

@ -0,0 +1,30 @@
/* 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/. */
#include "nsISupports.idl"
interface nsIInterfaceRequestor;
/**
* nsICertPickDialogs
* Provides generic UI for choosing a certificate
*/
[scriptable, uuid(51d59b08-1dd2-11b2-ad4a-a51b92f8a184)]
interface nsICertPickDialogs : nsISupports
{
/**
* PickCertificate
* General purpose certificate prompter
*/
void PickCertificate(in nsIInterfaceRequestor ctx,
[array, size_is(count)] in wstring certNickList,
[array, size_is(count)] in wstring certDetailsList,
in unsigned long count,
inout long selectedIndex,
out boolean canceled);
};
%{C++
#define NS_CERTPICKDIALOGS_CONTRACTID "@mozilla.org/nsCertPickDialogs;1"
%}

View file

@ -0,0 +1,24 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
/* This is a private interface used exclusively by SMIME.
It provides functionality to the JS UI code,
that is only accessible from C++.
*/
#include "nsISupports.idl"
[scriptable, uuid(f86e55c9-530b-483f-91a7-10fb5b852488)]
interface nsIEncryptedSMIMEURIsService : nsISupports
{
/// Remember that this URI is encrypted.
void rememberEncrypted(in AUTF8String uri);
/// Forget that this URI is encrypted.
void forgetEncrypted(in AUTF8String uri);
/// Check if this URI is encrypted.
boolean isEncrypted(in AUTF8String uri);
};

View file

@ -0,0 +1,18 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
/* This is a private interface used exclusively by SMIME. NO ONE outside of extensions/smime
should have any knowledge nor should be referring to this interface.
*/
#include "nsISupports.idl"
[scriptable, uuid(338E91F9-5970-4f81-B771-0822A32B1161)]
interface nsIMsgSMIMECompFields : nsISupports
{
attribute boolean signMessage;
attribute boolean requireEncryptMessage;
};

View file

@ -0,0 +1,23 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
/* This is a private interface used exclusively by SMIME. NO ONE outside of extensions/smime
or the hard coded smime decryption files in mime/src should have any knowledge nor should
be referring to this interface.
*/
#include "nsISupports.idl"
interface nsIX509Cert;
[scriptable, uuid(25380FA1-E70C-4e82-B0BC-F31C2F41C470)]
interface nsIMsgSMIMEHeaderSink : nsISupports
{
void signedStatus(in long aNestingLevel, in long aSignatureStatus, in nsIX509Cert aSignerCert);
void encryptionStatus(in long aNestingLevel, in long aEncryptionStatus, in nsIX509Cert aReceipientCert);
long maxWantedNesting(); // 1 == only info on outermost nesting level wanted
};

View file

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
/* This is a private interface used exclusively by SMIME.
It provides functionality to the JS UI code,
that is only accessible from C++.
*/
#include "nsISupports.idl"
interface nsIMsgCompFields;
interface nsIX509Cert;
[scriptable, uuid(a54e3c8f-a000-4901-898f-fafb297b1546)]
interface nsISMimeJSHelper : nsISupports
{
/**
* Obtains detailed information about the certificate availability
* status of email recipients.
*
* @param compFields - Attributes of the composed message
*
* @param count - The number of entries in returned arrays
*
* @param emailAddresses - The list of all recipient email addresses
*
* @param certVerification - The verification/validity status of recipient certs
*
* @param certIssuedInfos - If a recipient cert was found, when has it been issued?
*
* @param certExpiredInfos - If a recipient cert was found, when will it expire?
*
* @param certs - The recipient certificates, which can contain null for not found
*
* @param canEncrypt - whether valid certificates have been found for all recipients
*
* @exception NS_ERROR_FAILURE - unexptected failure
*
* @exception NS_ERROR_OUT_OF_MEMORY - could not create the out list
*
* @exception NS_ERROR_INVALID_ARG
*/
void getRecipientCertsInfo(in nsIMsgCompFields compFields,
out unsigned long count,
[array, size_is(count)] out wstring emailAddresses,
[array, size_is(count)] out long certVerification,
[array, size_is(count)] out wstring certIssuedInfos,
[array, size_is(count)] out wstring certExpiresInfos,
[array, size_is(count)] out nsIX509Cert certs,
out boolean canEncrypt);
/**
* Obtains a list of email addresses where valid email recipient certificates
* are not yet available.
*
* @param compFields - Attributes of the composed message
*
* @param count - The number of returned email addresses
*
* @param emailAddresses - The list of email addresses without valid certs
*
* @exception NS_ERROR_FAILURE - unexptected failure
*
* @exception NS_ERROR_OUT_OF_MEMORY - could not create the out list
*
* @exception NS_ERROR_INVALID_ARG
*/
void getNoCertAddresses(in nsIMsgCompFields compFields,
out unsigned long count,
[array, size_is(count)] out wstring emailAddresses);
};

View file

@ -0,0 +1,28 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "nsISupports.idl"
interface nsIX509Cert;
interface nsIInterfaceRequestor;
[scriptable, uuid(92396323-23f2-49e0-bf98-a25a725231ab)]
interface nsIUserCertPicker : nsISupports {
nsIX509Cert pickByUsage(in nsIInterfaceRequestor ctx,
in wstring selectedNickname,
in long certUsage, // as defined by NSS enum SECCertUsage
in boolean allowInvalid,
in boolean allowDuplicateNicknames,
in AString emailAddress, // optional - if non-empty,
// skip certificates which
// have at least one e-mail
// address but do not
// include this specific one
out boolean canceled);
};
%{C++
#define NS_CERT_PICKER_CONTRACTID "@mozilla.org/user_cert_picker;1"
%}

View file

@ -0,0 +1,23 @@
# vim: set filetype=python:
# 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/.
SOURCES += [
'nsCertPicker.cpp',
'nsEncryptedSMIMEURIsService.cpp',
'nsMsgComposeSecure.cpp',
'nsSMimeJSHelper.cpp',
]
EXTRA_COMPONENTS += [
'smime-service.js',
'smime-service.manifest',
]
FINAL_LIBRARY = 'mail'
LOCAL_INCLUDES += [
'/mozilla/security/manager/pki',
'/mozilla/security/pkix/include'
]

View file

@ -0,0 +1,471 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "nsCertPicker.h"
#include "MainThreadUtils.h"
#include "ScopedNSSTypes.h"
#include "cert.h"
#include "mozilla/RefPtr.h"
#include "nsCOMPtr.h"
#include "nsICertPickDialogs.h"
#include "nsIDOMWindow.h"
#include "nsIDialogParamBlock.h"
#include "nsIInterfaceRequestor.h"
#include "nsIServiceManager.h"
#include "nsIX509CertValidity.h"
#include "nsMemory.h"
#include "nsMsgComposeSecure.h"
#include "nsNSSCertificate.h"
#include "nsNSSComponent.h"
#include "nsNSSDialogHelper.h"
#include "nsNSSHelper.h"
#include "nsNSSShutDown.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#include "pkix/pkixtypes.h"
using namespace mozilla;
MOZ_TYPE_SPECIFIC_UNIQUE_PTR_TEMPLATE(UniqueCERTCertNicknames,
CERTCertNicknames,
CERT_FreeNicknames)
CERTCertNicknames*
getNSSCertNicknamesFromCertList(const UniqueCERTCertList& certList)
{
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
nsresult rv;
nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
if (NS_FAILED(rv))
return nullptr;
nsAutoString expiredString, notYetValidString;
nsAutoString expiredStringLeadingSpace, notYetValidStringLeadingSpace;
nssComponent->GetPIPNSSBundleString("NicknameExpired", expiredString);
nssComponent->GetPIPNSSBundleString("NicknameNotYetValid", notYetValidString);
expiredStringLeadingSpace.Append(' ');
expiredStringLeadingSpace.Append(expiredString);
notYetValidStringLeadingSpace.Append(' ');
notYetValidStringLeadingSpace.Append(notYetValidString);
NS_ConvertUTF16toUTF8 aUtf8ExpiredString(expiredStringLeadingSpace);
NS_ConvertUTF16toUTF8 aUtf8NotYetValidString(notYetValidStringLeadingSpace);
return CERT_NicknameStringsFromCertList(certList.get(),
const_cast<char*>(aUtf8ExpiredString.get()),
const_cast<char*>(aUtf8NotYetValidString.get()));
}
nsresult
FormatUIStrings(nsIX509Cert* cert, const nsAutoString& nickname,
nsAutoString& nickWithSerial, nsAutoString& details)
{
if (!NS_IsMainThread()) {
NS_ERROR("nsNSSCertificate::FormatUIStrings called off the main thread");
return NS_ERROR_NOT_SAME_THREAD;
}
RefPtr<nsMsgComposeSecure> mcs = new nsMsgComposeSecure;
if (!mcs) {
return NS_ERROR_FAILURE;
}
nsAutoString info;
nsAutoString temp1;
nickWithSerial.Append(nickname);
if (NS_SUCCEEDED(mcs->GetSMIMEBundleString(u"CertInfoIssuedFor", info))) {
details.Append(info);
details.Append(char16_t(' '));
if (NS_SUCCEEDED(cert->GetSubjectName(temp1)) && !temp1.IsEmpty()) {
details.Append(temp1);
}
details.Append(char16_t('\n'));
}
if (NS_SUCCEEDED(cert->GetSerialNumber(temp1)) && !temp1.IsEmpty()) {
details.AppendLiteral(" ");
if (NS_SUCCEEDED(mcs->GetSMIMEBundleString(u"CertDumpSerialNo", info))) {
details.Append(info);
details.AppendLiteral(": ");
}
details.Append(temp1);
nickWithSerial.AppendLiteral(" [");
nickWithSerial.Append(temp1);
nickWithSerial.Append(char16_t(']'));
details.Append(char16_t('\n'));
}
nsCOMPtr<nsIX509CertValidity> validity;
nsresult rv = cert->GetValidity(getter_AddRefs(validity));
if (NS_SUCCEEDED(rv) && validity) {
details.AppendLiteral(" ");
if (NS_SUCCEEDED(mcs->GetSMIMEBundleString(u"CertInfoValid", info))) {
details.Append(info);
}
if (NS_SUCCEEDED(validity->GetNotBeforeLocalTime(temp1)) && !temp1.IsEmpty()) {
details.Append(char16_t(' '));
if (NS_SUCCEEDED(mcs->GetSMIMEBundleString(u"CertInfoFrom", info))) {
details.Append(info);
details.Append(char16_t(' '));
}
details.Append(temp1);
}
if (NS_SUCCEEDED(validity->GetNotAfterLocalTime(temp1)) && !temp1.IsEmpty()) {
details.Append(char16_t(' '));
if (NS_SUCCEEDED(mcs->GetSMIMEBundleString(u"CertInfoTo", info))) {
details.Append(info);
details.Append(char16_t(' '));
}
details.Append(temp1);
}
details.Append(char16_t('\n'));
}
if (NS_SUCCEEDED(cert->GetKeyUsages(temp1)) && !temp1.IsEmpty()) {
details.AppendLiteral(" ");
if (NS_SUCCEEDED(mcs->GetSMIMEBundleString(u"CertDumpKeyUsage", info))) {
details.Append(info);
details.AppendLiteral(": ");
}
details.Append(temp1);
details.Append(char16_t('\n'));
}
UniqueCERTCertificate nssCert(cert->GetCert());
if (!nssCert) {
return NS_ERROR_FAILURE;
}
nsAutoString firstEmail;
const char* aWalkAddr;
for (aWalkAddr = CERT_GetFirstEmailAddress(nssCert.get())
;
aWalkAddr
;
aWalkAddr = CERT_GetNextEmailAddress(nssCert.get(), aWalkAddr))
{
NS_ConvertUTF8toUTF16 email(aWalkAddr);
if (email.IsEmpty())
continue;
if (firstEmail.IsEmpty()) {
// If the first email address from the subject DN is also present
// in the subjectAltName extension, GetEmailAddresses() will return
// it twice (as received from NSS). Remember the first address so that
// we can filter out duplicates later on.
firstEmail = email;
details.AppendLiteral(" ");
if (NS_SUCCEEDED(mcs->GetSMIMEBundleString(u"CertInfoEmail", info))) {
details.Append(info);
details.AppendLiteral(": ");
}
details.Append(email);
}
else {
// Append current address if it's different from the first one.
if (!firstEmail.Equals(email)) {
details.AppendLiteral(", ");
details.Append(email);
}
}
}
if (!firstEmail.IsEmpty()) {
// We got at least one email address, so we want a newline
details.Append(char16_t('\n'));
}
if (NS_SUCCEEDED(mcs->GetSMIMEBundleString(u"CertInfoIssuedBy", info))) {
details.Append(info);
details.Append(char16_t(' '));
if (NS_SUCCEEDED(cert->GetIssuerName(temp1)) && !temp1.IsEmpty()) {
details.Append(temp1);
}
details.Append(char16_t('\n'));
}
if (NS_SUCCEEDED(mcs->GetSMIMEBundleString(u"CertInfoStoredIn", info))) {
details.Append(info);
details.Append(char16_t(' '));
if (NS_SUCCEEDED(cert->GetTokenName(temp1)) && !temp1.IsEmpty()) {
details.Append(temp1);
}
}
// the above produces the following output:
//
// Issued to: $subjectName
// Serial number: $serialNumber
// Valid from: $starting_date to $expiration_date
// Certificate Key usage: $usages
// Email: $address(es)
// Issued by: $issuerName
// Stored in: $token
return rv;
}
NS_IMPL_ISUPPORTS(nsCertPicker, nsICertPickDialogs, nsIUserCertPicker)
nsCertPicker::nsCertPicker()
{
}
nsCertPicker::~nsCertPicker()
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return;
}
shutdown(ShutdownCalledFrom::Object);
}
nsresult
nsCertPicker::Init()
{
nsresult rv;
nsCOMPtr<nsISupports> psm = do_GetService("@mozilla.org/psm;1", &rv);
return rv;
}
NS_IMETHODIMP
nsCertPicker::PickCertificate(nsIInterfaceRequestor *ctx,
const char16_t **certNickList,
const char16_t **certDetailsList,
uint32_t count,
int32_t *selectedIndex,
bool *canceled)
{
nsresult rv;
uint32_t i;
*canceled = false;
nsCOMPtr<nsIDialogParamBlock> block =
do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID);
if (!block) return NS_ERROR_FAILURE;
block->SetNumberStrings(1+count*2);
for (i = 0; i < count; i++) {
rv = block->SetString(i, certNickList[i]);
if (NS_FAILED(rv)) return rv;
}
for (i = 0; i < count; i++) {
rv = block->SetString(i+count, certDetailsList[i]);
if (NS_FAILED(rv)) return rv;
}
rv = block->SetInt(0, count);
if (NS_FAILED(rv)) return rv;
rv = block->SetInt(1, *selectedIndex);
if (NS_FAILED(rv)) return rv;
rv = nsNSSDialogHelper::openDialog(nullptr,
"chrome://messenger/content/certpicker.xul",
block);
if (NS_FAILED(rv)) return rv;
int32_t status;
rv = block->GetInt(0, &status);
if (NS_FAILED(rv)) return rv;
*canceled = (status == 0)?true:false;
if (!*canceled) {
rv = block->GetInt(1, selectedIndex);
}
return rv;
}
NS_IMETHODIMP nsCertPicker::PickByUsage(nsIInterfaceRequestor *ctx,
const char16_t *selectedNickname,
int32_t certUsage,
bool allowInvalid,
bool allowDuplicateNicknames,
const nsAString &emailAddress,
bool *canceled,
nsIX509Cert **_retval)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown()) {
return NS_ERROR_NOT_AVAILABLE;
}
int32_t selectedIndex = -1;
bool selectionFound = false;
char16_t **certNicknameList = nullptr;
char16_t **certDetailsList = nullptr;
CERTCertListNode* node = nullptr;
nsresult rv = NS_OK;
{
// Iterate over all certs. This assures that user is logged in to all hardware tokens.
nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
UniqueCERTCertList allcerts(PK11_ListCerts(PK11CertListUnique, ctx));
}
/* find all user certs that are valid for the specified usage */
/* note that we are allowing expired certs in this list */
UniqueCERTCertList certList(
CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(),
(SECCertUsage)certUsage,
!allowDuplicateNicknames,
!allowInvalid,
ctx));
if (!certList) {
return NS_ERROR_NOT_AVAILABLE;
}
/* if a (non-empty) emailAddress argument is supplied to PickByUsage, */
/* remove non-matching certificates from the candidate list */
if (!emailAddress.IsEmpty()) {
node = CERT_LIST_HEAD(certList);
while (!CERT_LIST_END(node, certList)) {
/* if the cert has at least one e-mail address, check if suitable */
if (CERT_GetFirstEmailAddress(node->cert)) {
RefPtr<nsNSSCertificate> tempCert(nsNSSCertificate::Create(node->cert));
bool match = false;
rv = tempCert->ContainsEmailAddress(emailAddress, &match);
if (NS_FAILED(rv)) {
return rv;
}
if (!match) {
/* doesn't contain the specified address, so remove from the list */
CERTCertListNode* freenode = node;
node = CERT_LIST_NEXT(node);
CERT_RemoveCertListNode(freenode);
continue;
}
}
node = CERT_LIST_NEXT(node);
}
}
UniqueCERTCertNicknames nicknames(getNSSCertNicknamesFromCertList(certList));
if (!nicknames) {
return NS_ERROR_NOT_AVAILABLE;
}
certNicknameList = (char16_t **)moz_xmalloc(sizeof(char16_t *) * nicknames->numnicknames);
certDetailsList = (char16_t **)moz_xmalloc(sizeof(char16_t *) * nicknames->numnicknames);
if (!certNicknameList || !certDetailsList) {
free(certNicknameList);
free(certDetailsList);
return NS_ERROR_OUT_OF_MEMORY;
}
int32_t CertsToUse;
for (CertsToUse = 0, node = CERT_LIST_HEAD(certList.get());
!CERT_LIST_END(node, certList.get()) &&
CertsToUse < nicknames->numnicknames;
node = CERT_LIST_NEXT(node)
)
{
RefPtr<nsNSSCertificate> tempCert(nsNSSCertificate::Create(node->cert));
if (tempCert) {
nsAutoString i_nickname(NS_ConvertUTF8toUTF16(nicknames->nicknames[CertsToUse]));
nsAutoString nickWithSerial;
nsAutoString details;
if (!selectionFound) {
/* for the case when selectedNickname refers to a bare nickname */
if (i_nickname == nsDependentString(selectedNickname)) {
selectedIndex = CertsToUse;
selectionFound = true;
}
}
if (NS_SUCCEEDED(FormatUIStrings(tempCert, i_nickname, nickWithSerial,
details))) {
certNicknameList[CertsToUse] = ToNewUnicode(nickWithSerial);
certDetailsList[CertsToUse] = ToNewUnicode(details);
if (!selectionFound) {
/* for the case when selectedNickname refers to nickname + serial */
if (nickWithSerial == nsDependentString(selectedNickname)) {
selectedIndex = CertsToUse;
selectionFound = true;
}
}
}
else {
certNicknameList[CertsToUse] = nullptr;
certDetailsList[CertsToUse] = nullptr;
}
++CertsToUse;
}
}
if (CertsToUse) {
nsCOMPtr<nsICertPickDialogs> dialogs;
rv = getNSSDialogs(getter_AddRefs(dialogs), NS_GET_IID(nsICertPickDialogs),
NS_CERTPICKDIALOGS_CONTRACTID);
if (NS_SUCCEEDED(rv)) {
// Show the cert picker dialog and get the index of the selected cert.
rv = dialogs->PickCertificate(ctx, (const char16_t**)certNicknameList,
(const char16_t**)certDetailsList,
CertsToUse, &selectedIndex, canceled);
}
}
int32_t i;
for (i = 0; i < CertsToUse; ++i) {
free(certNicknameList[i]);
free(certDetailsList[i]);
}
free(certNicknameList);
free(certDetailsList);
if (!CertsToUse) {
return NS_ERROR_NOT_AVAILABLE;
}
if (NS_SUCCEEDED(rv) && !*canceled) {
for (i = 0, node = CERT_LIST_HEAD(certList);
!CERT_LIST_END(node, certList);
++i, node = CERT_LIST_NEXT(node)) {
if (i == selectedIndex) {
RefPtr<nsNSSCertificate> cert = nsNSSCertificate::Create(node->cert);
if (!cert) {
rv = NS_ERROR_OUT_OF_MEMORY;
break;
}
cert.forget(_retval);
break;
}
}
}
return rv;
}

View file

@ -0,0 +1,36 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef nsCertPicker_h
#define nsCertPicker_h
#include "nsICertPickDialogs.h"
#include "nsIUserCertPicker.h"
#include "nsNSSShutDown.h"
#define NS_CERT_PICKER_CID \
{ 0x735959a1, 0xaf01, 0x447e, { 0xb0, 0x2d, 0x56, 0xe9, 0x68, 0xfa, 0x52, 0xb4 } }
class nsCertPicker : public nsICertPickDialogs
, public nsIUserCertPicker
, public nsNSSShutDownObject
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICERTPICKDIALOGS
NS_DECL_NSIUSERCERTPICKER
nsCertPicker();
// Nothing to actually release.
virtual void virtualDestroyNSSReference() override {}
nsresult Init();
protected:
virtual ~nsCertPicker();
};
#endif // nsCertPicker_h

View file

@ -0,0 +1,36 @@
/* 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/. */
#include "nsEncryptedSMIMEURIsService.h"
NS_IMPL_ISUPPORTS(nsEncryptedSMIMEURIsService, nsIEncryptedSMIMEURIsService)
nsEncryptedSMIMEURIsService::nsEncryptedSMIMEURIsService()
{
}
nsEncryptedSMIMEURIsService::~nsEncryptedSMIMEURIsService()
{
}
NS_IMETHODIMP nsEncryptedSMIMEURIsService::RememberEncrypted(const nsACString & uri)
{
// Assuming duplicates are allowed.
mEncryptedURIs.AppendElement(uri);
return NS_OK;
}
NS_IMETHODIMP nsEncryptedSMIMEURIsService::ForgetEncrypted(const nsACString & uri)
{
// Assuming, this will only remove one copy of the string, if the array
// contains multiple copies of the same string.
mEncryptedURIs.RemoveElement(uri);
return NS_OK;
}
NS_IMETHODIMP nsEncryptedSMIMEURIsService::IsEncrypted(const nsACString & uri, bool *_retval)
{
*_retval = mEncryptedURIs.Contains(uri);
return NS_OK;
}

View file

@ -0,0 +1,25 @@
/* 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/. */
#ifndef _nsEncryptedSMIMEURIsService_H_
#define _nsEncryptedSMIMEURIsService_H_
#include "nsIEncryptedSMIMEURIsSrvc.h"
#include "nsTArray.h"
#include "nsStringGlue.h"
class nsEncryptedSMIMEURIsService : public nsIEncryptedSMIMEURIsService
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIENCRYPTEDSMIMEURISSERVICE
nsEncryptedSMIMEURIsService();
protected:
virtual ~nsEncryptedSMIMEURIsService();
nsTArray<nsCString> mEncryptedURIs;
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,106 @@
/* -*- Mode: idl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */
#ifndef _nsMsgComposeSecure_H_
#define _nsMsgComposeSecure_H_
#include "nsIMsgComposeSecure.h"
#include "nsIMsgSMIMECompFields.h"
#include "nsCOMPtr.h"
#include "nsICMSEncoder.h"
#include "nsIX509Cert.h"
#include "nsIStringBundle.h"
#include "nsICryptoHash.h"
#include "nsICMSMessage.h"
#include "nsIMutableArray.h"
#include "nsStringGlue.h"
#include "nsIOutputStream.h"
#include "nsAutoPtr.h"
class nsIMsgCompFields;
namespace mozilla {
namespace mailnews {
class MimeEncoder;
}
}
class nsMsgSMIMEComposeFields : public nsIMsgSMIMECompFields
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGSMIMECOMPFIELDS
nsMsgSMIMEComposeFields();
private:
virtual ~nsMsgSMIMEComposeFields();
bool mSignMessage;
bool mAlwaysEncryptMessage;
};
typedef enum {
mime_crypto_none, /* normal unencapsulated MIME message */
mime_crypto_clear_signed, /* multipart/signed encapsulation */
mime_crypto_opaque_signed, /* application/x-pkcs7-mime (signedData) */
mime_crypto_encrypted, /* application/x-pkcs7-mime */
mime_crypto_signed_encrypted /* application/x-pkcs7-mime */
} mimeDeliveryCryptoState;
class nsMsgComposeSecure : public nsIMsgComposeSecure
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGCOMPOSESECURE
nsMsgComposeSecure();
void GetOutputStream(nsIOutputStream **stream) { NS_IF_ADDREF(*stream = mStream);}
nsresult GetSMIMEBundleString(const char16_t *name, nsString &outString);
private:
virtual ~nsMsgComposeSecure();
typedef mozilla::mailnews::MimeEncoder MimeEncoder;
nsresult MimeInitMultipartSigned(bool aOuter, nsIMsgSendReport *sendReport);
nsresult MimeInitEncryption(bool aSign, nsIMsgSendReport *sendReport);
nsresult MimeFinishMultipartSigned (bool aOuter, nsIMsgSendReport *sendReport);
nsresult MimeFinishEncryption (bool aSign, nsIMsgSendReport *sendReport);
nsresult MimeCryptoHackCerts(const char *aRecipients, nsIMsgSendReport *sendReport, bool aEncrypt, bool aSign, nsIMsgIdentity *aIdentity);
bool InitializeSMIMEBundle();
nsresult SMIMEBundleFormatStringFromName(const char16_t *name,
const char16_t **params,
uint32_t numParams,
char16_t **outString);
nsresult ExtractEncryptionState(nsIMsgIdentity * aIdentity, nsIMsgCompFields * aComposeFields, bool * aSignMessage, bool * aEncrypt);
mimeDeliveryCryptoState mCryptoState;
nsCOMPtr<nsIOutputStream> mStream;
int16_t mHashType;
nsCOMPtr<nsICryptoHash> mDataHash;
nsAutoPtr<MimeEncoder> mSigEncoder;
char *mMultipartSignedBoundary;
nsString mSigningCertName;
nsAutoCString mSigningCertDBKey;
nsCOMPtr<nsIX509Cert> mSelfSigningCert;
nsString mEncryptionCertName;
nsAutoCString mEncryptionCertDBKey;
nsCOMPtr<nsIX509Cert> mSelfEncryptionCert;
nsCOMPtr<nsIMutableArray> mCerts;
nsCOMPtr<nsICMSMessage> mEncryptionCinfo;
nsCOMPtr<nsICMSEncoder> mEncryptionContext;
nsCOMPtr<nsIStringBundle> mSMIMEBundle;
nsAutoPtr<MimeEncoder> mCryptoEncoder;
bool mIsDraft;
enum {eBufferSize = 8192};
char *mBuffer;
uint32_t mBufferedBytes;
bool mErrorAlreadyReported;
void SetError(nsIMsgSendReport *sendReport, const char16_t *bundle_string);
void SetErrorWithParam(nsIMsgSendReport *sendReport, const char16_t *bundle_string, const char *param);
};
#endif

View file

@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef nsMsgSMIMECID_h__
#define nsMsgSMIMECID_h__
#include "nsISupports.h"
#include "nsIFactory.h"
#include "nsIComponentManager.h"
#define NS_MSGSMIMECOMPFIELDS_CONTRACTID \
"@mozilla.org/messenger-smime/composefields;1"
#define NS_MSGSMIMECOMPFIELDS_CID \
{ /* 122C919C-96B7-49a0-BBC8-0ABC67EEFFE0 */ \
0x122c919c, 0x96b7, 0x49a0, \
{ 0xbb, 0xc8, 0xa, 0xbc, 0x67, 0xee, 0xff, 0xe0 }}
#define NS_MSGCOMPOSESECURE_CID \
{ /* dd753201-9a23-4e08-957f-b3616bf7e012 */ \
0xdd753201, 0x9a23, 0x4e08, \
{0x95, 0x7f, 0xb3, 0x61, 0x6b, 0xf7, 0xe0, 0x12 }}
#define NS_SMIMEJSHELPER_CONTRACTID \
"@mozilla.org/messenger-smime/smimejshelper;1"
#define NS_SMIMEJSJELPER_CID \
{ /* d57d928c-60e4-4f81-999d-5c762e611205 */ \
0xd57d928c, 0x60e4, 0x4f81, \
{0x99, 0x9d, 0x5c, 0x76, 0x2e, 0x61, 0x12, 0x05 }}
#define NS_SMIMEENCRYPTURISERVICE_CONTRACTID \
"@mozilla.org/messenger-smime/smime-encrypted-uris-service;1"
#define NS_SMIMEENCRYPTURISERVICE_CID \
{ /* a0134d58-018f-4d40-a099-fa079e5024a6 */ \
0xa0134d58, 0x018f, 0x4d40, \
{0xa0, 0x99, 0xfa, 0x07, 0x9e, 0x50, 0x24, 0xa6 }}
#endif // nsMsgSMIMECID_h__

View file

@ -0,0 +1,335 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "mozilla/mailnews/MimeHeaderParser.h"
#include "nspr.h"
#include "nsSMimeJSHelper.h"
#include "nsCOMPtr.h"
#include "nsMemory.h"
#include "nsStringGlue.h"
#include "nsIX509CertDB.h"
#include "nsIX509CertValidity.h"
#include "nsIServiceManager.h"
#include "nsServiceManagerUtils.h"
#include "nsCRTGlue.h"
using namespace mozilla::mailnews;
NS_IMPL_ISUPPORTS(nsSMimeJSHelper, nsISMimeJSHelper)
nsSMimeJSHelper::nsSMimeJSHelper()
{
}
nsSMimeJSHelper::~nsSMimeJSHelper()
{
}
NS_IMETHODIMP nsSMimeJSHelper::GetRecipientCertsInfo(
nsIMsgCompFields *compFields,
uint32_t *count,
char16_t ***emailAddresses,
int32_t **certVerification,
char16_t ***certIssuedInfos,
char16_t ***certExpiresInfos,
nsIX509Cert ***certs,
bool *canEncrypt)
{
NS_ENSURE_ARG_POINTER(count);
*count = 0;
NS_ENSURE_ARG_POINTER(emailAddresses);
NS_ENSURE_ARG_POINTER(certVerification);
NS_ENSURE_ARG_POINTER(certIssuedInfos);
NS_ENSURE_ARG_POINTER(certExpiresInfos);
NS_ENSURE_ARG_POINTER(certs);
NS_ENSURE_ARG_POINTER(canEncrypt);
NS_ENSURE_ARG_POINTER(compFields);
nsTArray<nsCString> mailboxes;
nsresult rv = getMailboxList(compFields, mailboxes);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t mailbox_count = mailboxes.Length();
nsCOMPtr<nsIX509CertDB> certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
*count = mailbox_count;
*canEncrypt = false;
rv = NS_OK;
if (mailbox_count)
{
char16_t **outEA = static_cast<char16_t **>(moz_xmalloc(mailbox_count * sizeof(char16_t *)));
int32_t *outCV = static_cast<int32_t *>(moz_xmalloc(mailbox_count * sizeof(int32_t)));
char16_t **outCII = static_cast<char16_t **>(moz_xmalloc(mailbox_count * sizeof(char16_t *)));
char16_t **outCEI = static_cast<char16_t **>(moz_xmalloc(mailbox_count * sizeof(char16_t *)));
nsIX509Cert **outCerts = static_cast<nsIX509Cert **>(moz_xmalloc(mailbox_count * sizeof(nsIX509Cert *)));
if (!outEA || !outCV || !outCII || !outCEI || !outCerts)
{
free(outEA);
free(outCV);
free(outCII);
free(outCEI);
free(outCerts);
rv = NS_ERROR_OUT_OF_MEMORY;
}
else
{
char16_t **iEA = outEA;
int32_t *iCV = outCV;
char16_t **iCII = outCII;
char16_t **iCEI = outCEI;
nsIX509Cert **iCert = outCerts;
bool found_blocker = false;
bool memory_failure = false;
for (uint32_t i = 0;
i < mailbox_count;
++i, ++iEA, ++iCV, ++iCII, ++iCEI, ++iCert)
{
*iCert = nullptr;
*iCV = 0;
*iCII = nullptr;
*iCEI = nullptr;
if (memory_failure) {
*iEA = nullptr;
continue;
}
nsCString &email = mailboxes[i];
*iEA = ToNewUnicode(NS_ConvertUTF8toUTF16(email));
if (!*iEA) {
memory_failure = true;
continue;
}
nsCString email_lowercase;
ToLowerCase(email, email_lowercase);
nsCOMPtr<nsIX509Cert> cert;
if (NS_SUCCEEDED(certdb->FindCertByEmailAddress(
email_lowercase.get(), getter_AddRefs(cert))))
{
*iCert = cert;
NS_ADDREF(*iCert);
nsCOMPtr<nsIX509CertValidity> validity;
rv = cert->GetValidity(getter_AddRefs(validity));
if (NS_SUCCEEDED(rv)) {
nsString id, ed;
if (NS_SUCCEEDED(validity->GetNotBeforeLocalDay(id)))
{
*iCII = ToNewUnicode(id);
if (!*iCII) {
memory_failure = true;
continue;
}
}
if (NS_SUCCEEDED(validity->GetNotAfterLocalDay(ed)))
{
*iCEI = ToNewUnicode(ed);
if (!*iCEI) {
memory_failure = true;
continue;
}
}
}
}
else
{
found_blocker = true;
}
}
if (memory_failure) {
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mailbox_count, outEA);
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mailbox_count, outCII);
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(mailbox_count, outCEI);
NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(mailbox_count, outCerts);
free(outCV);
rv = NS_ERROR_OUT_OF_MEMORY;
}
else {
if (mailbox_count > 0 && !found_blocker)
{
*canEncrypt = true;
}
*emailAddresses = outEA;
*certVerification = outCV;
*certIssuedInfos = outCII;
*certExpiresInfos = outCEI;
*certs = outCerts;
}
}
}
return rv;
}
NS_IMETHODIMP nsSMimeJSHelper::GetNoCertAddresses(
nsIMsgCompFields *compFields,
uint32_t *count,
char16_t ***emailAddresses)
{
NS_ENSURE_ARG_POINTER(count);
*count = 0;
NS_ENSURE_ARG_POINTER(emailAddresses);
NS_ENSURE_ARG_POINTER(compFields);
nsTArray<nsCString> mailboxes;
nsresult rv = getMailboxList(compFields, mailboxes);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t mailbox_count = mailboxes.Length();
if (!mailbox_count)
{
*count = 0;
*emailAddresses = nullptr;
return NS_OK;
}
nsCOMPtr<nsIX509CertDB> certdb = do_GetService(NS_X509CERTDB_CONTRACTID);
uint32_t missing_count = 0;
bool *haveCert = new bool[mailbox_count];
if (!haveCert)
{
return NS_ERROR_OUT_OF_MEMORY;
}
rv = NS_OK;
if (mailbox_count)
{
for (uint32_t i = 0; i < mailbox_count; ++i)
{
haveCert[i] = false;
nsCString email_lowercase;
ToLowerCase(mailboxes[i], email_lowercase);
nsCOMPtr<nsIX509Cert> cert;
if (NS_SUCCEEDED(certdb->FindCertByEmailAddress(
email_lowercase.get(), getter_AddRefs(cert))))
haveCert[i] = true;
if (!haveCert[i])
++missing_count;
}
}
*count = missing_count;
if (missing_count)
{
char16_t **outEA = static_cast<char16_t **>(moz_xmalloc(missing_count * sizeof(char16_t *)));
if (!outEA )
{
rv = NS_ERROR_OUT_OF_MEMORY;
}
else
{
char16_t **iEA = outEA;
bool memory_failure = false;
for (uint32_t i = 0; i < mailbox_count; ++i)
{
if (!haveCert[i])
{
if (memory_failure) {
*iEA = nullptr;
}
else {
*iEA = ToNewUnicode(NS_ConvertUTF8toUTF16(mailboxes[i]));
if (!*iEA) {
memory_failure = true;
}
}
++iEA;
}
}
if (memory_failure) {
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(missing_count, outEA);
rv = NS_ERROR_OUT_OF_MEMORY;
}
else {
*emailAddresses = outEA;
}
}
}
else
{
*emailAddresses = nullptr;
}
delete [] haveCert;
return rv;
}
nsresult nsSMimeJSHelper::getMailboxList(nsIMsgCompFields *compFields,
nsTArray<nsCString> &mailboxes)
{
if (!compFields)
return NS_ERROR_INVALID_ARG;
nsresult res;
nsString to, cc, bcc, ng;
res = compFields->GetTo(to);
if (NS_FAILED(res))
return res;
res = compFields->GetCc(cc);
if (NS_FAILED(res))
return res;
res = compFields->GetBcc(bcc);
if (NS_FAILED(res))
return res;
res = compFields->GetNewsgroups(ng);
if (NS_FAILED(res))
return res;
{
nsCString all_recipients;
if (!to.IsEmpty()) {
all_recipients.Append(NS_ConvertUTF16toUTF8(to));
all_recipients.Append(',');
}
if (!cc.IsEmpty()) {
all_recipients.Append(NS_ConvertUTF16toUTF8(cc));
all_recipients.Append(',');
}
if (!bcc.IsEmpty()) {
all_recipients.Append(NS_ConvertUTF16toUTF8(bcc));
all_recipients.Append(',');
}
if (!ng.IsEmpty())
all_recipients.Append(NS_ConvertUTF16toUTF8(ng));
ExtractEmails(EncodedHeader(all_recipients),
UTF16ArrayAdapter<>(mailboxes));
}
return NS_OK;
}

View file

@ -0,0 +1,26 @@
/* 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/. */
#ifndef _nsSMimeJSHelper_H_
#define _nsSMimeJSHelper_H_
#include "nsISMimeJSHelper.h"
#include "nsIX509Cert.h"
#include "nsIMsgCompFields.h"
class nsSMimeJSHelper : public nsISMimeJSHelper
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISMIMEJSHELPER
nsSMimeJSHelper();
private:
virtual ~nsSMimeJSHelper();
nsresult getMailboxList(nsIMsgCompFields *compFields,
nsTArray<nsCString> &mailboxes);
};
#endif

View file

@ -0,0 +1,24 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* 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/. */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
function SMIMEService() {}
SMIMEService.prototype = {
name: "smime",
chromePackageName: "messenger",
showPanel: function(server) {
// don't show the panel for news, rss, or local accounts
return (server.type != "nntp" && server.type != "rss" &&
server.type != "im" && server.type != "none");
},
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIMsgAccountManagerExtension]),
classID: Components.ID("{f2809796-1dd1-11b2-8c1b-8f15f007c699}"),
};
var components = [SMIMEService];
var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);

View file

@ -0,0 +1,3 @@
component {f2809796-1dd1-11b2-8c1b-8f15f007c699} smime-service.js
contract @mozilla.org/accountmanager/extension;1?name=smime {f2809796-1dd1-11b2-8c1b-8f15f007c699}
category mailnews-accountmanager-extensions smime-account-manager-extension @mozilla.org/accountmanager/extension;1?name=smime