(clazz != (MimeObjectClass *)&mimeMessageClass) &&
static int mime_classinit(MimeObjectClass *clazz);/*  * These are the necessary defines/variables for doing * content type handlers in external plugins. */typedef struct {  char        content_type[128];  PRBool      force_inline_display;} cthandler_struct;nsVoidArray         *ctHandlerList = NULL;PRBool              foundIt = PR_FALSE; PRBool              force_display = PR_FALSE;PRBool EnumFunction(void* aElement, void *aData){  cthandler_struct    *ptr = (cthandler_struct *) aElement;  char                *ctPtr = (char *)aData;  if ( (!aElement) || (!aData) )    return PR_TRUE;  if (nsCRT::strcasecmp(ctPtr, ptr->content_type) == 0)  {    foundIt = PR_TRUE;    force_display = ptr->force_inline_display;    return PR_FALSE;  }  return PR_TRUE;}/* * This will return TRUE if the content_type is found in the * list, FALSE if it is not found.  */PRBoolfind_content_type_attribs(const char *content_type,                           PRBool     *force_inline_display){  *force_inline_display = PR_FALSE;  if (!ctHandlerList)    return PR_FALSE;  foundIt = PR_FALSE;  force_display = PR_FALSE;  ctHandlerList->EnumerateForwards(EnumFunction, (void *)content_type);  if (foundIt)    *force_inline_display = force_display;  return (foundIt);}voidadd_content_type_attribs(const char *content_type,                          contentTypeHandlerInitStruct  *ctHandlerInfo){  cthandler_struct    *ptr = NULL;  PRBool              force_inline_display;  if (find_content_type_attribs(content_type, &force_inline_display))    return;  if ( (!content_type) || (!ctHandlerInfo) )    return;  if (!ctHandlerList)    ctHandlerList = new nsVoidArray();  if (!ctHandlerList)    return;  ptr = (cthandler_struct *) PR_MALLOC(sizeof(cthandler_struct));  if (!ptr)    return;  PL_strncpy(ptr->content_type, content_type, sizeof(ptr->content_type));  ptr->force_inline_display = ctHandlerInfo->force_inline_display;  ctHandlerList->AppendElement(ptr);}/*  * This routine will find all content type handler for a specifc content * type (if it exists) */PRBoolforce_inline_display(const char *content_type){  PRBool     force_inline_disp;  find_content_type_attribs(content_type, &force_inline_disp);  return (force_inline_disp);}/*  * This routine will find all content type handler for a specifc content * type (if it exists) and is defined to the nsRegistry */MimeObjectClass *mime_locate_external_content_handler(const char *content_type,                                        contentTypeHandlerInitStruct  *ctHandlerInfo){  MimeObjectClass               *newObj = NULL;  nsCID                         classID = {0};  char                          lookupID[256];  nsCOMPtr<nsIMimeContentTypeHandler>     ctHandler;  nsresult rv = NS_OK;  PR_snprintf(lookupID, sizeof(lookupID), "mimecth:%s", content_type);	if (nsComponentManager::ProgIDToClassID(lookupID, &classID) != NS_OK)    return NULL;    rv  = nsComponentManager::CreateInstance(classID, (nsISupports *)nsnull, kIMimeContentTypeHandlerIID,                                      (void **) getter_AddRefs(ctHandler));  if (NS_FAILED(rv) || !ctHandler)    return nsnull;    rv = ctHandler->CreateContentTypeHandlerClass(content_type, ctHandlerInfo, &newObj);  if (NS_FAILED(rv))    return nsnull;  add_content_type_attribs(content_type, ctHandlerInfo);  return newObj;}/* This is necessary to expose the MimeObject method outside of this DLL */intMIME_MimeObject_write(MimeObject *obj, char *output, PRInt32 length, PRBool user_visible_p){  return MimeObject_write(obj, output, length, user_visible_p);}MimeObject *mime_new (MimeObjectClass *clazz, MimeHeaders *hdrs,		  const char *override_content_type){  int size = clazz->instance_size;  MimeObject *object;  int status;  /* Some assertions to verify that this isn't random junk memory... */  PR_ASSERT(clazz->class_name && nsCRT::strlen(clazz->class_name) > 0);  PR_ASSERT(size > 0 && size < 1000);  if (!clazz->class_initialized)	{	  status = mime_classinit(clazz);	  if (status < 0) return 0;	}  PR_ASSERT(clazz->initialize && clazz->finalize);  if (hdrs)	{    hdrs = MimeHeaders_copy (hdrs);	  if (!hdrs) return 0;	}  object = (MimeObject *) PR_MALLOC(size);  if (!object) return 0;  memset(object, 0, size);  object->clazz = clazz;  object->headers = hdrs;  object->showAttachmentIcon = PR_FALSE; /* initialize ricardob's new member. */  if (override_content_type && *override_content_type)	object->content_type = nsCRT::strdup(override_content_type);  status = clazz->initialize(object);  if (status < 0)	{	  clazz->finalize(object);	  PR_Free(object);	  return 0;	}  return object;}voidmime_free (MimeObject *object){# ifdef DEBUG__  int i, size = object->clazz->instance_size;  PRUint32 *array = (PRUint32*) object;# endif /* DEBUG */  object->clazz->finalize(object);# ifdef DEBUG__  for (i = 0; i < (size / sizeof(*array)); i++)	array[i] = (PRUint32) 0xDEADBEEF;# endif /* DEBUG */  PR_Free(object);}MimeObjectClass *mime_find_class (const char *content_type, MimeHeaders *hdrs,				 MimeDisplayOptions *opts, PRBool exact_match_p){  MimeObjectClass *clazz = 0;  MimeObjectClass *tempClass = 0;  contentTypeHandlerInitStruct  ctHandlerInfo;  /*   * What we do first is check for an external content handler plugin.   * This will actually extend the mime handling by calling a routine   * which will allow us to load an external content type handler  * for specific content types. If one is not found, we will drop back  * to the default handler.  */  if ((tempClass = mime_locate_external_content_handler(content_type, &ctHandlerInfo)) != NULL)  {    clazz = (MimeObjectClass *)tempClass;  }  else  {    if (!content_type || !*content_type ||      !nsCRT::strcasecmp(content_type, "text"))  /* with no / in the type */      clazz = (MimeObjectClass *)&mimeUntypedTextClass;          /* Subtypes of text...    */    else if (!nsCRT::strncasecmp(content_type,			"text/", 5))    {      if      (!nsCRT::strcasecmp(content_type+5,		"html"))        clazz = (MimeObjectClass *)&mimeInlineTextHTMLClass;      else if (!nsCRT::strcasecmp(content_type+5,		"enriched"))        clazz = (MimeObjectClass *)&mimeInlineTextEnrichedClass;      else if (!nsCRT::strcasecmp(content_type+5,		"richtext"))        clazz = (MimeObjectClass *)&mimeInlineTextRichtextClass;      else if (!nsCRT::strcasecmp(content_type+5,		"plain"))      {        // Check for format=flowed, damn, it is already stripped away from        // the contenttype!        // Look in headers instead even though it's expensive and clumsy        // First find Content-Type:        char *content_type_row = (hdrs                                  ? MimeHeaders_get(hdrs, HEADER_CONTENT_TYPE,                                                    PR_FALSE, PR_FALSE)                                  : 0);        // Then the format parameter if there is one.        // I would rather use a PARAM_FORMAT but I can't find the right        // place to put the define. The others seems to be in net.h        // but is that really really the right place? There is also        // a nsMimeTypes.h but that one isn't included. Bug?        char *content_type_format =          (content_type_row           ? MimeHeaders_get_parameter(content_type_row, "format", NULL, NULL)           : 0);        if(content_type_format && (!nsCRT::strcasecmp(content_type_format, "flowed")))          clazz = (MimeObjectClass *)&mimeInlineTextPlainFlowedClass;        else          clazz = (MimeObjectClass *)&mimeInlineTextPlainClass;               PR_FREEIF(content_type_format);        PR_FREEIF(content_type_row);             }      else if (!exact_match_p)        clazz = (MimeObjectClass *)&mimeInlineTextPlainClass;    }        /* Subtypes of multipart...    */    else if (!nsCRT::strncasecmp(content_type,			"multipart/", 10))    {      if      (!nsCRT::strcasecmp(content_type+10,	"alternative"))        clazz = (MimeObjectClass *)&mimeMultipartAlternativeClass;      else if (!nsCRT::strcasecmp(content_type+10,	"related"))        clazz = (MimeObjectClass *)&mimeMultipartRelatedClass;      else if (!nsCRT::strcasecmp(content_type+10,	"digest"))        clazz = (MimeObjectClass *)&mimeMultipartDigestClass;      else if (!nsCRT::strcasecmp(content_type+10,	"appledouble") ||        !nsCRT::strcasecmp(content_type+10,	"header-set"))        clazz = (MimeObjectClass *)&mimeMultipartAppleDoubleClass;      else if (!nsCRT::strcasecmp(content_type+10,	"parallel"))        clazz = (MimeObjectClass *)&mimeMultipartParallelClass;      else if (!nsCRT::strcasecmp(content_type+10,	"mixed"))        clazz = (MimeObjectClass *)&mimeMultipartMixedClass;            else if (!nsCRT::strcasecmp(content_type+10,	"signed"))      {      /* Check that the "protocol" and "micalg" parameters are ones we        know about. */        char *ct = (hdrs          ? MimeHeaders_get(hdrs, HEADER_CONTENT_TYPE,										PR_FALSE, PR_FALSE)                    : 0);        char *proto = (ct          ? MimeHeaders_get_parameter(ct, PARAM_PROTOCOL, NULL, NULL)          : 0);        char *micalg = (ct          ? MimeHeaders_get_parameter(ct, PARAM_MICALG, NULL, NULL)          : 0);        #ifdef MOZ_SECURITY        HG01444#endif                    PR_FREEIF(proto);        PR_FREEIF(micalg);        PR_FREEIF(ct);      }            if (!clazz && !exact_match_p)        /* Treat all unknown multipart subtypes as "multipart/mixed" */        clazz = (MimeObjectClass *)&mimeMultipartMixedClass;    }        /* Subtypes of message...    */    else if (!nsCRT::strncasecmp(content_type,			"message/", 8))    {      if      (!nsCRT::strcasecmp(content_type+8,		"rfc822") ||        !nsCRT::strcasecmp(content_type+8,		"news"))        clazz = (MimeObjectClass *)&mimeMessageClass;      else if (!nsCRT::strcasecmp(content_type+8,		"external-body"))        clazz = (MimeObjectClass *)&mimeExternalBodyClass;      else if (!nsCRT::strcasecmp(content_type+8,		"partial"))        /* I guess these are most useful as externals, for now... */        clazz = (MimeObjectClass *)&mimeExternalObjectClass;      else if (!exact_match_p)        /* Treat all unknown message subtypes as "text/plain" */        clazz = (MimeObjectClass *)&mimeInlineTextPlainClass;    }        /* The magic image types which we are able to display internally...    */    else if (!nsCRT::strcasecmp(content_type,			IMAGE_GIF)  ||      !nsCRT::strcasecmp(content_type,			IMAGE_JPG) ||      !nsCRT::strcasecmp(content_type,			IMAGE_PJPG) ||      !nsCRT::strcasecmp(content_type,			IMAGE_PNG) ||      !nsCRT::strcasecmp(content_type,			IMAGE_XBM)  ||      !nsCRT::strcasecmp(content_type,			IMAGE_XBM2) ||      !nsCRT::strcasecmp(content_type,			IMAGE_XBM3))      clazz = (MimeObjectClass *)&mimeInlineImageClass;    #ifdef MOZ_SECURITY    HG01555#endif          /* A few types which occur in the real world and which we would otherwise    treat as non-text types (which would be bad) without this special-case...    */    else if (!nsCRT::strcasecmp(content_type,			APPLICATION_PGP) ||    !nsCRT::strcasecmp(content_type,			APPLICATION_PGP2))    clazz = (MimeObjectClass *)&mimeInlineTextPlainClass;        else if (!nsCRT::strcasecmp(content_type,			SUN_ATTACHMENT))      clazz = (MimeObjectClass *)&mimeSunAttachmentClass;          /* Everything else gets represented as a clickable link.    */    else if (!exact_match_p)      clazz = (MimeObjectClass *)&mimeExternalObjectClass;    } if (!exact_match_p)   PR_ASSERT(clazz);  if (!clazz) return 0;  /* If the `Show Attachments as Links' kludge is on, now would be the time	 to change our mind... */  if (opts && opts->no_inline_p)	{	  if (mime_subclass_p(clazz, (MimeObjectClass *)&mimeInlineTextClass))		{		  /* It's a text type.  Write it only if it's the *first* part			 that we're writing, and then only if it has no "filename"			 specified (the assumption here being, if it has a filename,			 it wasn't simply typed into the text field -- it was actually			 an attached document.) */		  if (opts->state && opts->state->first_part_written_p)			clazz = (MimeObjectClass *)&mimeExternalObjectClass;		  else			{			  /* If there's a name, then write this as an attachment. */			  char *name = (hdrs ? MimeHeaders_get_name(hdrs) : 0);			  if (name)				clazz = (MimeObjectClass *)&mimeExternalObjectClass;			  PR_FREEIF(name);			}		  if (opts->state)			opts->state->first_part_written_p = PR_TRUE;		}	  else if (mime_subclass_p(clazz,(MimeObjectClass *)&mimeContainerClass) &&			   !mime_subclass_p(clazz,(MimeObjectClass *)&mimeMessageClass))		/* Multipart subtypes are ok, except for messages; descend into		   multiparts, and defer judgement.		   Xlateed blobs are just like other containers (make the xlation		   layer invisible, and treat them as simple containers.  So there's		   no easy way to save xlated data directly to disk; it will tend		   to always be wrapped inside a message/rfc822.  That's ok.)		 */		;	  else if (opts &&			   opts->part_to_load &&			   mime_subclass_p(clazz,(MimeObjectClass *)&mimeMessageClass))		/* Descend into messages only if we're looking for a specific sub-part.		 */		;	  else		{		  /* Anything else, and display it as a link (and cause subsequent			 text parts to also be displayed as links.) */		  clazz = (MimeObjectClass *)&mimeExternalObjectClass;		  if (opts->state)			opts->state->first_part_written_p = PR_TRUE;		}	}  PR_ASSERT(clazz);  if (clazz && !clazz->class_initialized)	{	  int status = mime_classinit(clazz);	  if (status < 0) return 0;	}  return clazz;}MimeObject *mime_create (const char *content_type, MimeHeaders *hdrs,			 MimeDisplayOptions *opts){  /* If there is no Content-Disposition header, or if the Content-Disposition	 is ``inline'', then we display the part inline (and let mime_find_class()	 decide how.)	 If there is any other Content-Disposition (either ``attachment'' or some	 disposition that we don't recognise) then we always display the part as	 an external link, by using MimeExternalObject to display it.	 But Content-Disposition is ignored for all containers except `message'.	 (including multipart/mixed, and multipart/digest.)  It's not clear if	 this is to spec, but from a usability standpoint, I think it's necessary.   */  MimeObjectClass *clazz = 0;  char *content_disposition = 0;  MimeObject *obj = 0;  char *override_content_type = 0;  static PRBool reverse_lookup = PR_FALSE, got_lookup_pref = PR_FALSE;  if (!got_lookup_pref)  {     nsIPref *pref = GetPrefServiceManager(opts);   // Pref service manager      if (pref)     {       pref->GetBoolPref("mailnews.autolookup_unknown_mime_types",&reverse_lookup);       got_lookup_pref = PR_TRUE;     }  }  /* There are some clients send out all attachments with a content-type	 of application/octet-stream.  So, if we have an octet-stream attachment,	 try to guess what type it really is based on the file extension.  I HATE	 that we have to do this...     If the preference "mailnews.autolookup_unknown_mime_types" is set to PR_TRUE,     then we try to do this EVERY TIME when we do not have an entry for the given	 MIME type in our table, not only when it's application/octet-stream. */  if (hdrs && opts && opts->file_type_fn &&	  /* ### mwelch - don't override AppleSingle */	  (content_type ? nsCRT::strcasecmp(content_type, APPLICATION_APPLEFILE) : PR_TRUE) &&	  /* ## davidm Apple double shouldn't use this #$%& either. */	  (content_type ? nsCRT::strcasecmp(content_type, MULTIPART_APPLEDOUBLE) : PR_TRUE) &&	  (!content_type ||	   !nsCRT::strcasecmp(content_type, APPLICATION_OCTET_STREAM) ||	   !nsCRT::strcasecmp(content_type, UNKNOWN_CONTENT_TYPE) ||	   (reverse_lookup#if 0	    && !NET_cinfo_find_info_by_type((char*)content_type))))#else        )))#endif	{	  char *name = MimeHeaders_get_name(hdrs);	  if (name)		{		  override_content_type = opts->file_type_fn (name,													  opts->stream_closure);		  PR_FREEIF(name);		  if (override_content_type &&			  !nsCRT::strcasecmp(override_content_type, UNKNOWN_CONTENT_TYPE))			PR_FREEIF(override_content_type);		  if (override_content_type)			content_type = override_content_type;		}	}  clazz = mime_find_class(content_type, hdrs, opts, PR_FALSE);  PR_ASSERT(clazz);  if (!clazz) goto FAIL;  if (opts && opts->part_to_load)	/* Always ignore Content-Disposition when we're loading some specific	   sub-part (which may be within some container that we wouldn't otherwise	   descend into, if the container itself had a Content-Disposition of	   `attachment'. */	content_disposition = 0;  else if (mime_subclass_p(clazz,(MimeObjectClass *)&mimeContainerClass) &&		   !mime_subclass_p(clazz,(MimeObjectClass *)&mimeMessageClass))	/* Ignore Content-Disposition on all containers except `message'.	   That is, Content-Disposition is ignored for multipart/mixed objects,	   but is obeyed for message/rfc822 objects. */	content_disposition = 0;  else  {    /* Check to see if the plugin should override the content disposition       to make it appear inline. One example is a vcard which has a content       disposition of an "attachment;" */    if (force_inline_display(content_type))  		mime_SACopy(&content_disposition, "inline");    else  		content_disposition = (hdrs							   ? MimeHeaders_get(hdrs, HEADER_CONTENT_DISPOSITION, PR_TRUE, PR_FALSE)							   : 0);  }  if (!content_disposition || !nsCRT::strcasecmp(content_disposition, "inline"))    ;	/* Use the class we've got. */  else  {     //     // rhp: Ok, this is a modification to try to deal with messages    //      that have content disposition set to "attachment" even though    //      we probably should show them inline.     //    if (  (clazz != (MimeObjectClass *)&mimeInlineTextHTMLClass) &&          (clazz != (MimeObjectClass *)&mimeInlineTextClass) &&          (clazz != (MimeObjectClass *)&mimeInlineTextPlainClass) &&          (clazz != (MimeObjectClass *)&mimeInlineTextPlainFlowedClass) &&          (clazz != (MimeObjectClass *)&mimeInlineTextHTMLClass) &&          (clazz != (MimeObjectClass *)&mimeInlineTextRichtextClass) &&          (clazz != (MimeObjectClass *)&mimeInlineTextEnrichedClass) &&          (clazz != (MimeObjectClass *)&mimeInlineImageClass) )      clazz = (MimeObjectClass *)&mimeExternalObjectClass;  }  PR_FREEIF(content_disposition);  obj = mime_new (clazz, hdrs, content_type); FAIL:  /* If we decided to ignore the content-type in the headers of this object	 (see above) then make sure that our new content-type is stored in the	 object itself.  (Or free it, if we're in an out-of-memory situation.)   */  if (override_content_type)	{	  if (obj)		{		  PR_FREEIF(obj->content_type);		  obj->content_type = override_content_type;		}	  else		{		  PR_Free(override_content_type);		}	}  return obj;}static int mime_classinit_1(MimeObjectClass *clazz, MimeObjectClass *target);static intmime_classinit(MimeObjectClass *clazz){  int status;  if (clazz->class_initialized)	return 0;  PR_ASSERT(clazz->class_initialize);  if (!clazz->class_initialize)	return -1;  /* First initialize the superclass.   */  if (clazz->superclass && !clazz->superclass->class_initialized)	{	  status = mime_classinit(clazz->superclass);	  if (status < 0) return status;	}  /* Now run each of the superclass-init procedures in turn,	 parentmost-first. */  status = mime_classinit_1(clazz, clazz);  if (status < 0) return status;  /* Now we're done. */  clazz->class_initialized = PR_TRUE;  return 0;}