Back to index

lightning-sunbird  0.9+nobinonly
mimevcrd.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #include "nsCOMPtr.h"
00038 #include "nsIIOService.h"
00039 #include "nsNetCID.h"
00040 #include "nsIServiceManager.h"
00041 #include "nsICharsetConverterManager.h"
00042 
00043 #include "msgCore.h"
00044 #include "prlog.h"
00045 #include "prtypes.h"
00046 #include "prmem.h"
00047 #include "plstr.h"
00048 #include "nsIMsgVCardService.h"
00049 #include "mimecth.h"
00050 #include "mimexpcom.h"
00051 #include "mimevcrd.h"
00052 #include "nsEscape.h"
00053 #include "nsIURI.h"
00054 #include "nsMsgI18N.h"
00055 #include "nsMsgUtils.h"
00056 #include "nsReadableUtils.h"
00057 
00058 #include "nsIStringBundle.h"
00059 #include "nsVCardStringResources.h"
00060 #include "nsPrintfCString.h"
00061 
00062 #include "nsCRT.h"
00063 #include "prprf.h"
00064 
00065 // String bundles...
00066 #ifndef XP_MAC
00067 static nsCOMPtr<nsIStringBundle>   stringBundle = nsnull;
00068 #endif
00069 
00070 static int MimeInlineTextVCard_parse_line (char *, PRInt32, MimeObject *);
00071 static int MimeInlineTextVCard_parse_eof (MimeObject *, PRBool);
00072 static int MimeInlineTextVCard_parse_begin (MimeObject *obj);
00073 
00074 static int s_unique = 0;
00075 
00076 static int BeginVCard (MimeObject *obj);
00077 static int EndVCard (MimeObject *obj);
00078 static int WriteOutVCard (MimeObject *obj, VObject* v);
00079 
00080 #ifdef MOZ_THUNDERBIRD
00081 static int GenerateVCardData(MimeObject * aMimeObj, VObject* aVcard);
00082 static int OutputVcardAttribute(MimeObject *aMimeObj, VObject *aVcard, const char* id, nsACString& vCardOutput);
00083 static int OutputBasicVcard(MimeObject *aMimeObj, VObject *aVcard, nsACString& vCardOutput);
00084 #else
00085 static int WriteOutEachVCardProperty (MimeObject *obj, VObject* v, int* numEmail);
00086 static int WriteOutVCardProperties (MimeObject *obj, VObject* v, int* numEmail);
00087 static int WriteLineToStream (MimeObject *obj, const char *line, PRBool aDoCharConversion);
00088 
00089 static void GetEmailProperties (VObject* o, char ** attribName);
00090 static void GetTelephoneProperties (VObject* o, char ** attribName);
00091 static void GetAddressProperties (VObject* o, char ** attribName);
00092 static int WriteValue (MimeObject *obj, const char *);
00093 static int WriteAttribute (MimeObject *obj, const char *);
00094 static int WriteOutVCardPhoneProperties (MimeObject *obj, VObject* v);
00095 static int WriteOutEachVCardPhoneProperty (MimeObject *obj, VObject* o);
00096 #endif
00097 
00098 typedef struct
00099   {
00100     const char *attributeName;
00101     int resourceId;
00102   } AttributeName;
00103 
00104 #define kNumAttributes 12
00105 
00106 #define     VCARD_URL     "chrome://messenger/locale/vcard.properties"
00107 #define     MSGVCARDSERVICE_CONTRACT_ID "@mozilla.org/addressbook/msgvcardservice;1"
00108 
00109 /* This is the object definition. Note: we will set the superclass 
00110    to NULL and manually set this on the class creation */
00111 MimeDefClass(MimeInlineTextVCard, MimeInlineTextVCardClass,
00112              mimeInlineTextVCardClass, NULL);
00113 
00114 extern "C" MimeObjectClass *
00115 MIME_VCardCreateContentTypeHandlerClass(const char *content_type, 
00116                                    contentTypeHandlerInitStruct *initStruct)
00117 {
00118   MimeObjectClass *clazz = (MimeObjectClass *)&mimeInlineTextVCardClass;
00119   /*
00120    * Must set the superclass by hand.
00121    */
00122   if (!COM_GetmimeInlineTextClass())
00123     return NULL;
00124 
00125   clazz->superclass = (MimeObjectClass *)COM_GetmimeInlineTextClass();
00126   initStruct->force_inline_display = PR_TRUE;
00127   return clazz;
00128 }
00129 
00130 /* 
00131  * Implementation of VCard clazz 
00132  */
00133 static int
00134 MimeInlineTextVCardClassInitialize(MimeInlineTextVCardClass *clazz)
00135 {
00136   MimeObjectClass *oclass = (MimeObjectClass *) clazz;
00137   NS_ASSERTION(!oclass->class_initialized, "1.1 <rhp@netscape.com> 19 Mar 1999 12:11");
00138   oclass->parse_begin = MimeInlineTextVCard_parse_begin;
00139   oclass->parse_line  = MimeInlineTextVCard_parse_line;
00140   oclass->parse_eof   = MimeInlineTextVCard_parse_eof;
00141   return 0;
00142 }
00143 
00144 static int
00145 MimeInlineTextVCard_parse_begin (MimeObject *obj)
00146 {
00147   int status = ((MimeObjectClass*)COM_GetmimeLeafClass())->parse_begin(obj);
00148   MimeInlineTextVCardClass *clazz;
00149   if (status < 0) return status;
00150   
00151   if (!obj->output_p) return 0;
00152   if (!obj->options || !obj->options->write_html_p) return 0;
00153   
00154   /* This is a fine place to write out any HTML before the real meat begins.
00155   In this sample code, we tell it to start a table. */
00156   
00157   clazz = ((MimeInlineTextVCardClass *) obj->clazz);
00158   /* initialize vcard string to empty; */
00159   NS_MsgSACopy(&(clazz->vCardString), "");
00160   
00161   obj->options->state->separator_suppressed_p = PR_TRUE;
00162   return 0;
00163 }
00164 
00165 char *strcpySafe (char *dest, const char *src, size_t destLength)
00166 {
00167   char *result = strncpy (dest, src, --destLength);
00168   dest[destLength] = '\0';
00169   return result;
00170 }
00171 
00172 static int
00173 MimeInlineTextVCard_parse_line (char *line, PRInt32 length, MimeObject *obj)
00174 {
00175   // This routine gets fed each line of data, one at a time.    
00176   char* linestring;
00177   MimeInlineTextVCardClass *clazz = ((MimeInlineTextVCardClass *) obj->clazz);
00178   
00179   if (!obj->output_p) return 0;
00180   if (!obj->options || !obj->options->output_fn) return 0;
00181   if (!obj->options->write_html_p) 
00182   {
00183     return COM_MimeObject_write(obj, line, length, PR_TRUE);
00184   }
00185   
00186   linestring = (char *) PR_MALLOC (length + 1);
00187   memset(linestring, 0, (length + 1));
00188   
00189   if (linestring) 
00190   {
00191     strcpySafe((char *)linestring, line, length + 1);
00192     NS_MsgSACat (&clazz->vCardString, linestring);
00193     PR_Free (linestring);
00194   }
00195   
00196   return 0;
00197 }
00198 
00199 
00201 static PRInt32 INTL_ConvertCharset(const char* from_charset, const char* to_charset,
00202                                    const char* inBuffer, const PRInt32 inLength,
00203                                    char** outBuffer, PRInt32* outLength)
00204 {
00205   nsresult res;
00206 
00207   // invalid input
00208   if (nsnull == from_charset || nsnull == to_charset || 
00209       '\0' == *from_charset || '\0' == *to_charset || nsnull == inBuffer) 
00210     return -1;
00211 
00212   // from to identical
00213   if (!nsCRT::strcasecmp(from_charset, to_charset))
00214     return -1;
00215 
00216   // us-ascii is a subset of utf-8
00217   if ((!nsCRT::strcasecmp(from_charset, "us-ascii") && !nsCRT::strcasecmp(to_charset, "UTF-8")) ||
00218       (!nsCRT::strcasecmp(from_charset, "UTF-8") && !nsCRT::strcasecmp(to_charset, "us-ascii")))
00219     return -1;
00220 
00221 
00222   nsAutoString outString;
00223   
00224   res = ConvertToUnicode(from_charset, inBuffer, outString);
00225 
00226   // known bug in 4.x, it mixes Shift_JIS (or EUC-JP) and ISO-2022-JP in vCard fields
00227   if (NS_ERROR_MODULE_UCONV == NS_ERROR_GET_MODULE(res)) {
00228     if (!nsCRT::strcasecmp("ISO-2022-JP", from_charset)) {
00229       res = ConvertToUnicode("Shift_JIS", inBuffer, outString);
00230       if (NS_ERROR_MODULE_UCONV == NS_ERROR_GET_MODULE(res)) {
00231         res = ConvertToUnicode("EUC-JP", inBuffer, outString);
00232       }
00233     }
00234   }
00235 
00236   if (NS_SUCCEEDED(res)) {
00237     nsCAutoString result;
00238     res = ConvertFromUnicode(to_charset, outString, result);
00239     if (NS_SUCCEEDED(res)) {
00240       *outLength = result.Length();
00241       *outBuffer = PL_strdup(result.get());
00242     }
00243   }
00244 
00245   return NS_SUCCEEDED(res) ? 0 : -1;
00246 }
00248 static int
00249 MimeInlineTextVCard_parse_eof (MimeObject *obj, PRBool abort_p)
00250 {
00251   nsCOMPtr<nsIMsgVCardService> vCardService = 
00252              do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
00253   if (!vCardService)
00254       return -1;
00255 
00256   int status = 0;
00257   MimeInlineTextVCardClass *clazz = ((MimeInlineTextVCardClass *) obj->clazz);
00258   
00259   VObject *t, *v;
00260   
00261   if (obj->closed_p) return 0;
00262   
00263   /* Run parent method first, to flush out any buffered data. */
00264   //    status = ((MimeObjectClass*)&MIME_SUPERCLASS)->parse_eof(obj, abort_p);
00265   status = ((MimeObjectClass*)COM_GetmimeInlineTextClass())->parse_eof(obj, abort_p);
00266   if (status < 0) return status;
00267  
00268   // Don't quote vCards...
00269   if (  (obj->options) && 
00270     ((obj->options->format_out == nsMimeOutput::nsMimeMessageQuoting) ||
00271     (obj->options->format_out == nsMimeOutput::nsMimeMessageBodyQuoting))
00272     )
00273     return 0;
00274 
00275   if (!clazz->vCardString) return 0;
00276   
00277   v = vCardService->Parse_MIME(clazz->vCardString, strlen(clazz->vCardString));
00278   NS_ASSERTION(v, "parse of vCard failed");
00279   
00280   if (clazz->vCardString) {
00281     PR_Free ((char*) clazz->vCardString);
00282     clazz->vCardString = NULL;
00283   }
00284   
00285   if (obj->output_p && obj->options && obj->options->write_html_p &&
00286     obj->options->headers != MimeHeadersCitation) {
00287     /* This is a fine place to write any closing HTML.  In fact, you may
00288     want all the writing to be here, and all of the above would just
00289     collect data into datastructures, though that isn't very
00290     "streaming". */
00291     t = v;
00292     while (v && status >= 0) {
00293       /* write out html */
00294       status = WriteOutVCard (obj, v);
00295       /* parse next vcard incase they're embedded */
00296       v = vCardService->NextVObjectInList(v);
00297     }
00298     
00299     (void)vCardService->CleanVObject(t);
00300   }
00301   
00302   if (status < 0) 
00303     return status;
00304   
00305   return 0;
00306 }
00307 
00308 static int EndVCard (MimeObject *obj)
00309 {
00310   int status = 0;
00311 
00312   /* Scribble HTML-ending stuff into the stream */
00313   char htmlFooters[32];
00314   PR_snprintf (htmlFooters, sizeof(htmlFooters), "</BODY>%s</HTML>%s", MSG_LINEBREAK, MSG_LINEBREAK);
00315   status = COM_MimeObject_write(obj, htmlFooters, strlen(htmlFooters), PR_FALSE);
00316 
00317   if (status < 0) return status;
00318 
00319   return 0;
00320 }
00321 
00322 static int BeginVCard (MimeObject *obj)
00323 {
00324   int status = 0;
00325 
00326   /* Scribble HTML-starting stuff into the stream */
00327   char htmlHeaders[32];
00328 
00329   s_unique++;
00330   PR_snprintf (htmlHeaders, sizeof(htmlHeaders), "<HTML>%s<BODY>%s", MSG_LINEBREAK, MSG_LINEBREAK);
00331     status = COM_MimeObject_write(obj, htmlHeaders, strlen(htmlHeaders), PR_TRUE);
00332 
00333   if (status < 0) return status;
00334 
00335   return 0;
00336 }
00337 
00338 #ifndef MOZ_THUNDERBIRD
00339 
00340 static int WriteEachLineToStream (MimeObject *obj, const char *line)
00341 {
00342   int status = 0;
00343   char *htmlLine;
00344   int htmlLen = strlen(line) + 1;
00345 
00346   htmlLine = (char *) PR_MALLOC (htmlLen);
00347   if (htmlLine)
00348   {
00349     htmlLine[0] = '\0';
00350     PL_strcat (htmlLine, line);
00351       status = COM_MimeObject_write(obj, htmlLine, strlen(htmlLine), PR_TRUE);
00352     PR_Free ((void*) htmlLine);
00353   }
00354   else
00355     status = VCARD_OUT_OF_MEMORY;
00356 
00357   return status;
00358 }
00359 
00360 static int OutputTable (MimeObject *obj, PRBool endTable, PRBool border, char *cellspacing, char *cellpadding, char *bgcolor)
00361 {
00362   int status = 0;
00363   char * htmlLine = NULL;
00364 
00365   if (endTable)
00366   {
00367     status = WriteEachLineToStream (obj, "</TABLE>");
00368   }
00369   else
00370   {
00371     int htmlLen = strlen("<TABLE>") + 1;
00372     if (border)
00373       htmlLen += strlen (" BORDER");
00374     if (cellspacing)
00375       htmlLen += strlen(" CELLSPACING=") + strlen(cellspacing);
00376     if (cellpadding)
00377       htmlLen += strlen(" CELLPADDING=") + strlen(cellpadding);
00378     if (bgcolor)
00379       htmlLen += strlen(" BGCOLOR=") + strlen(bgcolor);
00380     if (border || cellspacing || cellpadding || bgcolor)
00381       htmlLen++;
00382 
00383     htmlLine = (char *) PR_MALLOC (htmlLen);
00384     if (htmlLine)
00385     {
00386       htmlLine[0] = '\0';
00387       PL_strcat (htmlLine, "<TABLE");
00388       if (border)
00389         PL_strcat (htmlLine, " BORDER");
00390       if (cellspacing)
00391       { 
00392         PL_strcat (htmlLine, " CELLSPACING=");
00393         PL_strcat (htmlLine, cellspacing);
00394       }
00395       if (cellpadding)
00396       { 
00397         PL_strcat (htmlLine, " CELLPADDING=");
00398         PL_strcat (htmlLine, cellpadding);
00399       }
00400       if (bgcolor)
00401       { 
00402         PL_strcat (htmlLine, " BGCOLOR=");
00403         PL_strcat (htmlLine, bgcolor);
00404       }
00405 
00406       if (border || cellspacing || cellpadding || bgcolor)
00407         PL_strcat (htmlLine, " ");
00408 
00409       PL_strcat (htmlLine, ">");
00410 
00411       status = COM_MimeObject_write(obj, htmlLine, strlen(htmlLine), PR_TRUE);
00412       PR_Free ((void*) htmlLine);
00413     }
00414     else
00415       status = VCARD_OUT_OF_MEMORY;
00416   } 
00417   return status;
00418 }
00419 
00420 static int OutputTableRowOrData(MimeObject *obj, PRBool outputRow, 
00421                 PRBool end, char * align, 
00422                 char* valign, char* colspan,
00423                 char* width)
00424 {
00425   int status = 0;
00426   char * htmlLine = NULL;
00427 
00428   if (end)
00429     if (outputRow)
00430       status = WriteEachLineToStream (obj, "</TR>");
00431     else
00432       status = WriteEachLineToStream (obj, "</TD>");
00433   else
00434   {
00435     int htmlLen = strlen("<TR>") + 1;
00436     if (align)
00437       htmlLen += strlen(" ALIGN=") + strlen(align);
00438     if (colspan)
00439       htmlLen += strlen(" COLSPAN=") + strlen(colspan);
00440     if (width)
00441       htmlLen += strlen(" WIDTH=") + strlen(width);
00442     if (valign)
00443       htmlLen += strlen(" VALIGN=") + strlen(valign);
00444     if (align || valign || colspan || width)
00445       htmlLen++;
00446 
00447     htmlLine = (char *) PR_MALLOC (htmlLen);
00448     if (htmlLine)
00449     {
00450       htmlLine[0] = '\0';
00451       if (outputRow)
00452         PL_strcat (htmlLine, "<TR");
00453       else
00454         PL_strcat (htmlLine, "<TD");
00455       if (align)
00456       { 
00457         PL_strcat (htmlLine, " ALIGN=");
00458         PL_strcat (htmlLine, align);
00459       }
00460       if (valign)
00461       { 
00462         PL_strcat (htmlLine, " VALIGN=");
00463         PL_strcat (htmlLine, valign);
00464       }
00465       if (colspan)
00466       { 
00467         PL_strcat (htmlLine, " COLSPAN=");
00468         PL_strcat (htmlLine, colspan);
00469       }
00470       if (width)
00471       { 
00472         PL_strcat (htmlLine, " WIDTH=");
00473         PL_strcat (htmlLine, width);
00474       }
00475       if (align || valign || colspan || width)
00476         PL_strcat (htmlLine, " ");
00477 
00478       PL_strcat (htmlLine, ">");
00479 
00480       status = COM_MimeObject_write(obj, htmlLine, strlen(htmlLine), PR_TRUE);
00481       PR_Free ((void*) htmlLine);
00482     }
00483     else
00484       status = VCARD_OUT_OF_MEMORY;
00485   }
00486 
00487   return status;
00488 }
00489 
00490 
00491 static int OutputFont(MimeObject *obj, PRBool endFont, char * size, char* color)
00492 {
00493   int status = 0;
00494   char * htmlLine = NULL;
00495 
00496   if (endFont)
00497     status = WriteEachLineToStream (obj, "</FONT>");
00498   else
00499   {
00500     int htmlLen = strlen("<FONT>") + 1;
00501     if (size)
00502       htmlLen += strlen(" SIZE=") + strlen(size);
00503     if (color)
00504       htmlLen += strlen(" COLOR=") + strlen(color);
00505     if (size || color)
00506       htmlLen++;
00507 
00508     htmlLine = (char *) PR_MALLOC (htmlLen);
00509     if (htmlLine)
00510     {
00511       htmlLine[0] = '\0';
00512         PL_strcat (htmlLine, "<FONT");
00513       if (size)
00514       { 
00515         PL_strcat (htmlLine, " SIZE=");
00516         PL_strcat (htmlLine, size);
00517       }
00518       if (color)
00519       { 
00520         PL_strcat (htmlLine, " COLOR=");
00521         PL_strcat (htmlLine, color);
00522       }
00523       if (size || color)
00524         PL_strcat (htmlLine, " ");
00525 
00526       PL_strcat (htmlLine, ">");
00527 
00528       status = COM_MimeObject_write(obj, htmlLine, strlen(htmlLine), PR_TRUE);
00529       PR_Free ((void*) htmlLine);
00530     }
00531     else
00532       status = VCARD_OUT_OF_MEMORY;
00533   }
00534 
00535   return status;
00536 }
00537 
00538 static int OutputVcardAttribute(MimeObject *obj, VObject *v, const char* id) 
00539 {
00540   int status = 0;
00541   VObject *prop = NULL;
00542   char *string = NULL;
00543 
00544   nsCOMPtr<nsIMsgVCardService> vCardService = 
00545              do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
00546   if (!vCardService)
00547       return -1;
00548 
00549   prop = vCardService->IsAPropertyOf(v, id);
00550   if (prop)
00551     if (VALUE_TYPE(prop))
00552     {
00553       if (VALUE_TYPE(prop) != VCVT_RAW)
00554       {
00555         string = vCardService->FakeCString(prop);
00556       }
00557       else
00558       {
00559         string = vCardService->VObjectAnyValue(prop);
00560       }
00561       if (string) {
00562         status = OutputFont(obj, PR_FALSE, "-1", NULL);
00563         if (status < 0) {
00564           PR_FREEIF (string);
00565           return status;
00566         }
00567         status = WriteLineToStream (obj, string, PR_TRUE);
00568         PR_FREEIF (string);
00569         if (status < 0) return status;
00570         status = OutputFont(obj, PR_TRUE, NULL, NULL);
00571         if (status < 0) return status;
00572       }
00573     }
00574 
00575   return 0;
00576 }
00577 
00578 
00579 static int OutputBasicVcard(MimeObject *obj, VObject *v)
00580 {
00581   int status = 0;
00582   char * htmlLine1 = NULL;
00583   char * htmlLine2 = NULL;
00584   char * htmlLine = NULL;
00585   VObject *prop = NULL;
00586   char * urlstring = NULL;
00587   char * namestring = NULL;
00588   char * emailstring = NULL;
00589 
00590   nsCOMPtr<nsIMsgVCardService> vCardService = 
00591       do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
00592   if (!vCardService)
00593       return -1;
00594   
00595   /* get the name and email */
00596   prop = vCardService->IsAPropertyOf(v, VCFullNameProp);
00597   if (prop)
00598   {
00599     if (VALUE_TYPE(prop))
00600     {
00601       if (VALUE_TYPE(prop) != VCVT_RAW)
00602       {
00603         namestring = vCardService->FakeCString(prop);
00604       }
00605       else
00606       {
00607         namestring = vCardService->VObjectAnyValue(prop);
00608       }
00609       if (namestring)
00610       {
00611         prop = vCardService->IsAPropertyOf(v, VCURLProp);
00612         if (prop)
00613         {
00614           urlstring = vCardService->FakeCString(prop);
00615           if (urlstring)
00616             htmlLine1 = PR_smprintf ("<A HREF=""%s"" PRIVATE>%s</A> ", urlstring, namestring);
00617           else
00618             htmlLine1 = PR_smprintf ("%s ", namestring);
00619           PR_FREEIF (urlstring);
00620         }
00621         else
00622           htmlLine1 = PR_smprintf ("%s ", namestring);
00623 
00624         /* get the email address */
00625         prop = vCardService->IsAPropertyOf(v, VCEmailAddressProp);
00626         if (prop)
00627         {
00628          emailstring = vCardService->FakeCString(prop);
00629           if (emailstring)
00630           {
00631             htmlLine2 = PR_smprintf ("&lt;<A HREF=""mailto:%s"" PRIVATE>%s</A>&gt;", emailstring, emailstring);
00632             PR_FREEIF (emailstring);
00633           }
00634         }
00635 
00636         PR_FREEIF (namestring);
00637         if (!htmlLine1 && !htmlLine2)
00638         {
00639           PR_FREEIF (htmlLine1);
00640           PR_FREEIF (htmlLine2);
00641           return VCARD_OUT_OF_MEMORY;
00642         }
00643         else
00644         {
00645           htmlLine = NS_MsgSACat (&htmlLine, htmlLine1);
00646           htmlLine = NS_MsgSACat (&htmlLine, htmlLine2);
00647         }
00648 
00649         PR_FREEIF (htmlLine1);
00650         PR_FREEIF (htmlLine2);
00651       }
00652     }
00653   }
00654 
00655   status = OutputTable (obj, PR_FALSE, PR_FALSE, "0", "0", NULL);
00656   if (status < 0) {
00657     PR_FREEIF (htmlLine); 
00658     return status;
00659   }
00660   if (htmlLine)
00661   {
00662     status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
00663     if (status < 0) {
00664       PR_Free (htmlLine);
00665       return status;
00666     }
00667     status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, NULL, NULL, NULL, NULL);
00668     if (status < 0) {
00669       PR_Free (htmlLine);
00670       return status;
00671     }
00672 
00673     status = WriteLineToStream (obj, htmlLine, PR_TRUE);
00674     PR_Free (htmlLine); 
00675     if (status < 0) return status;
00676     status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
00677     if (status < 0) return status;
00678     status = OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL);
00679     if (status < 0) return status;
00680   }
00681   else
00682     status = VCARD_OUT_OF_MEMORY;
00683 
00684   status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL, NULL);
00685   if (status < 0) return status;
00686   status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, NULL, NULL, NULL, NULL);
00687   if (status < 0) return status;
00688   /* output the title */
00689   status = OutputVcardAttribute (obj, v, VCTitleProp);
00690   if (status < 0) return status;
00691   /* write out the org name and company name */
00692   prop = vCardService->IsAPropertyOf(v, VCOrgProp);
00693   if (prop)
00694   {
00695     status = OutputVcardAttribute (obj, prop, VCOrgNameProp);
00696     if (status < 0) return status;
00697     status = OutputVcardAttribute (obj, prop, VCOrgUnitProp);
00698     if (status < 0) return status;
00699     status = OutputVcardAttribute (obj, prop, VCOrgUnit2Prop);
00700     if (status < 0) return status;
00701     status = OutputVcardAttribute (obj, prop, VCOrgUnit3Prop);
00702     if (status < 0) return status;
00703   }
00704   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
00705   if (status < 0) return status;
00706   status = OutputTableRowOrData (obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL);
00707   if (status < 0) return status;
00708   status = OutputTable (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL);
00709   if (status < 0) return status;
00710 
00711   return 0;
00712 }
00713 
00714 static int OutputAdvancedVcard(MimeObject *obj, VObject *v)
00715 {
00716   int status = 0;
00717   char * htmlLine1 = NULL;
00718   char * htmlLine2 = NULL;
00719   VObject *prop = NULL;
00720   VObject* prop2 = NULL;
00721   char * urlstring = NULL;
00722   char * namestring = NULL;
00723   char * emailstring = NULL;
00724   int numEmail = 0;
00725 
00726   nsCOMPtr<nsIMsgVCardService> vCardService = 
00727       do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
00728   if (!vCardService)
00729       return -1;
00730   
00731   status = OutputTable (obj, PR_FALSE, PR_FALSE, "0", "0", NULL);
00732   if (status < 0) return status;
00733   /* beginning of first row */
00734   status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
00735   if (status < 0) return status;
00736   status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", "3", NULL);
00737   if (status < 0) return status;
00738 
00739   /* get the name and email */
00740   prop = vCardService->IsAPropertyOf(v, VCFullNameProp);
00741   if (prop)
00742   {
00743     if (VALUE_TYPE(prop))
00744     {
00745       if (VALUE_TYPE(prop) != VCVT_RAW) 
00746       {
00747         namestring = vCardService->FakeCString(prop);
00748       }
00749       else
00750       {
00751         namestring = vCardService->VObjectAnyValue(prop);
00752       }
00753       if (namestring)
00754       {
00755         prop = vCardService->IsAPropertyOf(v, VCURLProp);
00756         if (prop)
00757         {
00758           urlstring = vCardService->FakeCString(prop);
00759           if (urlstring)
00760             htmlLine1 = PR_smprintf ("<A HREF=""%s"" PRIVATE>%s</A> ", urlstring, namestring);
00761           else
00762             htmlLine1 = PR_smprintf ("%s ", namestring);
00763           PR_FREEIF (urlstring);
00764         }
00765         else
00766           htmlLine1 = PR_smprintf ("%s ", namestring);
00767 
00768         PR_FREEIF (namestring);
00769       }
00770       if (!htmlLine1)
00771       {
00772         return VCARD_OUT_OF_MEMORY;
00773       }
00774     }
00775   }
00776   /* output the name if there was one */
00777   if (htmlLine1)
00778   {
00779     status = WriteLineToStream (obj, htmlLine1, PR_TRUE);
00780     PR_FREEIF (htmlLine1);
00781     if (status < 0) return status;
00782   }
00783 
00784   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
00785   if (status < 0) return status;
00786   status = OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL);
00787   if (status < 0) return status;
00788   
00789   /* beginning of second row */
00790   status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
00791   if (status < 0) return status;
00792   status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
00793   if (status < 0) return status;
00794   /* output the title */
00795   status = OutputVcardAttribute (obj, v, VCTitleProp);
00796   if (status < 0) return status;
00797   /* write out the org name and company name */
00798   prop = vCardService->IsAPropertyOf(v, VCOrgProp);
00799   if (prop)
00800   {
00801     status = OutputVcardAttribute (obj, prop, VCOrgNameProp);
00802     if (status < 0) return status;
00803     status = OutputVcardAttribute (obj, prop, VCOrgUnitProp);
00804     if (status < 0) return status;
00805     status = OutputVcardAttribute (obj, prop, VCOrgUnit2Prop);
00806     if (status < 0) return status;
00807     status = OutputVcardAttribute (obj, prop, VCOrgUnit3Prop);
00808     if (status < 0) return status;
00809   }
00810   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
00811   if (status < 0) return status;
00812 
00813   status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE , "LEFT", "TOP", NULL, "\"10\"");
00814   if (status < 0) return status;
00815   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
00816   if (status < 0) return status;
00817 
00818   status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
00819   if (status < 0) return status;
00820 
00821   /* get the email address */
00822   prop = vCardService->IsAPropertyOf(v, VCEmailAddressProp);
00823   if (prop)
00824   {
00825     emailstring = vCardService->FakeCString(prop);
00826     if (emailstring)
00827     {
00828       numEmail++;
00829       /* if its an internet address prepend the mailto url */
00830       prop2 = vCardService->IsAPropertyOf(prop, VCInternetProp);
00831       if (prop2)
00832         htmlLine2 = PR_smprintf ("&lt;<A HREF=""mailto:%s"" PRIVATE>%s</A>&gt;", emailstring, emailstring);
00833       else
00834         htmlLine2 = PR_smprintf ("%s", emailstring);
00835 
00836       PR_FREEIF (emailstring);
00837     }
00838     if (!htmlLine2)
00839     {
00840       return VCARD_OUT_OF_MEMORY;
00841     }
00842   }
00843   /* output email address */
00844   if (htmlLine2)
00845   {
00846     status = OutputFont(obj, PR_FALSE, "-1", NULL);
00847     if (status < 0) {
00848       PR_FREEIF (htmlLine2);
00849       return status;
00850     }
00851     status = WriteLineToStream (obj, htmlLine2, PR_TRUE);
00852     PR_FREEIF (htmlLine2);
00853     if (status < 0) return status;
00854     status = OutputFont(obj, PR_TRUE, NULL, NULL);
00855     if (status < 0) return status;
00856     /* output html mail setting only if its true */
00857     prop = vCardService->IsAPropertyOf(v, VCUseHTML);
00858     if (prop)
00859     {
00860       if (VALUE_TYPE(prop))
00861       {
00862         namestring = vCardService->FakeCString(prop);
00863         if (namestring)
00864           if (nsCRT::strcasecmp (namestring, "TRUE") == 0)
00865           {
00866             PR_FREEIF (namestring);
00867             status = OutputFont(obj, PR_FALSE, "-1", NULL);
00868             if (status < 0) return status;
00869             char *tString = VCardGetStringByID(VCARD_LDAP_USEHTML);
00870             status = WriteLineToStream (obj, tString, PR_FALSE);
00871             PR_FREEIF(tString);
00872             if (status < 0) return status;
00873             status = OutputFont(obj, PR_TRUE, NULL, NULL);
00874             if (status < 0) return status;
00875           }
00876           else
00877             PR_FREEIF (namestring);
00878       }
00879     }
00880   }
00881   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
00882   if (status < 0) return status;
00883   status = OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL);
00884   if (status < 0) return status;
00885 
00886   /* beginning of third row */
00887   /* write out address information if we have any */
00888   status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
00889   if (status < 0) return status;
00890   /* first column */
00891   status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
00892   if (status < 0) return status;
00893   prop = vCardService->IsAPropertyOf(v, VCAdrProp);
00894   if (prop)
00895   {
00896     status = OutputVcardAttribute (obj, prop, VCPostalBoxProp);
00897     if (status < 0) return status;
00898     status = OutputVcardAttribute (obj, prop, VCExtAddressProp);
00899     if (status < 0) return status;
00900     status = OutputVcardAttribute (obj, prop, VCStreetAddressProp);
00901     if (status < 0) return status;
00902     status = OutputVcardAttribute (obj, prop, VCCityProp);
00903     if (status < 0) return status;
00904     status = OutputVcardAttribute (obj, prop, VCRegionProp);
00905     if (status < 0) return status;
00906     status = OutputVcardAttribute (obj, prop, VCPostalCodeProp);
00907     if (status < 0) return status;
00908     status = OutputVcardAttribute (obj, prop, VCCountryNameProp);
00909     if (status < 0) return status;
00910   }
00911   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
00912   if (status < 0) return status;
00913 
00914   /* second column */
00915   status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE , NULL, NULL, NULL, NULL);
00916   if (status < 0) return status;
00917   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
00918   if (status < 0) return status;
00919 
00920   /* third column */
00921   status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
00922   if (status < 0) return status;
00923   /* output telephone fields */
00924   status = WriteOutVCardPhoneProperties (obj, v);
00925   if (status < 0) return status;
00926   /* output conference fields */
00927   status = OutputFont(obj, PR_FALSE, "-1", NULL);
00928   if (status < 0) return status;
00929   prop = vCardService->IsAPropertyOf(v, VCCooltalk);
00930   if (prop)
00931   {
00932     char *tString = VCardGetStringByID(VCARD_ADDR_CONFINFO);
00933     WriteLineToStream (obj, tString, PR_FALSE);
00934     PR_FREEIF(tString);
00935     if (status < 0) return status;
00936     prop2 = vCardService->IsAPropertyOf(prop, VCUseServer);
00937     if (prop2)
00938     {
00939       if (VALUE_TYPE(prop2)) 
00940       {
00941         namestring = vCardService->FakeCString(prop2);
00942         char *tString1 = NULL;
00943         if (nsCRT::strcmp (namestring, "0") == 0)
00944         {
00945           tString1 = VCardGetStringByID(VCARD_ADDR_DEFAULT_DLS);
00946         }
00947         else 
00948         {
00949           if (nsCRT::strcmp (namestring, "1") == 0)
00950             tString1 = VCardGetStringByID(VCARD_ADDR_SPECIFIC_DLS);
00951           else
00952             if (nsCRT::strcmp (namestring, "2") == 0)
00953               tString1 = VCardGetStringByID(VCARD_ADDR_HOSTNAMEIP);
00954         }
00955         
00956         if (tString1) 
00957         {
00958           status = WriteLineToStream (obj, tString1, PR_FALSE);
00959         }
00960         PR_FREEIF(tString1);
00961         PR_FREEIF (namestring);
00962         if (status < 0) return status;
00963       }
00964     }
00965     status = OutputVcardAttribute (obj, prop, VCCooltalkAddress);
00966     if (status < 0) return status;
00967   }
00968 
00969   status = OutputFont(obj, PR_TRUE, NULL, NULL);
00970   if (status < 0) return status;
00971   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
00972   if (status < 0) return status;
00973 
00974   status = OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL);
00975   if (status < 0) return status;
00976 
00977   /* beginning of last row */
00978   /* output notes field */
00979   prop = vCardService->IsAPropertyOf(v, VCCommentProp);
00980   if (prop)
00981   {
00982     status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
00983     if (status < 0) return status;
00984     status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", "3", NULL);
00985     if (status < 0) return status;
00986     status = OutputVcardAttribute (obj, v, VCCommentProp);
00987     if (status < 0) return status;
00988     status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
00989     if (status < 0) return status;
00990     status = OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL);
00991     if (status < 0) return status;
00992   }
00993 
00994   status = OutputTable (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL);
00995   if (status < 0) return status;
00996 
00997   /* output second table containing all the additional info */
00998   status = OutputTable (obj, PR_FALSE, PR_FALSE, "0", "0", NULL);
00999   if (status < 0) return status;
01000   /* beginning of first row */
01001   status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
01002   if (status < 0) return status;
01003   status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", "2", NULL);
01004   if (status < 0) return status;
01005   /* output the additional info header */
01006   status = OutputFont(obj, PR_FALSE, "-1", NULL);
01007   if (status < 0) return status;
01008   char *tString = VCardGetStringByID(VCARD_ADDR_ADDINFO);
01009   status = WriteLineToStream (obj, tString, PR_FALSE);
01010   PR_FREEIF(tString);
01011   if (status < 0) return status;
01012   status = OutputFont(obj, PR_TRUE, NULL, NULL);
01013   if (status < 0) return status;
01014   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
01015   if (status < 0) return status;
01016   status = OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL);
01017   if (status < 0) return status;
01018   
01019   /* beginning of remaining rows */
01020   status = WriteOutVCardProperties (obj, v, &numEmail);
01021   if (status < 0) return status;
01022 
01023   status = OutputTable (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL);
01024   if (status < 0) return status;
01025 
01026   return 0;
01027 }
01028 
01029 static int OutputButtons(MimeObject *obj, PRBool basic, VObject *v)
01030 {
01031   int status = 0;
01032   char * htmlLine1 = NULL;
01033   char *htmlLine2 = NULL;
01034   char* vCard = NULL;
01035   char* vEscCard = NULL;
01036   int len = 0;
01037   char* rsrcString = NULL;
01038   
01039   if (!obj->options->output_vcard_buttons_p)
01040     return status;
01041 
01042   nsCOMPtr<nsIMsgVCardService> vCardService = 
01043       do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
01044   if (!vCardService)
01045       return -1;
01046 
01047   vCard = vCardService->WriteMemoryVObjects(0, &len, v, PR_FALSE);
01048 
01049   if (!vCard)
01050     return VCARD_OUT_OF_MEMORY;
01051 
01052   vEscCard = nsEscape (vCard, url_XAlphas);
01053 
01054   PR_FREEIF (vCard);
01055 
01056   if (!vEscCard)
01057     return VCARD_OUT_OF_MEMORY;
01058 
01059   if (basic)
01060   {
01061     rsrcString = VCardGetStringByID(VCARD_ADDR_VIEW_COMPLETE_VCARD);
01062     htmlLine1 = PR_smprintf ("<FORM name=form1><INPUT type=reset value=\\\"%s\\\" onClick=\\\"showAdvanced%d();\\\"></INPUT></FORM>", 
01063                               rsrcString, s_unique);
01064   }
01065   else 
01066   {
01067     rsrcString = VCardGetStringByID(VCARD_ADDR_VIEW_CONDENSED_VCARD);
01068     htmlLine1 = PR_smprintf ("<FORM name=form1><INPUT type=reset value=\\\"%s\\\" onClick=\\\"showBasic%d();\\\"></INPUT></FORM>", 
01069                               rsrcString, s_unique);
01070   }
01071   PR_FREEIF(rsrcString);
01072 
01073   rsrcString = VCardGetStringByID(VCARD_MSG_ADD_TO_ADDR_BOOK);
01074   htmlLine2 = PR_smprintf("<FORM name=form1 METHOD=get ACTION=\"addbook:add?action=add\"><INPUT TYPE=hidden name=vcard VALUE=\"%s\"><INPUT type=submit value=\"%s\"></INPUT></FORM>",
01075                            vEscCard, rsrcString); 
01076   PR_FREEIF(rsrcString);
01077 
01078   if (!htmlLine1 || !htmlLine2)
01079   {
01080     status = VCARD_OUT_OF_MEMORY;
01081     goto FAIL;
01082   }
01083   
01084   status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
01085   if (status < 0) goto FAIL;
01086 
01087   /*
01088    * WARNING: This HTML is written to the stream using JavaScript,
01089    * because we don't want this button to be displayed when JS has
01090    * been switched off (in the whole client or just in email). The
01091    * button won't work when JS is switched off (since it calls a JS
01092    * function), so then we don't want the button to be displayed.
01093    *   -- erik (and jfriend)
01094    */
01095   status = WriteEachLineToStream (obj, "<SCRIPT>document.write(\"");
01096   if (status < 0) goto FAIL;
01097 
01098   status = WriteLineToStream (obj, htmlLine1, PR_FALSE);
01099   if (status < 0) goto FAIL;
01100 
01101   status = WriteEachLineToStream (obj, "\")</SCRIPT>");
01102   if (status < 0) goto FAIL;
01103 
01104   status = WriteLineToStream (obj, htmlLine2, PR_FALSE);
01105   if (status < 0) goto FAIL;
01106 
01107   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
01108   if (status < 0) goto FAIL;
01109 
01110   FAIL:
01111   PR_FREEIF (vEscCard);
01112   PR_FREEIF (htmlLine1);
01113   PR_FREEIF(htmlLine2);
01114 
01115   return status;
01116 }
01117 
01118 static int BeginLayer(MimeObject *obj, PRBool basic)
01119 {
01120   int status = 0;
01121   char * captionLine = NULL;
01122 
01123   if (basic)
01124   {
01125     //CSS: START OF DIV   
01126     captionLine = PR_smprintf ("<DIV ID=basic%d style=\"position: 'absolute';\">", s_unique);
01127   }
01128   else
01129   {
01130     //CSS: START OF DIV   
01131     captionLine = PR_smprintf ("<DIV ID=advanced%d style=\"position: 'absolute'; display: none;\">", s_unique);
01132   }
01133 
01134   if (captionLine)
01135   {
01136     status = WriteEachLineToStream (obj, captionLine);
01137     PR_Free(captionLine);
01138     if (status < 0) return status;
01139     status = OutputTable (obj, PR_FALSE, PR_FALSE, NULL, NULL, NULL);
01140     if (status < 0) return status;
01141     status = OutputTableRowOrData (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL, NULL);
01142     if (status < 0) return status;
01143     status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, NULL, "TOP", NULL, NULL);
01144     if (status < 0) return status;
01145     status = OutputTable (obj, PR_FALSE, PR_TRUE, "0", "0", "#FFFFFF");
01146     if (status < 0) return status;
01147     if (basic)
01148     {
01149       status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
01150       if (status < 0) return status;
01151       status = OutputTableRowOrData(obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
01152       if (status < 0) return status;
01153     }
01154     else
01155     {
01156       status = OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL, NULL);
01157       if (status < 0) return status;
01158       status = OutputTableRowOrData(obj, PR_FALSE, PR_FALSE, NULL, NULL, NULL, NULL);
01159       if (status < 0) return status;
01160     }
01161 
01162     status = OutputTable (obj, PR_FALSE, PR_FALSE, "4", NULL, NULL);
01163     if (status < 0) return status;
01164     status = OutputTableRowOrData (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL, NULL);
01165     if (status < 0) return status;
01166     status = OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, NULL, NULL, NULL, NULL);
01167     if (status < 0) return status;
01168   }
01169   else
01170     status = VCARD_OUT_OF_MEMORY;
01171 
01172   return status;
01173 }
01174 
01175 static int EndLayer(MimeObject *obj, PRBool basic, VObject* v)
01176 {
01177   int status = 0;
01178   char * captionLine = NULL;
01179 
01180   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
01181   if (status < 0) return status;
01182   status = OutputTableRowOrData (obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL);
01183   if (status < 0) return status;
01184   status = OutputTable (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL);
01185   if (status < 0) return status;
01186 
01187   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
01188   if (status < 0) return status;
01189   status = OutputTableRowOrData (obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL);
01190   if (status < 0) return status;
01191   status = OutputTable (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL);
01192   if (status < 0) return status;
01193   status = OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
01194   if (status < 0) return status;
01195 
01196   status = OutputButtons(obj, basic, v);
01197   if (status < 0) return status;
01198 
01199   status = OutputTableRowOrData (obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL);
01200   if (status < 0) return status;
01201   status = OutputTable (obj, PR_TRUE, PR_FALSE, NULL, NULL, NULL);
01202   if (status < 0) return status;
01203 
01204   if (!basic) 
01205   {
01206     //CSS: END OF DIV   
01207     status = WriteEachLineToStream (obj, "</DIV>");
01208     if (status < 0) return status;
01209     status = WriteEachLineToStream (obj, "<P><SCRIPT>");
01210     if (status < 0) return status;
01211 
01212     captionLine = PR_smprintf (
01213 "function showAdvanced%d()\
01214 {\
01215   var longDiv  = document.getElementById(\"advanced%d\");\
01216   var shortDiv = document.getElementById(\"basic%d\");\
01217   longDiv.setAttribute(\"style\", \"display:block;\");\
01218   shortDiv.setAttribute(\"style\", \"display:none;\");\
01219 };\
01220 function showBasic%d()\
01221 {\
01222   var longDiv  = document.getElementById(\"advanced%d\");\
01223   var shortDiv = document.getElementById(\"basic%d\");\
01224   longDiv.setAttribute(\"style\", \"display:none;\");\
01225   shortDiv.setAttribute(\"style\", \"display:block;\");\
01226 };", 
01227                         s_unique, s_unique, s_unique, 
01228                         s_unique, s_unique, s_unique);
01229     if (captionLine)
01230       status = WriteEachLineToStream (obj, captionLine);
01231     PR_FREEIF (captionLine);
01232     if (status < 0) return status;
01233 
01234 
01235     status = WriteEachLineToStream (obj, "</SCRIPT></P>");
01236   } 
01237   else {
01238     //CSS: END DIV
01239     status = WriteEachLineToStream (obj, "</DIV>");
01240   }
01241 
01242   if (status < 0) return status;
01243   return 0;
01244 }
01245 
01246 static int WriteOutVCard (MimeObject *obj, VObject* v)
01247 {
01248   int status = 0;
01249 
01250   status = BeginVCard (obj);
01251   if (status < 0) return status;
01252   
01253   /* write out basic layer */
01254   status = BeginLayer(obj, PR_TRUE);
01255   if (status < 0) return status;
01256   status = OutputBasicVcard(obj, v);
01257   if (status < 0) return status;
01258   status = EndLayer(obj, PR_TRUE, v);
01259   if (status < 0) return status;
01260 
01261   /* write out advanced layer */
01262   status = BeginLayer(obj, PR_FALSE);
01263   if (status < 0) return status;
01264   status = OutputAdvancedVcard(obj, v);
01265   if (status < 0) return status;
01266   status = EndLayer(obj, PR_FALSE, v);
01267   if (status < 0) return status;
01268 
01269   status = EndVCard (obj);
01270   if (status < 0) return status;
01271 
01272   return 0;
01273 }
01274 
01275 static void GetAddressProperties (VObject* o, char ** attribName)
01276 {
01277   nsCOMPtr<nsIMsgVCardService> vCardService = 
01278         do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
01279   if (!vCardService)
01280     return;
01281     
01282   VObject* domProp = vCardService->IsAPropertyOf(o, VCDomesticProp);
01283   VObject* intlProp = vCardService->IsAPropertyOf(o, VCInternationalProp);
01284   VObject* postal = vCardService->IsAPropertyOf(o, VCPostalProp);
01285   VObject* parcel = vCardService->IsAPropertyOf(o, VCParcelProp);
01286   VObject* home = vCardService->IsAPropertyOf(o, VCHomeProp);
01287   VObject* work = vCardService->IsAPropertyOf(o, VCWorkProp);
01288   char    *tString = NULL;
01289 
01290   if (domProp) {
01291     tString = VCardGetStringByID(VCARD_LDAP_DOM_TYPE);
01292   }
01293   if (intlProp) {
01294     tString = VCardGetStringByID(VCARD_LDAP_INTL_TYPE);
01295   }
01296   if (postal) {
01297     tString = VCardGetStringByID(VCARD_LDAP_POSTAL_TYPE);
01298   }
01299   if (parcel) {
01300     tString = VCardGetStringByID(VCARD_LDAP_PARCEL_TYPE);
01301   }
01302   if (home) {
01303     tString = VCardGetStringByID(VCARD_LDAP_HOME_TYPE);
01304   }
01305   if (work) {
01306     tString = VCardGetStringByID(VCARD_LDAP_WORK_TYPE);
01307   }
01308 
01309   if (tString)
01310   {
01311     NS_MsgSACat (&(*attribName), " ");
01312     NS_MsgSACat (&(*attribName), tString);
01313     PR_FREEIF(tString);
01314   }
01315 }
01316 
01317 
01318 static void GetTelephoneProperties (VObject* o, char ** attribName)
01319 {
01320   nsCOMPtr<nsIMsgVCardService> vCardService = 
01321     do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
01322   if (!vCardService)
01323     return;
01324 
01325   VObject* prefProp = vCardService->IsAPropertyOf(o, VCPreferredProp);
01326   VObject* home = vCardService->IsAPropertyOf(o, VCHomeProp);
01327   VObject* work = vCardService->IsAPropertyOf(o, VCWorkProp);
01328   VObject* voiceProp = vCardService->IsAPropertyOf(o, VCVoiceProp);
01329   VObject* fax = vCardService->IsAPropertyOf(o, VCFaxProp);
01330   VObject* msg = vCardService->IsAPropertyOf(o, VCMessageProp);
01331   VObject* cell = vCardService->IsAPropertyOf(o, VCCellularProp);
01332   VObject* pager = vCardService->IsAPropertyOf(o, VCPagerProp);
01333   VObject* bbs = vCardService->IsAPropertyOf(o, VCBBSProp);
01334   char    *tString = NULL;
01335 
01336   if (prefProp) {
01337     tString = VCardGetStringByID(VCARD_LDAP_PREF_TYPE);
01338   }
01339   if (home) {
01340     tString = VCardGetStringByID(VCARD_LDAP_HOME_TYPE);
01341   }
01342   if (work) {
01343     tString = VCardGetStringByID(VCARD_LDAP_WORK_TYPE);
01344   }
01345   if (voiceProp) {
01346     tString = VCardGetStringByID(VCARD_LDAP_VOICE_TYPE);
01347   }
01348   if (fax) {
01349     tString = VCardGetStringByID(VCARD_LDAP_FAX_TYPE);
01350   }
01351   if (msg) {
01352     tString = VCardGetStringByID(VCARD_LDAP_MSG_TYPE);
01353   }
01354   if (cell) {
01355     tString = VCardGetStringByID(VCARD_LDAP_CELL_TYPE);
01356   }
01357   if (pager) {
01358     tString = VCardGetStringByID(VCARD_LDAP_PAGER_TYPE);
01359   }
01360   if (bbs) {
01361     tString = VCardGetStringByID(VCARD_LDAP_BBS_TYPE);
01362   }
01363 
01364   if (tString)
01365   {
01366     NS_MsgSACat (&(*attribName), " ");
01367     NS_MsgSACat (&(*attribName), tString);
01368     PR_FREEIF(tString);
01369   }
01370 }
01371 
01372 static void GetEmailProperties (VObject* o, char ** attribName)
01373 {
01374   nsCOMPtr<nsIMsgVCardService> vCardService = 
01375     do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
01376   if (!vCardService)
01377     return;
01378 
01379   VObject* prefProp = vCardService->IsAPropertyOf(o, VCPreferredProp);
01380   VObject* home = vCardService->IsAPropertyOf(o, VCHomeProp);
01381   VObject* work = vCardService->IsAPropertyOf(o, VCWorkProp);
01382   VObject* aol = vCardService->IsAPropertyOf(o, VCAOLProp);
01383   VObject* applelink = vCardService->IsAPropertyOf(o, VCAppleLinkProp);
01384   VObject* att = vCardService->IsAPropertyOf(o, VCATTMailProp);
01385   VObject* cis = vCardService->IsAPropertyOf(o, VCCISProp);
01386   VObject* eworld = vCardService->IsAPropertyOf(o, VCEWorldProp);
01387   VObject* internet = vCardService->IsAPropertyOf(o, VCInternetProp);
01388   VObject* ibmmail = vCardService->IsAPropertyOf(o, VCIBMMailProp);
01389   VObject* mcimail = vCardService->IsAPropertyOf(o, VCMCIMailProp);
01390   VObject* powershare = vCardService->IsAPropertyOf(o, VCPowerShareProp);
01391   VObject* prodigy = vCardService->IsAPropertyOf(o, VCProdigyProp);
01392   VObject* telex = vCardService->IsAPropertyOf(o, VCTLXProp);
01393   VObject* x400 = vCardService->IsAPropertyOf(o, VCX400Prop);
01394   char     *tString = NULL;
01395 
01396   if (prefProp) {
01397     tString = VCardGetStringByID(VCARD_LDAP_PREF_TYPE);
01398   }
01399   if (home) {
01400     tString = VCardGetStringByID(VCARD_LDAP_HOME_TYPE);
01401   }
01402   if (work) {
01403     tString = VCardGetStringByID(VCARD_LDAP_WORK_TYPE);
01404   }
01405   if (aol) {
01406     tString = VCardGetStringByID(VCARD_LDAP_AOL_TYPE);
01407   }
01408   if (applelink) {
01409     tString = VCardGetStringByID(VCARD_LDAP_APPLELINK_TYPE);
01410   }
01411   if (att) {
01412     tString = VCardGetStringByID(VCARD_LDAP_ATTMAIL_TYPE);
01413   }
01414   if (cis) {
01415     tString = VCardGetStringByID(VCARD_LDAP_CSI_TYPE);
01416   }
01417   if (eworld) {
01418     tString = VCardGetStringByID(VCARD_LDAP_EWORLD_TYPE);
01419   }
01420   if (internet) {
01421     tString = VCardGetStringByID(VCARD_LDAP_INTERNET_TYPE);
01422   }
01423   if (ibmmail) {
01424     tString = VCardGetStringByID(VCARD_LDAP_IBMMAIL_TYPE);
01425   }
01426   if (mcimail) {
01427     tString = VCardGetStringByID(VCARD_LDAP_MCIMAIL_TYPE);
01428   }
01429   if (powershare) {
01430     tString = VCardGetStringByID(VCARD_LDAP_POWERSHARE_TYPE);
01431   }
01432   if (prodigy) {
01433     tString = VCardGetStringByID(VCARD_LDAP_PRODIGY_TYPE);
01434   }
01435   if (telex) {
01436     tString = VCardGetStringByID(VCARD_LDAP_TLX_TYPE);
01437   }
01438   if (x400) {
01439     tString = VCardGetStringByID(VCARD_LDAP_X400);
01440   }
01441 
01442   if (tString)
01443   {
01444     NS_MsgSACat (&(*attribName), " ");
01445     NS_MsgSACat (&(*attribName), tString);
01446     PR_FREEIF(tString);
01447   }
01448 }
01449 
01450 static int WriteOutEachVCardPhoneProperty (MimeObject *obj, VObject* o)
01451 {
01452   char *attribName = NULL;
01453   char *value = NULL;
01454   int status = 0;
01455 
01456   nsCOMPtr<nsIMsgVCardService> vCardService = 
01457       do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
01458   if (!vCardService)
01459       return -1;
01460   
01461   if (vCardService->VObjectName(o)) 
01462   {
01463     if (nsCRT::strcasecmp (VCTelephoneProp, vCardService->VObjectName(o)) == 0) 
01464     {
01465       if (VALUE_TYPE(o)) 
01466       {
01467         GetTelephoneProperties(o, &attribName);
01468         if (!attribName)
01469           attribName = VCardGetStringByID(VCARD_LDAP_PHONE_NUMBER);
01470         attribName = NS_MsgSACat(&attribName, ": ");
01471         value = vCardService->FakeCString(o);
01472         if (value)
01473         {
01474           if (attribName)
01475           {
01476             status = OutputFont(obj, PR_FALSE, "-1", NULL);
01477             if (status < 0) {
01478               PR_FREEIF (value);
01479               PR_FREEIF (attribName);
01480               return status;
01481             }
01482             // write a label without charset conversion
01483             status = WriteLineToStream (obj, attribName, PR_FALSE);
01484             if (status < 0) {
01485               PR_FREEIF (value);
01486               PR_FREEIF (attribName);
01487               return status;
01488             }
01489             // write value with charset conversion
01490             status = WriteLineToStream (obj, value, PR_TRUE);
01491             if (status < 0) {
01492               PR_FREEIF (value);
01493               PR_FREEIF (attribName);
01494               return status;
01495             }
01496             status = OutputFont(obj, PR_TRUE, NULL, NULL);
01497             if (status < 0) {
01498               PR_FREEIF (value);
01499               PR_FREEIF (attribName);
01500               return status;
01501             }
01502           }
01503           PR_FREEIF (attribName);
01504         }
01505         PR_FREEIF (value);
01506       }
01507     }
01508   }
01509   return status;
01510 }
01511 
01512 static int WriteOutVCardPhoneProperties (MimeObject *obj, VObject* v)
01513 {
01514   int status = 0;
01515   VObjectIterator t;
01516   VObject *eachProp;
01517 
01518   nsCOMPtr<nsIMsgVCardService> vCardService = 
01519     do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
01520   if (!vCardService)
01521     return -1;
01522 
01523   WriteOutEachVCardPhoneProperty (obj, v);
01524   vCardService->InitPropIterator(&t,v);
01525   while (vCardService->MoreIteration(&t) && status >= 0)
01526   {
01527     eachProp = vCardService->NextVObject(&t);
01528     status = WriteOutEachVCardPhoneProperty (obj, eachProp);
01529   }
01530 
01531   if (status < 0) return status;
01532 
01533   return 0;
01534 }
01535 
01536 static int WriteOutEachVCardProperty (MimeObject *obj, VObject* o, int* numEmail)
01537 {
01538   char *attribName = NULL;
01539   char * url = NULL;
01540   char *value = NULL;
01541   int status = 0;
01542 
01543   nsCOMPtr<nsIMsgVCardService> vCardService = 
01544       do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
01545   if (!vCardService)
01546       return -1;
01547   
01548   if (vCardService->VObjectName(o)) {
01549 
01550     if (nsCRT::strcasecmp (VCPhotoProp, vCardService->VObjectName(o)) == 0) {
01551       VObject* urlProp = vCardService->IsAPropertyOf(o, VCURLProp);
01552       if (urlProp) {
01553         attribName = VCardGetStringByID(VCARD_LDAP_PHOTOGRAPH);
01554         /* format the value string to the url */
01555         value = vCardService->FakeCString(o);
01556         if (value)
01557           url = PR_smprintf ("<IMG SRC = ""%s""", value);
01558         PR_FREEIF (value);
01559         value = NULL;
01560         goto DOWRITE;
01561       }
01562     }
01563 
01564     if (nsCRT::strcasecmp (VCBirthDateProp, vCardService->VObjectName(o)) == 0) {
01565       if (VALUE_TYPE(o)) {
01566         attribName = VCardGetStringByID(VCARD_LDAP_BIRTHDAY);
01567         value = vCardService->FakeCString(o);
01568         goto DOWRITE;
01569       }
01570     }
01571 
01572     if (nsCRT::strcasecmp (VCDeliveryLabelProp, vCardService->VObjectName(o)) == 0) {
01573       attribName = VCardGetStringByID(VCARD_LDAP_LABEL);
01574       GetAddressProperties(o, &attribName);
01575       value = vCardService->FakeCString(o);
01576       goto DOWRITE;
01577     }
01578 
01579     if (nsCRT::strcasecmp (VCEmailAddressProp, vCardService->VObjectName(o)) == 0) {
01580       if ((*numEmail) != 1)
01581       {
01582         if (VALUE_TYPE(o)) {
01583           (*numEmail)++;
01584           attribName = VCardGetStringByID(VCARD_LDAP_EMAIL_ADDRESS);
01585           GetEmailProperties(o, &attribName);
01586           value = vCardService->FakeCString(o);
01587           goto DOWRITE;
01588         };
01589       }
01590     }
01591 
01592     if (nsCRT::strcasecmp (VCFamilyNameProp, vCardService->VObjectName(o)) == 0) {
01593       if (VALUE_TYPE(o)) {
01594         attribName = VCardGetStringByID(VCARD_LDAP_SURNAME);
01595         value = vCardService->FakeCString(o);
01596         goto DOWRITE;
01597       }
01598     }
01599 
01600     if (nsCRT::strcasecmp (VCGivenNameProp, vCardService->VObjectName(o)) == 0) {
01601       if (VALUE_TYPE(o)) {
01602         attribName = VCardGetStringByID(VCARD_LDAP_GIVEN_NAME);
01603         value = vCardService->FakeCString(o);
01604         goto DOWRITE;
01605       }
01606     }
01607 
01608     if (nsCRT::strcasecmp (VCNamePrefixesProp, vCardService->VObjectName(o)) == 0) {
01609       if (VALUE_TYPE(o)) {
01610         attribName = VCardGetStringByID(VCARD_LDAP_NAME_PREFIX);
01611         value = vCardService->FakeCString(o);
01612         goto DOWRITE;
01613       }
01614     }
01615 
01616     if (nsCRT::strcasecmp (VCNameSuffixesProp, vCardService->VObjectName(o)) == 0) {
01617       if (VALUE_TYPE(o)) {
01618         attribName = VCardGetStringByID(VCARD_LDAP_NAME_SUFFIX);
01619         value = vCardService->FakeCString(o);
01620         goto DOWRITE;
01621       }
01622     }
01623 
01624     if (nsCRT::strcasecmp (VCAdditionalNamesProp, vCardService->VObjectName(o)) == 0) {
01625       if (VALUE_TYPE(o)) {
01626         attribName = VCardGetStringByID(VCARD_LDAP_MIDDLE_NAME);
01627         value = vCardService->FakeCString(o);
01628         goto DOWRITE;
01629       }
01630     }
01631 
01632     if (nsCRT::strcasecmp (VCMailerProp, vCardService->VObjectName(o)) == 0) {
01633       if (VALUE_TYPE(o)) {
01634         attribName = VCardGetStringByID(VCARD_LDAP_MAILER);
01635         value = vCardService->FakeCString(o);
01636         goto DOWRITE;
01637       }
01638     }
01639 
01640     if (nsCRT::strcasecmp (VCTimeZoneProp, vCardService->VObjectName(o)) == 0) {
01641       if (VALUE_TYPE(o)) {
01642         attribName = VCardGetStringByID(VCARD_LDAP_TZ);
01643         value = vCardService->FakeCString(o);
01644         goto DOWRITE;
01645       }
01646     }
01647 
01648     if (nsCRT::strcasecmp (VCGeoProp, vCardService->VObjectName(o)) == 0) {
01649       if (VALUE_TYPE(o)) {
01650         attribName = VCardGetStringByID(VCARD_LDAP_GEO);
01651         value = vCardService->FakeCString(o);
01652         goto DOWRITE;
01653       }
01654     }
01655 
01656     if (nsCRT::strcasecmp (VCBusinessRoleProp, vCardService->VObjectName(o)) == 0) {
01657       if (VALUE_TYPE(o)) {
01658         attribName = VCardGetStringByID(VCARD_LDAP_ROLE);
01659         value = vCardService->FakeCString(o);
01660         goto DOWRITE;
01661       }
01662     }
01663 
01664     if (nsCRT::strcasecmp (VCLogoProp, vCardService->VObjectName(o)) == 0) {
01665       VObject* urlProp = vCardService->IsAPropertyOf(o, VCURLProp);
01666       if (urlProp) {
01667         attribName = VCardGetStringByID(VCARD_LDAP_LOGO);
01668         /* format the value string to the url */
01669         value = vCardService->FakeCString(o);
01670         if (value)
01671           url = PR_smprintf ("<IMG SRC = ""%s""", value);
01672         PR_FREEIF (value);
01673         goto DOWRITE;
01674       }
01675     }
01676 
01677     if (nsCRT::strcasecmp (VCAgentProp, vCardService->VObjectName(o)) == 0) {
01678       attribName = VCardGetStringByID(VCARD_LDAP_SECRETARY);
01679       goto DOWRITE;
01680     }
01681 
01682     if (nsCRT::strcasecmp (VCLastRevisedProp, vCardService->VObjectName(o)) == 0) {
01683       if (VALUE_TYPE(o)) {
01684         attribName = VCardGetStringByID(VCARD_LDAP_REVISION);
01685         value = vCardService->FakeCString(o);
01686         goto DOWRITE;
01687       }
01688     }
01689 
01690     if (nsCRT::strcasecmp (VCPronunciationProp, vCardService->VObjectName(o)) == 0) {
01691       if (VALUE_TYPE(o)) {
01692         attribName = VCardGetStringByID(VCARD_LDAP_SOUND);
01693         value = vCardService->FakeCString(o);
01694         goto DOWRITE;
01695       }
01696     }
01697 
01698 
01699     if (nsCRT::strcasecmp (VCVersionProp, vCardService->VObjectName(o)) == 0) {
01700       if (VALUE_TYPE(o)) {
01701         attribName = VCardGetStringByID(VCARD_LDAP_VERSION);
01702         value = vCardService->FakeCString(o);
01703         goto DOWRITE;
01704       }
01705     }
01706 
01707     if (!attribName) 
01708       return 0;
01709   
01710   DOWRITE:
01711     OutputTableRowOrData(obj, PR_TRUE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
01712     OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
01713     if (attribName) { 
01714       OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
01715       status = WriteAttribute (obj, attribName);
01716       PR_Free (attribName);
01717       OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
01718     }
01719 
01720     if (value) {
01721       OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
01722       status = WriteValue (obj, value);
01723       PR_Free (value);
01724       OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
01725     }
01726 
01727     if (url) {
01728       OutputTableRowOrData (obj, PR_FALSE, PR_FALSE, "LEFT", "TOP", NULL, NULL);
01729       status = WriteValue (obj, url);
01730       PR_Free (url);
01731       OutputTableRowOrData (obj, PR_FALSE, PR_TRUE, NULL, NULL, NULL, NULL);
01732     }
01733     OutputTableRowOrData(obj, PR_TRUE, PR_TRUE, NULL, NULL, NULL, NULL);
01734   }
01735 
01736   if (status < 0) return status;
01737 
01738   return 0;
01739 }
01740 
01741 
01742 static int WriteOutVCardProperties (MimeObject *obj, VObject* v, int* numEmail)
01743 {
01744   int status = 0;
01745   VObjectIterator t;
01746   VObject *eachProp;
01747 
01748   nsCOMPtr<nsIMsgVCardService> vCardService = 
01749     do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
01750   if (!vCardService)
01751     return -1;
01752 
01753   WriteOutEachVCardProperty (obj, v, numEmail);
01754   vCardService->InitPropIterator(&t,v);
01755   while (vCardService->MoreIteration(&t) && status >= 0)
01756   {
01757     eachProp = vCardService->NextVObject(&t);
01758     status = WriteOutVCardProperties (obj, eachProp, numEmail);
01759   }
01760 
01761   if (status < 0) return status;
01762 
01763   return 0;
01764 }
01765 
01766 char *
01767 FindCharacterSet(MimeObject *obj)
01768 {
01769   char    *retCharSet = nsnull;
01770   char    *tCharSet = nsnull;
01771   char    *workString = nsnull;
01772 
01773   if ( (!obj->headers) || (!obj->headers->all_headers) )
01774     return nsnull;
01775 
01776   workString = (char *)PR_Malloc(obj->headers->all_headers_size + 1);
01777   if (!workString)
01778     return nsnull;
01779 
01780   memset(workString, 0, obj->headers->all_headers_size + 1);
01781   memcpy(workString, obj->headers->all_headers, obj->headers->all_headers_size);
01782 
01783   char *cTypePtr = (char *) PL_strcasestr(workString, HEADER_CONTENT_TYPE);
01784   if (!cTypePtr)
01785   {
01786     PR_FREEIF(workString);
01787     return nsnull;
01788   }
01789 
01790   while ( (*cTypePtr) && (*cTypePtr != nsCRT::CR) && (*cTypePtr != nsCRT::LF) )
01791   {
01792     tCharSet  = (char *) PL_strcasestr(cTypePtr, "charset=");
01793     if (tCharSet )
01794       break;
01795 
01796     ++cTypePtr;
01797   }
01798 
01799   if (tCharSet)
01800   {
01801     if (strlen(tCharSet) > 8)
01802     {
01803       retCharSet = PL_strdup( (tCharSet + 8) );
01804       char  *ptr = retCharSet;
01805 
01806       while (*ptr)
01807       {
01808         if ( (*ptr == ' ') || (*ptr == ';') || (*ptr == nsCRT::CR) || (*ptr == nsCRT::LF) ) 
01809         {
01810           *ptr = '\0';
01811           break;
01812         }
01813 
01814         ptr++;
01815       }
01816     }
01817   }
01818 
01819   PR_FREEIF(workString);
01820   return retCharSet;
01821 }
01822 
01823 static int 
01824 WriteLineToStream (MimeObject *obj, const char *line, PRBool aDoCharConversion) 
01825 {                                                                              
01826   int     status = 0;
01827   char    *htmlLine;
01828   int     htmlLen ;
01829   char    *converted = NULL;
01830   PRInt32 converted_length;
01831   PRInt32 res;
01832   char    *charset = nsnull;
01833 
01834   if ( (!line) || (!*line) )
01835     return 0;
01836 
01837   if (aDoCharConversion)
01838   {
01839     // Seek out a charset!
01840     charset = PL_strcasestr(obj->content_type, "charset=");
01841     if (!charset)
01842       charset = FindCharacterSet(obj);
01843 
01844     if ( (!charset) || ( (charset) && (!nsCRT::strcasecmp(charset, "us-ascii"))) )
01845     {
01846       PR_Free(charset);
01847       charset = nsCRT::strdup("ISO-8859-1");
01848     }
01849     // convert from the resource charset.
01850     res = INTL_ConvertCharset(charset, "UTF-8", line, strlen(line),
01851                               &converted, &converted_length);
01852     if ( (res != 0) || (converted == NULL) )
01853       converted = (char *)line;
01854     else
01855       converted[converted_length] = '\0';
01856   }
01857   else
01858     converted = (char *)line;
01859   
01860   htmlLen = strlen(converted) + strlen("<DT></DT>") + 1;
01861   htmlLine = (char *) PR_MALLOC (htmlLen);
01862   if (htmlLine)
01863   {
01864     htmlLine[0] = '\0';
01865     PL_strcat (htmlLine, "<DT>");
01866     PL_strcat (htmlLine, converted);
01867     PL_strcat (htmlLine, "</DT>");
01868     status = COM_MimeObject_write(obj, htmlLine, strlen(htmlLine), PR_TRUE);
01869     PR_Free ((void*) htmlLine);
01870   }
01871   else
01872     status = VCARD_OUT_OF_MEMORY;
01873   
01874   if (converted != line)
01875     PR_FREEIF(converted);
01876 
01877   PR_FREEIF(charset);
01878   return status;
01879 }
01880 
01881 static int WriteAttribute (MimeObject *obj, const char *attrib)
01882 {
01883   int status = 0;
01884   OutputFont(obj, PR_FALSE, "-1", NULL);
01885   status  = WriteLineToStream (obj, attrib, PR_FALSE);
01886   OutputFont(obj, PR_TRUE, NULL, NULL);
01887   return status;
01888 }
01889 
01890 
01891 static int WriteValue (MimeObject *obj, const char *value)
01892 {
01893   int status = 0;
01894   OutputFont(obj, PR_FALSE, "-1", NULL);
01895   status  = WriteLineToStream (obj, value, PR_TRUE);
01896   OutputFont(obj, PR_TRUE, NULL, NULL);
01897   return status;
01898 }
01899 
01900 extern "C" 
01901 char *
01902 VCardGetStringByID(PRInt32 aMsgId)
01903 {
01904   char          *tempString = nsnull;
01905   nsresult res = NS_OK;
01906 
01907 #ifdef XP_MAC
01908 nsCOMPtr<nsIStringBundle>   stringBundle = nsnull;
01909 #endif
01910 
01911   if (!stringBundle)
01912   {
01913     char*       propertyURL = NULL;
01914 
01915     propertyURL = VCARD_URL;
01916 
01917     nsCOMPtr<nsIStringBundleService> sBundleService = 
01918              do_GetService(NS_STRINGBUNDLE_CONTRACTID, &res); 
01919     if (NS_SUCCEEDED(res) && (nsnull != sBundleService)) 
01920     {
01921       res = sBundleService->CreateBundle(propertyURL, getter_AddRefs(stringBundle));
01922     }
01923   }
01924 
01925   if (stringBundle)
01926   {
01927     PRUnichar *ptrv = nsnull;
01928     res = stringBundle->GetStringFromID(aMsgId, &ptrv);
01929 
01930     if (NS_FAILED(res)) 
01931       return nsCRT::strdup("???");
01932     else
01933     {
01934       nsAutoString v;
01935       v.Append(ptrv);
01936       PR_FREEIF(ptrv);
01937       tempString = ToNewUTF8String(v);
01938     }
01939   }
01940 
01941   if (!tempString)
01942     return nsCRT::strdup("???");
01943   else
01944     return tempString;
01945 }
01946 
01947 #else // THUNDERBIRD specific vCard formatting
01948 
01949 static int WriteOutVCard (MimeObject * aMimeObj, VObject* aVcard)
01950 {
01951   int status = 0;
01952   BeginVCard (aMimeObj);
01953 
01954   GenerateVCardData(aMimeObj, aVcard);
01955 
01956   return EndVCard (aMimeObj);
01957 }
01958 
01959 
01960 static int GenerateVCardData(MimeObject * aMimeObj, VObject* aVcard)
01961 {
01962   // style is driven from CSS not here. Just layout the minimal vCard data
01963   nsCString vCardOutput;
01964 
01965   vCardOutput = "<table class=\"moz-vcard-table\"> <tr> ";  // outer table plus the first (and only row) we use for this table
01966 
01967   // we need to get an escaped vCard url to bind to our add to address book button 
01968   nsCOMPtr<nsIMsgVCardService> vCardService = do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
01969   if (!vCardService)
01970       return -1;
01971 
01972   nsCAutoString vCard;
01973   nsCAutoString vEscCard;
01974   int len = 0;
01975 
01976   vCard.Adopt(vCardService->WriteMemoryVObjects(0, &len, aVcard, PR_FALSE));
01977   vEscCard.Adopt(nsEscape (vCard.get(), url_XAlphas));
01978 
01979   // first cell in the outer table row is a clickable image which brings up the rich address book UI for the vcard
01980   vCardOutput += "<td valign=\"top\"> <a class=\"moz-vcard-badge\" href=\"addbook:add?action=add?vcard=";
01981   vCardOutput += vEscCard; // the href is the vCard
01982   vCardOutput += "\"></a></td>";
01983   
01984   // the 2nd cell in the outer table row is a nested table containing the actual vCard properties
01985   vCardOutput += "<td> <table id=\"moz-vcard-properties-table\"> <tr> ";
01986 
01987   OutputBasicVcard(aMimeObj, aVcard, vCardOutput);
01988 
01989   // close the properties table
01990   vCardOutput += "</table> </td> ";
01991 
01992   // 2nd  cell in the outer table is our vCard image
01993 
01994   vCardOutput += "</tr> </table>";
01995 
01996   // now write out the vCard
01997   return COM_MimeObject_write(aMimeObj, (char *) vCardOutput.get(), vCardOutput.Length(), PR_TRUE);
01998 }
01999 
02000 
02001 static int OutputBasicVcard(MimeObject *aMimeObj, VObject *aVcard, nsACString& vCardOutput)
02002 {
02003   int status = 0;
02004 
02005   VObject *prop = NULL;
02006   nsCAutoString urlstring;
02007   nsCAutoString namestring;
02008   nsCAutoString emailstring;
02009 
02010   nsCOMPtr<nsIMsgVCardService> vCardService =  do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
02011   if (!vCardService)
02012       return -1;
02013   
02014   /* get the name and email */
02015   prop = vCardService->IsAPropertyOf(aVcard, VCFullNameProp);
02016   if (prop)
02017   {
02018     if (VALUE_TYPE(prop))
02019     {
02020       if (VALUE_TYPE(prop) != VCVT_RAW)
02021         namestring.Adopt(vCardService->FakeCString(prop));
02022       else
02023         namestring.Adopt(vCardService->VObjectAnyValue(prop));
02024       
02025       if (!namestring.IsEmpty())
02026       {
02027         vCardOutput += "<td class=\"moz-vcard-title-property\"> ";
02028 
02029         prop = vCardService->IsAPropertyOf(aVcard, VCURLProp);
02030         if (prop)
02031         {
02032           urlstring.Adopt(vCardService->FakeCString(prop));
02033           if (urlstring.IsEmpty())
02034             vCardOutput += namestring;
02035           else
02036             vCardOutput += nsPrintfCString(512, "<a href=""%s"" private>%s</a>", urlstring.get(), namestring.get());
02037         }
02038         else 
02039           vCardOutput += namestring;
02040 
02041         /* get the email address */
02042         prop = vCardService->IsAPropertyOf(aVcard, VCEmailAddressProp);
02043         if (prop)
02044         {
02045           emailstring.Adopt(vCardService->FakeCString(prop));
02046           if (!emailstring.IsEmpty())
02047           {
02048             vCardOutput += nsPrintfCString(512, "&nbsp;&lt;<a href=""mailto:%s"" private>%s</a>&gt;", emailstring.get(), emailstring.get());
02049           }
02050         } // if email address property
02051 
02052         vCardOutput += "</td> </tr> "; // end the cell for the name/email address
02053       } // if we have a name property
02054     }
02055   } // if full name property
02056 
02057   // now each basic property goes on its own line
02058 
02059   // title
02060   status = OutputVcardAttribute (aMimeObj, aVcard, VCTitleProp, vCardOutput);
02061 
02062   // org name and company name
02063   prop = vCardService->IsAPropertyOf(aVcard, VCOrgProp);
02064   if (prop)
02065   {
02066     OutputVcardAttribute (aMimeObj, prop, VCOrgUnitProp, vCardOutput);
02067     OutputVcardAttribute (aMimeObj, prop, VCOrgNameProp, vCardOutput);
02068   }
02069 
02070   return 0;
02071 }
02072 
02073 static int OutputVcardAttribute(MimeObject *aMimeObj, VObject *aVcard, const char* id, nsACString& vCardOutput) 
02074 {
02075   int status = 0;
02076   VObject *prop = NULL;
02077   nsCAutoString string;
02078 
02079   nsCOMPtr<nsIMsgVCardService> vCardService = do_GetService(MSGVCARDSERVICE_CONTRACT_ID);
02080   if (!vCardService)
02081       return -1;
02082 
02083   prop = vCardService->IsAPropertyOf(aVcard, id);
02084   if (prop)
02085     if (VALUE_TYPE(prop))
02086     {
02087       if (VALUE_TYPE(prop) != VCVT_RAW)
02088         string.Adopt(vCardService->FakeCString(prop));
02089       else
02090         string.Adopt(vCardService->VObjectAnyValue(prop));
02091       
02092       if (!string.IsEmpty()) 
02093       {
02094         vCardOutput += "<tr> <td class=\"moz-vcard-property\">";
02095         vCardOutput += string;
02096         vCardOutput += "</td> </tr> ";
02097       }
02098     }
02099 
02100   return 0;
02101 }
02102 
02103 #endif
02104