/* post an article */
/* Copyright (c) 1998 John E. Davis (davis@space.mit.edu)
 *
 * This file is part of slrn.
 *
 * Slrn is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 * 
 * Slrn is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Slrn; see the file COPYING.  If not, write to the Free
 * Software Foundation, 59 Temple Place - Suite 330, 
 * Boston, MA  02111-1307, USA.
 */

#include "config.h"
#include "slrnfeat.h"

#include <stdio.h>
#include <string.h>


#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif

#include <sys/types.h>
#include <time.h>
#include <slang.h>
#include "jdmacros.h"


#ifdef VMS
# include "vms.h"
#endif

#include "slrn.h"
#include "server.h"
#include "misc.h"
#include "post.h"
#include "group.h"
#include "art.h"
#include "uudecode.h"
#include "util.h"
#include "chmap.h"
#include "menu.h"

#if SLRN_HAS_MIME
# include "mime.h"
#endif

char *Slrn_Courtesy_CC_Message = NULL;
char *Slrn_Save_Posts_File;
char *Slrn_Save_Replies_File;
char *Slrn_Last_Message_Id;
char *Slrn_Post_Custom_Headers;
int Slrn_Reject_Long_Lines = 1;
char *Slrn_Postpone_Dir;
int Slrn_Generate_Message_Id = 1;

#ifdef VMS
# define SYSTEM_OS_NAME		"VMS"
#else
# ifdef __os2__
#  define SYSTEM_OS_NAME	"OS/2"
# else
#  ifdef AMIGA
#   define SYSTEM_OS_NAME	"Amiga"
#  else
#   ifdef __unix__
#    define SYSTEM_OS_NAME       "UNIX"
#   else
#    if defined(__WIN32__) || defined(__NT__)
#     define SYSTEM_OS_NAME	"Windows"
#    else
#     define SYSTEM_OS_NAME	"UNKNOWN"
#    endif
#   endif
#  endif
# endif
#endif

static int postpone_file (char *);

#if SLRN_HAS_GEN_MSGID
static char *slrn_create_message_id (void)
{
   unsigned long pid, now;
   static unsigned char baseid[64];
   unsigned char *b, *t, tmp[32];
   char *chars32 = "0123456789abcdefghijklmnopqrstuv";
   static unsigned long last_now;
   
   if (Slrn_Generate_Message_Id == 0)
     return NULL;

   while (1)
     {
	if ((Slrn_User_Info.posting_host == NULL)
	    || ((time_t) -1 == time ((time_t *)&now)))
	  return NULL;
	
	if (now != last_now) break;
	sleep (1);
     }
   last_now = now;
   
   pid = (unsigned long) getpid ();
   now -= 0x28000000;
   
   b = baseid;
   t = tmp;
   while (now)
     {
	*t++ = chars32[now & 0x1F];
	now = now >> 5;
     }
   while (t > tmp)
     {
	t--;
	*b++ = *t;
     }
   *b++ = '.';
   
   t = tmp;
   while (pid)
     {
	*t++ = chars32[pid & 0x1F];
	pid = pid >> 5;
     }
   while (t > tmp)
     {
	t--;
	*b++ = *t;
     }
   
   *b++ = '.';
   t = (unsigned char *) Slrn_User_Info.username;
   if (t != NULL)
     while ((*t != 0) && (b < baseid + sizeof(baseid) - 1)) *b++ = *t++;
   *b = 0;
   
   return (char *) baseid;
}
#endif
void slrn_add_signature (FILE *fp)
{
   FILE *sfp;
   char file[SLRN_MAX_PATH_LEN];
   char buf [256];
   
   if ((sfp = slrn_open_home_file (Slrn_User_Info.signature, "r", file, 0)) != NULL)
     {
	/* Apparantly some RFC suggests the -- \n. */
        fputs ("\n\n-- \n", fp);
	
	/* If signature file already has -- \n, do not add it. */
	if ((NULL != fgets (buf, sizeof (buf), sfp))
	    && (0 != strcmp (buf, "-- \n")))
	  fputs (buf, fp);
	  
        while (NULL != fgets (buf, sizeof(buf), sfp))
	  {
	     fputs (buf, fp);
	  }
        slrn_fclose(sfp);
     }
}

