tmp = '%'; *end = NULL;
tmp = '%'; *end = nsnull;
static void mime_text_attachment_url_exit (PrintSetup *p);static int mime_sanity_check_fields (const char *from,									 const char *reply_to,									 const char *to,									 const char *cc,									 const char *bcc,									 const char *fcc,									 const char *newsgroups,									 const char *followup_to,									 const char *subject,									 const char *references,									 const char *organization,									 const char *other_random_headers);static char *mime_generate_headers (nsMsgCompFields *fields,									int csid, 									MSG_Deliver_Mode deliver_mode);static char *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,											   MSG_DeliverMimeAttachment *ma,											   PRInt16 mail_csid);static char *RFC2231ParmFolding(const char *parmName, const char *charset,								const char *language, const char *parmValue);#if 0static PRBool mime_type_conversion_possible (const char *from_type,											  const char *to_type);#endif#ifdef XP_UNIXextern "C" void XFE_InitializePrintSetup (PrintSetup *p);#endif /* XP_UNIX *//*JFD extern "C"*/ char * NET_ExplainErrorDetails (int code, ...);MSG_DeliverMimeAttachment::MSG_DeliverMimeAttachment(){	m_url_string = NULL;	m_url = NULL;	m_done = PR_FALSE;	m_type = NULL;	m_override_type = NULL;	m_override_encoding = NULL;	m_desired_type = NULL;	m_description = NULL;	m_x_mac_type = NULL;	m_x_mac_creator = NULL;	m_encoding = NULL;	m_real_name = NULL;	m_mime_delivery_state = NULL;	m_encoding = NULL;	m_already_encoded_p = PR_FALSE;	m_file_name = NULL;	m_file = 0;#ifdef XP_MAC	m_ap_filename = NULL;#endif	m_decrypted_p = PR_FALSE;	m_size = 0;	m_unprintable_count = 0;	m_highbit_count = 0;	m_ctl_count = 0;	m_null_count = 0;	m_current_column = 0;	m_max_column = 0;	m_lines = 0;	m_encoder_data = NULL;//JFD  memset(&m_print_setup, 0, sizeof(m_print_setup));	m_graph_progress_started = PR_FALSE;}MSG_DeliverMimeAttachment::~MSG_DeliverMimeAttachment(){}   extern "C" char * mime_make_separator(const char *prefix){	unsigned char rand_buf[13]; 	RNG_GenerateGlobalRandomBytes((void *) rand_buf, 12);	return PR_smprintf("------------%s"					 "%02X%02X%02X%02X"					 "%02X%02X%02X%02X"					 "%02X%02X%02X%02X",					 prefix,					 rand_buf[0], rand_buf[1], rand_buf[2], rand_buf[3],					 rand_buf[4], rand_buf[5], rand_buf[6], rand_buf[7],					 rand_buf[8], rand_buf[9], rand_buf[10], rand_buf[11]);}PRBool MSG_DeliverMimeAttachment::UseUUEncode_p(void){	PRBool returnVal = (m_mime_delivery_state) && 	  					(m_mime_delivery_state->m_pane) &&	  					((nsMsgCompose*)(m_mime_delivery_state->m_pane))->				  		GetCompBoolHeader(MSG_UUENCODE_BINARY_BOOL_HEADER_MASK);		return returnVal;}static void msg_escape_file_name (URL_Struct *m_url) {    NS_ASSERTION (m_url->address && !PL_strncasecmp(m_url->address, "file:", 5), "Invalid URL type");	if (!m_url->address || PL_strncasecmp(m_url->address, "file:", 5))		return;	char * new_address = NET_Escape(PL_strchr(m_url->address, ':') + 1, URL_PATH);	NS_ASSERTION(new_address, "null ptr");	if (!new_address)		return;	PR_FREEIF(m_url->address);	m_url->address = PR_smprintf("file:%s", new_address);	PR_FREEIF(new_address);}// Returns a newly-allocated string containing the MIME type to be used for// outgoing attachments of the given document type.  The way this is determined// will be platform-specific, based on the real filename of the file (i.e. not the temp filename)// and some Mac creator info.// If there is no default specified in the prefs, then this returns NULL.static char *msg_GetMissionControlledOutgoingMIMEType(const char *filename,													  const char *x_mac_type,													  const char *x_mac_creator){	if (!filename)		return NULL;#ifdef XP_WIN	char *whereDot = PL_strrchr(filename, '.');	if (whereDot)	{		char *extension = whereDot + 1;		if (extension)		{			char *mcOutgoingMimeType = NULL;			char *prefString = PR_smprintf("mime.table.extension.%s.outgoing_default_type",extension);			if (prefString)			{				PREF_CopyCharPref(prefString, &mcOutgoingMimeType);				PR_Free(prefString);			}			return mcOutgoingMimeType;		}		else			return NULL;	// no file extension	}	else		return NULL;	// no file extension	#endif	return NULL;}static char *RFC2231ParmFolding(const char *parmName, const char *charset, 				   const char *language, const char *parmValue){#define PR_MAX_FOLDING_LEN 75			// this is to gurantee the folded line will								// never be greater than 78 = 75 + CRLFLWSP	char *foldedParm = NULL;	char *dupParm = NULL;	PRInt32 parmNameLen = 0;	PRInt32 parmValueLen = 0;	PRInt32 charsetLen = 0;	PRInt32 languageLen = 0;	PRBool needEscape = PR_FALSE;	NS_ASSERTION(parmName && *parmName && parmValue && *parmValue, "null parameters");	if (!parmName || !*parmName || !parmValue || !*parmValue)		return NULL;	if ((charset && *charset && PL_strcasecmp(charset, "us-ascii") != 0) || 		(language && *language && PL_strcasecmp(language, "en") != 0 &&		 PL_strcasecmp(language, "en-us") != 0))		needEscape = PR_TRUE;	if (needEscape)		dupParm = NET_Escape(parmValue, URL_PATH);	else 		dupParm = PL_strdup(parmValue);	if (!dupParm)		return NULL;	if (needEscape)	{		parmValueLen = PL_strlen(dupParm);		parmNameLen = PL_strlen(parmName);	}	if (needEscape)		parmNameLen += 5;		// *=__'__'___ or *[0]*=__'__'__ or *[1]*=___	else		parmNameLen += 5;		// *[0]="___";	charsetLen = charset ? PL_strlen(charset) : 0;	languageLen = language ? PL_strlen(language) : 0;	if ((parmValueLen + parmNameLen + charsetLen + languageLen) <		PR_MAX_FOLDING_LEN)	{		foldedParm = PL_strdup(parmName);		if (needEscape)		{			StrAllocCat(foldedParm, "*=");			if (charsetLen)				StrAllocCat(foldedParm, charset);			StrAllocCat(foldedParm, "'");			if (languageLen)				StrAllocCat(foldedParm, language);			StrAllocCat(foldedParm, "'");		}		else			StrAllocCat(foldedParm, "=\"");		StrAllocCat(foldedParm, dupParm);		if (!needEscape)			StrAllocCat(foldedParm, "\"");		goto done;	}	else	{		int curLineLen = 0;		int counter = 0;		char digits[32];		char *start = dupParm;		char *end = NULL;		char tmp = 0;		while (parmValueLen > 0)		{			curLineLen = 0;			if (counter == 0) {				PR_FREEIF(foldedParm)				foldedParm = PL_strdup(parmName);			}			else {				if (needEscape)					StrAllocCat(foldedParm, "\r\n ");				else					StrAllocCat(foldedParm, ";\r\n ");				StrAllocCat(foldedParm, parmName);			}			XP_SPRINTF(digits, "*%d", counter);			StrAllocCat(foldedParm, digits);			curLineLen += PL_strlen(digits);			if (needEscape)			{				StrAllocCat(foldedParm, "*=");				if (counter == 0)				{					if (charsetLen)						StrAllocCat(foldedParm, charset);					StrAllocCat(foldedParm, "'");					if (languageLen)						StrAllocCat(foldedParm, language);					StrAllocCat (foldedParm, "'");					curLineLen += charsetLen;					curLineLen += languageLen;				}			}			else			{				StrAllocCat(foldedParm, "=\"");			}			counter++;			curLineLen += parmNameLen;			if (parmValueLen <= PR_MAX_FOLDING_LEN - curLineLen)				end = start + parmValueLen;			else				end = start + (PR_MAX_FOLDING_LEN - curLineLen);			tmp = 0;			if (*end && needEscape)			{				// check to see if we are in the middle of escaped char				if (*end == '%')				{					tmp = '%'; *end = NULL;				}				else if (end-1 > start && *(end-1) == '%')				{					end -= 1; tmp = '%'; *end = NULL;				}				else if (end-2 > start && *(end-2) == '%')				{					end -= 2; tmp = '%'; *end = NULL;				}				else				{					tmp = *end; *end = NULL;				}			}			else			{				tmp = *end; *end = NULL;			}			StrAllocCat(foldedParm, start);			if (!needEscape)				StrAllocCat(foldedParm, "\"");			parmValueLen -= (end-start);			if (tmp)				*end = tmp;			start = end;		}	}done:	PR_FREEIF(dupParm);	return foldedParm;}PRInt32MSG_DeliverMimeAttachment::SnarfAttachment (){  PRInt32 status = 0;  NS_ASSERTION (! m_done, "Already done");  m_file_name = WH_TempName (xpFileToPost, "nsmail");  if (! m_file_name)	return (MK_OUT_OF_MEMORY);  m_file = XP_FileOpen (m_file_name, xpFileToPost, XP_FILE_WRITE_BIN);  if (! m_file)	return MK_UNABLE_TO_OPEN_TMP_FILE; /* #### how do we pass file name? */  m_url->fe_data = this;  /* #### m_type is still unknown at this point.	 We *really* need to find a way to make the textfe not blow	 up on documents that are not text/html!!   */   #ifdef XP_MAC  if (NET_IsLocalFileURL(m_url->address) &&	// do we need to add IMAP: to this list? NET_IsLocalFileURL returns PR_FALSE always for IMAP - DMB	  (PL_strncasecmp(m_url->address, "mailbox:", 8) != 0))	{	  /* convert the apple file to AppleDouble first, and then patch the		 address in the url.	   */	  char* src_filename = NET_GetLocalFileFromURL (m_url->address);		// ### mwelch Only use appledouble if we aren't uuencoding.	  if(isMacFile(src_filename) && (! UseUUEncode_p()))		{		  char	*separator, tmp[128];		  NET_StreamClass *ad_encode_stream;		  separator = mime_make_separator("ad");		  if (!separator)			return MK_OUT_OF_MEMORY;								  m_ap_filename  = WH_TempName (xpFileToPost, "nsmail");		  ad_encode_stream = (NET_StreamClass *)		/* need a prototype */			fe_MakeAppleDoubleEncodeStream (FO_CACHE_AND_MAIL_TO,											NULL,											m_url,											m_mime_delivery_state->GetContext(),											src_filename,											m_ap_filename,											separator,											m_real_name);		  if (ad_encode_stream == NULL)			{			  PR_FREEIF(separator);			  return MK_OUT_OF_MEMORY;			}		  do {			status = (*ad_encode_stream->put_block)			  (ad_encode_stream->data_object, NULL, 1024);		  } while (status == noErr);		  if (status >= 0)			ad_encode_stream->complete (ad_encode_stream->data_object);		  else			ad_encode_stream->abort (ad_encode_stream->data_object, status);		  PR_Free(ad_encode_stream);		  if (status < 0)			{			  PR_FREEIF(separator);			  return status;			}		  PR_Free(m_url->address);		  {		    char * temp = WH_FileName(m_ap_filename, xpFileToPost );		    m_url->address = XP_PlatformFileToURL(temp); // jrm 97/02/08			if (temp)				PR_Free(temp);		  }		  /* and also patch the types.		   */		  XP_SPRINTF(tmp, MULTIPART_APPLEDOUBLE ";\r\n boundary=\"%s\"",					 separator);		  PR_FREEIF(separator);		PR_FREIF (m_type);		m_type = PL_strdup(tmp);		}	  else		{			if (isMacFile(src_filename))			{				// The only time we want to send just the data fork of a two-fork				// Mac file is if uuencoding has been requested.				NS_ASSERTION(UseUUEncode_p(), "not UseUUEncode_p");				if (!((nsMsgCompose *) m_mime_delivery_state->m_pane)->m_confirmed_uuencode_p)				{					PRBool confirmed = FE_Confirm(m_mime_delivery_state->m_pane->GetContext(), 													XP_GetString(MK_MSG_MAC_PROMPT_UUENCODE)); 					// only want to do this once					((nsMsgCompose *) m_mime_delivery_state->m_pane)->m_confirmed_uuencode_p = PR_TRUE;										if (! confirmed) // cancelled						return MK_INTERRUPTED;				}			}		  /* make sure the file type and create are set.	*/		  char filetype[32];		  FSSpec fsSpec;		  FInfo info;		  Bool 	useDefault;		  char	*macType, *macEncoding;		  my_FSSpecFromPathname(src_filename, &fsSpec);		  if (FSpGetFInfo (&fsSpec, &info) == noErr)			{			  XP_SPRINTF(filetype, "%X", info.fdType);			  PR_FREEIF(m_x_mac_type);			  m_x_mac_type    = PL_strdup(filetype);			  XP_SPRINTF(filetype, "%X", info.fdCreator);			  PR_FREEIF(m_x_mac_creator);			  m_x_mac_creator = PL_strdup(filetype);			  if (m_type == NULL ||				  !PL_strcasecmp (m_type, TEXT_PLAIN))				{# define TEXT_TYPE	0x54455854  /* the characters 'T' 'E' 'X' 'T' */# define text_TYPE	0x74657874  /* the characters 't' 'e' 'x' 't' */				  if (info.fdType != TEXT_TYPE && info.fdType != text_TYPE)					{					  FE_FileType(m_url->address, &useDefault,								  &macType, &macEncoding);					  PR_FREEIF(m_type);					  m_type = macType;					}				}			}		  /* don't bother to set the types if we failed in getting the file			 info. */		}	  PR_FREEIF(src_filename);	  src_filename = 0;	}#else  /* if we are attaching a local file make sure the file name are escaped   * properly   */  if (NET_IsLocalFileURL(m_url->address) &&	  PL_strncasecmp (m_url->address, "file:", 5) == 0)   {	  msg_escape_file_name(m_url);  }#endif /* XP_MAC */  if (m_desired_type &&	  !PL_strcasecmp (m_desired_type, TEXT_PLAIN) /* #### &&	  mime_type_conversion_possible (m_type, m_desired_type) */ )	{	  /* Conversion to plain text desired.	   *//*JFD	  m_print_setup.url = m_url;	  m_print_setup.carg = this;	  m_print_setup.completion = mime_text_attachment_url_exit;	  m_print_setup.filename = NULL;	  m_print_setup.out = m_file;	  m_print_setup.eol = CRLF;JFD */	  PRInt32 width = 72;	  PREF_GetIntPref("mailnews.wraplength", &width);	  if (width == 0) width = 72;	  else if (width < 10) width = 10;	  else if (width > 30000) width = 30000;	  if (m_mime_delivery_state->m_pane->GetPaneType() == MSG_COMPOSITIONPANE)	  {		  int lineWidth = ((nsMsgCompose *) m_mime_delivery_state->m_pane)			  ->GetLineWidth();		  if (lineWidth > width)			  width = lineWidth;	  }/*JFD	  m_print_setup.width = width;	  m_url->savedData.FormList = 0;#ifdef _USRDLL	  if (! NDLLXL_TranslateText (m_mime_delivery_state->GetContext(), m_url,							&m_print_setup))		return MK_ATTACHMENT_LOAD_FAILED;#else	  if (! XL_TranslateText (m_mime_delivery_state->GetContext(), m_url,						&m_print_setup))		return MK_ATTACHMENT_LOAD_FAILED;#endifJFD */	  if (m_type) PR_Free (m_type);	  m_type = m_desired_type;	  m_desired_type = 0;	  if (m_encoding) PR_Free (m_encoding);	  m_encoding = 0;	}#ifdef XP_UNIX  else if (m_desired_type &&		   !PL_strcasecmp (m_desired_type, APPLICATION_POSTSCRIPT) /* #### &&		   mime_type_conversion_possible (m_type, m_desired_type) */ )	{      SHIST_SavedData saved_data;      /* Make sure layout saves the current state of form elements. */      LO_SaveFormData(m_mime_delivery_state->GetContext());      /* Hold on to the saved data. */      memcpy(&saved_data, &m_url->savedData, sizeof(SHIST_SavedData));	  /* Conversion to postscript desired.	   *//*JFD	  XFE_InitializePrintSetup (&m_print_setup);	  m_print_setup.url = m_url;	  m_print_setup.carg = this;	  m_print_setup.completion = mime_text_attachment_url_exit;	  m_print_setup.filename = NULL;	  m_print_setup.out = m_file;	  m_print_setup.eol = CRLF;      memset (&m_url->savedData, 0, sizeof (SHIST_SavedData));	  XL_TranslatePostscript (m_mime_delivery_state->GetContext(),							  m_url, &saved_data,							  &m_print_setup);JFD*/	  if (m_type) PR_Free (m_type);	  m_type = m_desired_type;	  m_desired_type = 0;	  if (m_encoding) PR_Free (m_encoding);	  m_encoding = 0;	}#endif /* XP_UNIX */  else	{	  m_url->allow_content_change = PR_FALSE;	// don't use modified content      if (NET_URL_Type (m_url->address) == NEWS_TYPE_URL && !m_url->msg_pane)		  m_url->msg_pane = m_mime_delivery_state->m_pane;/*JFD		  MSG_UrlQueue::AddUrlToPane(m_url, mime_attachment_url_exit,								 m_mime_delivery_state->m_pane, PR_TRUE,								 FO_CACHE_AND_MAIL_TO);JFD*/	  return 0;	}  return status;}static voidmime_attachment_url_exit (URL_Struct *url, int status, MWContext *context){  MSG_DeliverMimeAttachment *ma = (MSG_DeliverMimeAttachment *) url->fe_data;  NS_ASSERTION(ma != NULL, "not-null mime attachment");  if (ma != NULL)	ma->UrlExit(url, status, context);}void MSG_DeliverMimeAttachment::UrlExit(URL_Struct *url, int status,										MWContext *context){  char *error_msg = url->error_msg;  url->error_msg = 0;  url->fe_data = 0;  NS_ASSERTION(m_mime_delivery_state != NULL, "not-null m_mime_delivery_state");  NS_ASSERTION(m_mime_delivery_state->GetContext() != NULL, "not-null context");  NS_ASSERTION(m_url != NULL, "not-null m_url");  if (m_graph_progress_started)	{	  m_graph_progress_started = PR_FALSE;	  FE_GraphProgressDestroy (m_mime_delivery_state->GetContext(), m_url,							   m_url->content_length, m_size);	}  if (status < 0)	/* If any of the attachment URLs fail, kill them all. */	NET_InterruptWindow (context);  /* Close the file, but don't delete it (or the file name.) */  XP_FileClose (m_file);  m_file = 0;  NET_FreeURLStruct (m_url);  /* I'm pretty sure m_url == url */  m_url = 0;  url = 0;  if (status < 0) {	  if (m_mime_delivery_state->m_status >= 0)		m_mime_delivery_state->m_status = status;	  XP_FileRemove(m_file_name, xpFileToPost);	  PR_FREEIF(m_file_name);  }  m_done = PR_TRUE;  NS_ASSERTION (m_mime_delivery_state->m_attachment_pending_count > 0, "no more pending attachment");  m_mime_delivery_state->m_attachment_pending_count--;  if (status >= 0 && m_mime_delivery_state->m_be_synchronous_p)	{	  /* Find the next attachment which has not yet been loaded,		 if any, and start it going.	   */	  PRInt32 i;	  MSG_DeliverMimeAttachment *next = 0;	  for (i = 0; i < m_mime_delivery_state->m_attachment_count; i++)		if (!m_mime_delivery_state->m_attachments[i].m_done)		  {			next = &m_mime_delivery_state->m_attachments[i];			break;		  }	  if (next)		{		  int status = next->SnarfAttachment ();		  if (status < 0)			{			  m_mime_delivery_state->Fail(status, 0);			  return;			}		}	}  if (m_mime_delivery_state->m_attachment_pending_count == 0)	{	  /* If this is the last attachment, then either complete the		 delivery (if successful) or report the error by calling		 the exit routine and terminating the delivery.	   */	  if (status < 0)		{		  m_mime_delivery_state->Fail(status, error_msg);		  error_msg = 0;		}	  else		{		  m_mime_delivery_state->GatherMimeAttachments ();		}	}  else	{	  /* If this is not the last attachment, but it got an error,		 then report that error and continue (we won't actually		 abort the delivery until all the other pending URLs have		 caught up with the NET_InterruptWindow() we did up above.)	  if (status < 0 && error_msg)		FE_Alert (context, error_msg);	  */			  if (status < 0)		{		  m_mime_delivery_state->Fail(status, error_msg);		  error_msg = 0;		}	}  PR_FREEIF (error_msg);}voidMSG_DeliverMimeAttachment::AnalyzeDataChunk(const char *chunk, PRInt32 length){  unsigned char *s = (unsigned char *) chunk;  unsigned char *end = s + length;  for (; s < end; s++)	{	  if (*s > 126)		{		  m_highbit_count++;		  m_unprintable_count++;		}	  else if (*s < ' ' && *s != '\t' && *s != CR && *s != LF)		{		  m_unprintable_count++;		  m_ctl_count++;		  if (*s == 0)			m_null_count++;		}	  if (*s == CR || *s == LF)		{		  if (s+1 < end && s[0] == CR && s[1] == LF)			s++;		  if (m_max_column < m_current_column)			m_max_column = m_current_column;		  m_current_column = 0;		  m_lines++;		}	  else		{		  m_current_column++;		}	}}voidMSG_DeliverMimeAttachment::AnalyzeSnarfedFile(void){	char chunk[256];	XP_File fileHdl = NULL;	PRInt32 numRead = 0;		if (m_file_name && *m_file_name)	{		fileHdl = XP_FileOpen(m_file_name, xpFileToPost, XP_FILE_READ_BIN);		if (fileHdl)		{			do			{				numRead = XP_FileRead(chunk, 256, fileHdl);				if (numRead > 0)					AnalyzeDataChunk(chunk, numRead);			}			while (numRead > 0);			XP_FileClose(fileHdl);		}	}}static voidmime_text_attachment_url_exit (PrintSetup *p){#if 0 //JFD  MSG_DeliverMimeAttachment *ma = (MSG_DeliverMimeAttachment *) p->carg;  NS_ASSERTION (p->url == ma->m_url, "different url");  ma->m_url->fe_data = ma;  /* grr */  mime_attachment_url_exit (p->url, p->status,							ma->m_mime_delivery_state->GetContext());#endif //JFD}