Free the (distributed) Lizard! Automatic merge from CVS: Module mozilla: tag HG_REPO_INITIAL_IMPORT at 22 Mar 2007 10:30 PDT,
authorhg@mozilla.com
Thu, 22 Mar 2007 10:30:00 -0700
changeset 20349 2f69e0a3a05a4ca457c2d1472151573cf3825f59
child 20350 1a2269db784268294c185062ad1fccc7d6b552c9
push id1209
push usermbanner@mozilla.com
push dateTue, 02 Sep 2014 16:59:36 +0000
treeherdercomm-beta@842e0fd167ee [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
Free the (distributed) Lizard! Automatic merge from CVS: Module mozilla: tag HG_REPO_INITIAL_IMPORT at 22 Mar 2007 10:30 PDT,
mailnews/mime/public/nsICMSDecoder.idl
mailnews/mime/public/nsICMSEncoder.idl
mailnews/mime/public/nsICMSMessage.idl
mailnews/mime/public/nsICMSMessage2.idl
mailnews/mime/public/nsICMSMessageErrors.idl
mailnews/mime/public/nsICMSSecureMessage.idl
mailnews/mime/src/nsCMS.cpp
mailnews/mime/src/nsCMS.h
mailnews/mime/src/nsCMSSecureMessage.cpp
mailnews/mime/src/nsCMSSecureMessage.h
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/public/nsICMSDecoder.idl
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): David Drinan <ddrinan@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+%{ C++
+typedef void (*NSSCMSContentCallback)(void *arg, const char *buf, unsigned long len);
+
+#define NS_CMSDECODER_CONTRACTID "@mozilla.org/nsCMSDecoder;1"
+%}
+
+native NSSCMSContentCallback(NSSCMSContentCallback);
+
+interface nsICMSMessage;
+
+/**
+ * nsICMSDecoder
+ *  Interface to decode an CMS message
+ */
+[uuid(65244a06-a342-11d5-ba47-00108303b117)]
+interface nsICMSDecoder : nsISupports
+{
+  void start(in NSSCMSContentCallback cb, in voidPtr arg);
+  void update(in string aBuf, in long aLen);
+  void finish(out nsICMSMessage msg);
+};
+
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/public/nsICMSEncoder.idl
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): David Drinan <ddrinan@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+%{ C++
+typedef void (*NSSCMSContentCallback)(void *arg, const char *buf, unsigned long len);
+
+#define NS_CMSENCODER_CONTRACTID "@mozilla.org/nsCMSEncoder;1"
+%}
+
+native NSSCMSContentCallback(NSSCMSContentCallback);
+
+interface nsICMSMessage;
+
+/**
+ * nsICMSEncoder
+ *  Interface to Encode an CMS message
+ */
+[uuid(a15789aa-8903-462b-81e9-4aa2cff4d5cb)]
+interface nsICMSEncoder : nsISupports
+{
+  void start(in nsICMSMessage aMsg, in NSSCMSContentCallback cb, in voidPtr arg);
+  void update(in string aBuf, in long aLen);
+  void finish();
+  void encode(in nsICMSMessage aMsg);
+};
+
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/public/nsICMSMessage.idl
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): David Drinan <ddrinan@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+%{ C++
+#define NS_CMSMESSAGE_CONTRACTID "@mozilla.org/nsCMSMessage;1"
+%}
+
+[ptr] native UnsignedCharPtr(unsigned char);
+
+interface nsIX509Cert;
+interface nsIArray;
+
+/**
+ * nsICMSMessage
+ *  Interface to a CMS Message
+ */
+[uuid(a4557478-ae16-11d5-ba4b-00108303b117)]
+interface nsICMSMessage : nsISupports
+{
+  void contentIsSigned(out boolean aSigned);
+  void contentIsEncrypted(out boolean aEncrypted);
+  void getSignerCommonName(out string aName);
+  void getSignerEmailAddress(out string aEmail);
+  void getSignerCert(out nsIX509Cert scert);
+  void getEncryptionCert(out nsIX509Cert ecert);
+  void verifySignature();
+  void verifyDetachedSignature(in UnsignedCharPtr aDigestData, in unsigned long aDigestDataLen);
+  void CreateEncrypted(in nsIArray aRecipientCerts);
+  void CreateSigned(in nsIX509Cert scert, in nsIX509Cert ecert, in UnsignedCharPtr aDigestData, in unsigned long aDigestDataLen);
+};
+
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/public/nsICMSMessage2.idl
@@ -0,0 +1,97 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Red Hat, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Kai Engert <kengert@redhat.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsISMimeVerificationListener;
+
+[ptr] native UnsignedCharPtr(unsigned char);
+
+/*
+ * This interface is currently not marked scriptable,
+ * because its verification functions are meant to look like those
+ * in nsICMSMessage. At the time the ptr type is eliminated in both 
+ * interfaces, both should be made scriptable.
+ */
+
+[uuid(a99a3203-39e3-45e1-909c-175b0e471c2b)]
+interface nsICMSMessage2 : nsISupports
+{
+  /**
+    * Async version of nsICMSMessage::VerifySignature.
+    * Code will be executed on a background thread and
+    * availability of results will be notified using a 
+    * call to nsISMimeVerificationListener.
+   */
+  void asyncVerifySignature(in nsISMimeVerificationListener listener);
+  
+  /**
+    * Async version of nsICMSMessage::VerifyDetachedSignature.
+    * Code will be executed on a background thread and
+    * availability of results will be notified using a 
+    * call to nsISMimeVerificationListener.
+    *
+    * We are using "native unsigned char" ptr, because the function 
+    * signatures of this one and nsICMSMessage::verifyDetachedSignature 
+    * should be the identical. Cleaning up nsICMSMessages needs to be
+    * postponed, because this async version is needed on MOZILLA_1_8_BRANCH.
+    *
+    * Once both interfaces get cleaned up, the function signature should
+    * look like:
+    *     [array, length_is(aDigestDataLen)]
+    *     in octet aDigestData,
+    *     in unsigned long aDigestDataLen);
+   */
+  void asyncVerifyDetachedSignature(in nsISMimeVerificationListener listener,
+                                     in UnsignedCharPtr aDigestData, 
+                                     in unsigned long aDigestDataLen);
+};
+
+[uuid(56310af6-dffc-48b4-abca-85eae4059064)]
+interface nsISMimeVerificationListener : nsISupports {
+
+  /**
+   *  Notify that results are ready, that have been requested
+   *  using nsICMSMessage2::asyncVerify[Detached]Signature()
+   *
+   *  verificationResultCode matches synchronous result code from
+   *  nsICMSMessage::verify[Detached]Signature
+   */
+  void notify(in nsICMSMessage2 verifiedMessage,
+              in nsresult verificationResultCode);
+};
+
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/public/nsICMSMessageErrors.idl
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): David Drinan <ddrinan@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+/**
+ * nsICMSMessageErrors
+ *  Scriptable error constants for nsICMSMessage
+ */
+[scriptable,uuid(f2aec680-60a0-49f0-afe5-6cf1d3f15e0d)]
+interface nsICMSMessageErrors : nsISupports
+{
+  const long SUCCESS = 0;
+  const long GENERAL_ERROR = 1;
+  const long VERIFY_NOT_SIGNED = 1024;
+  const long VERIFY_NO_CONTENT_INFO = 1025;
+  const long VERIFY_BAD_DIGEST = 1026;
+  const long VERIFY_NOCERT = 1028;
+  const long VERIFY_UNTRUSTED = 1029;
+  const long VERIFY_ERROR_UNVERIFIED = 1031;
+  const long VERIFY_ERROR_PROCESSING = 1032;
+  const long VERIFY_BAD_SIGNATURE = 1033;
+  const long VERIFY_DIGEST_MISMATCH = 1034;
+  const long VERIFY_UNKNOWN_ALGO = 1035;
+  const long VERIFY_UNSUPPORTED_ALGO = 1036;
+  const long VERIFY_MALFORMED_SIGNATURE = 1037;
+  const long VERIFY_HEADER_MISMATCH = 1038;
+  const long VERIFY_NOT_YET_ATTEMPTED = 1039;
+  const long VERIFY_CERT_WITHOUT_ADDRESS = 1040;
+
+  const long ENCRYPT_NO_BULK_ALG = 1056;
+};
+
+%{ C++
+/**
+ * CMS specific nsresult error codes
+ */
+
+#define NS_ERROR_CMS_VERIFY_NOT_SIGNED \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_NOT_SIGNED)
+#define NS_ERROR_CMS_VERIFY_NO_CONTENT_INFO \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_NO_CONTENT_INFO)
+#define NS_ERROR_CMS_VERIFY_BAD_DIGEST \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_BAD_DIGEST)
+#define NS_ERROR_CMS_VERIFY_NOCERT \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_NOCERT)
+#define NS_ERROR_CMS_VERIFY_UNTRUSTED \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_UNTRUSTED)
+#define NS_ERROR_CMS_VERIFY_ERROR_UNVERIFIED \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_ERROR_UNVERIFIED)
+#define NS_ERROR_CMS_VERIFY_ERROR_PROCESSING \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_ERROR_PROCESSING)
+#define NS_ERROR_CMS_VERIFY_BAD_SIGNATURE \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_BAD_SIGNATURE)
+#define NS_ERROR_CMS_VERIFY_DIGEST_MISMATCH \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_DIGEST_MISMATCH)
+#define NS_ERROR_CMS_VERIFY_UNKNOWN_ALGO \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_UNKNOWN_ALGO)
+#define NS_ERROR_CMS_VERIFY_UNSUPPORTED_ALGO \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_UNSUPPORTED_ALGO)
+#define NS_ERROR_CMS_VERIFY_MALFORMED_SIGNATURE \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_MALFORMED_SIGNATURE)
+#define NS_ERROR_CMS_VERIFY_HEADER_MISMATCH \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_HEADER_MISMATCH)
+#define NS_ERROR_CMS_VERIFY_NOT_YET_ATTEMPTED \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_NOT_YET_ATTEMPTED)
+#define NS_ERROR_CMS_VERIFY_CERT_WITHOUT_ADDRESS \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::VERIFY_CERT_WITHOUT_ADDRESS)
+#define NS_ERROR_CMS_ENCRYPT_NO_BULK_ALG \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_SECURITY, \
+                            nsICMSMessageErrors::ENCRYPT_NO_BULK_ALG)
+%}
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/public/nsICMSSecureMessage.idl
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Terry Hayes <thayes@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIX509Cert;
+
+/**
+ * nsICMSManager (service)
+ *  Interface to access users certificate store
+ */
+[scriptable, uuid(14b4394a-1dd2-11b2-b4fd-ba4a194fe97e)]
+interface nsICMSSecureMessage : nsISupports
+{
+  /**
+   * getCertByPrefID - a BASE64 string representing a user's
+   *   certificate (or NULL if there isn't one)
+   */
+  string getCertByPrefID(in string certID);
+
+  /**
+   * decodeCert - decode a BASE64 string into an X509Certificate object
+   */
+  nsIX509Cert decodeCert(in string value);
+
+  /**
+   * sendMessage - send a text message to the recipient indicated
+   *   by the base64-encoded cert.
+   */
+  string sendMessage(in string msg, in string cert);
+
+  /**
+   * receiveMessage - recieve an encrypted (enveloped) message
+   */
+  string receiveMessage(in string msg);
+};
+
+%{C++
+#define NS_CMSSECUREMESSAGE_CONTRACTID "@mozilla.org/nsCMSSecureMessage;1"
+%}
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/src/nsCMS.cpp
@@ -0,0 +1,932 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): David Drinan <ddrinan@netscape.com>
+ *   Kai Engert <kengert@redhat.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.h"
+#include "nsCMS.h"
+#include "nsNSSHelper.h"
+#include "nsNSSCertificate.h"
+#include "smime.h"
+#include "cms.h"
+#include "nsICMSMessageErrors.h"
+#include "nsIArray.h"
+#include "nsArrayUtils.h"
+#include "nsCertVerificationThread.h"
+
+#include "prlog.h"
+#ifdef PR_LOGGING
+extern PRLogModuleInfo* gPIPNSSLog;
+#endif
+
+#include "nsNSSCleaner.h"
+
+NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate)
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(nsCMSMessage, nsICMSMessage, 
+                                            nsICMSMessage2)
+
+nsCMSMessage::nsCMSMessage()
+{
+  m_cmsMsg = nsnull;
+}
+nsCMSMessage::nsCMSMessage(NSSCMSMessage *aCMSMsg)
+{
+  m_cmsMsg = aCMSMsg;
+}
+
+nsCMSMessage::~nsCMSMessage()
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return;
+
+  destructorSafeDestroyNSSReference();
+  shutdown(calledFromObject);
+}
+
+void nsCMSMessage::virtualDestroyNSSReference()
+{
+  destructorSafeDestroyNSSReference();
+}
+
+void nsCMSMessage::destructorSafeDestroyNSSReference()
+{
+  if (isAlreadyShutDown())
+    return;
+
+  if (m_cmsMsg) {
+    NSS_CMSMessage_Destroy(m_cmsMsg);
+  }
+}
+
+NS_IMETHODIMP nsCMSMessage::VerifySignature()
+{
+  return CommonVerifySignature(nsnull, 0);
+}
+
+NSSCMSSignerInfo* nsCMSMessage::GetTopLevelSignerInfo()
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return nsnull;
+
+  if (!m_cmsMsg)
+    return nsnull;
+
+  if (!NSS_CMSMessage_IsSigned(m_cmsMsg))
+    return nsnull;
+
+  NSSCMSContentInfo *cinfo = NSS_CMSMessage_ContentLevel(m_cmsMsg, 0);
+  if (!cinfo)
+    return nsnull;
+
+  NSSCMSSignedData *sigd = (NSSCMSSignedData*)NSS_CMSContentInfo_GetContent(cinfo);
+  if (!sigd)
+    return nsnull;
+
+  PR_ASSERT(NSS_CMSSignedData_SignerInfoCount(sigd) > 0);
+  return NSS_CMSSignedData_GetSignerInfo(sigd, 0);
+}
+
+NS_IMETHODIMP nsCMSMessage::GetSignerEmailAddress(char * * aEmail)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::GetSignerEmailAddress\n"));
+  NS_ENSURE_ARG(aEmail);
+
+  NSSCMSSignerInfo *si = GetTopLevelSignerInfo();
+  if (!si)
+    return NS_ERROR_FAILURE;
+
+  *aEmail = NSS_CMSSignerInfo_GetSignerEmailAddress(si);
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsCMSMessage::GetSignerCommonName(char ** aName)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::GetSignerCommonName\n"));
+  NS_ENSURE_ARG(aName);
+
+  NSSCMSSignerInfo *si = GetTopLevelSignerInfo();
+  if (!si)
+    return NS_ERROR_FAILURE;
+
+  *aName = NSS_CMSSignerInfo_GetSignerCommonName(si);
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsCMSMessage::ContentIsEncrypted(PRBool *isEncrypted)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::ContentIsEncrypted\n"));
+  NS_ENSURE_ARG(isEncrypted);
+
+  if (!m_cmsMsg)
+    return NS_ERROR_FAILURE;
+
+  *isEncrypted = NSS_CMSMessage_IsEncrypted(m_cmsMsg);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsCMSMessage::ContentIsSigned(PRBool *isSigned)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::ContentIsSigned\n"));
+  NS_ENSURE_ARG(isSigned);
+
+  if (!m_cmsMsg)
+    return NS_ERROR_FAILURE;
+
+  *isSigned = NSS_CMSMessage_IsSigned(m_cmsMsg);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsCMSMessage::GetSignerCert(nsIX509Cert **scert)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  NSSCMSSignerInfo *si = GetTopLevelSignerInfo();
+  if (!si)
+    return NS_ERROR_FAILURE;
+
+  if (si->cert) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::GetSignerCert got signer cert\n"));
+
+    *scert = new nsNSSCertificate(si->cert);
+    if (*scert) {
+      (*scert)->AddRef();
+    }
+  }
+  else {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::GetSignerCert no signer cert, do we have a cert list? %s\n",
+      (si->certList != nsnull ? "yes" : "no") ));
+
+    *scert = nsnull;
+  }
+  
+  return NS_OK;
+}
+
+NS_IMETHODIMP nsCMSMessage::GetEncryptionCert(nsIX509Cert **ecert)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP nsCMSMessage::VerifyDetachedSignature(unsigned char* aDigestData, PRUint32 aDigestDataLen)
+{
+  if (!aDigestData || !aDigestDataLen)
+    return NS_ERROR_FAILURE;
+
+  return CommonVerifySignature(aDigestData, aDigestDataLen);
+}
+
+nsresult nsCMSMessage::CommonVerifySignature(unsigned char* aDigestData, PRUint32 aDigestDataLen)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature, content level count %d\n", NSS_CMSMessage_ContentLevelCount(m_cmsMsg)));
+  NSSCMSContentInfo *cinfo = nsnull;
+  NSSCMSSignedData *sigd = nsnull;
+  NSSCMSSignerInfo *si;
+  PRInt32 nsigners;
+  nsresult rv = NS_ERROR_FAILURE;
+
+  if (NSS_CMSMessage_IsSigned(m_cmsMsg) == PR_FALSE) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - not signed\n"));
+    return NS_ERROR_CMS_VERIFY_NOT_SIGNED;
+  } 
+
+  cinfo = NSS_CMSMessage_ContentLevel(m_cmsMsg, 0);
+  if (cinfo) {
+    // I don't like this hard cast. We should check in some way, that we really have this type.
+    sigd = (NSSCMSSignedData*)NSS_CMSContentInfo_GetContent(cinfo);
+  }
+  
+  if (!sigd) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - no content info\n"));
+    rv = NS_ERROR_CMS_VERIFY_NO_CONTENT_INFO;
+    goto loser;
+  }
+
+  if (aDigestData && aDigestDataLen)
+  {
+    SECItem digest;
+    digest.data = aDigestData;
+    digest.len = aDigestDataLen;
+
+    if (NSS_CMSSignedData_SetDigestValue(sigd, SEC_OID_SHA1, &digest)) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - bad digest\n"));
+      rv = NS_ERROR_CMS_VERIFY_BAD_DIGEST;
+      goto loser;
+    }
+  }
+
+  // Import certs. Note that import failure is not a signature verification failure. //
+  if (NSS_CMSSignedData_ImportCerts(sigd, CERT_GetDefaultCertDB(), certUsageEmailRecipient, PR_TRUE) != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - can not import certs\n"));
+  }
+
+  nsigners = NSS_CMSSignedData_SignerInfoCount(sigd);
+  PR_ASSERT(nsigners > 0);
+  si = NSS_CMSSignedData_GetSignerInfo(sigd, 0);
+
+
+  // See bug 324474. We want to make sure the signing cert is 
+  // still valid at the current time.
+  if (CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), si->cert, PR_TRUE, 
+                                certificateUsageEmailSigner,
+                                si->cmsg->pwfn_arg, NULL) != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - signing cert not trusted now\n"));
+    rv = NS_ERROR_CMS_VERIFY_UNTRUSTED;
+    goto loser;
+  }
+
+  // We verify the first signer info,  only //
+  if (NSS_CMSSignedData_VerifySignerInfo(sigd, 0, CERT_GetDefaultCertDB(), certUsageEmailSigner) != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - unable to verify signature\n"));
+
+    if (NSSCMSVS_SigningCertNotFound == si->verificationStatus) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - signing cert not found\n"));
+      rv = NS_ERROR_CMS_VERIFY_NOCERT;
+    }
+    else if(NSSCMSVS_SigningCertNotTrusted == si->verificationStatus) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - signing cert not trusted at signing time\n"));
+      rv = NS_ERROR_CMS_VERIFY_UNTRUSTED;
+    }
+    else if(NSSCMSVS_Unverified == si->verificationStatus) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - can not verify\n"));
+      rv = NS_ERROR_CMS_VERIFY_ERROR_UNVERIFIED;
+    }
+    else if(NSSCMSVS_ProcessingError == si->verificationStatus) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - processing error\n"));
+      rv = NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
+    }
+    else if(NSSCMSVS_BadSignature == si->verificationStatus) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - bad signature\n"));
+      rv = NS_ERROR_CMS_VERIFY_BAD_SIGNATURE;
+    }
+    else if(NSSCMSVS_DigestMismatch == si->verificationStatus) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - digest mismatch\n"));
+      rv = NS_ERROR_CMS_VERIFY_DIGEST_MISMATCH;
+    }
+    else if(NSSCMSVS_SignatureAlgorithmUnknown == si->verificationStatus) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - algo unknown\n"));
+      rv = NS_ERROR_CMS_VERIFY_UNKNOWN_ALGO;
+    }
+    else if(NSSCMSVS_SignatureAlgorithmUnsupported == si->verificationStatus) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - algo not supported\n"));
+      rv = NS_ERROR_CMS_VERIFY_UNSUPPORTED_ALGO;
+    }
+    else if(NSSCMSVS_MalformedSignature == si->verificationStatus) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - malformed signature\n"));
+      rv = NS_ERROR_CMS_VERIFY_MALFORMED_SIGNATURE;
+    }
+
+    goto loser;
+  }
+
+  // Save the profile. Note that save import failure is not a signature verification failure. //
+  if (NSS_SMIMESignerInfo_SaveSMIMEProfile(si) != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - unable to save smime profile\n"));
+  }
+
+  rv = NS_OK;
+loser:
+  return rv;
+}
+
+NS_IMETHODIMP nsCMSMessage::AsyncVerifySignature(
+                              nsISMimeVerificationListener *aListener)
+{
+  return CommonAsyncVerifySignature(aListener, nsnull, 0);
+}
+
+NS_IMETHODIMP nsCMSMessage::AsyncVerifyDetachedSignature(
+                              nsISMimeVerificationListener *aListener,
+                              unsigned char* aDigestData, PRUint32 aDigestDataLen)
+{
+  if (!aDigestData || !aDigestDataLen)
+    return NS_ERROR_FAILURE;
+
+  return CommonAsyncVerifySignature(aListener, aDigestData, aDigestDataLen);
+}
+
+nsresult nsCMSMessage::CommonAsyncVerifySignature(nsISMimeVerificationListener *aListener,
+                                                  unsigned char* aDigestData, PRUint32 aDigestDataLen)
+{
+  nsSMimeVerificationJob *job = new nsSMimeVerificationJob;
+  if (!job)
+    return NS_ERROR_OUT_OF_MEMORY;
+  
+  if (aDigestData)
+  {
+    job->digest_data = new unsigned char[aDigestDataLen];
+    if (!job->digest_data)
+    {
+      delete job;
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+    
+    memcpy(job->digest_data, aDigestData, aDigestDataLen);
+  }
+  else
+  {
+    job->digest_data = nsnull;
+  }
+  
+  job->digest_len = aDigestDataLen;
+  job->mMessage = this;
+  job->mListener = aListener;
+
+  nsresult rv = nsCertVerificationThread::addJob(job);
+  if (NS_FAILED(rv))
+    delete job;
+
+  return rv;
+}
+
+class nsZeroTerminatedCertArray : public nsNSSShutDownObject
+{
+public:
+  nsZeroTerminatedCertArray()
+  :mCerts(nsnull), mPoolp(nsnull), mSize(0)
+  {
+  }
+  
+  ~nsZeroTerminatedCertArray()
+  {
+    nsNSSShutDownPreventionLock locker;
+    if (isAlreadyShutDown())
+      return;
+
+    destructorSafeDestroyNSSReference();
+    shutdown(calledFromObject);
+  }
+
+  void virtualDestroyNSSReference()
+  {
+    destructorSafeDestroyNSSReference();
+  }
+
+  void destructorSafeDestroyNSSReference()
+  {
+    if (isAlreadyShutDown())
+      return;
+
+    if (mCerts)
+    {
+      for (PRUint32 i=0; i < mSize; i++) {
+        if (mCerts[i]) {
+          CERT_DestroyCertificate(mCerts[i]);
+        }
+      }
+    }
+
+    if (mPoolp)
+      PORT_FreeArena(mPoolp, PR_FALSE);
+  }
+
+  PRBool allocate(PRUint32 count)
+  {
+    // only allow allocation once
+    if (mPoolp)
+      return PR_FALSE;
+  
+    mSize = count;
+
+    if (!mSize)
+      return PR_FALSE;
+  
+    mPoolp = PORT_NewArena(1024);
+    if (!mPoolp)
+      return PR_FALSE;
+
+    mCerts = (CERTCertificate**)PORT_ArenaZAlloc(
+      mPoolp, (count+1)*sizeof(CERTCertificate*));
+
+    if (!mCerts)
+      return PR_FALSE;
+
+    // null array, including zero termination
+    for (PRUint32 i = 0; i < count+1; i++) {
+      mCerts[i] = nsnull;
+    }
+
+    return PR_TRUE;
+  }
+  
+  void set(PRUint32 i, CERTCertificate *c)
+  {
+    nsNSSShutDownPreventionLock locker;
+    if (isAlreadyShutDown())
+      return;
+
+    if (i >= mSize)
+      return;
+    
+    if (mCerts[i]) {
+      CERT_DestroyCertificate(mCerts[i]);
+    }
+    
+    mCerts[i] = CERT_DupCertificate(c);
+  }
+  
+  CERTCertificate *get(PRUint32 i)
+  {
+    nsNSSShutDownPreventionLock locker;
+    if (isAlreadyShutDown())
+      return nsnull;
+
+    if (i >= mSize)
+      return nsnull;
+    
+    return CERT_DupCertificate(mCerts[i]);
+  }
+
+  CERTCertificate **getRawArray()
+  {
+    nsNSSShutDownPreventionLock locker;
+    if (isAlreadyShutDown())
+      return nsnull;
+
+    return mCerts;
+  }
+
+private:
+  CERTCertificate **mCerts;
+  PLArenaPool *mPoolp;
+  PRUint32 mSize;
+};
+
+NS_IMETHODIMP nsCMSMessage::CreateEncrypted(nsIArray * aRecipientCerts)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateEncrypted\n"));
+  NSSCMSContentInfo *cinfo;
+  NSSCMSEnvelopedData *envd;
+  NSSCMSRecipientInfo *recipientInfo;
+  nsZeroTerminatedCertArray recipientCerts;
+  SECOidTag bulkAlgTag;
+  int keySize;
+  PRUint32 i;
+  nsCOMPtr<nsIX509Cert2> nssRecipientCert;
+  nsresult rv = NS_ERROR_FAILURE;
+
+  // Check the recipient certificates //
+  PRUint32 recipientCertCount;
+  aRecipientCerts->GetLength(&recipientCertCount);
+  PR_ASSERT(recipientCertCount > 0);
+
+  if (!recipientCerts.allocate(recipientCertCount)) {
+    goto loser;
+  }
+
+  for (i=0; i<recipientCertCount; i++) {
+    nsCOMPtr<nsIX509Cert> x509cert = do_QueryElementAt(aRecipientCerts, i);
+
+    nssRecipientCert = do_QueryInterface(x509cert);
+
+    if (!nssRecipientCert)
+      return NS_ERROR_FAILURE;
+
+    CERTCertificate *c = nssRecipientCert->GetCert();
+    CERTCertificateCleaner rcCleaner(c);
+    recipientCerts.set(i, c);
+  }
+  
+  // Find a bulk key algorithm //
+  if (NSS_SMIMEUtil_FindBulkAlgForRecipients(recipientCerts.getRawArray(), &bulkAlgTag,
+                                            &keySize) != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateEncrypted - can't find bulk alg for recipients\n"));
+    rv = NS_ERROR_CMS_ENCRYPT_NO_BULK_ALG;
+    goto loser;
+  }
+
+  m_cmsMsg = NSS_CMSMessage_Create(NULL);
+  if (m_cmsMsg == nsnull) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateEncrypted - can't create new cms message\n"));
+    rv = NS_ERROR_OUT_OF_MEMORY;
+    goto loser;
+  }
+
+  if ((envd = NSS_CMSEnvelopedData_Create(m_cmsMsg, bulkAlgTag, keySize)) == nsnull) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateEncrypted - can't create enveloped data\n"));
+    goto loser;
+  }
+
+  cinfo = NSS_CMSMessage_GetContentInfo(m_cmsMsg);
+  if (NSS_CMSContentInfo_SetContent_EnvelopedData(m_cmsMsg, cinfo, envd) != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateEncrypted - can't create content enveloped data\n"));
+    goto loser;
+  }
+
+  cinfo = NSS_CMSEnvelopedData_GetContentInfo(envd);
+  if (NSS_CMSContentInfo_SetContent_Data(m_cmsMsg, cinfo, nsnull, PR_FALSE) != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateEncrypted - can't set content data\n"));
+    goto loser;
+  }
+
+  // Create and attach recipient information //
+  for (i=0; i < recipientCertCount; i++) {
+    CERTCertificate *rc = recipientCerts.get(i);
+    CERTCertificateCleaner rcCleaner(rc);
+    if ((recipientInfo = NSS_CMSRecipientInfo_Create(m_cmsMsg, rc)) == nsnull) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateEncrypted - can't create recipient info\n"));
+      goto loser;
+    }
+    if (NSS_CMSEnvelopedData_AddRecipient(envd, recipientInfo) != SECSuccess) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateEncrypted - can't add recipient info\n"));
+      goto loser;
+    }
+  }
+
+  return NS_OK;
+loser:
+  if (m_cmsMsg) {
+    NSS_CMSMessage_Destroy(m_cmsMsg);
+    m_cmsMsg = nsnull;
+  }
+
+  return rv;
+}
+
+NS_IMETHODIMP nsCMSMessage::CreateSigned(nsIX509Cert* aSigningCert, nsIX509Cert* aEncryptCert, unsigned char* aDigestData, PRUint32 aDigestDataLen)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned\n"));
+  NSSCMSContentInfo *cinfo;
+  NSSCMSSignedData *sigd;
+  NSSCMSSignerInfo *signerinfo;
+  CERTCertificate *scert = nsnull, *ecert = nsnull;
+  nsCOMPtr<nsIX509Cert2> aSigningCert2 = do_QueryInterface(aSigningCert);
+  nsresult rv = NS_ERROR_FAILURE;
+
+  /* Get the certs */
+  if (aSigningCert2) {
+    scert = aSigningCert2->GetCert();
+  }
+  if (!scert) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (aEncryptCert) {
+    nsCOMPtr<nsIX509Cert2> aEncryptCert2 = do_QueryInterface(aEncryptCert);
+    if (aEncryptCert2) {
+      ecert = aEncryptCert2->GetCert();
+    }
+  }
+
+  CERTCertificateCleaner ecertCleaner(ecert);
+  CERTCertificateCleaner scertCleaner(scert);
+
+  /*
+   * create the message object
+   */
+  m_cmsMsg = NSS_CMSMessage_Create(NULL); /* create a message on its own pool */
+  if (m_cmsMsg == NULL) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't create new message\n"));
+    rv = NS_ERROR_OUT_OF_MEMORY;
+    goto loser;
+  }
+
+  /*
+   * build chain of objects: message->signedData->data
+   */
+  if ((sigd = NSS_CMSSignedData_Create(m_cmsMsg)) == NULL) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't create signed data\n"));
+    goto loser;
+  }
+  cinfo = NSS_CMSMessage_GetContentInfo(m_cmsMsg);
+  if (NSS_CMSContentInfo_SetContent_SignedData(m_cmsMsg, cinfo, sigd) 
+          != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't set content signed data\n"));
+    goto loser;
+  }
+
+  cinfo = NSS_CMSSignedData_GetContentInfo(sigd);
+
+  /* we're always passing data in and detaching optionally */
+  if (NSS_CMSContentInfo_SetContent_Data(m_cmsMsg, cinfo, nsnull, PR_TRUE) 
+          != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't set content data\n"));
+    goto loser;
+  }
+
+  /* 
+   * create & attach signer information
+   */
+  if ((signerinfo = NSS_CMSSignerInfo_Create(m_cmsMsg, scert, SEC_OID_SHA1)) 
+          == NULL) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't create signer info\n"));
+    goto loser;
+  }
+
+  /* we want the cert chain included for this one */
+  if (NSS_CMSSignerInfo_IncludeCerts(signerinfo, NSSCMSCM_CertChain, 
+                                       certUsageEmailSigner) 
+          != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't include signer cert chain\n"));
+    goto loser;
+  }
+
+  if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now()) 
+	      != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't add signing time\n"));
+    goto loser;
+  }
+
+  if (NSS_CMSSignerInfo_AddSMIMECaps(signerinfo) != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't add smime caps\n"));
+    goto loser;
+  }
+
+  if (ecert) {
+    if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, ecert, 
+	                                    CERT_GetDefaultCertDB())
+	  != SECSuccess) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't add smime enc key prefs\n"));
+      goto loser;
+    }
+
+    if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, ecert, 
+	                                    CERT_GetDefaultCertDB())
+	  != SECSuccess) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't add MS smime enc key prefs\n"));
+      goto loser;
+    }
+
+    if (NSS_CMSSignedData_AddCertificate(sigd, ecert) != SECSuccess) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't add own encryption certificate\n"));
+      goto loser;
+    }
+  }
+
+  if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't add signer info\n"));
+    goto loser;
+  }
+
+  // Finally, add the pre-computed digest if passed in
+  if (aDigestData) {
+    SECItem digest;
+
+    digest.data = aDigestData;
+    digest.len = aDigestDataLen;
+
+    if (NSS_CMSSignedData_SetDigestValue(sigd, SEC_OID_SHA1, &digest)) {
+      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CreateSigned - can't set digest value\n"));
+      goto loser;
+    }
+  }
+
+  return NS_OK;
+loser:
+  if (m_cmsMsg) {
+    NSS_CMSMessage_Destroy(m_cmsMsg);
+    m_cmsMsg = nsnull;
+  }
+  return rv;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsCMSDecoder, nsICMSDecoder)
+
+nsCMSDecoder::nsCMSDecoder()
+: m_dcx(nsnull)
+{
+}
+
+nsCMSDecoder::~nsCMSDecoder()
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return;
+
+  destructorSafeDestroyNSSReference();
+  shutdown(calledFromObject);
+}
+
+void nsCMSDecoder::virtualDestroyNSSReference()
+{
+  destructorSafeDestroyNSSReference();
+}
+
+void nsCMSDecoder::destructorSafeDestroyNSSReference()
+{
+  if (isAlreadyShutDown())
+    return;
+
+  if (m_dcx) {
+    NSS_CMSDecoder_Cancel(m_dcx);
+    m_dcx = nsnull;
+  }
+}
+
+/* void start (in NSSCMSContentCallback cb, in voidPtr arg); */
+NS_IMETHODIMP nsCMSDecoder::Start(NSSCMSContentCallback cb, void * arg)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSDecoder::Start\n"));
+  m_ctx = new PipUIContext();
+
+  m_dcx = NSS_CMSDecoder_Start(0, cb, arg, 0, m_ctx, 0, 0);
+  if (!m_dcx) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSDecoder::Start - can't start decoder\n"));
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
+/* void update (in string bug, in long len); */
+NS_IMETHODIMP nsCMSDecoder::Update(const char *buf, PRInt32 len)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSDecoder::Update\n"));
+  NSS_CMSDecoder_Update(m_dcx, (char *)buf, len);
+  return NS_OK;
+}
+
+/* void finish (); */
+NS_IMETHODIMP nsCMSDecoder::Finish(nsICMSMessage ** aCMSMsg)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSDecoder::Finish\n"));
+  NSSCMSMessage *cmsMsg;
+  cmsMsg = NSS_CMSDecoder_Finish(m_dcx);
+  m_dcx = nsnull;
+  if (cmsMsg) {
+    nsCMSMessage *obj = new nsCMSMessage(cmsMsg);
+    // The NSS object cmsMsg still carries a reference to the context
+    // we gave it on construction.
+    // Make sure the context will live long enough.
+    obj->referenceContext(m_ctx);
+    *aCMSMsg = obj;
+    NS_ADDREF(*aCMSMsg);
+  }
+  return NS_OK;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsCMSEncoder, nsICMSEncoder)
+
+nsCMSEncoder::nsCMSEncoder()
+: m_ecx(nsnull)
+{
+}
+
+nsCMSEncoder::~nsCMSEncoder()
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return;
+
+  destructorSafeDestroyNSSReference();
+  shutdown(calledFromObject);
+}
+
+void nsCMSEncoder::virtualDestroyNSSReference()
+{
+  destructorSafeDestroyNSSReference();
+}
+
+void nsCMSEncoder::destructorSafeDestroyNSSReference()
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return;
+
+  if (m_ecx)
+    NSS_CMSEncoder_Cancel(m_ecx);
+}
+
+/* void start (); */
+NS_IMETHODIMP nsCMSEncoder::Start(nsICMSMessage *aMsg, NSSCMSContentCallback cb, void * arg)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSEncoder::Start\n"));
+  nsCMSMessage *cmsMsg = NS_STATIC_CAST(nsCMSMessage*, aMsg);
+  m_ctx = new PipUIContext();
+
+  m_ecx = NSS_CMSEncoder_Start(cmsMsg->getCMS(), cb, arg, 0, 0, 0, m_ctx, 0, 0, 0, 0);
+  if (m_ecx == nsnull) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSEncoder::Start - can't start encoder\n"));
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
+/* void update (in string aBuf, in long aLen); */
+NS_IMETHODIMP nsCMSEncoder::Update(const char *aBuf, PRInt32 aLen)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSEncoder::Update\n"));
+  if (!m_ecx || NSS_CMSEncoder_Update(m_ecx, aBuf, aLen) != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSEncoder::Update - can't update encoder\n"));
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
+/* void finish (); */
+NS_IMETHODIMP nsCMSEncoder::Finish()
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  nsresult rv = NS_OK;
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSEncoder::Finish\n"));
+  if (!m_ecx || NSS_CMSEncoder_Finish(m_ecx) != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSEncoder::Finish - can't finish encoder\n"));
+    rv = NS_ERROR_FAILURE;
+  }
+  m_ecx = nsnull;
+  return rv;
+}
+
+/* void encode (in nsICMSMessage aMsg); */
+NS_IMETHODIMP nsCMSEncoder::Encode(nsICMSMessage *aMsg)
+{
+  nsNSSShutDownPreventionLock locker;
+  if (isAlreadyShutDown())
+    return NS_ERROR_NOT_AVAILABLE;
+
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSEncoder::Encode\n"));
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/src/nsCMS.h
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): David Drinan <ddrinan@netscape.com>
+ *   Kai Engert <kengert@redhat.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef __NS_CMS_H__
+#define __NS_CMS_H__
+
+#include "nsISupports.h"
+#include "nsCOMPtr.h"
+#include "nsXPIDLString.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsICMSMessage.h"
+#include "nsICMSMessage2.h"
+#include "nsIX509Cert3.h"
+#include "nsVerificationJob.h"
+#include "nsICMSEncoder.h"
+#include "nsICMSDecoder.h"
+#include "sechash.h"
+#include "cms.h"
+#include "nsNSSShutDown.h"
+
+#define NS_CMSMESSAGE_CLASSNAME "CMS Message Object"
+#define NS_CMSMESSAGE_CID \
+  { 0xa4557478, 0xae16, 0x11d5, { 0xba,0x4b,0x00,0x10,0x83,0x03,0xb1,0x17 } }
+
+class nsCMSMessage : public nsICMSMessage,
+                     public nsICMSMessage2,
+                     public nsNSSShutDownObject
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSICMSMESSAGE
+  NS_DECL_NSICMSMESSAGE2
+
+  nsCMSMessage();
+  nsCMSMessage(NSSCMSMessage* aCMSMsg);
+  virtual ~nsCMSMessage();
+  
+  void referenceContext(nsIInterfaceRequestor* aContext) {m_ctx = aContext;}
+  NSSCMSMessage* getCMS() {return m_cmsMsg;};
+private:
+  nsCOMPtr<nsIInterfaceRequestor> m_ctx;
+  NSSCMSMessage * m_cmsMsg;
+  NSSCMSSignerInfo* GetTopLevelSignerInfo();
+  nsresult CommonVerifySignature(unsigned char* aDigestData, PRUint32 aDigestDataLen);
+
+  nsresult CommonAsyncVerifySignature(nsISMimeVerificationListener *aListener,
+                                      unsigned char* aDigestData, PRUint32 aDigestDataLen);
+
+  virtual void virtualDestroyNSSReference();
+  void destructorSafeDestroyNSSReference();
+
+friend class nsSMimeVerificationJob;
+};
+
+// ===============================================
+// nsCMSDecoder - implementation of nsICMSDecoder
+// ===============================================
+
+#define NS_CMSDECODER_CLASSNAME "CMS Decoder Object"
+#define NS_CMSDECODER_CID \
+  { 0x9dcef3a4, 0xa3bc, 0x11d5, { 0xba, 0x47, 0x00, 0x10, 0x83, 0x03, 0xb1, 0x17 } }
+
+class nsCMSDecoder : public nsICMSDecoder,
+                     public nsNSSShutDownObject
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSICMSDECODER
+
+  nsCMSDecoder();
+  virtual ~nsCMSDecoder();
+
+private:
+  nsCOMPtr<nsIInterfaceRequestor> m_ctx;
+  NSSCMSDecoderContext *m_dcx;
+  virtual void virtualDestroyNSSReference();
+  void destructorSafeDestroyNSSReference();
+};
+
+// ===============================================
+// nsCMSEncoder - implementation of nsICMSEncoder
+// ===============================================
+
+#define NS_CMSENCODER_CLASSNAME "CMS Decoder Object"
+#define NS_CMSENCODER_CID \
+  { 0xa15789aa, 0x8903, 0x462b, { 0x81, 0xe9, 0x4a, 0xa2, 0xcf, 0xf4, 0xd5, 0xcb } }
+class nsCMSEncoder : public nsICMSEncoder,
+                     public nsNSSShutDownObject
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSICMSENCODER
+
+  nsCMSEncoder();
+  virtual ~nsCMSEncoder();
+
+private:
+  nsCOMPtr<nsIInterfaceRequestor> m_ctx;
+  NSSCMSEncoderContext *m_ecx;
+  virtual void virtualDestroyNSSReference();
+  void destructorSafeDestroyNSSReference();
+};
+
+#endif
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/src/nsCMSSecureMessage.cpp
@@ -0,0 +1,386 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Terry Hayes <thayes@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsMemory.h"
+#include "nsXPIDLString.h"
+#include "nsCOMPtr.h"
+#include "nsISupports.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsCRT.h"
+
+#include "nsICMSSecureMessage.h"
+
+#include "nsCMSSecureMessage.h"
+#include "nsNSSCertificate.h"
+#include "nsNSSHelper.h"
+#include "nsNSSShutDown.h"
+
+#include <string.h>
+#include "plbase64.h"
+#include "cert.h"
+#include "cms.h"
+
+#include "nsIServiceManager.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+
+#include "prlog.h"
+#ifdef PR_LOGGING
+extern PRLogModuleInfo* gPIPNSSLog;
+#endif
+
+// Standard ISupports implementation
+// NOTE: Should these be the thread-safe versions?
+
+/*****
+ * nsCMSSecureMessage
+ *****/
+
+// Standard ISupports implementation
+NS_IMPL_ISUPPORTS1(nsCMSSecureMessage, nsICMSSecureMessage)
+
+// nsCMSSecureMessage constructor
+nsCMSSecureMessage::nsCMSSecureMessage()
+{
+  // initialize superclass
+}
+
+// nsCMSMessage destructor
+nsCMSSecureMessage::~nsCMSSecureMessage()
+{
+}
+
+/* string getCertByPrefID (in string certID); */
+NS_IMETHODIMP nsCMSSecureMessage::
+GetCertByPrefID(const char *certID, char **_retval)
+{
+  nsNSSShutDownPreventionLock locker;
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::GetCertByPrefID\n"));
+  nsresult rv = NS_OK;
+  CERTCertificate *cert = 0;
+  nsXPIDLCString nickname;
+  nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
+
+  *_retval = 0;
+
+  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+  if (NS_FAILED(rv)) {
+    goto done;
+  }
+
+  rv = prefs->GetCharPref(certID,
+                          getter_Copies(nickname));
+  if (NS_FAILED(rv)) goto done;
+
+  /* Find a good cert in the user's database */
+  cert = CERT_FindUserCertByUsage(CERT_GetDefaultCertDB(), NS_CONST_CAST(char*, nickname.get()), 
+           certUsageEmailRecipient, PR_TRUE, ctx);
+
+  if (!cert) { 
+    /* Success, but no value */
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::GetCertByPrefID - can't find user cert\n"));
+    goto done;
+  } 
+
+  /* Convert the DER to a BASE64 String */
+  encode(cert->derCert.data, cert->derCert.len, _retval);
+
+done:
+  if (cert) CERT_DestroyCertificate(cert);
+  return rv;
+}
+
+
+// nsCMSSecureMessage::DecodeCert
+nsresult nsCMSSecureMessage::
+DecodeCert(const char *value, nsIX509Cert ** _retval)
+{
+  nsNSSShutDownPreventionLock locker;
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::DecodeCert\n"));
+  nsresult rv = NS_OK;
+  PRInt32 length;
+  unsigned char *data = 0;
+
+  *_retval = 0;
+
+  if (!value) { return NS_ERROR_FAILURE; }
+
+  rv = decode(value, &data, &length);
+  if (NS_FAILED(rv)) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::DecodeCert - can't decode cert\n"));
+    return rv;
+  }
+
+  nsCOMPtr<nsIX509Cert> cert =  nsNSSCertificate::ConstructFromDER((char *)data, length);
+
+  if (cert) {
+    *_retval = cert;
+    NS_ADDREF(*_retval);
+  }
+  else {
+    rv = NS_ERROR_FAILURE;
+  }
+
+  nsCRT::free((char*)data);
+  return rv;
+}
+
+// nsCMSSecureMessage::SendMessage
+nsresult nsCMSSecureMessage::
+SendMessage(const char *msg, const char *base64Cert, char ** _retval)
+{
+  nsNSSShutDownPreventionLock locker;
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage\n"));
+  nsresult rv = NS_OK;
+  CERTCertificate *cert = 0;
+  NSSCMSMessage *cmsMsg = 0;
+  unsigned char *certDER = 0;
+  PRInt32 derLen;
+  NSSCMSEnvelopedData *env;
+  NSSCMSContentInfo *cinfo;
+  NSSCMSRecipientInfo *rcpt;
+  SECItem item;
+  SECItem output;
+  PLArenaPool *arena = PORT_NewArena(1024);
+  SECStatus s;
+  nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
+
+  /* Step 0. Create a CMS Message */
+  cmsMsg = NSS_CMSMessage_Create(NULL);
+  if (!cmsMsg) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't create NSSCMSMessage\n"));
+    rv = NS_ERROR_FAILURE;
+    goto done;
+  }
+
+  /* Step 1.  Import the certificate into NSS */
+  rv = decode(base64Cert, &certDER, &derLen);
+  if (NS_FAILED(rv)) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't decode / import cert into NSS\n"));
+    goto done;
+  }
+
+  cert = CERT_DecodeCertFromPackage((char *)certDER, derLen);
+  if (!cert) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't decode cert from package\n"));
+    rv = NS_ERROR_FAILURE;
+    goto done;
+  }
+
+#if 0
+  cert->dbhandle = CERT_GetDefaultCertDB();  /* work-around */
+#endif
+
+  /* Step 2.  Get a signature cert */
+
+  /* Step 3. Build inner (signature) content */
+
+  /* Step 4. Build outer (enveloped) content */
+  env = NSS_CMSEnvelopedData_Create(cmsMsg, SEC_OID_DES_EDE3_CBC, 0);
+  if (!env) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't create envelope data\n"));
+    rv = NS_ERROR_FAILURE;
+    goto done;
+  }
+
+  cinfo = NSS_CMSEnvelopedData_GetContentInfo(env);
+  item.data = (unsigned char *)msg;
+  item.len = strlen(msg);  /* XPCOM equiv?? */
+  s = NSS_CMSContentInfo_SetContent_Data(cmsMsg, cinfo, 0, PR_FALSE);
+  if (s != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't set content data\n"));
+    rv = NS_ERROR_FAILURE;
+    goto done;
+  }
+
+  rcpt = NSS_CMSRecipientInfo_Create(cmsMsg, cert);
+  if (!rcpt) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't create recipient info\n"));
+    rv = NS_ERROR_FAILURE;
+    goto done;
+  }
+
+  s = NSS_CMSEnvelopedData_AddRecipient(env, rcpt);
+  if (s != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't add recipient\n"));
+    rv = NS_ERROR_FAILURE;
+    goto done;
+  }
+
+  /* Step 5. Add content to message */
+  cinfo = NSS_CMSMessage_GetContentInfo(cmsMsg);
+  s = NSS_CMSContentInfo_SetContent_EnvelopedData(cmsMsg, cinfo, env);
+  if (s != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't set content enveloped data\n"));
+    rv = NS_ERROR_FAILURE;
+    goto done;
+  }
+  
+  /* Step 6. Encode */
+  NSSCMSEncoderContext *ecx;
+
+  output.data = 0; output.len = 0;
+  ecx = NSS_CMSEncoder_Start(cmsMsg, 0, 0, &output, arena,
+            0, ctx, 0, 0, 0, 0);
+  if (!ecx) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't start cms encoder\n"));
+    rv = NS_ERROR_FAILURE;
+    goto done;
+  }
+
+  s = NSS_CMSEncoder_Update(ecx, msg, strlen(msg));
+  if (s != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't update encoder\n"));
+    rv = NS_ERROR_FAILURE;
+    goto done;
+  }
+
+  s = NSS_CMSEncoder_Finish(ecx);
+  if (s != SECSuccess) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::SendMessage - can't finish encoder\n"));
+    rv = NS_ERROR_FAILURE;
+    goto done;
+  }
+
+  /* Step 7. Base64 encode and return the result */
+  rv = encode(output.data, output.len, _retval);
+
+done:
+  if (certDER) nsCRT::free((char *)certDER);
+  if (cert) CERT_DestroyCertificate(cert);
+  if (cmsMsg) NSS_CMSMessage_Destroy(cmsMsg);
+  if (arena) PORT_FreeArena(arena, PR_FALSE);  /* PR_FALSE? */
+
+  return rv;
+}
+
+/*
+ * nsCMSSecureMessage::ReceiveMessage
+ */
+nsresult nsCMSSecureMessage::
+ReceiveMessage(const char *msg, char **_retval)
+{
+  nsNSSShutDownPreventionLock locker;
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::ReceiveMessage\n"));
+  nsresult rv = NS_OK;
+  NSSCMSDecoderContext *dcx;
+  unsigned char *der = 0;
+  PRInt32 derLen;
+  NSSCMSMessage *cmsMsg = 0;
+  SECItem *content;
+  nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();
+
+  /* Step 1. Decode the base64 wrapper */
+  rv = decode(msg, &der, &derLen);
+  if (NS_FAILED(rv)) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::ReceiveMessage - can't base64 decode\n"));
+    goto done;
+  }
+
+  dcx = NSS_CMSDecoder_Start(0, 0, 0, /* pw */ 0, ctx, /* key */ 0, 0);
+  if (!dcx) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::ReceiveMessage - can't start decoder\n"));
+    rv = NS_ERROR_FAILURE;
+    goto done;
+  }
+
+  (void)NSS_CMSDecoder_Update(dcx, (char *)der, derLen);
+  cmsMsg = NSS_CMSDecoder_Finish(dcx);
+  if (!cmsMsg) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::ReceiveMessage - can't finish decoder\n"));
+    rv = NS_ERROR_FAILURE;
+    /* Memory leak on dcx?? */
+    goto done;
+  }
+
+  content = NSS_CMSMessage_GetContent(cmsMsg);
+  if (!content) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::ReceiveMessage - can't get content\n"));
+    rv = NS_ERROR_FAILURE;
+    goto done;
+  }
+
+  /* Copy the data */
+  *_retval = (char*)malloc(content->len+1);
+  memcpy(*_retval, content->data, content->len);
+  (*_retval)[content->len] = 0;
+
+done:
+  if (der) free(der);
+  if (cmsMsg) NSS_CMSMessage_Destroy(cmsMsg);
+
+  return rv;
+}
+
+nsresult nsCMSSecureMessage::
+encode(const unsigned char *data, PRInt32 dataLen, char **_retval)
+{
+  nsresult rv = NS_OK;
+
+  *_retval = PL_Base64Encode((const char *)data, dataLen, NULL);
+  if (!*_retval) { rv = NS_ERROR_OUT_OF_MEMORY; goto loser; }
+
+loser:
+  return rv;
+}
+
+nsresult nsCMSSecureMessage::
+decode(const char *data, unsigned char **result, PRInt32 * _retval)
+{
+  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::decode\n"));
+  nsresult rv = NS_OK;
+  PRUint32 len = PL_strlen(data);
+  int adjust = 0;
+
+  /* Compute length adjustment */
+  if (data[len-1] == '=') {
+    adjust++;
+    if (data[len-2] == '=') adjust++;
+  }
+
+  *result = (unsigned char *)PL_Base64Decode(data, len, NULL);
+  if (!*result) {
+    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSSecureMessage::decode - error decoding base64\n"));
+    rv = NS_ERROR_ILLEGAL_VALUE;
+    goto loser;
+  }
+
+  *_retval = (len*3)/4 - adjust;
+
+loser:
+  return rv;
+}
new file mode 100644
--- /dev/null
+++ b/mailnews/mime/src/nsCMSSecureMessage.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corp..
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Terry Hayes <thayes@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _NSCMSSECUREMESSAGE_H_
+#define _NSCMSSECUREMESSAGE_H_
+
+#include "nsICMSSecureMessage.h"
+
+#include "cms.h"
+
+// ===============================================
+// nsCMSManager - implementation of nsICMSManager
+// ===============================================
+
+#define NS_CMSSECUREMESSAGE_CLASSNAME "CMS Secure Message"
+#define NS_CMSSECUREMESSAGE_CID \
+  { 0x5fb907e0, 0x1dd2, 0x11b2, { 0xa7, 0xc0, 0xf1, 0x4c, 0x41, 0x6a, 0x62, 0xa1 } }
+
+class nsCMSSecureMessage
+: public nsICMSSecureMessage
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSICMSSECUREMESSAGE
+
+  nsCMSSecureMessage();
+  virtual ~nsCMSSecureMessage();
+
+private:
+  NS_METHOD encode(const unsigned char *data, PRInt32 dataLen, char **_retval);
+  NS_METHOD decode(const char *data, unsigned char **result, PRInt32 * _retval);
+};
+
+
+#endif /* _NSCMSMESSAGE_H_ */