static int is_empty_header (char *line)
{
   char *b;
   
   if ((*line == ' ') || (*line == '\t')) return 0;
   
   b = slrn_strchr (line, ':');
   if (b == NULL) return 0;
   
   b = slrn_skip_whitespace (b + 1);
   return (*b == 0);
}


static int slrn_cc_file (char *file, char *to, char *msgid)
{
#if defined(VMS) || !SLRN_HAS_PIPING
   return -1;
#else
#if defined(IBMPC_SYSTEM)
   char outfile [SLRN_MAX_PATH_LEN];
#endif
   FILE *pp, *fp;
   char line[1024];
   unsigned int cc_line = 0;
   unsigned int linenum;
   char buf [1024];
   unsigned int nth;
   char *l;

   if (NULL == (fp = fopen (file, "r")))
     {
	slrn_error ("Unable to open %s.");
	return -1;
     }
   
   /* Look for CC line */
   linenum = 0;
   while ((NULL != fgets (line, sizeof (line) - 1, fp)) && (*line != '\n'))
     {
	linenum++;
	if (0 == slrn_case_strncmp ((unsigned char *)line,
				    (unsigned char *) "Cc: ", 4))
	  {
	     l = slrn_skip_whitespace (line + 4);
	     if (*l && (*l != ',')) cc_line = linenum;
	     break;
	  }
     }
   
   /* At this point, if all has gone well line contains the cc information */
   
   if (cc_line == 0)
     {
	slrn_fclose (fp);
	return -1;
     }
   
#if defined(IBMPC_SYSTEM)
   pp = slrn_open_tmpfile (outfile, "w");
#else
   pp = slrn_popen (Slrn_SendMail_Command, "w");
#endif
   if (pp == NULL)
     {
	slrn_fclose (fp);
	return -1;
     }
   
   fputs ("To: ", pp);
   
   /* This line consists of a comma separated list of addresses.  In
    * particular, "poster" will be replaced by 'to'.
    */
   l = line + 4;
   nth = 0;
   while (0 == SLextract_list_element (l, nth, ',', buf, sizeof (buf)))
     {
	char *b;

	/* Knock whitespace from ends of string */
	b = slrn_skip_whitespace (buf);
	slrn_trim_string (b);

	if (nth != 0)
	  putc (',', pp);
	
	if ((0 == slrn_case_strcmp ((unsigned char *)b, (unsigned char *)"poster"))
	    && (to != NULL))
	  b = to;
	
	fputs (b, pp);
	nth++;
     }

   putc ('\n', pp);
   rewind (fp);

   linenum = 0;
   
#if SLRN_GEN_FROM_EMAIL_HEADER
   fprintf (pp, "From: %s@%s (%s)\n",
            Slrn_User_Info.username, Slrn_User_Info.host,
            ((Slrn_User_Info.realname == NULL) ? "" : Slrn_User_Info.realname));
#endif
   
   if (msgid != NULL)
     fprintf (pp, "Message-Id: <slrn%s@%s>\n", 
	      msgid, Slrn_User_Info.posting_host);
   
   
   while ((NULL != fgets (line, sizeof (line) - 1, fp)) && (*line != '\n'))
     {
	linenum++;
	if (linenum == cc_line) continue;
	if (is_empty_header (line)) continue;
	if (0 == slrn_case_strncmp ((unsigned char *)line,
				    (unsigned char *) "To: ", 4))
	  continue;
	
	/* There is some discussion of this extension to mail headers.  For
	 * now, assume that this extension will be adopted.
	 */
	if (0 == slrn_case_strncmp ((unsigned char *)line,
				    (unsigned char *) "Newsgroups: ", 12))
	  {
	     fputs ("Posted-To: ", pp);
	     fputs (line + 12, pp);
	  }
	else
	  fputs (line, pp);
     }

# if SLRN_HAS_MIME
   if (Slrn_Use_Mime) slrn_mime_add_headers (pp);
# endif
   
   fputs ("\n", pp);
   
   if ((NULL != Slrn_Courtesy_CC_Message) && (*Slrn_Courtesy_CC_Message))
     {
	slrn_insert_followup_format (Slrn_Courtesy_CC_Message, pp);
	fputs ("\n", pp);
     }
   
# if SLRN_HAS_MIME
   if (Slrn_Use_Mime) fp = slrn_mime_encode (fp);
# endif
   
   while (NULL != fgets (line, sizeof (line) - 1, fp))
     {
	fputs (line, pp);
     }
   slrn_fclose (fp);
# if defined(IBMPC_SYSTEM)
   slrn_fclose (pp);
   sprintf (buf, "%s %s", Slrn_SendMail_Command, outfile);
   slrn_posix_system (buf, 0);
# else
   slrn_pclose (pp);
# endif
   return 0;
#endif				       /* NOT VMS */
}

