PR_FREEIF(acceptlang);
mime_generate_headers (nsMsgCompFields *fields,									     const char *charset,									     nsMsgDeliverMode deliver_mode, nsIPrompt * aPrompt, PRInt32 *status){  nsresult rv;  *status = 0;  nsCOMPtr<nsIPref> prefs(do_GetService(kPrefCID, &rv));   if (NS_FAILED(rv)) {	*status = rv;    return nsnull;  }	int size = 0;	char *buffer = 0, *buffer_tail = 0;	PRBool isDraft =  deliver_mode == nsIMsgSend::nsMsgSaveAsDraft ||  deliver_mode == nsIMsgSend::nsMsgSaveAsTemplate ||  deliver_mode == nsIMsgSend::nsMsgQueueForLater;	const char* pFrom;	const char* pTo;	const char* pCc;	const char* pMessageID;	const char* pReplyTo;	const char* pOrg;	const char* pNewsGrp;	const char* pFollow;	const char* pSubject;	const char* pPriority;	const char* pReference;	const char* pOtherHdr;	NS_ASSERTION (fields, "null fields");	if (!fields)		return nsnull;	/* Multiply by 3 here to make enough room for MimePartII conversion */	pFrom = fields->GetFrom(); if (pFrom)						size += 3 * PL_strlen (pFrom);	pReplyTo =fields->GetReplyTo(); if (pReplyTo)				size += 3 * PL_strlen (pReplyTo);	pTo = fields->GetTo(); if (pTo)								size += 3 * PL_strlen (pTo);	pCc = fields->GetCc(); if (pCc)								size += 3 * PL_strlen (pCc);	pNewsGrp = fields->GetNewsgroups(); if (pNewsGrp)			size += 3 * PL_strlen (pNewsGrp);	pFollow= fields->GetFollowupTo(); if (pFollow)				size += 3 * PL_strlen (pFollow);	pSubject = fields->GetSubject(); if (pSubject)				size += 3 * PL_strlen (pSubject);	pReference = fields->GetReferences(); if (pReference)		size += 3 * PL_strlen (pReference);	pOrg= fields->GetOrganization(); if (pOrg)					size += 3 * PL_strlen (pOrg);	pOtherHdr= fields->GetOtherRandomHeaders(); if (pOtherHdr)	size += 3 * PL_strlen (pOtherHdr);	pPriority = fields->GetPriority();  if (pPriority)			size += 3 * PL_strlen (pPriority);	pMessageID = fields->GetMessageId(); if (pMessageID)		size += PL_strlen (pMessageID);	/* Add a bunch of slop for the static parts of the headers. */	/* size += 2048; */	size += 2560;	buffer = (char *) PR_Malloc (size);	if (!buffer)		return nsnull; /* NS_ERROR_OUT_OF_MEMORY */		buffer_tail = buffer;	if (pMessageID && *pMessageID) {		char *convbuf = NULL;		PUSH_STRING ("Message-ID: ");		PUSH_STRING (pMessageID);		PUSH_NEWLINE ();		/* MDN request header requires to have MessageID header presented		* in the message in order to		* coorelate the MDN reports to the original message. Here will be		* the right place		*/		if (fields->GetReturnReceipt() && 			(fields->GetReturnReceiptType() == 2 ||			fields->GetReturnReceiptType() == 3) && 			(deliver_mode != nsIMsgSend::nsMsgSaveAsDraft &&			deliver_mode != nsIMsgSend::nsMsgSaveAsTemplate))		{			PRInt32 receipt_header_type = 0;      if (prefs)     	  prefs->GetIntPref("mail.receipt.request_header_type", &receipt_header_type);			// 0 = MDN Disposition-Notification-To: ; 1 = Return-Receipt-To: ; 2 =			// both MDN DNT & RRT headers			if (receipt_header_type == 1) {				RRT_HEADER:				PUSH_STRING ("Return-Receipt-To: ");				convbuf = nsMsgI18NEncodeMimePartIIStr((char *)pFrom, charset, nsMsgMIMEGetConformToStandard());				if (convbuf) {    /* MIME-PartII conversion */					PUSH_STRING (convbuf);					PR_FREEIF(convbuf);				}				else					PUSH_STRING (pFrom);				PUSH_NEWLINE ();			}			else  {				PUSH_STRING ("Disposition-Notification-To: ");				convbuf = nsMsgI18NEncodeMimePartIIStr((char *)pFrom, charset,												nsMsgMIMEGetConformToStandard());				if (convbuf) {     /* MIME-PartII conversion */					PUSH_STRING (convbuf);					PR_FREEIF(convbuf);				}				else					PUSH_STRING (pFrom);				PUSH_NEWLINE ();				if (receipt_header_type == 2)					goto RRT_HEADER;			}		}#ifdef SUPPORT_X_TEMPLATE_NAME		if (deliver_mode == MSG_SaveAsTemplate) {			PUSH_STRING ("X-Template: ");			char * pStr = fields->GetTemplateName();			if (pStr) {				convbuf = nsMsgI18NEncodeMimePartIIStr((char *)									 pStr,									 charset,									 nsMsgMIMEGetConformToStandard());				if (convbuf) {				  PUSH_STRING (convbuf);				  PR_FREEIF(convbuf);				}				else				  PUSH_STRING(pStr);			}			PUSH_NEWLINE ();		}#endif /* SUPPORT_X_TEMPLATE_NAME */	}	PRExplodedTime now;  PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &now);  int gmtoffset = (now.tm_params.tp_gmt_offset + now.tm_params.tp_dst_offset) / 60;	/* Use PR_FormatTimeUSEnglish() to format the date in US English format,	   then figure out what our local GMT offset is, and append it (since	   PR_FormatTimeUSEnglish() can't do that.) Generate four digit years as	   per RFC 1123 (superceding RFC 822.)	 */	PR_FormatTimeUSEnglish(buffer_tail, 100,						   "Date: %a, %d %b %Y %H:%M:%S ",						   &now);	buffer_tail += PL_strlen (buffer_tail);	PR_snprintf(buffer_tail, buffer + size - buffer_tail,				"%c%02d%02d" CRLF,				(gmtoffset >= 0 ? '+' : '-'),				((gmtoffset >= 0 ? gmtoffset : -gmtoffset) / 60),				((gmtoffset >= 0 ? gmtoffset : -gmtoffset) % 60));	buffer_tail += PL_strlen (buffer_tail);	if (pFrom && *pFrom) {		char *convbuf;		PUSH_STRING ("From: ");		convbuf = nsMsgI18NEncodeMimePartIIStr((char *)pFrom, charset,										nsMsgMIMEGetConformToStandard());		if (convbuf) {    /* MIME-PartII conversion */			PUSH_STRING (convbuf);			PR_Free(convbuf);		}		else			PUSH_STRING (pFrom);		PUSH_NEWLINE ();	}	if (pReplyTo && *pReplyTo)	{		char *convbuf;		PUSH_STRING ("Reply-To: ");		convbuf = nsMsgI18NEncodeMimePartIIStr((char *)pReplyTo, charset,										nsMsgMIMEGetConformToStandard());		if (convbuf) {     /* MIME-PartII conversion */			PUSH_STRING (convbuf);			PR_Free(convbuf);		}		else			PUSH_STRING (pReplyTo);		PUSH_NEWLINE ();	}	if (pOrg && *pOrg)	{		char *convbuf;		PUSH_STRING ("Organization: ");		convbuf = nsMsgI18NEncodeMimePartIIStr((char *)pOrg, charset,										nsMsgMIMEGetConformToStandard());		if (convbuf) {     /* MIME-PartII conversion */			PUSH_STRING (convbuf);			PR_Free(convbuf);		}		else			PUSH_STRING (pOrg);		PUSH_NEWLINE ();	}	// X-Mozilla-Draft-Info	if (isDraft)   {		PUSH_STRING(HEADER_X_MOZILLA_DRAFT_INFO);		PUSH_STRING(": internal/draft; ");		if (fields->GetAttachVCard())			PUSH_STRING("vcard=1");		else			PUSH_STRING("vcard=0");		PUSH_STRING("; ");		if (fields->GetReturnReceipt()) {			char *type = PR_smprintf("%d", (int) fields->GetReturnReceiptType());			if (type)			{				PUSH_STRING("receipt=");				PUSH_STRING(type);				PR_FREEIF(type);			}		}		else			PUSH_STRING("receipt=0");		PUSH_STRING("; ");		if (fields->GetUuEncodeAttachments())		  PUSH_STRING("uuencode=1");		else		  PUSH_STRING("uuencode=0");		PUSH_NEWLINE ();	}	nsCOMPtr<nsIHttpProtocolHandler> pHTTPHandler = 	         do_GetService(kHTTPHandlerCID, &rv); 	if (NS_SUCCEEDED(rv) && pHTTPHandler)	{        nsXPIDLCString userAgentString;        pHTTPHandler->GetUserAgent(getter_Copies(userAgentString));		if (userAgentString)		{			// PUSH_STRING ("X-Mailer: ");  // To be more standards compliant			PUSH_STRING ("User-Agent: ");  			PUSH_STRING(userAgentString.get());			PUSH_NEWLINE ();		}	}	/* for Netscape Server, Accept-Language data sent in Mail header */	char *acceptlang = nsMsgI18NGetAcceptLanguage();	if( (acceptlang != NULL) && ( *acceptlang != '\0') ){		PUSH_STRING( "X-Accept-Language: " );		PUSH_STRING( acceptlang );		PUSH_NEWLINE();	}        PR_FREEIF(acceptlang);	PUSH_STRING ("MIME-Version: 1.0" CRLF);	if (pNewsGrp && *pNewsGrp) {		/* turn whitespace into a comma list		*/		char *ptr, *ptr2;		char *n2;		char *convbuf;		convbuf = nsMsgI18NEncodeMimePartIIStr((char *)pNewsGrp, charset,										nsMsgMIMEGetConformToStandard());		if (convbuf)	  		n2 = nsMsgStripLine (convbuf);		else {			ptr = PL_strdup(pNewsGrp);			if (!ptr) {				PR_FREEIF(buffer);				return nsnull; /* NS_ERROR_OUT_OF_MEMORY */			}  	  		n2 = nsMsgStripLine(ptr);			NS_ASSERTION(n2 == ptr, "n2 != ptr");	/* Otherwise, the PR_Free below is													   gonna choke badly. */		}		for(ptr=n2; *ptr != '\0'; ptr++) {			/* find first non white space */			while(!IS_SPACE(*ptr) && *ptr != ',' && *ptr != '\0')				ptr++;			if(*ptr == '\0')				break;			if(*ptr != ',')				*ptr = ',';			/* find next non white space */			ptr2 = ptr+1;			while(IS_SPACE(*ptr2))				ptr2++;			if(ptr2 != ptr+1)				PL_strcpy(ptr+1, ptr2);		}    // we need to decide the Newsgroup related headers    // to write to the outgoing message. In ANY case, we need to write the    // "Newsgroup" header which is the "proper" header as opposed to the    // HEADER_X_MOZILLA_NEWSHOST which can contain the "news:" URL's.    //    // Since n2 can contain data in the form of:    // "news://news.mozilla.org/netscape.test,news://news.mozilla.org/netscape.junk"    // we need to turn that into: "netscape.test,netscape.junk"    //    nsCOMPtr <nsINntpService> nntpService = do_GetService("@mozilla.org/messenger/nntpservice;1");    if (NS_FAILED(rv) || !nntpService) {      *status = NS_ERROR_FAILURE;      return nsnull;    }    nsXPIDLCString newsgroupsHeaderVal;    nsXPIDLCString newshostHeaderVal;    rv = nntpService->GenerateNewsHeaderValsForPosting(n2, getter_Copies(newsgroupsHeaderVal), getter_Copies(newshostHeaderVal));    if (NS_FAILED(rv)) {      *status = rv;      return nsnull;    }    PUSH_STRING ("Newsgroups: ");    PUSH_STRING (newsgroupsHeaderVal.get());    PUSH_NEWLINE ();    // If we are here, we are NOT going to send this now. (i.e. it is a Draft,     // Send Later file, etc...). Because of that, we need to store what the user    // typed in on the original composition window for use later when rebuilding    // the headers    if (deliver_mode != nsIMsgSend::nsMsgDeliverNow)    {      // This is going to be saved for later, that means we should just store      // what the user typed into the "Newsgroup" line in the HEADER_X_MOZILLA_NEWSHOST      // header for later use by "Send Unsent Messages", "Drafts" or "Templates"      PUSH_STRING (HEADER_X_MOZILLA_NEWSHOST);      PUSH_STRING (": ");      PUSH_STRING (newshostHeaderVal.get());      PUSH_NEWLINE ();    }		PR_FREEIF(n2);	}	/* #### shamelessly duplicated from above */	if (pFollow && *pFollow) {		/* turn whitespace into a comma list		*/		char *ptr, *ptr2;		char *n2;		char *convbuf;		convbuf = nsMsgI18NEncodeMimePartIIStr((char *)pFollow, charset,										nsMsgMIMEGetConformToStandard());		if (convbuf)			n2 = nsMsgStripLine (convbuf);		else {			ptr = PL_strdup(pFollow);			if (!ptr) {				PR_FREEIF(buffer);				return nsnull; /* NS_ERROR_OUT_OF_MEMORY */			}			n2 = nsMsgStripLine (ptr);			NS_ASSERTION(n2 == ptr, "n2 != ptr");	/* Otherwise, the PR_Free below is													   gonna choke badly. */		}		for (ptr=n2; *ptr != '\0'; ptr++) {			/* find first non white space */			while(!IS_SPACE(*ptr) && *ptr != ',' && *ptr != '\0')				ptr++;			if(*ptr == '\0')				break;			if(*ptr != ',')				*ptr = ',';			/* find next non white space */			ptr2 = ptr+1;			while(IS_SPACE(*ptr2))				ptr2++;			if(ptr2 != ptr+1)				PL_strcpy(ptr+1, ptr2);		}		PUSH_STRING ("Followup-To: ");		PUSH_STRING (n2);		PR_Free (n2);		PUSH_NEWLINE ();	}	if (pTo && *pTo) {		char *convbuf;		PUSH_STRING ("To: ");		convbuf = nsMsgI18NEncodeMimePartIIStr((char *)pTo, charset,										nsMsgMIMEGetConformToStandard());		if (convbuf) {     /* MIME-PartII conversion */			PUSH_STRING (convbuf);			PR_Free(convbuf);		}		else			PUSH_STRING (pTo);		PUSH_NEWLINE ();	} 	if (pCc && *pCc) {		char *convbuf;		PUSH_STRING ("CC: ");		convbuf = nsMsgI18NEncodeMimePartIIStr((char *)pCc, charset,										nsMsgMIMEGetConformToStandard());		if (convbuf) {   /* MIME-PartII conversion */			PUSH_STRING (convbuf);			PR_Free(convbuf);		}		else			PUSH_STRING (pCc);		PUSH_NEWLINE ();	}	if (pSubject && *pSubject) {    // alert the user if the subject contains characters out of charset range (e.g. multilingual data)    nsAutoString u; // need to convert from UTF-8 to UCS2    if (NS_OK == nsMsgI18NConvertToUnicode(nsCAutoString(msgCompHeaderInternalCharset()), nsCAutoString(pSubject), u) &&        !nsMsgI18Ncheck_data_in_charset_range(charset, u) &&        nsIMsgSend::nsMsgDeliverNow == deliver_mode) {      PRBool proceedTheSend;      rv = nsMsgAskBooleanQuestionByID(aPrompt, NS_MSG_MULTILINGUAL_SEND, &proceedTheSend);      if (!proceedTheSend) {        *status = NS_ERROR_BUT_DONT_SHOW_ALERT;        return nsnull;      }    }		char *convbuf;		PUSH_STRING ("Subject: ");		convbuf = nsMsgI18NEncodeMimePartIIStr((char *)pSubject, charset,										nsMsgMIMEGetConformToStandard());		if (convbuf) {  /* MIME-PartII conversion */			PUSH_STRING (convbuf);			PR_Free(convbuf);		}		else			PUSH_STRING (pSubject);		PUSH_NEWLINE ();	}		if (pPriority && *pPriority)		if (!PL_strcasestr(pPriority, "normal")) {			PUSH_STRING ("X-Priority: ");			/* Important: do not change the order of the 			* following if statements			*/			if (PL_strcasestr (pPriority, "highest"))				PUSH_STRING("1 (");			else if (PL_strcasestr(pPriority, "high"))				PUSH_STRING("2 (");			else if (PL_strcasestr(pPriority, "lowest"))				PUSH_STRING("5 (");			else if (PL_strcasestr(pPriority, "low"))				PUSH_STRING("4 (");			PUSH_STRING (pPriority);			PUSH_STRING(")");			PUSH_NEWLINE ();		}	if (pReference && *pReference) {		PUSH_STRING ("References: ");		if (PL_strlen(pReference) >= 986) {			char *references = PL_strdup(pReference);			char *trimAt = PL_strchr(references+1, '<');			char *ptr;			// per sfraser, RFC 1036 - a message header line should not exceed			// 998 characters including the header identifier			// retiring the earliest reference one after the other			// but keep the first one for proper threading			while (references && PL_strlen(references) >= 986 && trimAt) {				ptr = PL_strchr(trimAt+1, '<');				if (ptr)				  nsCRT::memmove(trimAt, ptr, PL_strlen(ptr)+1); // including the				else				  break;			}			NS_ASSERTION(references, "null references");			if (references) {			  PUSH_STRING (references);			  PR_Free(references);			}		}		else		  PUSH_STRING (pReference);		PUSH_NEWLINE ();	}	if (pOtherHdr && *pOtherHdr) {		/* Assume they already have the right newlines and continuations		 and so on. */		PUSH_STRING (pOtherHdr);	}	if (buffer_tail > buffer + size - 1)    return nsnull;	/* realloc it smaller... */	buffer = (char*)PR_REALLOC (buffer, buffer_tail - buffer + 1);	return buffer;}