n = msg_LineBuffer (ibuffer, n,
n = (PRInt32)msg_LineBuffer (ibuffer, n,
mime_do_fcc_1 (MSG_Pane *pane,			   const char *input_file_name,  XP_FileType input_file_type,			   const char *output_name, XP_FileType output_file_type,			   MSG_Deliver_Mode mode,			   const char *bcc_header,			   const char *fcc_header,			   const char *news_url){  int status = 0;  XP_File in = 0;  XP_File out = 0;  PRBool file_existed_p;  XP_StatStruct st;  char *ibuffer = 0;  int ibuffer_size = TEN_K;  char *obuffer = 0;  PRInt32 obuffer_size = 0, obuffer_fp = 0;  PRInt32 n;  PRBool summaryWasValid = PR_FALSE;  PRBool summaryIsValid = PR_FALSE;  PRBool mark_as_read = PR_TRUE;  ParseOutgoingMessage *outgoingParser = NULL;  MailDB	*mail_db = NULL;  nsresult err = NS_OK;  char *envelope;  char *output_file_name = NET_ParseURL(output_name, GET_PATH_PART);    if (!output_file_name || !*output_file_name) { // must be real file path	  PR_FREEIF(output_file_name);	  output_file_name = PL_strdup(output_name);  }  if (mode == MSG_QueueForLater)	FE_Progress (pane->GetContext(), XP_GetString(MK_MSG_QUEUEING));  else if ( mode == MSG_SaveAsDraft )	FE_Progress (pane->GetContext(), XP_GetString(MK_MSG_SAVING_AS_DRAFT));  else if ( mode == MSG_SaveAsTemplate )	FE_Progress (pane->GetContext(), XP_GetString(MK_MSG_SAVING_AS_TEMPLATE));  else	FE_Progress (pane->GetContext(), XP_GetString(MK_MSG_WRITING_TO_FCC));  ibuffer = NULL;  while (!ibuffer && (ibuffer_size >= 1024))  {	  ibuffer = (char *) PR_Malloc (ibuffer_size);	  if (!ibuffer)		  ibuffer_size /= 2;  }  if (!ibuffer)	{	  status = MK_OUT_OF_MEMORY;	  goto FAIL;	}  file_existed_p = !XP_Stat (output_file_name, &st, output_file_type);  if (file_existed_p)	{	  summaryWasValid = msg_IsSummaryValid(output_file_name, &st);	  if (!msg_ConfirmMailFile (pane->GetContext(), output_file_name))		{		  PR_FREEIF(output_file_name);		  return MK_INTERRUPTED; /* #### What a hack.  It turns out we already									were testing for this result code and									silently canceling the send if we ever got									it (because it meant that the user hit the									Stop button).  Returning it here has a									similar effect -- the user was asked to									confirm writing to the FCC folder, and he									hit the Cancel button, so we now quietly									do nothing. */		}	}  else	{	  pane->GetMaster()->FindMailFolder(output_file_name,										PR_TRUE /*createIfMissing*/);	  if (-1 == XP_Stat (output_file_name, &st, output_file_type))		FE_Alert (pane->GetContext(), XP_GetString(MK_MSG_CANT_CREATE_FOLDER));	}  out = XP_FileOpen (output_file_name, output_file_type, XP_FILE_APPEND_BIN);  if (!out)	{	  /* #### include file name in error message! */    /* Need to determine what type of operation failed and set status accordingly. Used to always return       MK_MSG_COULDNT_OPEN_FCC_FILE */    switch (mode)		{		case MSG_SaveAsDraft:			status = MK_MSG_UNABLE_TO_SAVE_DRAFT;			break;		case MSG_SaveAsTemplate:			status = MK_MSG_UNABLE_TO_SAVE_TEMPLATE;			break;		case MSG_DeliverNow:		default:			status = MK_MSG_COULDNT_OPEN_FCC_FILE;			break;		}	  goto FAIL;	}  in = XP_FileOpen (input_file_name, input_file_type, XP_FILE_READ_BIN);  if (!in)	{	  status = MK_UNABLE_TO_OPEN_FILE; /* rb -1; */ /* How did this happen? */	  goto FAIL;	}  // set up database and outbound message parser to keep db up to date.  outgoingParser = new ParseOutgoingMessage;  err = MailDB::Open(output_file_name, PR_FALSE, &mail_db);  if (err != NS_OK)	mail_db = NULL;  if (!outgoingParser)	{	  status = MK_OUT_OF_MEMORY;	  goto FAIL;	}  outgoingParser->SetOutFile(out);  outgoingParser->SetMailDB(mail_db);  outgoingParser->SetWriteToOutFile(PR_FALSE);  /* Write a BSD mailbox envelope line to the file.	 If the file existed, preceed it by a linebreak: this file format wants a	 *blank* line before all "From " lines except the first.  This assumes	 that the previous message in the file was properly closed, that is, that	 the last line in the file ended with a linebreak.   */  XP_FileSeek(out, 0, SEEK_END);  if (file_existed_p && st.st_size > 0)	{	  if (XP_FileWrite (LINEBREAK, LINEBREAK_LEN, out) < LINEBREAK_LEN)		{		  status = MK_MIME_ERROR_WRITING_FILE;		  goto FAIL;		}	}  outgoingParser->Init(XP_FileTell(out));  envelope = msg_GetDummyEnvelope();  if (msg_do_fcc_handle_line (envelope, PL_strlen (envelope), outgoingParser)	  < 0)	{	  status = MK_MIME_ERROR_WRITING_FILE;	  goto FAIL;	}  /* Write out an X-Mozilla-Status header.	 This is required for the queue file, so that we can overwrite it once	 the messages have been delivered, and so that the MSG_FLAG_QUEUED bit	 is set.	 For FCC files, we don't necessarily need one, but we might as well put	 one in so that it's marked as read already.   */  if (mode == MSG_QueueForLater ||	  mode == MSG_SaveAsDraft ||	  mode == MSG_SaveAsTemplate ||	  mark_as_read)	{	  char *buf = 0;	  PRUint16 flags = 0;	  mark_as_read = PR_TRUE;	  flags |= MSG_FLAG_READ;	  if (mode == MSG_QueueForLater )		flags |= MSG_FLAG_QUEUED;	  buf = PR_smprintf(X_MOZILLA_STATUS_FORMAT LINEBREAK, flags);	  if (buf)	  {		  status = msg_do_fcc_handle_line(buf, PL_strlen(buf), outgoingParser);		  PR_FREEIF(buf);		  if (status < 0)			goto FAIL;	  }	  	  PRUint32 flags2 = 0;	  if (mode == MSG_SaveAsTemplate)		  flags2 |= MSG_FLAG_TEMPLATE;	  buf = PR_smprintf(X_MOZILLA_STATUS2_FORMAT LINEBREAK, flags2);	  if (buf)	  {		  status = msg_do_fcc_handle_line(buf, PL_strlen(buf), outgoingParser);		  PR_FREEIF(buf);		  if (status < 0)			  goto FAIL;	  }	}  /* Write out the FCC and BCC headers.	 When writing to the Queue file, we *must* write the FCC and BCC	 headers, or else that information would be lost.  Because, when actually	 delivering the message (with "deliver now") we do FCC/BCC right away;	 but when queueing for later delivery, we do FCC/BCC at delivery-time.	 The question remains of whether FCC and BCC should be written into normal	 BCC folders (like the Sent Mail folder.)	 For FCC, there seems no point to do that; it's not information that one	 would want to refer back to.	 For BCC, the question isn't as clear.  On the one hand, if I send someone	 a BCC'ed copy of the message, and save a copy of it for myself (with FCC)	 I might want to be able to look at that message later and see the list of	 people to whom I had BCC'ed it.	 On the other hand, the contents of the BCC header is sensitive	 information, and should perhaps not be stored at all.	 Thus the consultation of the #define SAVE_BCC_IN_FCC_FILE.	 (Note that, if there is a BCC header present in a message in some random	 folder, and that message is forwarded to someone, then the attachment	 code will strip out the BCC header before forwarding it.)   */  if ((mode == MSG_QueueForLater ||	   mode == MSG_SaveAsDraft ||	   mode == MSG_SaveAsTemplate) &&	  fcc_header && *fcc_header)	{	  PRInt32 L = PL_strlen(fcc_header) + 20;	  char *buf = (char *) PR_Malloc (L);	  if (!buf)		{		  status = MK_OUT_OF_MEMORY;		  goto FAIL;		}	  PR_snprintf(buf, L-1, "FCC: %s" LINEBREAK, fcc_header);	  status = msg_do_fcc_handle_line(buf, PL_strlen(buf), outgoingParser);	  if (status < 0)		goto FAIL;	}  if (bcc_header && *bcc_header#ifndef SAVE_BCC_IN_FCC_FILE	  && (mode == MSG_QueueForLater ||		  mode == MSG_SaveAsDraft ||		  mode == MSG_SaveAsTemplate)#endif	  )	{	  PRInt32 L = PL_strlen(bcc_header) + 20;	  char *buf = (char *) PR_Malloc (L);	  if (!buf)		{		  status = MK_OUT_OF_MEMORY;		  goto FAIL;		}	  PR_snprintf(buf, L-1, "BCC: %s" LINEBREAK, bcc_header);	  status = msg_do_fcc_handle_line(buf, PL_strlen(buf), outgoingParser);	  if (status < 0)		goto FAIL;	}  /* Write out the X-Mozilla-News-Host header.	 This is done only when writing to the queue file, not the FCC file.	 We need this to complement the "Newsgroups" header for the case of	 queueing a message for a non-default news host.	 Convert a URL like "snews://host:123/" to the form "host:123/secure"	 or "news://user@host:222" to simply "host:222".   */  if ((mode == MSG_QueueForLater ||	   mode == MSG_SaveAsDraft ||	   mode == MSG_SaveAsTemplate) && news_url && *news_url)	{	  PRBool secure_p = (news_url[0] == 's' || news_url[0] == 'S');	  char *orig_hap = NET_ParseURL (news_url, GET_HOST_PART);	  char *host_and_port = orig_hap;	  if (host_and_port)		{		  /* There may be authinfo at the front of the host - it could be of			 the form "user:password@host:port", so take off everything before			 the first at-sign.  We don't want to store authinfo in the queue			 folder, I guess, but would want it to be re-prompted-for at			 delivery-time.		   */		  char *at = PL_strchr (host_and_port, '@');		  if (at)			host_and_port = at + 1;		}	  if ((host_and_port && *host_and_port) || !secure_p)		{		  char *line = PR_smprintf(X_MOZILLA_NEWSHOST ": %s%s" LINEBREAK,								   host_and_port ? host_and_port : "",								   secure_p ? "/secure" : "");		  PR_FREEIF(orig_hap);		  orig_hap = 0;		  if (!line)			{			  status = MK_OUT_OF_MEMORY;			  goto FAIL;			}		  status = msg_do_fcc_handle_line(line, PL_strlen(line),										  outgoingParser);		  PR_FREEIF(line);		  if (status < 0)			goto FAIL;		}	  PR_FREEIF(orig_hap);	  orig_hap = 0;	}  /* Read from the message file, and write to the FCC or Queue file.	 There are two tricky parts: the first is that the message file	 uses CRLF, and the FCC file should use LINEBREAK.  The second	 is that the message file may have lines beginning with "From "	 but the FCC file must have those lines mangled.	 It's unfortunate that we end up writing the FCC file a line	 at a time, but it's the easiest way...   */  while (1)	{	  n = XP_FileRead (ibuffer, ibuffer_size, in);	  if (n == 0)		break;	  if (n < 0) /* read failed (not eof) */		{		  status = n;		  goto FAIL;		}	  n = msg_LineBuffer (ibuffer, n,						  &obuffer, (PRUint32 *)&obuffer_size,						  (PRUint32*)&obuffer_fp,						  PR_TRUE, msg_do_fcc_handle_line,						  outgoingParser);	  if (n < 0) /* write failed */		{		  status = n;		  goto FAIL;		}	}  /* If there's still stuff in the buffer (meaning the last line had no	 newline) push it out. */  if (obuffer_fp > 0)	msg_do_fcc_handle_line (obuffer, obuffer_fp, outgoingParser);  /* Terminate with a final newline. */  if (XP_FileWrite (LINEBREAK, LINEBREAK_LEN, out) < LINEBREAK_LEN)  {	  status = MK_MIME_ERROR_WRITING_FILE;  }  else	outgoingParser->AdvanceOutPosition(LINEBREAK_LEN);  if (mail_db != NULL && outgoingParser != NULL &&	  outgoingParser->m_newMsgHdr != NULL)	{	  outgoingParser->FinishHeader();	  mail_db->AddHdrToDB(outgoingParser->m_newMsgHdr, NULL, PR_TRUE);	  if (summaryWasValid)		summaryIsValid = PR_TRUE;	} FAIL:  if (ibuffer)	PR_Free (ibuffer);  if (obuffer && obuffer != ibuffer)	PR_Free (obuffer);  if (in)	XP_FileClose (in);  if (out)	{	  if (status >= 0)		{		  XP_FileClose (out);		  if (summaryIsValid) {			msg_SetSummaryValid(output_file_name, 0, 0);                  }		}	  else if (! file_existed_p)		{		  XP_FileClose (out);		  XP_FileRemove (output_file_name, output_file_type);		}	  else		{		  XP_FileClose (out);		  XP_FileTruncate (output_file_name, output_file_type, st.st_size);	/* restore original size */		}	}  if (mail_db != NULL && status >= 0) {	if ( mode == MSG_SaveAsDraft || mode == MSG_SaveAsTemplate )	{		MSG_PostDeliveryActionInfo *actionInfo =		  pane->GetPostDeliveryActionInfo();		if (actionInfo) {/*JFD		  if (actionInfo->m_flags & MSG_FLAG_EXPUNGED &&			  actionInfo->m_msgKeyArray.GetSize() >= 1) {			mail_db->DeleteMessage(actionInfo->m_msgKeyArray.GetAt(0));			actionInfo->m_msgKeyArray.RemoveAt(0);		  }*/		}		else {		  actionInfo = new MSG_PostDeliveryActionInfo((MSG_FolderInfo*)			pane->GetMaster()->			FindMailFolder(output_file_name, PR_TRUE));		  if (actionInfo) {			actionInfo->m_flags |= MSG_FLAG_EXPUNGED;			pane->SetPostDeliveryActionInfo(actionInfo);		  }		}/*JFD		if (outgoingParser->m_newMsgHdr && actionInfo)		  actionInfo->m_msgKeyArray.Add(outgoingParser->m_newMsgHdr->GetMessageKey());*/	}	mail_db->Close();  }  PR_FREEIF(output_file_name);  delete outgoingParser;  if (status < 0)	{	  /* Fail, and terminate. */	  return status;	}  else	{	  /* Otherwise, continue on to _deliver_as_mail or _deliver_as_news		 or mime_queue_for_later. */	  return 0;	}}