/* Returns -1 upon error, 0, if ok, 1 if needs repair, 2 is warning is issued */
static int check_file_for_posting (char *file)
{
   char line[1024], *the_line;
   FILE *fp;
   unsigned int num;
   char *err;
   int newsgroups_found, subject_found, only_warning;
   char ch;
   char *colon;
   
   only_warning = newsgroups_found = subject_found = 0;
   err = NULL;
   fp = fopen (file, "r");
   
   if (fp == NULL)
     {
	slrn_error ("Unable to open %s", file);
	return -1;
     }
   
   the_line = line;
   
   /* scan the header */
   num = 0;
   while (NULL != fgets (line, sizeof (line), fp))
     {
	ch = *line;	
	num++;
	if ((ch == ' ') || (ch == '\t') || (ch == '\n'))
	  {
	     if (num == 1) 
	       {
		  err = "The first line must begin with a header.";
		  break;
	       }
	     if (ch == '\n') break;
	     
	     continue;
	  }
	
	if (NULL == (colon = slrn_strchr (line, ':')))
	  {
	     err = "Expecting a header.  This is not a header line.";
	     break;
	  }
	
	if (!slrn_case_strncmp ((unsigned char *) line, (unsigned char *) "Subject:", 8))
	  {
	     if (is_empty_header (line))
	       {
		  err = "The subject header is not allowed be to empty.";
		  break;
	       }
	     subject_found = 1;
	     continue;
	  }
	
	if (!slrn_case_strncmp ((unsigned char *) line, (unsigned char *) "Newsgroups:", 11))
	  {
	     if (is_empty_header (line)) 
	       {
		  err = "The Newsgroups header is not allowed be to empty.";
		  break;
	       }
	     newsgroups_found = 1;
	     continue;
	  }
	
	/* slrn will remove it later if it is empty */
	if (is_empty_header (line)) continue;
	
	if (*(colon + 1) != ' ') 
	  {
	     err = "A space must follow the ':' in a header";
	     break;
	  }
	
	if (!slrn_case_strncmp ((unsigned char *) line, (unsigned char *) "From:", 5))
	  {
	     err = "This news reader will not accept user generated From lines.";
	     break;
	  }
     }

   if (err == NULL) 
     {
	if (subject_found == 0) 
	  {
	     err = "Subject header is required.";
	     num = 0;
	  }
	else if (newsgroups_found == 0)
	  {
	     err = "Newsgroups header is required.";
	     num = 0;
	  }
     }
   
   /* Now body.  Check for non-quoted lines. */
   if (err == NULL) 
     {
	char *qs = Slrn_Quote_String;
	unsigned int qlen;
	
	if (qs == NULL) qs = ">";
	qlen = strlen (qs);
	
	err = "Your message does not appear to have any unquoted text.";
	the_line = NULL;
	while (NULL != fgets (line, sizeof (line), fp))
	  {
	     num++;
	     if (!strncmp (line, qs, qlen))
	       continue;
	     
	     colon = slrn_skip_whitespace (line);
	     if (*colon == 0) continue;
	     
	     err = NULL;
	     if (Slrn_Reject_Long_Lines == 0)
	       break;
	     
	     if (strlen (line) > 81)   /* allow \n to slip */
	       {
		  err = "Line contains more than 80 characters.  You need to wrap it.";
		  the_line = line;
		  if (Slrn_Reject_Long_Lines == 2)
		    only_warning = 1;
		  break;
	       }
	  }
     }
   
   fclose (fp);

   if (err == NULL) return 0;
   
   if (Slrn_Batch)
     {
	slrn_error ("Message is not acceptable.");
	if (err != NULL) slrn_error ("Reason: %s", err);
	return -1;
     }
	  
   Slrn_Full_Screen_Update = 1;

   slrn_set_color (0);
   
   SLsmg_cls ();
   SLsmg_gotorc (2,0);
   slrn_set_color (SUBJECT_COLOR);
   SLsmg_write_string ("Your message is not acceptable for the following reason:");
   slrn_set_color (ERROR_COLOR);
   SLsmg_gotorc (4,8); SLsmg_write_string (err);
   if (num && (the_line != NULL))
     {
	SLsmg_gotorc (6,0);
	slrn_set_color (SUBJECT_COLOR);
	SLsmg_printf ("This message was generated while looking at line %d:", num);
	SLsmg_gotorc (8,0);
	slrn_set_color (QUOTE_COLOR);
	SLsmg_write_string (the_line);
	SLsmg_gotorc (12, 0);
	slrn_set_color (ARTICLE_COLOR);
	SLsmg_write_string ("Perhaps this error was generated because you did not separate the header");
	SLsmg_gotorc (13, 0);
	SLsmg_write_string ("section from the body by a BLANK line.");
     }
   
   if (only_warning) return 2;
   return 1;
}


