const char *charset,
const char *attachmentCharset, const char *bodyCharset,
mime_generate_attachment_headers (const char *type, const char *encoding,                  const char *description,                  const char *x_mac_type,                  const char *x_mac_creator,                  const char *real_name,                  const char *base_url,                  PRBool /*digest_p*/,                  nsMsgAttachmentHandler * /*ma*/,                  const char *charset,                  PRBool bodyIsAsciiOnly,                  const char *content_id,                   PRBool      aBodyDocument){  nsresult rv;  nsCOMPtr<nsIPref> prefs(do_GetService(kPrefCID, &rv));   PRInt32 buffer_size = 2048 + (base_url ? 2*PL_strlen(base_url) : 0);  char *buffer = (char *) PR_Malloc (buffer_size);  char *buffer_tail = buffer;  if (! buffer)    return 0; /* NS_ERROR_OUT_OF_MEMORY */  NS_ASSERTION (encoding, "null encoding");  PRBool usemime = nsMsgMIMEGetConformToStandard();  PRInt32 parmFolding = 0;  if (NS_SUCCEEDED(rv) && prefs)     prefs->GetIntPref("mail.strictly_mime.parm_folding", &parmFolding);  /* Let's encode the real name */  char *encodedRealName = nsnull;  if (real_name)  {    encodedRealName = nsMsgI18NEncodeMimePartIIStr(real_name, PR_FALSE, nsMsgI18NFileSystemCharset(), 0, usemime);    if (!encodedRealName || !*encodedRealName)    {      /* Let's try one more time using UTF8 */        encodedRealName = nsMsgI18NEncodeMimePartIIStr(real_name, PR_FALSE, "UTF-8", 0, usemime);      if (!encodedRealName || !*encodedRealName)      {        PR_FREEIF(encodedRealName);        encodedRealName = PL_strdup(real_name);      }    }    /* ... and then put backslashes before special characters (RFC 822 tells us to). */    char *qtextName = msg_make_filename_qtext(encodedRealName, (parmFolding == 0 ? PR_TRUE : PR_FALSE));        if (qtextName)    {      PR_FREEIF(encodedRealName);      encodedRealName = qtextName;    }  }  PUSH_STRING ("Content-Type: ");  PUSH_STRING (type);  if (mime_type_needs_charset (type))   {        char charset_label[65] = "";   // Content-Type: charset    PL_strncpy(charset_label, charset, sizeof(charset_label)-1);    charset_label[sizeof(charset_label)-1] = '\0';        /* If the characters are all 7bit, then it's better (and true) to    claim the charset to be US-  rather than Latin1.  Should we    do this all the time, for all charsets?  I'm not sure.  But we    should definitely do it for Latin1. */    if (encoding &&                  !PL_strcasecmp (encoding, "7bit") &&                  bodyIsAsciiOnly)      PL_strcpy (charset_label, "us-ascii");        // If charset is multibyte then no charset to be specified (apply base64 instead).    // The list of file types match with PickEncoding() where we put base64 label.    if ( ((charset && !nsMsgI18Nmultibyte_charset(charset)) ||         ((PL_strcasecmp(type, TEXT_HTML) == 0) ||         (PL_strcasecmp(type, TEXT_MDL) == 0) ||         (PL_strcasecmp(type, TEXT_PLAIN) == 0) ||         (PL_strcasecmp(type, TEXT_RICHTEXT) == 0) ||         (PL_strcasecmp(type, TEXT_ENRICHED) == 0) ||         (PL_strcasecmp(type, TEXT_VCARD) == 0) ||         (PL_strcasecmp(type, APPLICATION_DIRECTORY) == 0) || /* text/x-vcard synonym */         (PL_strcasecmp(type, TEXT_CSS) == 0) ||         (PL_strcasecmp(type, TEXT_JSSS) == 0)) ||         (PL_strcasecmp(encoding, ENCODING_BASE64) != 0)) &&         (*charset_label))    {      PUSH_STRING ("; charset=");      PUSH_STRING (charset_label);    }  }  // Only do this if we are in the body of a message  if (aBodyDocument)  {    // Add format=flowed as in RFC 2646 if we are using that    if(type && !PL_strcasecmp(type, "text/plain"))    {      if(UseFormatFlowed(charset))        PUSH_STRING ("; format=flowed");      // else      // {      // Don't add a markup. Could use       //        PUSH_STRING ("; format=fixed");      // but it is equivalent to nothing at all and we do want      // to save bandwidth. Don't we?      // }    }  }      if (x_mac_type && *x_mac_type) {    PUSH_STRING ("; x-mac-type=\"");    PUSH_STRING (x_mac_type);    PUSH_STRING ("\"");  }  if (x_mac_creator && *x_mac_creator) {    PUSH_STRING ("; x-mac-creator=\"");    PUSH_STRING (x_mac_creator);    PUSH_STRING ("\"");  }#ifdef EMIT_NAME_IN_CONTENT_TYPE  if (encodedRealName && *encodedRealName) {    if (parmFolding == 0 || parmFolding == 1) {      PUSH_STRING (";\r\n name=\"");      PUSH_STRING (encodedRealName);      PUSH_STRING ("\"");    }    else // if (parmFolding == 2)    {      char *rfc2231Parm = RFC2231ParmFolding("name", charset,                         nsMsgI18NGetAcceptLanguage(), encodedRealName);      if (rfc2231Parm) {        PUSH_STRING(";\r\n ");        PUSH_STRING(rfc2231Parm);        PR_Free(rfc2231Parm);      }    }  }#endif /* EMIT_NAME_IN_CONTENT_TYPE */  PUSH_NEWLINE ();  PUSH_STRING ("Content-Transfer-Encoding: ");  PUSH_STRING (encoding);  PUSH_NEWLINE ();  if (description && *description) {    char *s = mime_fix_header (description);    if (s) {      PUSH_STRING ("Content-Description: ");      PUSH_STRING (s);      PUSH_NEWLINE ();      PR_Free(s);    }  }  if ( (content_id) && (*content_id) )  {    PUSH_STRING ("Content-ID: <");    PUSH_STRING (content_id);    PUSH_STRING (">");    PUSH_NEWLINE ();  }  if (encodedRealName && *encodedRealName) {    char *period = PL_strrchr(encodedRealName, '.');    PRInt32 pref_content_disposition = 0;        rv = prefs->GetIntPref("mail.content_disposition_type", &pref_content_disposition);        NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get mail.content_disposition_type");    PUSH_STRING ("Content-Disposition: ");    if (pref_content_disposition == 1)      PUSH_STRING ("attachment");    else      if (pref_content_disposition == 2 &&           (!PL_strcasecmp(type, TEXT_PLAIN) ||           (period && !PL_strcasecmp(period, ".txt"))))        PUSH_STRING("attachment");      /* If this document is an anonymous binary file or a vcard,       then always show it as an attachment, never inline. */      else        if (!PL_strcasecmp(type, APPLICATION_OCTET_STREAM) ||             !PL_strcasecmp(type, TEXT_VCARD) ||            !PL_strcasecmp(type, APPLICATION_DIRECTORY)) /* text/x-vcard synonym */          PUSH_STRING ("attachment");        else          PUSH_STRING ("inline");    if (parmFolding == 0 || parmFolding == 1) {      PUSH_STRING (";\r\n filename=\"");      PUSH_STRING (encodedRealName);      PUSH_STRING ("\"" CRLF);    }    else // if (parmFolding == 2)    {      char *rfc2231Parm = RFC2231ParmFolding("filename", charset,                       nsMsgI18NGetAcceptLanguage(), encodedRealName);      if (rfc2231Parm) {        PUSH_STRING(";\r\n ");        PUSH_STRING(rfc2231Parm);        PUSH_NEWLINE ();        PR_Free(rfc2231Parm);      }    }  }  else    if (type &&        (!PL_strcasecmp (type, MESSAGE_RFC822) ||        !PL_strcasecmp (type, MESSAGE_NEWS)))      PUSH_STRING ("Content-Disposition: inline" CRLF);  #ifdef GENERATE_CONTENT_BASE  /* If this is an HTML document, and we know the URL it originally     came from, write out a Content-Base header. */  if (type &&      (!PL_strcasecmp (type, TEXT_HTML) ||      !PL_strcasecmp (type, TEXT_MDL)) &&      base_url && *base_url)  {    PRInt32 col = 0;    const char *s = base_url;    const char *colon = PL_strchr (s, ':');    PRBool useContentLocation = PR_FALSE;   /* rhp - add this  */    if (!colon)      goto GIVE_UP_ON_CONTENT_BASE;  /* malformed URL? */    /* Don't emit a content-base that points to (or into) a news or       mail message. */    if (!PL_strncasecmp (s, "news:", 5) ||        !PL_strncasecmp (s, "snews:", 6) ||        !PL_strncasecmp (s, "IMAP:", 5) ||        !PL_strncasecmp (s, "file:", 5) ||    /* rhp: fix targets from included HTML files */        !PL_strncasecmp (s, "mailbox:", 8))      goto GIVE_UP_ON_CONTENT_BASE;    /* rhp - Put in a pref for using Content-Location instead of Content-Base.           This will get tweaked to default to true in 5.0    */    if (NS_SUCCEEDED(rv) && prefs)       prefs->GetBoolPref("mail.use_content_location_on_send", &useContentLocation);    if (useContentLocation)      PUSH_STRING ("Content-Location: \"");    else      PUSH_STRING ("Content-Base: \"");    /* rhp - Pref for Content-Location usage *//* rhp: this is to work with the Content-Location stuff */CONTENT_LOC_HACK:    while (*s != 0 && *s != '#')    {      const char *ot = buffer_tail;      /* URLs must be wrapped at 40 characters or less. */      if (col >= 38) {        PUSH_STRING(CRLF "\t");        col = 0;      }      if (*s == ' ')        PUSH_STRING("%20");      else if (*s == '\t')        PUSH_STRING("%09");      else if (*s == '\n')        PUSH_STRING("%0A");      else if (*s == '\r')        PUSH_STRING("%0D");      else {        *buffer_tail++ = *s;        *buffer_tail = '\0';      }      s++;      col += (buffer_tail - ot);    }    PUSH_STRING ("\"" CRLF);    /* rhp: this is to try to get around this fun problem with Content-Location */    if (!useContentLocation) {      PUSH_STRING ("Content-Location: \"");      s = base_url;      col = 0;      useContentLocation = PR_TRUE;      goto CONTENT_LOC_HACK;    }    /* rhp: this is to try to get around this fun problem with Content-Location */GIVE_UP_ON_CONTENT_BASE:    ;  }#endif /* GENERATE_CONTENT_BASE */  /* realloc it smaller... */  buffer = (char*) PR_REALLOC (buffer, buffer_tail - buffer + 1);  PR_FREEIF(encodedRealName);  return buffer;}