summaryrefslogtreecommitdiffstats
path: root/mailnews/mime/cthandlers
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2019-11-03 00:17:46 -0400
committerMatt A. Tobin <email@mattatobin.com>2019-11-03 00:17:46 -0400
commit302bf1b523012e11b60425d6eee1221ebc2724eb (patch)
treeb191a895f8716efcbe42f454f37597a545a6f421 /mailnews/mime/cthandlers
parent21b3f6247403c06f85e1f45d219f87549862198f (diff)
downloadUXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.gz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.lz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.xz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.zip
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
Diffstat (limited to 'mailnews/mime/cthandlers')
-rw-r--r--mailnews/mime/cthandlers/glue/mimexpcom.cpp132
-rw-r--r--mailnews/mime/cthandlers/glue/mimexpcom.h93
-rw-r--r--mailnews/mime/cthandlers/glue/moz.build18
-rw-r--r--mailnews/mime/cthandlers/glue/nsMimeContentTypeHandler.cpp60
-rw-r--r--mailnews/mime/cthandlers/glue/nsMimeContentTypeHandler.h47
-rw-r--r--mailnews/mime/cthandlers/moz.build12
-rw-r--r--mailnews/mime/cthandlers/pgpmime/moz.build20
-rw-r--r--mailnews/mime/cthandlers/pgpmime/nsPgpMimeProxy.cpp634
-rw-r--r--mailnews/mime/cthandlers/pgpmime/nsPgpMimeProxy.h69
-rw-r--r--mailnews/mime/cthandlers/vcard/mimevcrd.cpp378
-rw-r--r--mailnews/mime/cthandlers/vcard/mimevcrd.h33
-rw-r--r--mailnews/mime/cthandlers/vcard/moz.build14
12 files changed, 1510 insertions, 0 deletions
diff --git a/mailnews/mime/cthandlers/glue/mimexpcom.cpp b/mailnews/mime/cthandlers/glue/mimexpcom.cpp
new file mode 100644
index 000000000..094f61e37
--- /dev/null
+++ b/mailnews/mime/cthandlers/glue/mimexpcom.cpp
@@ -0,0 +1,132 @@
+/* -*- 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/. */
+#include "nsIComponentManager.h"
+#include "nsIMimeObjectClassAccess.h"
+#include "nsMsgMimeCID.h"
+#include "nsCOMPtr.h"
+#include "nsComponentManagerUtils.h"
+static NS_DEFINE_CID(kMimeObjectClassAccessCID, NS_MIME_OBJECT_CLASS_ACCESS_CID);
+
+/*
+ * These calls are necessary to expose the object class hierarchy
+ * to externally developed content type handlers.
+ */
+extern "C" void *
+COM_GetmimeInlineTextClass(void)
+{
+ void *ptr = NULL;
+
+ nsresult res;
+ nsCOMPtr<nsIMimeObjectClassAccess> objAccess =
+ do_CreateInstance(kMimeObjectClassAccessCID, &res);
+ if (NS_SUCCEEDED(res) && objAccess)
+ objAccess->GetmimeInlineTextClass(&ptr);
+
+ return ptr;
+}
+
+extern "C" void *
+COM_GetmimeLeafClass(void)
+{
+ void *ptr = NULL;
+
+ nsresult res;
+ nsCOMPtr<nsIMimeObjectClassAccess> objAccess =
+ do_CreateInstance(kMimeObjectClassAccessCID, &res);
+ if (NS_SUCCEEDED(res) && objAccess)
+ objAccess->GetmimeLeafClass(&ptr);
+
+ return ptr;
+}
+
+extern "C" void *
+COM_GetmimeObjectClass(void)
+{
+ void *ptr = NULL;
+
+ nsresult res;
+ nsCOMPtr<nsIMimeObjectClassAccess> objAccess =
+ do_CreateInstance(kMimeObjectClassAccessCID, &res);
+ if (NS_SUCCEEDED(res) && objAccess)
+ objAccess->GetmimeObjectClass(&ptr);
+
+ return ptr;
+}
+
+extern "C" void *
+COM_GetmimeContainerClass(void)
+{
+ void *ptr = NULL;
+
+ nsresult res;
+ nsCOMPtr<nsIMimeObjectClassAccess> objAccess =
+ do_CreateInstance(kMimeObjectClassAccessCID, &res);
+ if (NS_SUCCEEDED(res) && objAccess)
+ objAccess->GetmimeContainerClass(&ptr);
+
+ return ptr;
+}
+
+extern "C" void *
+COM_GetmimeMultipartClass(void)
+{
+ void *ptr = NULL;
+
+ nsresult res;
+ nsCOMPtr<nsIMimeObjectClassAccess> objAccess =
+ do_CreateInstance(kMimeObjectClassAccessCID, &res);
+ if (NS_SUCCEEDED(res) && objAccess)
+ objAccess->GetmimeMultipartClass(&ptr);
+
+ return ptr;
+}
+
+extern "C" void *
+COM_GetmimeMultipartSignedClass(void)
+{
+ void *ptr = NULL;
+
+ nsresult res;
+ nsCOMPtr<nsIMimeObjectClassAccess> objAccess =
+ do_CreateInstance(kMimeObjectClassAccessCID, &res);
+ if (NS_SUCCEEDED(res) && objAccess)
+ objAccess->GetmimeMultipartSignedClass(&ptr);
+
+ return ptr;
+}
+
+extern "C" int
+COM_MimeObject_write(void *mimeObject, char *data, int32_t length,
+ bool user_visible_p)
+{
+ int32_t rc = -1;
+
+ nsresult res;
+ nsCOMPtr<nsIMimeObjectClassAccess> objAccess =
+ do_CreateInstance(kMimeObjectClassAccessCID, &res);
+ if (NS_SUCCEEDED(res) && objAccess)
+ {
+ if (NS_SUCCEEDED(objAccess->MimeObjectWrite(mimeObject, data, length, user_visible_p)))
+ rc = length;
+ else
+ rc = -1;
+ }
+
+ return rc;
+}
+
+extern "C" void *
+COM_MimeCreate(char * content_type, void * hdrs, void * opts)
+{
+ void *ptr = NULL;
+
+ nsresult res;
+ nsCOMPtr<nsIMimeObjectClassAccess> objAccess =
+ do_CreateInstance(kMimeObjectClassAccessCID, &res);
+ if (NS_SUCCEEDED(res) && objAccess)
+ objAccess->MimeCreate(content_type, hdrs, opts, &ptr);
+
+ return ptr;
+}
diff --git a/mailnews/mime/cthandlers/glue/mimexpcom.h b/mailnews/mime/cthandlers/glue/mimexpcom.h
new file mode 100644
index 000000000..9468b22b4
--- /dev/null
+++ b/mailnews/mime/cthandlers/glue/mimexpcom.h
@@ -0,0 +1,93 @@
+/* -*- 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 the definitions for the Content Type Handler plugins to
+ * access internals of libmime via XP-COM calls
+ */
+#ifndef _MIMEXPCOM_H_
+#define _MIMEXPCOM_H_
+
+/*
+ This header exposes functions that are necessary to access the
+ object hierarchy for the mime chart. The class hierarchy is:
+
+ MimeObject (abstract)
+ |
+ |--- MimeContainer (abstract)
+ | |
+ | |--- MimeMultipart (abstract)
+ | | |
+ | | |--- MimeMultipartMixed
+ | | |
+ | | |--- MimeMultipartDigest
+ | | |
+ | | |--- MimeMultipartParallel
+ | | |
+ | | |--- MimeMultipartAlternative
+ | | |
+ | | |--- MimeMultipartRelated
+ | | |
+ | | |--- MimeMultipartAppleDouble
+ | | |
+ | | |--- MimeSunAttachment
+ | | |
+ | | |--- MimeMultipartSigned (abstract)
+ | | |
+ | | |--- MimeMultipartSigned
+ | |
+ | |--- MimeXlateed (abstract)
+ | | |
+ | | |--- MimeXlateed
+ | |
+ | |--- MimeMessage
+ | |
+ | |--- MimeUntypedText
+ |
+ |--- MimeLeaf (abstract)
+ | |
+ | |--- MimeInlineText (abstract)
+ | | |
+ | | |--- MimeInlineTextPlain
+ | | |
+ | | |--- MimeInlineTextHTML
+ | | |
+ | | |--- MimeInlineTextRichtext
+ | | | |
+ | | | |--- MimeInlineTextEnriched
+ | | |
+ | | |--- MimeInlineTextVCard
+ | |
+ | |--- MimeInlineImage
+ | |
+ | |--- MimeExternalObject
+ |
+ |--- MimeExternalBody
+ */
+
+/*
+ * These functions are exposed by libmime to be used by content type
+ * handler plugins for processing stream data.
+ */
+/*
+ * This is the write call for outputting processed stream data.
+ */
+extern "C" int COM_MimeObject_write(void *mimeObject, const char *data,
+ int32_t length,
+ bool user_visible_p);
+/*
+ * The following group of calls expose the pointers for the object
+ * system within libmime.
+ */
+extern "C" void *COM_GetmimeInlineTextClass(void);
+extern "C" void *COM_GetmimeLeafClass(void);
+extern "C" void *COM_GetmimeObjectClass(void);
+extern "C" void *COM_GetmimeContainerClass(void);
+extern "C" void *COM_GetmimeMultipartClass(void);
+extern "C" void *COM_GetmimeMultipartSignedClass(void);
+
+extern "C" void *COM_MimeCreate(char * content_type, void * hdrs, void * opts);
+
+#endif /* _MIMEXPCOM_H_ */
diff --git a/mailnews/mime/cthandlers/glue/moz.build b/mailnews/mime/cthandlers/glue/moz.build
new file mode 100644
index 000000000..f51518ca9
--- /dev/null
+++ b/mailnews/mime/cthandlers/glue/moz.build
@@ -0,0 +1,18 @@
+# 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/.
+
+EXPORTS += [
+ 'nsMimeContentTypeHandler.h',
+]
+
+SOURCES += [
+ 'mimexpcom.cpp',
+ 'nsMimeContentTypeHandler.cpp',
+]
+
+FINAL_LIBRARY = 'mail'
+
+Library('mimecthglue_s')
+
diff --git a/mailnews/mime/cthandlers/glue/nsMimeContentTypeHandler.cpp b/mailnews/mime/cthandlers/glue/nsMimeContentTypeHandler.cpp
new file mode 100644
index 000000000..369f8c4bf
--- /dev/null
+++ b/mailnews/mime/cthandlers/glue/nsMimeContentTypeHandler.cpp
@@ -0,0 +1,60 @@
+/* -*- 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/. */
+#include <stdio.h>
+#include "nscore.h"
+#include "plstr.h"
+//#include "mimecth.h"
+#include "nsMimeContentTypeHandler.h"
+
+/*
+ * The following macros actually implement addref, release and
+ * query interface for our component.
+ */
+NS_IMPL_ISUPPORTS(nsMimeContentTypeHandler, nsIMimeContentTypeHandler)
+
+/*
+ * nsIMimeEmitter definitions....
+ */
+nsMimeContentTypeHandler::nsMimeContentTypeHandler(const char *aMimeType,
+ MCTHCreateCTHClass callback)
+{
+ NS_ASSERTION(aMimeType, "nsMimeContentTypeHandler should be initialized with non-null mime type");
+ NS_ASSERTION(callback, "nsMimeContentTypeHandler should be initialized with non-null callback");
+ mimeType = PL_strdup(aMimeType);
+ realCreateContentTypeHandlerClass = callback;
+}
+
+nsMimeContentTypeHandler::~nsMimeContentTypeHandler(void)
+{
+ if (mimeType) {
+ NS_Free(mimeType);
+ mimeType = 0;
+ }
+ realCreateContentTypeHandlerClass = 0;
+}
+
+// Get the content type if necessary
+nsresult
+nsMimeContentTypeHandler::GetContentType(char **contentType)
+{
+ *contentType = PL_strdup(mimeType);
+ return NS_OK;
+}
+
+// Set the output stream for processed data.
+nsresult
+nsMimeContentTypeHandler::CreateContentTypeHandlerClass(const char *content_type,
+ contentTypeHandlerInitStruct *initStruct,
+ MimeObjectClass **objClass)
+{
+ *objClass = realCreateContentTypeHandlerClass(content_type, initStruct);
+ if (!*objClass)
+ return NS_ERROR_OUT_OF_MEMORY; /* we couldn't allocate the object */
+ else
+ return NS_OK;
+}
+
+
+
diff --git a/mailnews/mime/cthandlers/glue/nsMimeContentTypeHandler.h b/mailnews/mime/cthandlers/glue/nsMimeContentTypeHandler.h
new file mode 100644
index 000000000..8cc142268
--- /dev/null
+++ b/mailnews/mime/cthandlers/glue/nsMimeContentTypeHandler.h
@@ -0,0 +1,47 @@
+/* -*- 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 interface is implemented by content type handlers that will be
+ * called upon by libmime to process various attachments types. The primary
+ * purpose of these handlers will be to represent the attached data in a
+ * viewable HTML format that is useful for the user
+ *
+ * Note: These will all register by their content type prefixed by the
+ * following: mimecth:text/vcard
+ *
+ * libmime will then use the XPCOM Component Manager to
+ * locate the appropriate Content Type handler
+ */
+#ifndef nsMimeContentTypeHandler_h_
+#define nsMimeContentTypeHandler_h_
+
+#include "mozilla/Attributes.h"
+#include "nsIMimeContentTypeHandler.h"
+
+typedef MimeObjectClass *
+(* MCTHCreateCTHClass)(const char *content_type,
+ contentTypeHandlerInitStruct *initStruct);
+
+class nsMimeContentTypeHandler : public nsIMimeContentTypeHandler {
+public:
+ nsMimeContentTypeHandler (const char *aMimeType,
+ MCTHCreateCTHClass callback);
+
+ /* this macro defines QueryInterface, AddRef and Release for this class */
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD GetContentType(char **contentType) override;
+
+ NS_IMETHOD CreateContentTypeHandlerClass(const char *content_type,
+ contentTypeHandlerInitStruct *initStruct,
+ MimeObjectClass **objClass) override;
+ private:
+ virtual ~nsMimeContentTypeHandler();
+ char *mimeType;
+ MCTHCreateCTHClass realCreateContentTypeHandlerClass;
+};
+
+#endif /* nsMimeContentTypeHandler_h_ */
diff --git a/mailnews/mime/cthandlers/moz.build b/mailnews/mime/cthandlers/moz.build
new file mode 100644
index 000000000..31807499d
--- /dev/null
+++ b/mailnews/mime/cthandlers/moz.build
@@ -0,0 +1,12 @@
+# 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/.
+
+# pgpmime depends on glue.
+DIRS += [
+ 'glue',
+ 'vcard',
+ 'pgpmime',
+]
+
diff --git a/mailnews/mime/cthandlers/pgpmime/moz.build b/mailnews/mime/cthandlers/pgpmime/moz.build
new file mode 100644
index 000000000..878bd5bfa
--- /dev/null
+++ b/mailnews/mime/cthandlers/pgpmime/moz.build
@@ -0,0 +1,20 @@
+# 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/.
+
+EXPORTS += [
+ 'nsPgpMimeProxy.h',
+]
+
+SOURCES += [
+ 'nsPgpMimeProxy.cpp',
+]
+
+FINAL_LIBRARY = 'mail'
+
+Library('pgpmime_s')
+
+LOCAL_INCLUDES += [
+ '../glue',
+]
diff --git a/mailnews/mime/cthandlers/pgpmime/nsPgpMimeProxy.cpp b/mailnews/mime/cthandlers/pgpmime/nsPgpMimeProxy.cpp
new file mode 100644
index 000000000..de4ec3174
--- /dev/null
+++ b/mailnews/mime/cthandlers/pgpmime/nsPgpMimeProxy.cpp
@@ -0,0 +1,634 @@
+/* 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 "nsPgpMimeProxy.h"
+#include "nspr.h"
+#include "plstr.h"
+#include "nsCOMPtr.h"
+#include "nsStringGlue.h"
+#include "mozilla/Services.h"
+#include "nsIRequest.h"
+#include "nsIStringBundle.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+#include "nsIURI.h"
+#include "mimexpcom.h"
+#include "nsMsgUtils.h"
+
+#include "nsMsgMimeCID.h"
+
+#include "mimecth.h"
+#include "mimemoz2.h"
+#include "nspr.h"
+#include "plstr.h"
+#include "nsIPgpMimeProxy.h"
+#include "nsComponentManagerUtils.h"
+
+#define MIME_SUPERCLASS mimeEncryptedClass
+MimeDefClass(MimeEncryptedPgp, MimeEncryptedPgpClass,
+ mimeEncryptedPgpClass, &MIME_SUPERCLASS);
+
+#define kCharMax 1024
+
+extern "C" MimeObjectClass *
+MIME_PgpMimeCreateContentTypeHandlerClass(
+ const char *content_type,
+ contentTypeHandlerInitStruct *initStruct)
+{
+ MimeObjectClass *objClass = (MimeObjectClass *) &mimeEncryptedPgpClass;
+
+ initStruct->force_inline_display = false;
+
+ return objClass;
+}
+
+static void *MimePgpe_init(MimeObject *,
+ int (*output_fn) (const char *, int32_t, void *),
+ void *);
+static int MimePgpe_write (const char *, int32_t, void *);
+static int MimePgpe_eof (void *, bool);
+static char* MimePgpe_generate (void *);
+static void MimePgpe_free (void *);
+
+/* Returns a string describing the location of the part (like "2.5.3").
+ This is not a full URL, just a part-number.
+ */
+static nsCString determineMimePart(MimeObject* obj);
+
+
+#define PGPMIME_PROPERTIES_URL "chrome://messenger/locale/pgpmime.properties"
+#define PGPMIME_STR_NOT_SUPPORTED_ID u"pgpMimeNeedsAddon"
+#define PGPMIME_URL_PREF "mail.pgpmime.addon_url"
+
+static void PgpMimeGetNeedsAddonString(nsCString &aResult)
+{
+ aResult.AssignLiteral("???");
+
+ nsCOMPtr<nsIStringBundleService> stringBundleService =
+ mozilla::services::GetStringBundleService();
+
+ nsCOMPtr<nsIStringBundle> stringBundle;
+ nsresult rv = stringBundleService->CreateBundle(PGPMIME_PROPERTIES_URL,
+ getter_AddRefs(stringBundle));
+ if (NS_FAILED(rv))
+ return;
+
+ nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+ if (NS_FAILED(rv))
+ return;
+
+ nsCString url;
+ if (NS_FAILED(prefs->GetCharPref("mail.pgpmime.addon_url",
+ getter_Copies(url))))
+ return;
+
+ NS_ConvertUTF8toUTF16 url16(url);
+ const char16_t *formatStrings[] = { url16.get() };
+
+ nsString result;
+ rv = stringBundle->FormatStringFromName(PGPMIME_STR_NOT_SUPPORTED_ID,
+ formatStrings, 1, getter_Copies(result));
+ if (NS_FAILED(rv))
+ return;
+ aResult = NS_ConvertUTF16toUTF8(result);
+}
+
+static int
+MimeEncryptedPgpClassInitialize(MimeEncryptedPgpClass *clazz)
+{
+ mozilla::DebugOnly<MimeObjectClass *> oclass = (MimeObjectClass *) clazz;
+ NS_ASSERTION(!oclass->class_initialized, "oclass is not initialized");
+
+ MimeEncryptedClass *eclass = (MimeEncryptedClass *) clazz;
+
+ eclass->crypto_init = MimePgpe_init;
+ eclass->crypto_write = MimePgpe_write;
+ eclass->crypto_eof = MimePgpe_eof;
+ eclass->crypto_generate_html = MimePgpe_generate;
+ eclass->crypto_free = MimePgpe_free;
+
+ return 0;
+}
+
+class MimePgpeData : public nsISupports
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ int (*output_fn) (const char *buf, int32_t buf_size, void *output_closure);
+ void *output_closure;
+ MimeObject *self;
+
+ nsCOMPtr<nsIPgpMimeProxy> mimeDecrypt;
+
+ MimePgpeData()
+ : output_fn(nullptr),
+ output_closure(nullptr)
+ {
+ }
+
+private:
+ virtual ~MimePgpeData()
+ {
+ }
+};
+
+NS_IMPL_ISUPPORTS0(MimePgpeData)
+
+static void*
+MimePgpe_init(MimeObject *obj,
+ int (*output_fn) (const char *buf, int32_t buf_size,
+ void *output_closure),
+ void *output_closure)
+{
+ if (!(obj && obj->options && output_fn))
+ return nullptr;
+
+ MimePgpeData* data = new MimePgpeData();
+ NS_ENSURE_TRUE(data, nullptr);
+
+ data->self = obj;
+ data->output_fn = output_fn;
+ data->output_closure = output_closure;
+ data->mimeDecrypt = nullptr;
+
+ nsresult rv;
+ data->mimeDecrypt = do_CreateInstance(NS_PGPMIMEPROXY_CONTRACTID, &rv);
+ if (NS_FAILED(rv))
+ return data;
+
+ char *ct = MimeHeaders_get(obj->headers, HEADER_CONTENT_TYPE, false, false);
+
+ rv = (ct ? data->mimeDecrypt->SetContentType(nsDependentCString(ct))
+ : data->mimeDecrypt->SetContentType(EmptyCString()));
+
+ PR_Free(ct);
+
+ if (NS_FAILED(rv))
+ return nullptr;
+
+ nsCString mimePart = determineMimePart(obj);
+
+ rv = data->mimeDecrypt->SetMimePart(mimePart);
+ if (NS_FAILED(rv))
+ return nullptr;
+
+ mime_stream_data *msd = (mime_stream_data *) (data->self->options->stream_closure);
+ nsIChannel *channel = msd->channel;
+
+ nsCOMPtr<nsIURI> uri;
+ if (channel)
+ channel->GetURI(getter_AddRefs(uri));
+
+ if (NS_FAILED(data->mimeDecrypt->SetMimeCallback(output_fn, output_closure, uri)))
+ return nullptr;
+
+ return data;
+}
+
+static int
+MimePgpe_write(const char *buf, int32_t buf_size, void *output_closure)
+{
+ MimePgpeData* data = (MimePgpeData *) output_closure;
+
+ if (!data || !data->output_fn)
+ return -1;
+
+ if (!data->mimeDecrypt)
+ return 0;
+
+ return (NS_SUCCEEDED(data->mimeDecrypt->Write(buf, buf_size)) ? 0 : -1);
+}
+
+static int
+MimePgpe_eof(void* output_closure, bool abort_p)
+{
+ MimePgpeData* data = (MimePgpeData *) output_closure;
+
+ if (!data || !data->output_fn)
+ return -1;
+
+ if (NS_FAILED(data->mimeDecrypt->Finish()))
+ return -1;
+
+ data->mimeDecrypt = nullptr;
+ return 0;
+}
+
+static char*
+MimePgpe_generate(void *output_closure)
+{
+ const char htmlMsg[] = "<html><body><b>GEN MSG<b></body></html>";
+ char* msg = (char *) PR_MALLOC(strlen(htmlMsg) + 1);
+ if (msg)
+ PL_strcpy(msg, htmlMsg);
+
+ return msg;
+}
+
+static void
+MimePgpe_free(void *output_closure)
+{
+}
+
+/* Returns a string describing the location of the part (like "2.5.3").
+ This is not a full URL, just a part-number.
+ */
+static nsCString
+determineMimePart(MimeObject* obj)
+{
+ char mimePartNum[20];
+ MimeObject *kid;
+ MimeContainer *cont;
+ int32_t i;
+
+ nsCString mimePart;
+
+ while (obj->parent) {
+ cont = (MimeContainer *) obj->parent;
+ for (i = 0; i < cont->nchildren; i++) {
+ kid = cont->children[i];
+ if (kid == obj) {
+ sprintf(mimePartNum, ".%d", i + 1);
+ mimePart.Insert(mimePartNum, 0);
+ }
+ }
+ obj = obj->parent;
+ }
+
+ // remove leading "."
+ if (mimePart.Length() > 0)
+ mimePart.Cut(0, 1);
+
+ return mimePart;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+NS_IMPL_ISUPPORTS(nsPgpMimeProxy,
+ nsIPgpMimeProxy,
+ nsIRequestObserver,
+ nsIStreamListener,
+ nsIRequest,
+ nsIInputStream)
+
+// nsPgpMimeProxy implementation
+nsPgpMimeProxy::nsPgpMimeProxy()
+ : mInitialized(false),
+ mDecryptor(nullptr),
+ mLoadGroup(nullptr),
+ mLoadFlags(LOAD_NORMAL),
+ mCancelStatus(NS_OK)
+{
+}
+
+nsPgpMimeProxy::~nsPgpMimeProxy()
+{
+ Finalize();
+}
+
+nsresult
+nsPgpMimeProxy::Finalize()
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::SetMimeCallback(MimeDecodeCallbackFun outputFun,
+ void* outputClosure,
+ nsIURI* myUri)
+{
+ if (!outputFun || !outputClosure)
+ return NS_ERROR_NULL_POINTER;
+
+ mOutputFun = outputFun;
+ mOutputClosure = outputClosure;
+ mInitialized = true;
+
+ mStreamOffset = 0;
+ mByteBuf.Truncate();
+
+ if (mDecryptor)
+ return mDecryptor->OnStartRequest((nsIRequest*) this, myUri);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::Init()
+{
+ mByteBuf.Truncate();
+
+ nsresult rv;
+ nsCOMPtr<nsIPrefBranch> pbi(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+ if (NS_FAILED(rv))
+ return rv;
+
+ mDecryptor = do_CreateInstance(PGPMIME_JS_DECRYPTOR_CONTRACTID, &rv);
+ if (NS_FAILED(rv))
+ mDecryptor = nullptr;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::Write(const char *buf, uint32_t buf_size)
+{
+ NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+ mByteBuf.Assign(buf, buf_size);
+ mStreamOffset = 0;
+
+ if (mDecryptor)
+ return mDecryptor->OnDataAvailable((nsIRequest*) this, nullptr, (nsIInputStream*) this,
+ 0, buf_size);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::Finish() {
+ NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+ if (mDecryptor) {
+ return mDecryptor->OnStopRequest((nsIRequest*) this, nullptr, NS_OK);
+ }
+ else {
+ nsCString temp;
+ temp.Append("Content-Type: text/html\r\nCharset: UTF-8\r\n\r\n<html><body>");
+ temp.Append("<BR><text=\"#000000\" bgcolor=\"#FFFFFF\" link=\"#FF0000\" vlink=\"#800080\" alink=\"#0000FF\">");
+ temp.Append("<center><table BORDER=1 ><tr><td><CENTER>");
+
+ nsCString tString;
+ PgpMimeGetNeedsAddonString(tString);
+ temp.Append(tString);
+ temp.Append("</CENTER></td></tr></table></center><BR></body></html>\r\n");
+
+ PR_SetError(0,0);
+ int status = mOutputFun(temp.get(), temp.Length(), mOutputClosure);
+ if (status < 0) {
+ PR_SetError(status, 0);
+ mOutputFun = nullptr;
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::GetDecryptor(nsIStreamListener **aDecryptor)
+{
+ NS_IF_ADDREF(*aDecryptor = mDecryptor);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::SetDecryptor(nsIStreamListener *aDecryptor)
+{
+ mDecryptor = aDecryptor;
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsPgpMimeProxy::GetContentType(nsACString &aContentType)
+{
+ aContentType = mContentType;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsPgpMimeProxy::SetContentType(const nsACString &aContentType)
+{
+ mContentType = aContentType;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::GetMimePart(nsACString &aMimePart)
+{
+ aMimePart = mMimePart;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsPgpMimeProxy::SetMimePart(const nsACString &aMimePart)
+{
+ mMimePart = aMimePart;
+ return NS_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// nsIRequest methods
+///////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsPgpMimeProxy::GetName(nsACString &result)
+{
+ result = "pgpmimeproxy";
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::IsPending(bool *result)
+{
+ NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+ *result = NS_SUCCEEDED(mCancelStatus);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::GetStatus(nsresult *status)
+{
+ NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+ *status = mCancelStatus;
+ return NS_OK;
+}
+
+// NOTE: We assume that OnStopRequest should not be called if
+// request is canceled. This may be wrong!
+NS_IMETHODIMP
+nsPgpMimeProxy::Cancel(nsresult status)
+{
+ NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+ // Need a non-zero status code to cancel
+ if (NS_SUCCEEDED(status))
+ return NS_ERROR_FAILURE;
+
+ if (NS_SUCCEEDED(mCancelStatus))
+ mCancelStatus = status;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::Suspend(void)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::Resume(void)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::GetLoadGroup(nsILoadGroup * *aLoadGroup)
+{
+ NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::SetLoadGroup(nsILoadGroup* aLoadGroup)
+{
+ mLoadGroup = aLoadGroup;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::GetLoadFlags(nsLoadFlags *aLoadFlags)
+{
+ *aLoadFlags = mLoadFlags;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::SetLoadFlags(nsLoadFlags aLoadFlags)
+{
+ mLoadFlags = aLoadFlags;
+ return NS_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// nsIInputStream methods
+///////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsPgpMimeProxy::Available(uint64_t* _retval)
+{
+ NS_ENSURE_ARG(_retval);
+
+ NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+ *_retval = (mByteBuf.Length() > mStreamOffset) ?
+ mByteBuf.Length() - mStreamOffset : 0;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::Read(char* buf, uint32_t count,
+ uint32_t *readCount)
+{
+ NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+ if (!buf || !readCount)
+ return NS_ERROR_NULL_POINTER;
+
+ int32_t avail = (mByteBuf.Length() > mStreamOffset) ?
+ mByteBuf.Length() - mStreamOffset : 0;
+
+ uint32_t readyCount = ((uint32_t) avail > count) ? count : avail;
+
+ if (readyCount) {
+ memcpy(buf, mByteBuf.get()+mStreamOffset, readyCount);
+ *readCount = readyCount;
+ }
+
+ mStreamOffset += *readCount;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::ReadSegments(nsWriteSegmentFun writer,
+ void * aClosure, uint32_t count,
+ uint32_t *readCount)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::IsNonBlocking(bool *aNonBlocking)
+{
+ NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+ *aNonBlocking = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::Close()
+{
+ NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+ mStreamOffset = 0;
+ mByteBuf.Truncate();
+
+ return NS_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// nsIStreamListener methods
+///////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsPgpMimeProxy::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPgpMimeProxy::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
+ nsresult aStatus)
+{
+ return NS_OK;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// nsIStreamListener method
+///////////////////////////////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsPgpMimeProxy::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
+ nsIInputStream *aInputStream,
+ uint64_t aSourceOffset,
+ uint32_t aLength)
+{
+ NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
+
+ NS_ENSURE_ARG(aInputStream);
+
+ char buf[kCharMax];
+ uint32_t readCount, readMax;
+
+ while (aLength > 0) {
+ readMax = (aLength < kCharMax) ? aLength : kCharMax;
+
+ nsresult rv;
+ rv = aInputStream->Read((char *) buf, readMax, &readCount);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ int status = mOutputFun(buf, readCount, mOutputClosure);
+ if (status < 0) {
+ PR_SetError(status, 0);
+ mOutputFun = nullptr;
+ return NS_ERROR_FAILURE;
+ }
+
+ aLength -= readCount;
+ }
+
+ return NS_OK;
+}
diff --git a/mailnews/mime/cthandlers/pgpmime/nsPgpMimeProxy.h b/mailnews/mime/cthandlers/pgpmime/nsPgpMimeProxy.h
new file mode 100644
index 000000000..41e7f59cc
--- /dev/null
+++ b/mailnews/mime/cthandlers/pgpmime/nsPgpMimeProxy.h
@@ -0,0 +1,69 @@
+/* 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 _nsPgpmimeDecrypt_h_
+#define _nsPgpmimeDecrypt_h_
+
+#include "mimecth.h"
+#include "nsIPgpMimeProxy.h"
+#include "nsCOMPtr.h"
+#include "nsIStreamListener.h"
+#include "nsIInputStream.h"
+#include "nsILoadGroup.h"
+
+#define PGPMIME_JS_DECRYPTOR_CONTRACTID "@mozilla.org/mime/pgp-mime-js-decrypt;1"
+
+typedef struct MimeEncryptedPgpClass MimeEncryptedPgpClass;
+typedef struct MimeEncryptedPgp MimeEncryptedPgp;
+
+struct MimeEncryptedPgpClass {
+ MimeEncryptedClass encrypted;
+};
+
+struct MimeEncryptedPgp {
+ MimeEncrypted encrypted;
+};
+
+class nsPgpMimeProxy : public nsIPgpMimeProxy,
+ public nsIRequest,
+ public nsIInputStream
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIPGPMIMEPROXY
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSIREQUEST
+ NS_DECL_NSIINPUTSTREAM
+
+ nsPgpMimeProxy();
+
+ // Define a Create method to be used with a factory:
+ static NS_METHOD
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+protected:
+ virtual ~nsPgpMimeProxy();
+ bool mInitialized;
+ nsCOMPtr<nsIStreamListener> mDecryptor;
+
+ MimeDecodeCallbackFun mOutputFun;
+ void* mOutputClosure;
+
+ nsCOMPtr<nsILoadGroup> mLoadGroup;
+ nsLoadFlags mLoadFlags;
+ nsresult mCancelStatus;
+
+ uint32_t mStreamOffset;
+ nsCString mByteBuf;
+ nsCString mContentType;
+ nsCString mMimePart;
+
+ nsresult Finalize();
+};
+
+#define MimeEncryptedPgpClassInitializer(ITYPE,CSUPER) \
+ { MimeEncryptedClassInitializer(ITYPE,CSUPER) }
+
+#endif
diff --git a/mailnews/mime/cthandlers/vcard/mimevcrd.cpp b/mailnews/mime/cthandlers/vcard/mimevcrd.cpp
new file mode 100644
index 000000000..140afb5aa
--- /dev/null
+++ b/mailnews/mime/cthandlers/vcard/mimevcrd.cpp
@@ -0,0 +1,378 @@
+/* -*- 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/. */
+
+#include "mimevcrd.h"
+
+#include "mimecth.h"
+#include "mimexpcom.h"
+#include "nsIMsgVCardService.h"
+#include "nsINetUtil.h"
+#include "nsMsgUtils.h"
+#include "prmem.h"
+#include "prprf.h"
+#include "nsServiceManagerUtils.h"
+
+static int MimeInlineTextVCard_parse_line (const char *, int32_t, MimeObject *);
+static int MimeInlineTextVCard_parse_eof (MimeObject *, bool);
+static int MimeInlineTextVCard_parse_begin (MimeObject *obj);
+
+static int s_unique = 0;
+
+static int BeginVCard (MimeObject *obj);
+static int EndVCard (MimeObject *obj);
+static int WriteOutVCard (MimeObject *obj, VObject* v);
+
+static int GenerateVCardData(MimeObject * aMimeObj, VObject* aVcard);
+static int OutputVcardAttribute(MimeObject *aMimeObj, VObject *aVcard, const char* id, nsACString& vCardOutput);
+static int OutputBasicVcard(MimeObject *aMimeObj, VObject *aVcard, nsACString& vCardOutput);
+
+typedef struct
+ {
+ const char *attributeName;
+ int resourceId;
+ } AttributeName;
+
+#define kNumAttributes 12
+
+#define MSGVCARDSERVICE_CONTRACT_ID "@mozilla.org/addressbook/msgvcardservice;1"
+
+/* This is the object definition. Note: we will set the superclass
+ to NULL and manually set this on the class creation */
+MimeDefClass(MimeInlineTextVCard, MimeInlineTextVCardClass,
+ mimeInlineTextVCardClass, NULL);
+
+extern "C" MimeObjectClass *
+MIME_VCardCreateContentTypeHandlerClass(const char *content_type,
+ contentTypeHandlerInitStruct *initStruct)
+{
+ MimeObjectClass *clazz = (MimeObjectClass *)&mimeInlineTextVCardClass;
+ /*
+ * Must set the superclass by hand.
+ */
+ if (!COM_GetmimeInlineTextClass())
+ return NULL;
+
+ clazz->superclass = (MimeObjectClass *)COM_GetmimeInlineTextClass();
+ initStruct->force_inline_display = true;
+ return clazz;
+}
+
+/*
+ * Implementation of VCard clazz
+ */
+static int
+MimeInlineTextVCardClassInitialize(MimeInlineTextVCardClass *clazz)
+{
+ MimeObjectClass *oclass = (MimeObjectClass *) clazz;
+ NS_ASSERTION(!oclass->class_initialized, "1.1 <rhp@netscape.com> 19 Mar 1999 12:11");
+ oclass->parse_begin = MimeInlineTextVCard_parse_begin;
+ oclass->parse_line = MimeInlineTextVCard_parse_line;
+ oclass->parse_eof = MimeInlineTextVCard_parse_eof;
+ return 0;
+}
+
+static int
+MimeInlineTextVCard_parse_begin (MimeObject *obj)
+{
+ int status = ((MimeObjectClass*)COM_GetmimeLeafClass())->parse_begin(obj);
+ MimeInlineTextVCardClass *clazz;
+ if (status < 0) return status;
+
+ if (!obj->output_p) return 0;
+ if (!obj->options || !obj->options->write_html_p) return 0;
+
+ /* This is a fine place to write out any HTML before the real meat begins.
+ In this sample code, we tell it to start a table. */
+
+ clazz = ((MimeInlineTextVCardClass *) obj->clazz);
+ /* initialize vcard string to empty; */
+ NS_MsgSACopy(&(clazz->vCardString), "");
+
+ obj->options->state->separator_suppressed_p = true;
+ return 0;
+}
+
+char *strcpySafe (char *dest, const char *src, size_t destLength)
+{
+ char *result = strncpy (dest, src, --destLength);
+ dest[destLength] = '\0';
+ return result;
+}
+
+static int
+MimeInlineTextVCard_parse_line (const char *line, int32_t length, MimeObject *obj)
+{
+ // This routine gets fed each line of data, one at a time.
+ char* linestring;
+ MimeInlineTextVCardClass *clazz = ((MimeInlineTextVCardClass *) obj->clazz);
+
+ if (!obj->output_p) return 0;
+ if (!obj->options || !obj->options->output_fn) return 0;
+ if (!obj->options->write_html_p)
+ {
+ return COM_MimeObject_write(obj, line, length, true);
+ }
+
+ linestring = (char *) PR_MALLOC (length + 1);
+ memset(linestring, 0, (length + 1));
+
+ if (linestring)
+ {
+ strcpySafe((char *)linestring, line, length + 1);
+ NS_MsgSACat (&clazz->vCardString, linestring);
+ PR_Free (linestring);
+ }
+
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+static int
+MimeInlineTextVCard_parse_eof (MimeObject *obj, bool abort_p)
+{
+ nsCOMPtr<nsIMsgVCardService> vCardService =
+ do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
+ if (!vCardService)
+ return -1;
+
+ int status = 0;
+ MimeInlineTextVCardClass *clazz = ((MimeInlineTextVCardClass *) obj->clazz);
+
+ VObject *t, *v;
+
+ if (obj->closed_p) return 0;
+
+ /* Run parent method first, to flush out any buffered data. */
+ // status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
+ status = ((MimeObjectClass*)COM_GetmimeInlineTextClass())->parse_eof(obj, abort_p);
+ if (status < 0) return status;
+
+ // Don't quote vCards...
+ if ( (obj->options) &&
+ ((obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting) ||
+ (obj->options->format_out == nsMimeOutput::nsMimeMessageBodyQuoting))
+ )
+ return 0;
+
+ if (!clazz->vCardString) return 0;
+
+ v = vCardService->Parse_MIME(clazz->vCardString, strlen(clazz->vCardString));
+ NS_ASSERTION(v, "parse of vCard failed");
+
+ if (clazz->vCardString) {
+ PR_Free ((char*) clazz->vCardString);
+ clazz->vCardString = NULL;
+ }
+
+ if (obj->output_p && obj->options && obj->options->write_html_p &&
+ obj->options->headers != MimeHeadersCitation) {
+ /* This is a fine place to write any closing HTML. In fact, you may
+ want all the writing to be here, and all of the above would just
+ collect data into datastructures, though that isn't very
+ "streaming". */
+ t = v;
+ while (v && status >= 0) {
+ /* write out html */
+ status = WriteOutVCard (obj, v);
+ /* parse next vcard incase they're embedded */
+ v = vCardService->NextVObjectInList(v);
+ }
+
+ (void)vCardService->CleanVObject(t);
+ }
+
+ if (status < 0)
+ return status;
+
+ return 0;
+}
+
+static int EndVCard (MimeObject *obj)
+{
+ int status = 0;
+
+ /* Scribble HTML-ending stuff into the stream */
+ char htmlFooters[32];
+ PR_snprintf (htmlFooters, sizeof(htmlFooters), "</BODY>%s</HTML>%s", MSG_LINEBREAK, MSG_LINEBREAK);
+ status = COM_MimeObject_write(obj, htmlFooters, strlen(htmlFooters), false);
+
+ if (status < 0) return status;
+
+ return 0;
+}
+
+static int BeginVCard (MimeObject *obj)
+{
+ int status = 0;
+
+ /* Scribble HTML-starting stuff into the stream */
+ char htmlHeaders[32];
+
+ s_unique++;
+ PR_snprintf (htmlHeaders, sizeof(htmlHeaders), "<HTML>%s<BODY>%s", MSG_LINEBREAK, MSG_LINEBREAK);
+ status = COM_MimeObject_write(obj, htmlHeaders, strlen(htmlHeaders), true);
+
+ if (status < 0) return status;
+
+ return 0;
+}
+
+
+static int WriteOutVCard (MimeObject * aMimeObj, VObject* aVcard)
+{
+ BeginVCard (aMimeObj);
+
+ GenerateVCardData(aMimeObj, aVcard);
+
+ return EndVCard (aMimeObj);
+}
+
+
+static int GenerateVCardData(MimeObject * aMimeObj, VObject* aVcard)
+{
+ // style is driven from CSS not here. Just layout the minimal vCard data
+ nsCString vCardOutput;
+
+ vCardOutput = "<table class=\"moz-vcard-table\"> <tr> "; // outer table plus the first (and only row) we use for this table
+
+ // we need to get an escaped vCard url to bind to our add to address book button
+ nsCOMPtr<nsIMsgVCardService> vCardService = do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
+ if (!vCardService)
+ return -1;
+
+ nsAutoCString vCard;
+ nsAutoCString vEscCard;
+ int len = 0;
+
+ vCard.Adopt(vCardService->WriteMemoryVObjects(0, &len, aVcard, false));
+ MsgEscapeString(vCard, nsINetUtil::ESCAPE_XALPHAS, vEscCard);
+
+ // first cell in the outer table row is a clickable image which brings up the rich address book UI for the vcard
+ vCardOutput += "<td valign=\"top\"> <a class=\"moz-vcard-badge\" href=\"addbook:add?action=add?vcard=";
+ vCardOutput += vEscCard; // the href is the vCard
+ vCardOutput += "\"></a></td>";
+
+ // the 2nd cell in the outer table row is a nested table containing the actual vCard properties
+ vCardOutput += "<td> <table id=\"moz-vcard-properties-table\"> <tr> ";
+
+ OutputBasicVcard(aMimeObj, aVcard, vCardOutput);
+
+ // close the properties table
+ vCardOutput += "</table> </td> ";
+
+ // 2nd cell in the outer table is our vCard image
+
+ vCardOutput += "</tr> </table>";
+
+ // now write out the vCard
+ return COM_MimeObject_write(aMimeObj, (char *) vCardOutput.get(), vCardOutput.Length(), true);
+}
+
+
+static int OutputBasicVcard(MimeObject *aMimeObj, VObject *aVcard, nsACString& vCardOutput)
+{
+ VObject *prop = NULL;
+ nsAutoCString urlstring;
+ nsAutoCString namestring;
+ nsAutoCString emailstring;
+
+ nsCOMPtr<nsIMsgVCardService> vCardService = do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
+ if (!vCardService)
+ return -1;
+
+ /* get the name and email */
+ prop = vCardService->IsAPropertyOf(aVcard, VCFullNameProp);
+ if (prop)
+ {
+ if (VALUE_TYPE(prop))
+ {
+ if (VALUE_TYPE(prop) != VCVT_RAW)
+ namestring.Adopt(vCardService->FakeCString(prop));
+ else
+ namestring.Adopt(vCardService->VObjectAnyValue(prop));
+
+ if (!namestring.IsEmpty())
+ {
+ vCardOutput += "<td class=\"moz-vcard-title-property\"> ";
+
+ prop = vCardService->IsAPropertyOf(aVcard, VCURLProp);
+ if (prop)
+ {
+ urlstring.Adopt(vCardService->FakeCString(prop));
+ if (urlstring.IsEmpty())
+ vCardOutput += namestring;
+ else
+ {
+ char buf[512];
+ PR_snprintf(buf, 512, "<a href=""%s"" private>%s</a>", urlstring.get(), namestring.get());
+ vCardOutput.Append(buf);
+ }
+ }
+ else
+ vCardOutput += namestring;
+
+ /* get the email address */
+ prop = vCardService->IsAPropertyOf(aVcard, VCEmailAddressProp);
+ if (prop)
+ {
+ emailstring.Adopt(vCardService->FakeCString(prop));
+ if (!emailstring.IsEmpty())
+ {
+ char buf[512];
+ PR_snprintf(buf, 512, "&nbsp;&lt;<a href=""mailto:%s"" private>%s</a>&gt;", emailstring.get(), emailstring.get());
+ vCardOutput.Append(buf);
+ }
+ } // if email address property
+
+ vCardOutput += "</td> </tr> "; // end the cell for the name/email address
+ } // if we have a name property
+ }
+ } // if full name property
+
+ // now each basic property goes on its own line
+
+ // title
+ (void) OutputVcardAttribute (aMimeObj, aVcard, VCTitleProp, vCardOutput);
+
+ // org name and company name
+ prop = vCardService->IsAPropertyOf(aVcard, VCOrgProp);
+ if (prop)
+ {
+ OutputVcardAttribute (aMimeObj, prop, VCOrgUnitProp, vCardOutput);
+ OutputVcardAttribute (aMimeObj, prop, VCOrgNameProp, vCardOutput);
+ }
+
+ return 0;
+}
+
+static int OutputVcardAttribute(MimeObject *aMimeObj, VObject *aVcard, const char* id, nsACString& vCardOutput)
+{
+ VObject *prop = NULL;
+ nsAutoCString string;
+
+ nsCOMPtr<nsIMsgVCardService> vCardService = do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
+ if (!vCardService)
+ return -1;
+
+ prop = vCardService->IsAPropertyOf(aVcard, id);
+ if (prop)
+ if (VALUE_TYPE(prop))
+ {
+ if (VALUE_TYPE(prop) != VCVT_RAW)
+ string.Adopt(vCardService->FakeCString(prop));
+ else
+ string.Adopt(vCardService->VObjectAnyValue(prop));
+
+ if (!string.IsEmpty())
+ {
+ vCardOutput += "<tr> <td class=\"moz-vcard-property\">";
+ vCardOutput += string;
+ vCardOutput += "</td> </tr> ";
+ }
+ }
+
+ return 0;
+}
diff --git a/mailnews/mime/cthandlers/vcard/mimevcrd.h b/mailnews/mime/cthandlers/vcard/mimevcrd.h
new file mode 100644
index 000000000..6e731f555
--- /dev/null
+++ b/mailnews/mime/cthandlers/vcard/mimevcrd.h
@@ -0,0 +1,33 @@
+/* -*- 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/. */
+
+#ifndef _MIMEVCRD_H_
+#define _MIMEVCRD_H_
+
+#include "mimetext.h"
+#include "nsCOMPtr.h"
+
+/* The MimeInlineTextHTML class implements the text/x-vcard and (maybe?
+ someday?) the application/directory MIME content types.
+ */
+
+typedef struct MimeInlineTextVCardClass MimeInlineTextVCardClass;
+typedef struct MimeInlineTextVCard MimeInlineTextVCard;
+
+struct MimeInlineTextVCardClass {
+ MimeInlineTextClass text;
+ char *vCardString;
+};
+
+extern MimeInlineTextVCardClass mimeInlineTextVCardClass;
+
+struct MimeInlineTextVCard {
+ MimeInlineText text;
+};
+
+#define MimeInlineTextVCardClassInitializer(ITYPE,CSUPER) \
+ { MimeInlineTextClassInitializer(ITYPE,CSUPER) }
+
+#endif /* _MIMEVCRD_H_ */
diff --git a/mailnews/mime/cthandlers/vcard/moz.build b/mailnews/mime/cthandlers/vcard/moz.build
new file mode 100644
index 000000000..55de22391
--- /dev/null
+++ b/mailnews/mime/cthandlers/vcard/moz.build
@@ -0,0 +1,14 @@
+# 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 += [
+ 'mimevcrd.cpp',
+]
+
+FINAL_LIBRARY = 'mail'
+
+LOCAL_INCLUDES += [
+ '../glue',
+]