int slrn_save_file_to_mail_file (char *file, char *save_file, char *msgid)
{
   FILE *infp, *outfp;
   time_t now;
   char save_post_file[SLRN_MAX_PATH_LEN];
   char line [1024];

   if ((save_file == NULL) || (*save_file == 0))
     return 0;
	
   if (NULL == (infp = fopen (file, "r")))
     {
	slrn_error ("File not found: %s--- message not posted.", file);
	return -1;
     }
	
   if (NULL == (outfp = slrn_open_home_file (save_file, "a",
					     save_post_file, 1)))
     {
	slrn_error ("Error saving to %s", save_post_file);
	slrn_fclose (infp);
	return -1;
     }
	
   time (&now);
   fprintf (outfp, "From %s@%s %s", Slrn_User_Info.username, Slrn_User_Info.host, ctime(&now));
   fprintf (outfp, "From: %s@%s (%s)\n", Slrn_User_Info.username, Slrn_User_Info.host, Slrn_User_Info.realname);
   if (msgid != NULL) fprintf (outfp, "Message-Id: <slrn%s@%s>\n", msgid, Slrn_User_Info.posting_host);

   while (NULL != fgets (line, sizeof(line) - 1, infp))
     {
	if ((*line == 'F')
	    && !strncmp ("From", line, 4)
	    && ((unsigned char)line[4] <= ' '))
	  {
	     putc ('>', outfp);
	  }
	
	fputs (line, outfp);
     }
   fputs ("\n\n", outfp);	       /* separator */
   slrn_fclose (infp);
   return slrn_fclose (outfp);
}

