if (mime_typep(obj, (MimeObjectClass *) &mimeMessageClass))
if (isAnInlineMessage)
MimeObject    *mime_get_main_object(MimeObject* obj);nsresultProcessBodyAsAttachment(MimeObject *obj, nsMsgAttachmentData **data){  nsMsgAttachmentData   *tmp;  PRInt32               n;  char                  *disp = nsnull;  char                  *charset = nsnull;  // Ok, this is the special case when somebody sends an "attachment" as the body  // of an RFC822 message...I really don't think this is the way this should be done.  // I belive this should really be a multipart/mixed message with an empty body part,  // but what can ya do...our friends to the North seem to do this.  //  MimeObject    *child = obj;  n = 1;  *data = (nsMsgAttachmentData *)PR_Malloc( (n + 1) * sizeof(nsMsgAttachmentData));  if (!*data)     return NS_ERROR_OUT_OF_MEMORY;  tmp = *data;  memset(*data, 0, (n + 1) * sizeof(nsMsgAttachmentData));  tmp->real_type = child->content_type ? nsCRT::strdup(child->content_type) : NULL;  tmp->real_encoding = child->encoding ? nsCRT::strdup(child->encoding) : NULL;  disp = MimeHeaders_get(child->headers, HEADER_CONTENT_DISPOSITION, PR_FALSE, PR_FALSE);  tmp->real_name = MimeHeaders_get_parameter(disp, "name", &charset, NULL);  if (tmp->real_name)  {    char *fname = NULL;    fname = mime_decode_filename(tmp->real_name, charset, obj->options);    PR_FREEIF(charset);    if (fname && fname != tmp->real_name)    {      PR_Free(tmp->real_name);      tmp->real_name = fname;    }  }  else  {    tmp->real_name = MimeHeaders_get_name(child->headers, obj->options);  }  if ( (!tmp->real_name) && (tmp->real_type) && (nsCRT::strncasecmp(tmp->real_type, "text", 4)) )    ValidateRealName(tmp, child->headers);  char  *tmpURL = nsnull;  char  *id = nsnull;  char  *id_imap = nsnull;  id = mime_part_address (obj);  if (obj->options->missing_parts)    id_imap = mime_imap_part_address (obj);  if (! id)  {    PR_FREEIF(*data);    PR_FREEIF(id_imap);    return NS_ERROR_OUT_OF_MEMORY;  }  if (obj->options && obj->options->url)  {    const char  *url = obj->options->url;    nsresult    rv;    if (id_imap && id)    {      // if this is an IMAP part.       tmpURL = mime_set_url_imap_part(url, id_imap, id);      rv = nsMimeNewURI(&(tmp->url), tmpURL, nsnull);      tmp->notDownloaded = PR_TRUE;    }    else    {      // This is just a normal MIME part as usual.       tmpURL = mime_set_url_part(url, id, PR_TRUE);      rv = nsMimeNewURI(&(tmp->url), tmpURL, nsnull);    }    if ( (!tmp->url) || (NS_FAILED(rv)) )    {      PR_FREEIF(*data);      PR_FREEIF(id);      PR_FREEIF(id_imap);      return NS_ERROR_OUT_OF_MEMORY;    }  }  PR_FREEIF(id);  PR_FREEIF(id_imap);  PR_FREEIF(tmpURL);  tmp->description = MimeHeaders_get(child->headers, HEADER_CONTENT_DESCRIPTION, PR_FALSE, PR_FALSE);  return NS_OK;}PRInt32CountTotalMimeAttachments(MimeContainer *aObj){  PRInt32     i;  PRInt32     rc = 0;  if ( (!aObj) || (!aObj->children) || (aObj->nchildren <= 0) )    return 0;  if (mime_typep((MimeObject *)aObj, (MimeObjectClass *)&mimeExternalBodyClass))    return 0;  for (i=0; i<aObj->nchildren; i++)    rc += CountTotalMimeAttachments((MimeContainer *)aObj->children[i]) + 1;  return rc;}voidValidateRealName(nsMsgAttachmentData *aAttach, MimeHeaders *aHdrs){   // Sanity.  if (!aAttach)    return;  // Do we need to validate?  if ( (aAttach->real_name) && (*(aAttach->real_name)) )    return;  // Internal MIME structures need not be named!  if ( (!aAttach->real_type) || (aAttach->real_type &&                                  !nsCRT::strncasecmp(aAttach->real_type, "multipart", 9)) )    return;  // Special case...if this is a enclosed RFC822 message, give it a nice  // name.  if (aAttach->real_type && !nsCRT::strcasecmp(aAttach->real_type, MESSAGE_RFC822))  {    if (aHdrs->munged_subject)    {      aAttach->real_name = PR_smprintf("%s.eml", aHdrs->munged_subject);    }    else      NS_MsgSACopy(&(aAttach->real_name), "ForwardedMessage.eml");    return;  }  //   // Now validate any other name we have for the attachment!  //  if (!aAttach->real_name || *aAttach->real_name == 0)  {    nsString  newAttachName(NS_LITERAL_STRING("attachment"));    nsresult  rv = NS_OK;    nsCAutoString contentType (aAttach->real_type);    PRInt32 pos = contentType.FindCharInSet(";");    if (pos > 0)      contentType.Truncate(pos);    nsCOMPtr<nsIMIMEService> mimeFinder (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));    if (NS_SUCCEEDED(rv) && mimeFinder)     {      nsIMIMEInfo *mimeInfo = nsnull;      rv = mimeFinder->GetFromMIMEType(contentType.get(), &mimeInfo);      if (NS_SUCCEEDED(rv) && mimeInfo)       {        char *aFileExtension = nsnull;        if ( (NS_SUCCEEDED(mimeInfo->GetPrimaryExtension(&aFileExtension))) && aFileExtension)        {          newAttachName.Append(NS_LITERAL_STRING("."));          newAttachName.AppendWithConversion(aFileExtension);          PR_FREEIF(aFileExtension);        }      }            }    aAttach->real_name = ToNewCString(newAttachName);  }  }static  PRInt32     attIndex = 0;nsresultGenerateAttachmentData(MimeObject *object, const char *aMessageURL, MimeDisplayOptions *options,                       PRBool isAnAppleDoublePart, nsMsgAttachmentData *aAttachData){  nsXPIDLCString imappart;  nsXPIDLCString part;  PRBool isIMAPPart;  part.Adopt(mime_part_address(object));  if (part.IsEmpty())     return NS_ERROR_OUT_OF_MEMORY;  if (options->missing_parts)    imappart.Adopt(mime_imap_part_address(object));  char *urlSpec = nsnull;  if (!imappart.IsEmpty())  {    isIMAPPart = PR_TRUE;    urlSpec = mime_set_url_imap_part(aMessageURL, imappart.get(), part.get());  }  else  {    isIMAPPart = PR_FALSE;    urlSpec = mime_set_url_part(aMessageURL, part.get(), PR_TRUE);  }  if (!urlSpec)    return NS_ERROR_OUT_OF_MEMORY;  nsMsgAttachmentData *tmp = &(aAttachData[attIndex++]);  nsresult rv = nsMimeNewURI(&(tmp->url), urlSpec, nsnull);	PR_FREEIF(urlSpec);  if ( (NS_FAILED(rv)) || (!tmp->url) )    return NS_ERROR_OUT_OF_MEMORY;  tmp->real_type = object->content_type ? nsCRT::strdup(object->content_type) : nsnull;  tmp->real_encoding = object->encoding ? nsCRT::strdup(object->encoding) : nsnull;    PRInt32 i;  char *charset = nsnull;  char *disp = MimeHeaders_get(object->headers, HEADER_CONTENT_DISPOSITION, PR_FALSE, PR_FALSE);  if (disp)   {    tmp->real_name = MimeHeaders_get_parameter(disp, "filename", &charset, nsnull);    if (isAnAppleDoublePart)      for (i = 0; i < 2 && !tmp->real_name; i ++)      {        PR_FREEIF(disp);        PR_FREEIF(charset);        disp = MimeHeaders_get(((MimeContainer *)object)->children[i]->headers, HEADER_CONTENT_DISPOSITION, PR_FALSE, PR_FALSE);        tmp->real_name = MimeHeaders_get_parameter(disp, "filename", &charset, nsnull);      }    if (tmp->real_name)    {      // check encoded type      //      // The parameter of Content-Disposition must use RFC 2231.      // But old Netscape 4.x and Outlook Express etc. use RFC2047.      // So we should parse both types.      char *fname = nsnull;      fname = mime_decode_filename(tmp->real_name, charset, options);      PR_FREEIF(charset);      if (fname && fname != tmp->real_name)      {        PR_FREEIF(tmp->real_name);        tmp->real_name = fname;      }    }    PR_FREEIF(disp);  }  disp = MimeHeaders_get(object->headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE);  if (disp)  {    tmp->x_mac_type   = MimeHeaders_get_parameter(disp, PARAM_X_MAC_TYPE, nsnull, nsnull);    tmp->x_mac_creator= MimeHeaders_get_parameter(disp, PARAM_X_MAC_CREATOR, nsnull, nsnull);        if (!tmp->real_name || *tmp->real_name == 0)    {      PR_FREEIF(tmp->real_name);      tmp->real_name = MimeHeaders_get_parameter(disp, "name", &charset, nsnull);      if (isAnAppleDoublePart)        for (i = 0; i < 2 && !tmp->real_name; i ++)        {          PR_FREEIF(disp);          PR_FREEIF(charset);          disp = MimeHeaders_get(((MimeContainer *)object)->children[i]->headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE);          tmp->real_name = MimeHeaders_get_parameter(disp, "name", &charset, nsnull);        }            if (tmp->real_name)      {        // check encoded type        //        // The parameter of Content-Disposition must use RFC 2231.        // But old Netscape 4.x and Outlook Express etc. use RFC2047.        // So we should parse both types.        char *fname = nsnull;        fname = mime_decode_filename(tmp->real_name, charset, options);        PR_FREEIF(charset);        if (fname && fname != tmp->real_name)        {          PR_Free(tmp->real_name);          tmp->real_name = fname;        }      }    }    PR_FREEIF(disp);  }  tmp->description = MimeHeaders_get(object->headers, HEADER_CONTENT_DESCRIPTION,                                      PR_FALSE, PR_FALSE);  // Now, do the right thing with the name!  if (!tmp->real_name && nsCRT::strcasecmp(tmp->real_type, MESSAGE_RFC822))  {    /* If this attachment doesn't have a name, just give it one... */    tmp->real_name = MimeGetStringByID(MIME_MSG_DEFAULT_ATTACHMENT_NAME);    if (tmp->real_name)    {      char *newName = PR_smprintf(tmp->real_name, part.get());      if (newName)      {        PR_Free(tmp->real_name);        tmp->real_name = newName;      }    }    else      tmp->real_name = mime_part_address(object);  }  ValidateRealName(tmp, object->headers);  if (isIMAPPart)  {    // If we get here, we should mark this attachment as not being    // downloaded.     tmp->notDownloaded = PR_TRUE;  }  return NS_OK;}nsresultBuildAttachmentList(MimeObject *anObject, nsMsgAttachmentData *aAttachData, const char *aMessageURL){  nsresult              rv;  PRInt32               i;  MimeContainer         *cobj = (MimeContainer *) anObject;  if ( (!anObject) || (!cobj->children) || (!cobj->nchildren) ||       (mime_typep(anObject, (MimeObjectClass *)&mimeExternalBodyClass)))    return NS_OK;  for (i = 0; i < cobj->nchildren ; i++)   {    MimeObject    *child = cobj->children[i];    // Skip the first child if it's in fact a message body    if (i == 0)                                         // it's the first child      if (child->content_type)                          // and it's content-type is one of folowing...        if (!nsCRT::strcasecmp (child->content_type, TEXT_PLAIN) ||            !nsCRT::strcasecmp (child->content_type, TEXT_HTML) ||            !nsCRT::strcasecmp (child->content_type, TEXT_MDL) ||            !nsCRT::strcasecmp (child->content_type, MULTIPART_ALTERNATIVE) ||            !nsCRT::strcasecmp (child->content_type, MULTIPART_RELATED))        {          if (child->headers) // and finally, be sure it doesn't have a content-disposition: attachment           {            char * disp = MimeHeaders_get (child->headers, HEADER_CONTENT_DISPOSITION, PR_TRUE, PR_FALSE);            if (!disp || nsCRT::strcasecmp (disp, "attachment"))              continue;          }          else            continue;        }        // We should generate an attachment for leaf object only but...    PRBool isALeafObject = mime_subclass_p(child->clazz, (MimeObjectClass *) &mimeLeafClass);    // ...we will generate an attachment for inline message too.    PRBool isAnInlineMessage = mime_typep(child, (MimeObjectClass *) &mimeMessageClass);        // AppleDouble part need special care: we need to fetch the part as well its two    // children for the needed info as they could be anywhere, eventually, they won't contain    // a name or file name. In any case we need to build only one attachment data    PRBool isAnAppleDoublePart = mime_typep(child, (MimeObjectClass *) &mimeMultipartAppleDoubleClass) &&                                 ((MimeContainer *)child)->nchildren == 2;    if (isALeafObject || isAnInlineMessage || isAnAppleDoublePart)    {      rv = GenerateAttachmentData(child, aMessageURL, anObject->options, isAnAppleDoublePart, aAttachData);      NS_ENSURE_SUCCESS(rv, rv);    }        // Now build the attachment list for the children of our object...    if (!isALeafObject && !isAnAppleDoublePart)    {      rv = BuildAttachmentList((MimeObject *)child, aAttachData, aMessageURL);      NS_ENSURE_SUCCESS(rv, rv);    }  }  return NS_OK;}extern "C" nsresultMimeGetAttachmentList(MimeObject *tobj, const char *aMessageURL, nsMsgAttachmentData **data){  MimeObject            *obj;  MimeContainer         *cobj;  PRInt32               n;  PRBool                isAlternativeOrRelated = PR_FALSE;  if (!data)     return 0;  *data = NULL;  obj = mime_get_main_object(tobj);  if ( (obj) && (!mime_subclass_p(obj->clazz, (MimeObjectClass*) &mimeContainerClass)) )  {    if (!PL_strcasecmp(obj->content_type, MESSAGE_RFC822))      return 0;    else      return ProcessBodyAsAttachment(obj, data);  }  (void) MimeObjectChildIsMessageBody(obj, &isAlternativeOrRelated);  if (isAlternativeOrRelated)    return 0;    cobj = (MimeContainer*) obj;  n = CountTotalMimeAttachments(cobj);  if (n <= 0)     return n;  *data = (nsMsgAttachmentData *)PR_Malloc( (n + 1) * sizeof(nsMsgAttachmentData));  if (!*data)     return NS_ERROR_OUT_OF_MEMORY;  attIndex = 0;  memset(*data, 0, (n + 1) * sizeof(nsMsgAttachmentData));    // Now, build the list!  nsresult rv;  if (mime_typep(obj, (MimeObjectClass *) &mimeMessageClass))  {    rv = GenerateAttachmentData(obj, aMessageURL, obj->options, PR_FALSE, *data);    NS_ENSURE_SUCCESS(rv, rv);  }  return BuildAttachmentList((MimeObject *) cobj, *data, aMessageURL);}extern "C" voidMimeFreeAttachmentList(nsMsgAttachmentData *data){  if (data)   {    nsMsgAttachmentData   *tmp;    for (tmp = data ; tmp->url ; tmp++)     {      /* Can't do PR_FREEIF on `const' values... */      NS_IF_RELEASE(tmp->url);      if (tmp->real_type) PR_Free((char *) tmp->real_type);      if (tmp->real_encoding) PR_Free((char *) tmp->real_encoding);      if (tmp->real_name) PR_Free((char *) tmp->real_name);      if (tmp->x_mac_type) PR_Free((char *) tmp->x_mac_type);      if (tmp->x_mac_creator) PR_Free((char *) tmp->x_mac_creator);      if (tmp->description) PR_Free((char *) tmp->description);      tmp->url = 0;      tmp->real_type = 0;      tmp->real_name = 0;      tmp->description = 0;    }    PR_Free(data);  }}extern "C" voidNotifyEmittersOfAttachmentList(MimeDisplayOptions     *opt,                               nsMsgAttachmentData    *data){  PRInt32     i = 0;  struct      nsMsgAttachmentData  *tmp = data;  if (!tmp)     return;  while (tmp->url)  {    char  *spec;    if (!tmp->real_name)    {      ++i;      ++tmp;            continue;    }    spec = nsnull;    if ( tmp->url )       tmp->url->GetSpec(&spec);    mimeEmitterStartAttachment(opt, tmp->real_name, tmp->real_type, spec, tmp->notDownloaded);    mimeEmitterAddAttachmentField(opt, HEADER_X_MOZILLA_PART_URL, spec);	  if (spec)		  nsMemory::Free(spec);    if ( (opt->format_out == nsMimeOutput::nsMimeMessageQuoting) ||          (opt->format_out == nsMimeOutput::nsMimeMessageBodyQuoting) ||          (opt->format_out == nsMimeOutput::nsMimeMessageSaveAs) ||          (opt->format_out == nsMimeOutput::nsMimeMessagePrintOutput) )    {      mimeEmitterAddAttachmentField(opt, HEADER_CONTENT_DESCRIPTION, tmp->description);      mimeEmitterAddAttachmentField(opt, HEADER_CONTENT_TYPE, tmp->real_type);      mimeEmitterAddAttachmentField(opt, HEADER_CONTENT_ENCODING,    tmp->real_encoding);      /* rhp - for now, just leave these here, but they are really               not necessary      printf("URL for Part      : %s\n", spec);      printf("Real Name         : %s\n", tmp->real_name);	    printf("Desired Type      : %s\n", tmp->desired_type);      printf("Real Type         : %s\n", tmp->real_type);	    printf("Real Encoding     : %s\n", tmp->real_encoding);       printf("Description       : %s\n", tmp->description);      printf("Mac Type          : %s\n", tmp->x_mac_type);      printf("Mac Creator       : %s\n", tmp->x_mac_creator);      */    }    mimeEmitterEndAttachment(opt);    ++i;    ++tmp;  }  mimeEmitterEndAllAttachments(opt);}// Utility to create a nsIURI object...extern "C" nsresult nsMimeNewURI(nsIURI** aInstancePtrResult, const char *aSpec, nsIURI *aBase){    nsresult  res;  if (nsnull == aInstancePtrResult)     return NS_ERROR_NULL_POINTER;    nsCOMPtr<nsIIOService> pService(do_GetService(kIOServiceCID, &res));  if (NS_FAILED(res))     return NS_ERROR_FACTORY_NOT_REGISTERED;  return pService->NewURI(aSpec, aBase, aInstancePtrResult);}extern "C" nsresult SetMailCharacterSetToMsgWindow(MimeObject *obj, const PRUnichar *aCharacterSet){  nsresult rv = NS_OK;  if (obj && obj->options)  {    mime_stream_data *msd = (mime_stream_data *) (obj->options->stream_closure);    if (msd)    {      nsIChannel *channel = msd->channel;      if (channel)      {        nsCOMPtr<nsIURI> uri;        channel->GetURI(getter_AddRefs(uri));        if (uri)        {          nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(uri));          if (msgurl)          {            nsCOMPtr<nsIMsgWindow> msgWindow;            msgurl->GetMsgWindow(getter_AddRefs(msgWindow));            if (msgWindow)              rv = msgWindow->SetMailCharacterSet(aCharacterSet);          }        }      }    }  }  return rv;}static char *mime_reformat_date(const char *date, void *stream_closure){  /*  struct mime_stream_data *msd = (struct mime_stream_data *) stream_closure; */  return nsCRT::strdup(date);}static char *mime_file_type (const char *filename, void *stream_closure){  char        *retType = nsnull;  char        *ext = nsnull;  nsresult    rv;  ext = PL_strrchr(filename, '.');  if (ext)  {    ext++;    nsCOMPtr<nsIMIMEService> mimeFinder (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));    if (NS_SUCCEEDED(rv) && mimeFinder)       mimeFinder->GetTypeFromExtension(ext, &retType);  }  return retType;}int ConvertUsingEncoderAndDecoder(const char *stringToUse, PRInt32 inLength,                                   nsIUnicodeEncoder *encoder, nsIUnicodeDecoder *decoder,                                   char **pConvertedString, PRInt32 *outLength){  // buffer size 144 =  // 72 (default line len for compose)   // times 2 (converted byte len might be larger)  const int klocalbufsize = 144;  // do the conversion  PRUnichar *unichars;  PRInt32 unicharLength;  PRInt32 srcLen = inLength;  PRInt32 dstLength = 0;  char *dstPtr;  nsresult rv;  // use this local buffer if possible  PRUnichar localbuf[klocalbufsize+1];  if (inLength > klocalbufsize) {    rv = decoder->GetMaxLength(stringToUse, srcLen, &unicharLength);    // allocate temporary buffer to hold unicode string    unichars = new PRUnichar[unicharLength];  }  else {    unichars = localbuf;    unicharLength = klocalbufsize+1;  }  if (unichars == nsnull) {    rv = NS_ERROR_OUT_OF_MEMORY;  }  else {    // convert to unicode    rv = decoder->Convert(stringToUse, &srcLen, unichars, &unicharLength);    if (NS_SUCCEEDED(rv)) {      rv = encoder->GetMaxLength(unichars, unicharLength, &dstLength);      // allocale an output buffer      dstPtr = (char *) PR_Malloc(dstLength + 1);      if (dstPtr == nsnull) {        rv = NS_ERROR_OUT_OF_MEMORY;      }      else {        PRInt32 buffLength = dstLength;        // convert from unicode        rv = encoder->SetOutputErrorBehavior(nsIUnicodeEncoder::kOnError_Replace, nsnull, '?');        if (NS_SUCCEEDED(rv)) {          rv = encoder->Convert(unichars, &unicharLength, dstPtr, &dstLength);          if (NS_SUCCEEDED(rv)) {            PRInt32 finLen = buffLength - dstLength;            rv = encoder->Finish((char *)(dstPtr+dstLength), &finLen);            if (NS_SUCCEEDED(rv)) {              dstLength += finLen;            }            dstPtr[dstLength] = '\0';            *pConvertedString = dstPtr;       // set the result string            *outLength = dstLength;          }        }      }    }    if (inLength > klocalbufsize)      delete [] unichars;  }  return NS_SUCCEEDED(rv) ? 0 : -1;}static intmime_convert_charset (const char *input_line, PRInt32 input_length,                      const char *input_charset, const char *output_charset,                      char **output_ret, PRInt32 *output_size_ret,                      void *stream_closure, nsIUnicodeDecoder *decoder, nsIUnicodeEncoder *encoder){  PRInt32 res = -1;  char  *convertedString = NULL;  PRInt32 convertedStringLen = 0;  if (encoder && decoder)  {    res = ConvertUsingEncoderAndDecoder(input_line, input_length, encoder, decoder, &convertedString, &convertedStringLen);  }  if (res != 0)  {      *output_ret = 0;      *output_size_ret = 0;  }  else  {    *output_ret = (char *) convertedString;    *output_size_ret = convertedStringLen;  }    return 0;}static intmime_output_fn(char *buf, PRInt32 size, void *stream_closure){  PRUint32  written = 0;  struct mime_stream_data *msd = (struct mime_stream_data *) stream_closure;  if ( (!msd->pluginObj2) && (!msd->output_emitter) )    return -1;    // Fire pending start request  ((nsStreamConverter*)msd->pluginObj2)->FirePendingStartRequest();      // Now, write to the WriteBody method if this is a message body and not  // a part retrevial  if (!msd->options->part_to_load)  {    if (msd->output_emitter)    {      msd->output_emitter->WriteBody(buf, (PRUint32) size, &written);    }  }  else  {    if (msd->output_emitter)    {      msd->output_emitter->Write(buf, (PRUint32) size, &written);    }  }  return written;}#ifdef XP_MACstatic intcompose_only_output_fn(char *buf, PRInt32 size, void *stream_closure){    return 0;}#endifextern "C" intmime_display_stream_write (nsMIMESession *stream,                           const char* buf,                           PRInt32 size){  struct mime_stream_data *msd = (struct mime_stream_data *) ((nsMIMESession *)stream)->data_object;  MimeObject *obj = (msd ? msd->obj : 0);    if (!obj) return -1;  //  // Ok, now check to see if this is a display operation for a MIME Parts on Demand  // enabled call.  //  if (msd->firstCheck)  {    if (msd->channel)    {      nsCOMPtr<nsIURI> aUri;	    if (NS_SUCCEEDED(msd->channel->GetURI(getter_AddRefs(aUri))))      {        nsCOMPtr<nsIImapUrl> imapURL = do_QueryInterface(aUri);        if (imapURL)        {          nsImapContentModifiedType   cModified;          if (NS_SUCCEEDED(imapURL->GetContentModified(&cModified)))          {            if ( cModified != nsImapContentModifiedTypes::IMAP_CONTENT_NOT_MODIFIED )              msd->options->missing_parts = PR_TRUE;          }        }      }    }    msd->firstCheck = PR_FALSE;  }  return obj->clazz->parse_buffer((char *) buf, size, obj);}extern "C" void mime_display_stream_complete (nsMIMESession *stream){  struct mime_stream_data *msd = (struct mime_stream_data *) ((nsMIMESession *)stream)->data_object;  MimeObject *obj = (msd ? msd->obj : 0);    if (obj)  {    int       status;    PRBool    abortNow = PR_FALSE;    // Release the prefs service    if ( (obj->options) && (obj->options->prefs) )      nsServiceManager::ReleaseService(kPrefCID, obj->options->prefs);        if ((obj->options) && (obj->options->headers == MimeHeadersOnly))      abortNow = PR_TRUE;    status = obj->clazz->parse_eof(obj, abortNow);    obj->clazz->parse_end(obj, (status < 0 ? PR_TRUE : PR_FALSE));      //    // Ok, now we are going to process the attachment data by getting all    // of the attachment info and then driving the emitter with this data.    //    if (!msd->options->part_to_load)    {      extern void  mime_dump_attachments ( nsMsgAttachmentData *attachData );      nsMsgAttachmentData *attachments;      nsresult rv = MimeGetAttachmentList(obj, msd->url_name, &attachments);      if (NS_SUCCEEDED(rv))      {        NotifyEmittersOfAttachmentList(msd->options, attachments);        MimeFreeAttachmentList(attachments);      }    }    // Release the conversion object - this has to be done after    // we finish processing data.    if ( obj->options)    {      NS_IF_RELEASE(obj->options->conv);    }    // Destroy the object now.    PR_ASSERT(msd->options == obj->options);    mime_free(obj);    obj = NULL;    if (msd->options)    {      delete msd->options;      msd->options = 0;    }  }  if (msd->headers)  	MimeHeaders_free (msd->headers);  if (msd->url_name)	  nsCRT::free(msd->url_name);  if (msd->orig_url_name)      nsCRT::free(msd->orig_url_name);  PR_FREEIF(msd);}extern "C" voidmime_display_stream_abort (nsMIMESession *stream, int status){  struct mime_stream_data *msd = (struct mime_stream_data *) ((nsMIMESession *)stream)->data_object;    MimeObject *obj = (msd ? msd->obj : 0);    if (obj)  {    if (!obj->closed_p)      obj->clazz->parse_eof(obj, PR_TRUE);    if (!obj->parsed_p)      obj->clazz->parse_end(obj, PR_TRUE);        // Destroy code....    PR_ASSERT(msd->options == obj->options);    mime_free(obj);    if (msd->options)    {      delete msd->options;      msd->options = 0;    }  }  if (msd->headers)  	MimeHeaders_free (msd->headers);  if (msd->url_name)	  nsCRT::free(msd->url_name);  if (msd->orig_url_name)      nsCRT::free(msd->orig_url_name);  PR_FREEIF(msd);}#ifdef XP_MACstatic PRUint32mime_convert_chars_to_ostype(const char *osTypeStr){	if (!osTypeStr)		return '????';	PRUint32 result;	const char *p = osTypeStr;	for (result = 0; *p; p++)	{		char C = *p;		PRInt8 unhex = ((C >= '0' && C <= '9') ? C - '0' :			((C >= 'A' && C <= 'F') ? C - 'A' + 10 :			 ((C >= 'a' && C <= 'f') ? C - 'a' + 10 : -1)));		if (unhex < 0)			break;		result = (result << 4) | unhex;	}	return result;}#endifstatic intmime_output_init_fn (const char *type,                     const char *charset,                     const char *name,                     const char *x_mac_type,                     const char *x_mac_creator,                     void *stream_closure){  struct mime_stream_data *msd = (struct mime_stream_data *) stream_closure;    // Now, all of this stream creation is done outside of libmime, so this  // is just a check of the pluginObj member and returning accordingly.  if (!msd->pluginObj2)    return -1;  else    return 0;}static void   *mime_image_begin(const char *image_url, const char *content_type,                              void *stream_closure);static void   mime_image_end(void *image_closure, int status);static char   *mime_image_make_image_html(void *image_data);static int    mime_image_write_buffer(char *buf, PRInt32 size, void *image_closure);/* Interface between libmime and inline display of images: the abomination   that is known as "internal-external-reconnect". */class mime_image_stream_data {public:  mime_image_stream_data();  struct mime_stream_data *msd;  char                    *url;  nsMIMESession           *istream;  nsCOMPtr<nsIOutputStream> memCacheOutputStream;  PRBool m_shouldCacheImage;};mime_image_stream_data::mime_image_stream_data(){  url = nsnull;  istream = nsnull;  msd = nsnull;  m_shouldCacheImage = PR_FALSE;}static void *mime_image_begin(const char *image_url, const char *content_type,                 void *stream_closure){  struct mime_stream_data *msd = (struct mime_stream_data *) stream_closure;  class mime_image_stream_data *mid;   mid = new mime_image_stream_data;  if (!mid) return nsnull;  mid->msd = msd;  mid->url = (char *) nsCRT::strdup(image_url);  if (!mid->url)  {    PR_Free(mid);    return nsnull;  }  if (msd->channel)  {    nsCOMPtr <nsIURI> uri;    nsresult rv = msd->channel->GetURI(getter_AddRefs(uri));    if (NS_SUCCEEDED(rv) && uri)    {      nsCOMPtr <nsIMsgMailNewsUrl> mailUrl = do_QueryInterface(uri);      if (mailUrl)      {        nsCOMPtr<nsICacheSession> memCacheSession;        mailUrl->GetImageCacheSession(getter_AddRefs(memCacheSession));        if (memCacheSession)        {          nsXPIDLCString spec;          uri->GetSpec(getter_Copies(spec));          nsCOMPtr<nsICacheEntryDescriptor> entry;          // we may need to convert the image_url into just a part url - in any case,          // it has to be the same as what imglib will be asking imap for later          // on so that we'll find this in the memory cache.          rv = memCacheSession->OpenCacheEntry(image_url, nsICache::ACCESS_READ_WRITE, nsICache::BLOCKING, getter_AddRefs(entry));          nsCacheAccessMode access;          if (entry)          {            entry->GetAccessGranted(&access);#ifdef DEBUG_bienvenu            printf("Mime opening cache entry for %s access = %ld\n", image_url, access);#endif            // if we only got write access, then we should fill in this cache entry            if (access & nsICache::ACCESS_WRITE && !(access & nsICache::ACCESS_READ))            {              mailUrl->CacheCacheEntry(entry);              entry->MarkValid();              nsCOMPtr<nsITransport> transport;              rv = entry->GetTransport(getter_AddRefs(transport));              if (NS_FAILED(rv)) return nsnull;              // remember the content type as meta data so we can pull it out in the imap code              // to feed the cache entry directly to imglib w/o going through mime.              entry->SetMetaDataElement("contentType", content_type);              nsCOMPtr<nsIOutputStream> out;              rv = transport->OpenOutputStream(0, PRUint32(-1), 0, getter_AddRefs(mid->memCacheOutputStream));              if (NS_FAILED(rv)) return nsnull;            }          }        }      }    }  }  mid->istream = (nsMIMESession *) msd->pluginObj2;  return mid;}static voidmime_image_end(void *image_closure, int status){  mime_image_stream_data *mid =    (mime_image_stream_data *) image_closure;    PR_ASSERT(mid);  if (!mid)     return;  if (mid->memCacheOutputStream)    mid->memCacheOutputStream->Close();  PR_FREEIF(mid->url);  delete mid;}static char *mime_image_make_image_html(void *image_closure){  mime_image_stream_data *mid =    (mime_image_stream_data *) image_closure;  const char *prefix = "<P><CENTER><IMG SRC=\"";  const char *suffix = "\"></CENTER><P>";  const char *url;  char *buf;  PR_ASSERT(mid);  if (!mid) return 0;  /* Internal-external-reconnect only works when going to the screen. */  if (!mid->istream)    return nsCRT::strdup("<P><CENTER><IMG SRC=\"resource:/res/network/gopher-image.gif\" ALT=\"[Image]\"></CENTER><P>");  if ( (!mid->url) || (!(*mid->url)) )    url = "";  else    url = mid->url;  buf = (char *) PR_MALLOC (strlen(prefix) + strlen(suffix) +                            strlen(url) + 20) ;  if (!buf)     return 0;  *buf = 0;  PL_strcat (buf, prefix);  PL_strcat (buf, url);  PL_strcat (buf, suffix);  return buf;}static intmime_image_write_buffer(char *buf, PRInt32 size, void *image_closure){  mime_image_stream_data *mid =                (mime_image_stream_data *) image_closure;  struct mime_stream_data *msd = mid->msd;  if ( ( (!msd->output_emitter) ) &&       ( (!msd->pluginObj2)     ) )    return -1;  //  // If we get here, we are just eating the data this time around  // and the returned URL will deal with writing the data to the viewer.  // Just return the size value to the caller.  //  if (mid->memCacheOutputStream)  {    PRUint32 bytesWritten;    mid->memCacheOutputStream->Write(buf, size, &bytesWritten);  }  return size;}// // Utility for finding HTML part.//static MimeObject*mime_find_text_html_part_1(MimeObject* obj){  if (mime_subclass_p(obj->clazz,                      (MimeObjectClass*) &mimeInlineTextHTMLClass)) {    return obj;  }  if (mime_subclass_p(obj->clazz, (MimeObjectClass*) &mimeContainerClass)) {    MimeContainer* cobj = (MimeContainer*) obj;    PRInt32 i;    for (i=0 ; i<cobj->nchildren ; i++) {      MimeObject* result = mime_find_text_html_part_1(cobj->children[i]);      if (result) return result;    }  }  return NULL;}MimeObject*mime_get_main_object(MimeObject* obj){  MimeContainer *cobj;  if (!(mime_subclass_p(obj->clazz, (MimeObjectClass*) &mimeMessageClass)))   {    return obj;  }  cobj = (MimeContainer*) obj;  if (cobj->nchildren != 1) return obj;  obj = cobj->children[0];  while (obj)  {    if ( (!mime_subclass_p(obj->clazz,         (MimeObjectClass*) &mimeMultipartSignedClass)) &&         (PL_strcasecmp(obj->content_type, MULTIPART_SIGNED) != 0)       )    {        return obj;    }    else    {      // We don't care about a signed/smime object; Go inside to the       // thing that we signed or smime'ed      //      cobj = (MimeContainer*) obj;      if (cobj->nchildren > 0)        obj = cobj->children[0];      else        obj = nsnull;    }  }  return NULL;}