ValidateRealName(nsMsgAttachmentData *aAttach)
ValidateRealName(nsMsgAttachmentData *aAttach, MimeHeaders *aHdrs)
MimeObject    *mime_get_main_object(MimeObject* obj);nsresultProcessBodyAsAttachment(MimeObject *obj, nsMsgAttachmentData **data){  nsMsgAttachmentData   *tmp;  PRInt32               n;  char                  *disp;  // 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(MSG_AttachmentData));  if (!*data)     return NS_ERROR_OUT_OF_MEMORY;  tmp = *data;  nsCRT::memset(*data, 0, (n + 1) * sizeof(MSG_AttachmentData));  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", NULL, NULL);  if (tmp->real_name)  {    char *fname = NULL;    fname = mime_decode_filename(tmp->real_name);    if (fname && fname != tmp->real_name)    {      PR_Free(tmp->real_name);      tmp->real_name = fname;    }  }  else  {    tmp->real_name = MimeHeaders_get_name(child->headers);  }  char  *tmpURL = nsnull;  char  *id = nsnull;  char  *id_imap = nsnull;  //PRBool all_headers_p = obj->options->headers == MimeHeadersAll;  id = mime_part_address (obj);  if (obj->options->missing_parts)    id_imap = mime_imap_part_address (obj);  if (! id)  {    PR_FREEIF(*data);    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);    }    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);      return NS_ERROR_OUT_OF_MEMORY;    }  }  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;  for (i=0; i<aObj->nchildren; i++)    rc += CountTotalMimeAttachments((MimeContainer *)aObj->children[i]) + 1;  return rc;}voidValidateRealName(nsMsgAttachmentData *aAttach){   // 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) &&      (!aAttach->real_name || *aAttach->real_name == 0))  {    mime_SACopy(&(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 = "attachment";    nsresult  rv = NS_OK;    NS_WITH_SERVICE(nsIMIMEService, mimeFinder, kMimeServiceCID, &rv);     if (NS_SUCCEEDED(rv) && mimeFinder)     {      nsIMIMEInfo *mimeInfo = nsnull;      rv = mimeFinder->GetFromMIMEType(aAttach->real_type, &mimeInfo);      if (NS_SUCCEEDED(rv) && mimeInfo)       {        char *aFileExtension = nsnull;        if ( (NS_SUCCEEDED(mimeInfo->FirstExtension(&aFileExtension))) && aFileExtension)        {          newAttachName.Append(".");          newAttachName.Append(aFileExtension);          PR_FREEIF(aFileExtension);        }      }            }    aAttach->real_name = newAttachName.ToNewCString();  }  }static  PRInt32     attIndex = 0;nsresultBuildAttachmentList(MimeObject *aChild, nsMsgAttachmentData *aAttachData,                    const char *aMessageURL){  char                  *disp;  PRInt32               i;  MimeContainer         *cobj = (MimeContainer *) aChild;  nsMsgAttachmentData   *tmp = nsnull;  PRBool                isAlternativeOrRelated;  if ( (!aChild) || (!cobj->children) )    return NS_OK;  if (MimeObjectChildIsMessageBody(aChild, &isAlternativeOrRelated))    i = 1;  else    i = 0;  for (; i<cobj->nchildren ; i++)   {    MimeObject    *child = cobj->children[i];    char          *part = mime_part_address(child);    char          *imappart = NULL;    if ( NS_FAILED(BuildAttachmentList((MimeObject *)child, aAttachData, aMessageURL)) )      return NS_OK;    // If this is a child of an AppleDouble handler, these are subparts of a single file (ugh!)    // So don't add them to the attachment list!    if ( (child->parent) && (mime_typep(child->parent, (MimeObjectClass *) &mimeMultipartAppleDoubleClass)) )      continue;    if (!part)       return NS_ERROR_OUT_OF_MEMORY;    if (aChild->options->missing_parts)      imappart = mime_imap_part_address(child);    char *urlSpec = nsnull;    if (imappart)      urlSpec = mime_set_url_imap_part(aMessageURL, imappart, part);    else      urlSpec = mime_set_url_part(aMessageURL, part, PR_TRUE);  	  PR_FREEIF(part);  	PR_FREEIF(imappart);    if (!urlSpec)      return NS_ERROR_OUT_OF_MEMORY;    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 = 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);    if (disp)     {      tmp->real_name = MimeHeaders_get_parameter(disp, "filename", NULL, NULL);      if (tmp->real_name)      {        char *fname = NULL;        fname = mime_decode_filename(tmp->real_name);        if (fname && fname != tmp->real_name)        {          PR_FREEIF(tmp->real_name);          tmp->real_name = fname;        }      }      PR_FREEIF(disp);    }    disp = MimeHeaders_get(child->headers, HEADER_CONTENT_TYPE, PR_FALSE, PR_FALSE);    if (disp)    {      tmp->x_mac_type   = MimeHeaders_get_parameter(disp, PARAM_X_MAC_TYPE, NULL, NULL);      tmp->x_mac_creator= MimeHeaders_get_parameter(disp, PARAM_X_MAC_CREATOR, NULL, NULL);      if (!tmp->real_name || *tmp->real_name == 0)      {        PR_FREEIF(tmp->real_name);        tmp->real_name = MimeHeaders_get_parameter(disp, "name", NULL, NULL);        if (tmp->real_name)        {          char *fname = NULL;          fname = mime_decode_filename(tmp->real_name);          if (fname && fname != tmp->real_name)          {            PR_Free(tmp->real_name);            tmp->real_name = fname;          }        }      }      PR_FREEIF(disp);    }    tmp->description = MimeHeaders_get(child->headers, HEADER_CONTENT_DESCRIPTION,                                        PR_FALSE, PR_FALSE);    // Now, do the right thing with the name!    ValidateRealName(tmp);  }  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(MSG_AttachmentData));  if (!*data)     return NS_ERROR_OUT_OF_MEMORY;  attIndex = 0;  nsCRT::memset(*data, 0, (n + 1) * sizeof(MSG_AttachmentData));    // Now, build the list!  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);    mimeEmitterAddAttachmentField(opt, HEADER_X_MOZILLA_PART_URL, spec);	  if (spec)		  nsAllocator::Free(spec);    if ( (opt->format_out == nsMimeOutput::nsMimeMessageQuoting) ||          (opt->format_out == nsMimeOutput::nsMimeMessageBodyQuoting) ||          (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;  }}// 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;    NS_WITH_SERVICE(nsIIOService, pService, kIOServiceCID, &res);  if (NS_FAILED(res))     return NS_ERROR_FACTORY_NOT_REGISTERED;  return pService->NewURI(aSpec, aBase, aInstancePtrResult);}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++;    NS_WITH_SERVICE(nsIMIMEService, mimeFinder, kMimeServiceCID, &rv);     if (NS_SUCCEEDED(rv) && mimeFinder)       mimeFinder->GetTypeFromExtension(ext, &retType);  }  return retType;}static intmime_convert_charset (const PRBool input_autodetect, 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){  // Now do conversion to UTF-8 for output  char  *convertedString = NULL;  PRInt32 convertedStringLen;  PRInt32 res = MIME_ConvertCharset(input_autodetect, input_charset, "UTF-8", input_line, input_length,                                     &convertedString, &convertedStringLen, NULL);  if (res != 0)  {      *output_ret = 0;      *output_size_ret = 0;  }  else  {    *output_ret = (char *) convertedString;    *output_size_ret = convertedStringLen;  }    return 0;}static intmime_convert_rfc1522 (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){  char *converted;  char *line;  char charset[128];    charset[0] = '\0';  if (input_line[input_length] == 0)  /* oh good, it's null-terminated */    line = (char *) input_line;  else    {      line = (char *) PR_MALLOC(input_length+1);      if (!line) return MIME_OUT_OF_MEMORY;      nsCRT::memcpy(line, input_line, input_length);      line[input_length] = 0;    }  converted = MIME_DecodeMimePartIIStr(line, charset, PR_TRUE);  if (line != input_line)    PR_Free(line);  if (converted)    {      char  *convertedString = NULL;       PRInt32 res = MIME_ConvertString(charset, "UTF-8", converted, &convertedString);       if ( (res != 0) || (!convertedString) )      {        *output_ret = converted;        *output_size_ret = nsCRT::strlen(converted);      }      else      {        PR_Free(converted);         *output_ret = convertedString;        *output_size_ret = nsCRT::strlen(convertedString);      }    }  else    {      *output_ret = 0;      *output_size_ret = 0;    }  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;    // 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;}#endifstatic intmime_set_html_state_fn (void *stream_closure,                        PRBool layer_encapsulate_p,                        PRBool start_p,                        PRBool abort_p){  int status = 0;  /*  struct mime_stream_data *msd = (struct mime_stream_data *) stream_closure; */    if (start_p)   {  }   else   {  }  return status;}extern "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;  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) && (obj->options->conv) )      NS_RELEASE(obj->options->conv);    // Destroy the object now.    PR_ASSERT(msd->options == obj->options);    mime_free(obj);    obj = NULL;    if (msd->options)    {      PR_FREEIF(msd->options->part_to_load);      PR_FREEIF(msd->options->default_charset);      PR_FREEIF(msd->options->override_charset);      PR_Free(msd->options);      msd->options = 0;    }  }  if (msd->headers)  	MimeHeaders_free (msd->headers);  if (msd->url_name)	  nsCRT::free(msd->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)    {      PR_FREEIF(msd->options->part_to_load);      PR_FREEIF(msd->options);      msd->options = 0;    }  }  if (msd->headers)  	MimeHeaders_free (msd->headers);  PR_FREEIF(msd);}static intmime_insert_html_convert_charset (const PRBool input_autodetect, 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){  //struct mime_stream_data *msd = (struct mime_stream_data *) stream_closure;    return mime_convert_charset (input_autodetect, input_line, input_length,                               input_charset, output_charset,                               output_ret, output_size_ret,                               stream_closure);}static 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". */struct mime_image_stream_data {  struct mime_stream_data *msd;  char                    *url;  nsMIMESession           *istream;};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;  struct mime_image_stream_data *mid;  mid = PR_NEW(struct mime_image_stream_data);  if (!mid) return 0;  memset(mid, 0, sizeof(*mid));  mid->msd = msd;  mid->url = (char *) nsCRT::strdup(image_url);  if (!mid->url)  {    PR_Free(mid);    return 0;  }  mid->istream = (nsMIMESession *) msd->pluginObj2;  return mid;}static voidmime_image_end(void *image_closure, int status){  struct mime_image_stream_data *mid =    (struct mime_image_stream_data *) image_closure;    PR_ASSERT(mid);  if (!mid)     return;  PR_FREEIF(mid->url);  PR_FREEIF(mid);}static char *mime_image_make_image_html(void *image_closure){  struct mime_image_stream_data *mid =    (struct mime_image_stream_data *) image_closure;    const char *prefix = "<P><CENTER><IMG SRC=\"";  const char *suffix = "\"></CENTER><P><BR>";  const char *url;  char *buf;  static PRInt32  makeUniqueHackID = 1;  char            makeUniqueHackString[128] = "";    PR_ASSERT(mid);  if (!mid) return 0;  PR_snprintf(makeUniqueHackString, sizeof(makeUniqueHackString), "&hackID=%d", makeUniqueHackID++);  /* 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 (nsCRT::strlen(prefix) + nsCRT::strlen(suffix) +                           nsCRT::strlen(url) + nsCRT::strlen(makeUniqueHackString) + 20) ;  if (!buf)     return 0;  *buf = 0;  PL_strcat (buf, prefix);  PL_strcat (buf, url);  PL_strcat (buf, makeUniqueHackString);  PL_strcat (buf, suffix);  return buf;}static intmime_image_write_buffer(char *buf, PRInt32 size, void *image_closure){  struct mime_image_stream_data *mid =                (struct 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.  //  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;}