static int post_references_header (char *line)
{
#define GNKSA_LENGTH 998
   char buf[GNKSA_LENGTH + 1];
   char *p;
   unsigned int total_len, len;

   /* Make sure line does not end in whitespace */
   (void) slrn_trim_string (line);
   
   len = strlen (line);
   if (len <= GNKSA_LENGTH)
     {
	Slrn_Post_Obj->po_puts (line);
	Slrn_Post_Obj->po_puts ("\n");
	return 0;
     }

   /* The reference header is too long so start truncating */
   /* We have to preserve the first message-id */
   p = slrn_strchr (line, '>');
   if (p == NULL) return -1;
   p++;
   len = p - line;
   if (len >= GNKSA_LENGTH)
     {
	/* Must have been generated by Pine */
	Slrn_Post_Obj->po_puts (line);
	Slrn_Post_Obj->po_puts ("\n");
	return 0;
     }
   strncpy (buf, line, len);
   buf[len] = 0;
   Slrn_Post_Obj->po_puts (buf);
   Slrn_Post_Obj->po_puts (" ");
   total_len = len + 1;
   
   line += len;
   if ((*line == '\t') || (*line == ' ')) 
     line++;	       /* already handled space */

   /* Now use message-ids at end of the line */
   p = line + strlen (line);

   while (1)
     {
	if (*p == '<')
	  {
	     if (strlen (p) + total_len > GNKSA_LENGTH)
	       {
		  p = slrn_strchr (p + 1, '<');
		  if (p == NULL) p = line;
		  break;
	       }
	  }
	if (p == line) break;
	p--;
     }
   
   Slrn_Post_Obj->po_puts (p);
   Slrn_Post_Obj->po_puts ("\n");
   return 0;
}


/* This function returns 1 if postponed, 0 upon sucess, -1 upon error */
int slrn_post_file (char *file, char *to, int is_postponed)
{
   char line[1024], *linep;
   int len, header;
   FILE *fp;
   int rsp;
   int perform_cc;
   int status;
   char *msgid = NULL;
#if SLRN_HAS_GEN_MSGID
   int has_messageid = 0;
#endif
#if SLRN_HAS_SLANG
   SLang_Name_Type *filter_hook;
#endif
   int once_more;
   
#if SLRN_HAS_SLANG
   filter_hook = SLang_get_function ("post_filter_hook");
#endif

   try_again:

   perform_cc = 0;
   once_more = 1;

   if (Slrn_Batch == 0) while (once_more)
     {
#if SLRN_HAS_SLANG
	if (filter_hook != NULL)
	  {
	     if (is_postponed)
	       rsp = slrn_get_response ("yYnNeEsSDdFf", "Post the message? \001Yes, \001No, \001Edit, po\001Stpone, \001Delete, \001Filter");
	     else
	       rsp = slrn_get_response ("yYnNeEsSFf", "Post the message? \001Yes, \001No, \001Edit, po\001Stpone, \001Filter");
	  }
	else
	  {
#endif
	     if (is_postponed)
	       rsp = slrn_get_response ("yYnNeEsSDd", "Post the message? \001Yes, \001No, \001Edit, po\001Stpone, \001Delete");
	     else
	       rsp = slrn_get_response ("yYnNeEsS", "Post the message? \001Yes, \001No, \001Edit, po\001Stpone");
#if SLRN_HAS_SLANG
	  }
#endif
	switch (rsp)
	  {
	   case 'n':
	   case 'N':
	     return -1;
	     
	   case 's':
	   case 'S':
	     
	     if (is_postponed
		 || (0 == postpone_file (file)))
	       return 1;

	     /* Instead of returning, let user have another go at it */
	     /* return -1; */
	     break;
	     
	   case 'd':
	   case 'D':
	     rsp = slrn_get_yesno_cancel ("Sure you want to delete it");
	     if (rsp == 0)
	       continue;
	     if (rsp == -1)
	       return 1;
	     /* Calling routine will delete it. */
	     return 0;
	  
	   case 'y': case 'Y':
	     if (0 == (rsp = check_file_for_posting (file)))
	       {
		  once_more = 0;
		  break;
	       }
	     if (rsp == -1)
	       return -1;
	     
	     SLtt_beep ();
	     if (rsp == 1)
	       rsp = slrn_get_response ("yYEenNcC\007", "re-\001Edit,  or \001Cancel");
	     else
	       rsp = slrn_get_response ("EeyYnNcC\007Ff", "re-\001Edit, \001Cancel, or \001Force the posting (not recommended)");
	     
	     switch (rsp)
	       {
		case 'y': case 'Y': case 'E': case 'e':
		  rsp = 'y';
		  break;
		  
		case 'c': case 'C': case 7:
		  return -1;
		  
		case 'F': case 'f':
		  once_more = 0;
	       }

	     if (rsp != 'y')
	       break;
	     
	     /* Drop */
	     
	   case 'e':
	   case 'E':
	     if (slrn_edit_file (Slrn_Editor_Post, file, 1) < 0) 
	       {
		  slrn_error ("User abort.");
		  return -1;
	       }
	     break;

#if SLRN_HAS_SLANG
	   case 'F':
	   case 'f':
	     if (filter_hook != NULL)
	       {
		  SLang_push_string (file);
		  if (SLang_Error == 0)
		    SLexecute_function (filter_hook);
		  if (SLang_Error) 
		    filter_hook = NULL;
	       }
#endif
	  }
     }
   
   slrn_message_now ("Posting ...");
   
#if SLRN_HAS_GEN_MSGID
   msgid = slrn_create_message_id ();
#endif

   if (-1 == slrn_save_file_to_mail_file (file, Slrn_Save_Posts_File, msgid))
     return -1;

   slrn_chmap_fix_file (file);

   if ((fp = fopen (file, "r")) == NULL)
     {
	slrn_error ("File not found: %s--- message not posted.", file);
	return -1;
     }
   
#if SLRN_HAS_MIME
   if (Slrn_Use_Mime)
     slrn_mime_scan_file (fp);
#endif
#if SLRN_HAS_SLANG
   if (NULL != SLang_get_function ("post_file_hook"))
     {
	fclose (fp);
	(void) SLang_run_hooks ("post_file_hook", 1, file);
	if (SLang_Error)
	  {
	     slrn_error ("post_file_hook returned error.  %s not posted.", file);
	     return -1;
	  }

	if ((fp = fopen (file, "r")) == NULL)
	  {
	     slrn_error ("File not found: %s--- message not posted.", file);
	     return -1;
	  }
	slrn_message_now ("Posting ...");
     }
#endif

   /* slrn_set_suspension (1); */
   status = Slrn_Post_Obj->po_start ();
   if (status != CONT_POST)
     {
	/* FIXME!! Put the file in a known place, e.g., dead.letter */
	if (status != -1)
	  slrn_error ("Posting not allowed.");
	return -1;
     }
   
   if (Slrn_User_Info.username != NULL)
     Slrn_Post_Obj->po_printf ("Path: %s\n", Slrn_User_Info.username);
   
   Slrn_Post_Obj->po_printf ("From: %s@%s (%s)\n", Slrn_User_Info.username, Slrn_User_Info.host, Slrn_User_Info.realname);
   /* if (Slrn_User_Info.posting_host != NULL)
     * Slrn_Post_Obj->po_printf ("X-Posting-Host: %s\n", Slrn_User_Info.posting_host); */

   linep = line + 1;
   header = 1;
   while (fgets (linep, sizeof(line) - 1, fp) != NULL)
     {
	len = strlen (linep);
	if (len == 0) continue;

	if (header)
	  {
	     unsigned char *b;
	     char *white = linep;

	     /* Check the references header.  Rumor has it that many
	      * servers choke on long references lines.  In fact, to be
	      * GNKSA compliant, references headers cannot be longer than
	      * 998 characters.  Sigh.
	      */

	     if (((*white == 'R') || (*white == 'r'))
		 && (0 == slrn_case_strncmp ((unsigned char *)"References: ",
					     (unsigned char *)white,
					     12)))
	       {
		  (void) post_references_header (white);
		  continue;
	       }

	     while ((*white == ' ') || (*white == '\t')) white++;

	     if (*white == '\n')
	       {
#if SLRN_HAS_GEN_MSGID
		  if (has_messageid == 0)
		    {
		       Slrn_Last_Message_Id = msgid;
		       if (msgid != NULL)
			 {
			    Slrn_Post_Obj->po_printf ("Message-Id: <slrn%s@%s>\n", msgid, Slrn_User_Info.posting_host);
			 }
		    }
#endif
#if SLRN_HAS_MIME
		  if (Slrn_Use_Mime)
		    slrn_mime_add_headers (0);   /* 0 --> Slrn_Post_Obj->po_puts */
#endif
#if SLRN_HAS_USER_AGENT
		  Slrn_Post_Obj->po_printf ("User-Agent: slrn/%s (%s)\n\n", 
					    Slrn_Version, 
					    SYSTEM_OS_NAME);
#else
		  Slrn_Post_Obj->po_printf ("X-Newsreader: slrn (%s %s)\n\n", Slrn_Version,
			       SYSTEM_OS_NAME);
#endif
		  header = 0;
#if SLRN_HAS_MIME
		  if (Slrn_Use_Mime) fp = slrn_mime_encode (fp);
#endif
		  
		  continue;
	       }
	     
	     if (!slrn_case_strncmp ((unsigned char *)"Cc: ", 
				     (unsigned char *)linep, 4))
	       {
		  b = (unsigned char *) linep + 4;
		  b = (unsigned char *) slrn_skip_whitespace ((char *) b);
		  if (*b && (*b != ',')) perform_cc = 1;
		  continue;
	       }

	     if (is_empty_header (linep)) continue;
#if SLRN_HAS_GEN_MSGID
	     if (!slrn_case_strncmp ((unsigned char *)"Message-Id: ",
				     (unsigned char *)linep, 12))
	       has_messageid = 1;
#endif	     
	     linep[len - 1] = 0;
#if SLRN_HAS_MIME
	     if (Slrn_Use_Mime)
	       slrn_mime_header_encode (linep, sizeof (line) - 1);
#endif
	  }

	/* Since the header may not have ended in a \n, make sure the 
	 * other lines do not either.  Later, the \n will be added.
	 */
	if (linep[len - 1] == '\n')
	  {
	     len--;
	     linep[len] = 0;
	  }
	
	if (*linep == '.')
	  {
	     linep--;
	     *linep = '.';
	  }
	
	Slrn_Post_Obj->po_puts (linep);
	Slrn_Post_Obj->po_puts ("\n");
	
	linep = line + 1;
     }
   slrn_fclose (fp);
   
   if (0 == Slrn_Post_Obj->po_end ())
     slrn_message ("Posting...done.");
   else
     {
	if (Slrn_Batch) return -1;

	/* slrn_set_suspension (0); */
	slrn_smg_refresh ();
	sleep (2);
	slrn_clear_message (); SLang_Error = 0;
	rsp = slrn_get_response ("RrEeCc\007", "Select one: \001Repost, \001Edit, \001Cancel");
	if (rsp == 7) return -1;
	rsp |= 0x20;
	if (rsp == 'c') return -1;
	if ((rsp == 'e') && (slrn_edit_file (Slrn_Editor_Post, file, 1) < 0)) return -1;
	goto try_again;
     }
   
   if (perform_cc)
     {
	slrn_cc_file (file, to, msgid);
     }
   return 0;
}




int slrn_post (char *newsgroup, char *subj, char *dist)
{
   FILE *fp;
   char file[SLRN_MAX_PATH_LEN];
   unsigned int header_lines;
   int ret;
   
   if (Slrn_Use_Tmpdir)
     {
	fp = slrn_open_tmpfile (file, "w");
     }
   else fp = slrn_open_home_file (SLRN_ARTICLE_FILENAME, "w", file, 0);
   
   if (fp == NULL)
     {
	slrn_error ("Unable to create %s.", file);
	return -1;
     }
   
   header_lines = 9;
   fprintf (fp, "Newsgroups: %s\nSubject: %s\n", newsgroup, subj);
   
   if (Slrn_User_Info.org != NULL)
     {
	header_lines++;
	fprintf (fp, "Organization: %s\n", Slrn_User_Info.org);
     }
   
   fprintf (fp, "Reply-To: %s\nFollowup-To: \n", Slrn_User_Info.replyto);
   fprintf (fp, "Keywords: \nSummary: \n");
   
   if (dist != NULL) fprintf (fp, "Distribution: %s\n", dist);
   
   header_lines += slrn_add_custom_headers (fp, Slrn_Post_Custom_Headers, NULL);

   fputs ("\n", fp);
   
   slrn_add_signature (fp);
   slrn_fclose (fp);
   
   if (slrn_edit_file (Slrn_Editor_Post, file, header_lines) >= 0)
     {
	ret = slrn_post_file (file, NULL, 0);
     }
   else ret = -1;
   
   if (Slrn_Use_Tmpdir) (void) slrn_delete_file (file);
   return ret;
}



int slrn_add_custom_headers (FILE *fp, char *headers, int (*write_fun)(char *, FILE *))
{
   int n;
   char *s, *s1, ch, last_ch;
   
   if (headers == NULL) return 0;
   
   s = slrn_skip_whitespace (headers);
   if (*s == 0) return 0;
   
   s1 = s;
   n = 0;
   last_ch = 0;
   while ((ch = *s1) != 0)
     {
	if (ch == '\n') 
	  {
	     n++;
	     while (s1[1] == '\n') s1++;   /* skip multiple newlines */
	  }
	last_ch = ch;
	s1++;
     }

   if (write_fun != NULL)
     (*write_fun)(s, fp);
   else fputs (s, fp);
   
   if (last_ch != '\n')
     {
	fputc ('\n', fp);
	n++;
     }
   
   return n;
}

static int get_postpone_dir (char *dirbuf)
{
   char *dir;
   
   if (Slrn_Postpone_Dir != NULL)
     dir = Slrn_Postpone_Dir;
   else 
     dir = Slrn_Save_Directory;
   
   if ((dir == NULL)
       || (-1 == slrn_make_home_dirname (dir, dirbuf))
       || (2 != slrn_file_exists (dirbuf)))
     {
	slrn_error_now (2, "postpone_directory not specified or does not exist");
	return -1;
     }

   return 0;
}

	     
static int postpone_file (char *file)
{
#ifdef VMS
   slrn_error ("Not implemented yet. Sorry");
   return -1;
#else
   char dir [SLRN_MAX_PATH_LEN];
   char dirfile [SLRN_MAX_PATH_LEN + 256];

   if (-1 == get_postpone_dir (dir))
     return -1;
   
   while (1)
     {
	int status;

	if (-1 == slrn_dircat (dir, NULL, dirfile))
	  return -1;

	if (-1 == slrn_read_input ("Save to", NULL, dirfile, 1, 1))
	  return -1;
	
	status = slrn_file_exists (dirfile);
	if (status == 1)
	  {
	     status = slrn_get_yesno_cancel ("File exists, overwrite");
	     if (status == 0)
	       continue;
	     if (status == 1)
	       break;

	     return -1;
	  }
	
	if (status == 0)
	  break;
	if (status == 2)
	  slrn_error_now (2, "You must specify a name");
	else
	  slrn_error_now (2, "Illegal filename. Try again");
     }
   
   if (-1 == slrn_move_file (file, dirfile))
     return -1;
   
   return 0;
#endif
}

void slrn_post_postponed (void)
{
   char dir [SLRN_MAX_PATH_LEN];
   char *file;

   if (-1 == get_postpone_dir (dir))
     return;
   
   file = slrn_browse_dir (dir);
   if (file == NULL)
     return;
   
   if (1 != slrn_file_exists (file))
     {
	slrn_error ("%s: not a regular file");
	return;
     }
   
   if (0 == slrn_post_file (file, NULL, 1))
     slrn_delete_file (file);

   slrn_free (file);
}

   

	     
	  
	  
