/*****************************************************************************
 *
 * $Id: ftn2rfc.c,v 1.34 2007/08/26 12:21:16 mbse Exp $
 * Purpose ...............: Gate netmail->email or echomail->news
 *
 *****************************************************************************
 * Copyright (C) 1997-2007
 *   
 * Michiel Broek		FIDO:		2:280/2802
 * Beekmansbos 10
 * 1971 BV IJmuiden
 * the Netherlands
 *
 * This file is part of MBSE BBS.
 *
 * This BBS 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.
 *
 * MBSE BBS 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 MBSE BBS; 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 "../lib/mbselib.h"
#include "../lib/users.h"
#include "../lib/mbsedb.h"
#include "rollover.h"
#include "aliasdb.h"
#include "postemail.h"
#include "backalias.h"
#include "msgflags.h"
#include "rfc2ftn.h"
#include "ftn2rfc.h"


#define KWDCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
#define MAXPATH  73
#define	BOUNDARY 79


/*
 * Global variables
 */
extern	int	news_in;		/* Total news articles		    */
extern	int	news_out;		/* News articles posted		    */
extern	int	news_bad;		/* News articles refused	    */
extern	int	defaultrfcchar;		/* Default RFC charset		    */
extern	int	defaultftnchar;		/* Default FTN charset		    */

int		newsopen = FALSE;	/* News tempfile status		    */
FILE		*nfp;			/* News tempfile		    */


void fill_rlist(fa_list **, char *);
void fill_rlist(fa_list **fap, char *str)
{
	fa_list			*tmp;
	faddr			*ta;
	static unsigned int	oldnet;
	char			*buf, *p, *q;

	if ((str == NULL) || (*str == '\0')) 
		return;

	buf = xstrcpy(str);
	for (p = buf, q = strchr(p,'!'); *p; p = q, q = strchr(p,'!')) {
		if (q) 
			*q++='\0';
		else 
			q=p+strlen(p);
		if ((ta = parsefaddr(p))) {
			if (ta->net == 0) 
				ta->net=oldnet;
			else 
				oldnet=ta->net;
			tmp=(fa_list *)malloc(sizeof(fa_list));
			tmp->next=*fap;
			tmp->addr=ta;
			*fap=tmp;
		}
	}
	free(buf);
	for (tmp=*fap;tmp;tmp=tmp->next)
	return;
}


static char	*rbuf;


char *rfcmsgid(char *, faddr *);
char *rfcmsgid(char *msgid, faddr *bestaka)
{
    char	    *p, *q, *r;
    unsigned int    id = 0L;
    faddr	    *ta = NULL;
    size_t	    bufsize;

    if (msgid == NULL)
	return NULL;

    /*
     * +40 for the additionnal stuff we need to write, should be enough
     */
    bufsize = strlen(msgid) + 40;
    rbuf = malloc(bufsize);
    if ((r = strrchr(msgid,'\n'))) 
	*r = '\0'; 

    /*
     * sometimes there is "^aMSGID: 1:23/45@@domain 152ad589"
     */
    if ((p = strstr(msgid, "@@"))) {
	*p='\0';
	strcat(msgid, p+1);
    } else if ((p = strstr(msgid,"@ "))) {
	/*
	 * other times there is "^aMSGID: 1:23/45@ 152ad589"
	 */
	*p='\0';
	strcat(msgid,p+1);
    }

    if ((p=strrchr(msgid,' '))) {
	/*
	 * here we have a parseable address
	 */
	*p = '\0';
	sscanf(p+1, "%x", &id);
	ta = parsefnode(msgid);
	*p=' ';
    }

    if (id != 0L) {
	/* if we only check for (ta) a Message-ID like
	 * <123456.7890@internet.domain> will be recognized as
	 * a fidonet one (ta->node=123456, ta->point=7890,
	 * ta->domain="internet", but ta->net=0) which obviously
	 * isn't the case. By cheking also (ta->net) we avoid that
	 */
	if ((ta) && (ta->net)) {
	    snprintf(rbuf, bufsize, "<%u@%s.ftn>", id, ascinode(ta,0x1f));
	} else {
	    p = xstrcpy(msgid);
	    if ((q = strchr(p,' '))) 
		*q = '\0';
	    /* ### Modified by P.Saratxaga on 18 Aug 1995 */
	    if (strstr(p, "@")) {
		/* "mid__<local@domain>" are generated by gigo */
		if (!strncmp(p, "mid__<", 6)) {
		    snprintf(rbuf, bufsize, "%s", p+6);
		    while ((q = strstr(rbuf, ">_<")))
			*(q+1) = ' ';
		
		}
		/* "mid__local@domain" are also generated by gigo */
		else if (!strncmp(p, "mid__", 5))
		    snprintf(rbuf, bufsize, "<%s>", p+5);
		/* "wgmid$<local@domain>" */
		else if (!strncmp(p, "wgmid$<", 7))
		    snprintf(rbuf, bufsize, "%s", p+6);
		/* in case we have "<local@domain>" */
		else if (!strncmp(p, "<", 1))
		    snprintf(rbuf, bufsize, "%s", p);
		/* or "local@domain" */
		else 
		    snprintf(rbuf, bufsize, "<%s>", p);
		while ((q = strchr(rbuf, '@')) != strrchr(rbuf, '@')) {
		    /* we (still) have more than one @ */
		    *q = '%';
		}
	    } else {
		snprintf(rbuf, bufsize, "<%u@%s>", id, p);
	    }
	    free(p);
	}
    } else {
	snprintf(rbuf, bufsize, "<%u@%s.ftn>", (unsigned int)sequencer(), ascinode(bestaka,0x1f));
    }
    tidy_faddr(ta);
    if (r) 
	*r='\n';
    return rbuf;
}



/*
 * check address for localness, substitute alises and replace it *in place* 
 */
void substitude(char *, size_t);
void substitute(char *buf, size_t size)
{
	faddr	*fa;
	char	*l,*r,*p=NULL;
	int	inquotes,inbrackets;

	Syslog('m', "to address before subst: \"%s\"",buf);
	if ((l=strchr(buf,'<')) && (r=strchr(buf,'>')) && (l < r)) {
		l++;
		*r='\0';
	} else 
		l=buf;
	while (*l == ' ') 
		l++;
	for (r=l,inquotes=0,inbrackets=0;*r;r++) 
		switch (*r) {
			case '"':       inquotes=(!inquotes); break;
			case ',':
			case ' ':       if (!inquotes && !inbrackets) *r='\0'; break;
			case '(':       if (!inquotes) inbrackets++; break;
			case ')':       if (!inquotes && inbrackets) inbrackets--; break;
			default:        break;
		}
	if ((fa = parsefaddr(l))) {
		Syslog('m', "it is an ftn address: %s",ascfnode(fa,0x7f));
		if (is_local(fa)) {
			Syslog('m', "it is local");
			snprintf(buf,size, "%s",fa->name);
			if (!strchr(buf,'@') && (p=strrchr(buf,'%')))
				*p='@';
			if (!strchr(buf,'@')) {
				/*
				 * Lookup the name first in the alias database, then
				 * the userbase and finally check the password file
				 * (gecos->username). If not found it's and error.
				 */
				if ((p = lookup(buf)))
					strcpy(buf, p);
				else if (SearchUser(buf))
					snprintf(buf, size, "%s@%s", usr.Name, CFG.sysdomain);
				else if (!strcasecmp(buf,"sysop"))
					strcpy(buf,"postmaster");
				else
					snprintf(buf, size, "%s",ascinode(fa,0x7f));
			}
		} else {
			WriteError("substitute(%s) it is not local, may not happen", buf);
			snprintf(buf,size, "%s",ascinode(fa,0x7f));
		}
		tidy_faddr(fa);
	} else {
		Syslog('m', "it is not ftn address");
		for (r=buf;*l;l++,r++) 
			*r=*l;
		*r='\0';
	}
	if (buf[0] == '\0') 
		strcpy(buf,"postmaster");
	Syslog('m', "to address after  subst: \"%s\"",buf);
	return;
}



/*
 * Lines to send, if it is a newsarticle, the Message-Id is checked.
 */
void Send(int, char *);
void Send(int newsmode, char *outstr)
{
    char            *p;
    unsigned int    crc;

    charwrite(outstr, nfp);
    Syslog('m', "+ %s", printable(outstr, 0));

    if (newsmode) {
	Striplf(outstr);
	if (strncmp(outstr, (char*)"Message-ID: ", 12) == 0) {
	    /*
	     *  The Message-ID that is sent to the newsserver is stored in
	     *  the dupes database. The database isn't checked for dupes, this
	     *  message is already checked for dupes. The function that will 
	     *  pull news articles from the news server will check the dupes
	     *  database and thus will not fetch this local posted article.
	     */ 
	    p = xstrcpy(outstr+12);
	    p = xstrcat(p, msgs.Newsgroup);
	    crc = str_crc32(p);
	    CheckDupe(crc, D_NEWS, CFG.nntpdupes);
	    free(p);
	}
    }
}



/*
 * Gate FTN style netmail->email or echomail->news.
 *
 *  0 - All seems well.
 *  1 - Something went wrong.
 *  4 - Unable to open temporary file
 *
 */
int ftn2rfc(faddr *f, faddr *t, char *subj, char *origline, time_t mdate, int flags, FILE *pkt)
{
    int		    rrq, result = 1, waskludge = FALSE, badkludge;
    int             bNeedToGetAddressFromMsgid = (int)NULL, newsmode = 0, lines, pass, count, first;
    char	    *newsgroup = NULL, *charset = NULL;
    char            *temp, *p, *q, *r, *l, *b, *To = NULL, buf[4096], c, MailFrom[128], MailTo[128];
    time_t	    now;
    rfcmsg	    *kmsg = NULL, **tmsg, *qmsg, *msg = NULL;
    off_t	    endmsg_off, tear_off, orig_off, via_off;
    faddr	    *o, *bestaka, *ta, *tfaddr;
    FILE	    *fp;
    fa_list	    *rlist, *tfa, *ftnpath = NULL;
    struct utsname  utsbuf;

    temp = calloc(32768, sizeof(char));
    tmsg = &kmsg;
    tear_off = orig_off = via_off = 0L;
    rbuf = NULL;

    if ((fp = tmpfile()) == NULL) {
	WriteError("$Unable to open temporary file");
	free(temp);
	return 4;
    }

    rewind(pkt);
    while ((fgets(buf, sizeof(buf)-2, pkt)) != NULL) {
	/*
	 *  Simple test to see how large the buffer must be. 2048 bytes has been seen.
	 */
	if (strlen(buf) > (sizeof(buf) /2))
	    Syslog('+', "FTN: Possible bufferoverflow: line read %d bytes", strlen(buf));
	if ((buf[0] == '\1') || !strncmp(buf,"AREA:",5) || !strncmp(buf,"SEEN-BY",7)) { /* This is a kluge line */
	    waskludge = TRUE;
	    badkludge = FALSE;
	    if (buf[0] == '\1') {
		l = buf+1;
		if (!strncmp(l,"AREA:",5) || !strncmp(l,"SEEN-BY",7))
		    badkludge = TRUE;
	    } else
		l = buf;
	    if (*l == '\n')
		badkludge = TRUE;
	    else
		while (isspace(*l))
		    l++;
	    if (strncmp(l, "RFC-", 4))
		for (p = l; *p; p++)
		    if ((*p != '\n') && (((*p)&0x7f) < ' '))
			badkludge = TRUE;
	    p = strchr(l,':');
	    r = strchr(l,' ');
	    if (p && (!r || (r > p))) 
		r = p;
	    else 
		p = r;
	    if (r == NULL) 
		badkludge = TRUE;
	    else if (!*(p+1) || (*(p+1)=='\n')) 
		badkludge = TRUE;
	    else {
		c = *r;
		*r = '\0';
		if (strspn(l,KWDCHARS) != strlen(l)) 
		    badkludge = TRUE;
		*r = c;
	    }
	    *tmsg = (rfcmsg *)malloc(sizeof(rfcmsg));
	    (*tmsg)->next = NULL;
	    if (badkludge) {
		(*tmsg)->key = xstrcpy((char *)"KLUDGE");
		p = printable(l,0);
		r = p+strlen(p)-2;
		if (strcmp(r,"\\n") == 0) {
		    *r++ = '\n';
		    *r = '\0';
		}
		(*tmsg)->val = xstrcpy(p);
	    } else {
		*r++ = '\0';
		while (isspace(*r)) 
		    r++;
		(*tmsg)->key = xstrcpy(l);
		(*tmsg)->val = xstrcpy(r);
	    }
	    tmsg = &((*tmsg)->next);

	    if (!strcmp(l,"Via") && (via_off == 0L)) { 
		via_off = ftell(fp);
		Syslog('m', "^AVia \"%s\" at offset %d", printable(buf, 0), (int)via_off);
	    }
	} else { 
	    /*
	     * this is not a kludge line
	     */
	    if (waskludge && (isspace(buf[0])))
		fputs("\n",fp); /* first body line is not RFC hdr */
	    waskludge=0;
	    if ((!strncmp(buf,"---",3)) && (buf[3] != '-')) {
		tear_off=ftell(fp);
		if ((hdr((char *)"Tearline",kmsg) == NULL)) {
		    *tmsg=(rfcmsg *)malloc(sizeof(rfcmsg));
		    (*tmsg)->next=NULL;
		    (*tmsg)->key=xstrcpy((char *)"Tearline");
		    if (strlen(buf+3) == strspn(buf+3," \t\r\n"))
			(*tmsg)->val=xstrcpy((char *)"(none)\n");
		    else
			(*tmsg)->val=xstrcpy(buf+4);
		    tmsg=&((*tmsg)->next);
		}
	    } else if (!strncmp(buf," * Origin:",10)) {
		orig_off = ftell(fp);
		*tmsg = (rfcmsg *)malloc(sizeof(rfcmsg));
		(*tmsg)->next = NULL;
		(*tmsg)->key = xstrcpy((char *)"Origin");
		(*tmsg)->val = xstrcpy(buf+11);
		tmsg = &((*tmsg)->next);
		p = buf+10;
		while (*p == ' ') 
		    p++;
		if ((l = strrchr(p,'(')) && (r = strrchr(p,')')) && (l < r)) {
		    /*
		     *  Extract origin address from the Origin line.
		     */
		    *l = '\0';
		    *r = '\0';
		    l++;
		    if ((o = parsefnode(l))) {
			f->point = o->point;
			f->node  = o->node;
			f->net   = o->net;
			f->zone  = o->zone;
			if (o->domain) 
			    f->domain = o->domain;
			o->domain = NULL;
			tidy_faddr(o);
		    }
		} else {
		    bNeedToGetAddressFromMsgid = !NULL;
		    Syslog('+', "Couldn't find address in origin line (%s of %s, [%s])", 
			    f->name, ascfnode(f, 0x1f), hdr((char *)"Origin", kmsg));
		    if (*(l = p+strlen(p)-1) == '\n') 
			*l = '\0';
		}
		for (l = p+strlen(p)-1; *l == ' '; l--) 
		    *l = '\0';
		origline = xstrcpy(p);
	    } else if (!strncmp(buf," * Message split",16)) {
		*tmsg = (rfcmsg *)malloc(sizeof(rfcmsg));
		(*tmsg)->next = NULL;
		(*tmsg)->key = xstrcpy((char *)"Split");
		(*tmsg)->val = xstrcpy((char *)"already\n");
		tmsg=&((*tmsg)->next);
		Syslog('m', "Split indicator found");
	    }
	    fputs(buf,fp);
	}
    }

    if (bNeedToGetAddressFromMsgid && (p = hdr((char *)"MSGID", kmsg))) {
	Syslog('m', "Need To Get Address From Msgid start...");
	l = p;
	while(isspace(*l) && *l)
	    l++;
	r = strchr(l, ' ');
	if(r) {
	    *r-- = '\0';
	    while(isspace(*r) && *r)
		r--;
	}
	if (l && r && l > r) {
	    if ((o = parsefnode(l))) {
		f->point = o->point;
		f->node  = o->node;
		f->net   = o->net;
		f->zone  = o->zone;
		if (o->domain) 
		    f->domain = o->domain;
		o->domain = NULL;
		tidy_faddr(o);
		Syslog('+', "Origin from: %s (src MSGID)", ascfnode(f,0x7f));
	    }
	}
    }

    endmsg_off=ftell(fp);
    if ((tear_off) && (tear_off < endmsg_off)) 
	endmsg_off = tear_off;
    if ((orig_off) && (orig_off < endmsg_off)) 
	endmsg_off = orig_off;
    if ((via_off) && (via_off < endmsg_off)) 
	endmsg_off = via_off;

    rewind(fp);
    msg = parsrfc(fp);
    bestaka = bestaka_s(f);
    rewind(fp);

    /*
     * Get characterset encoding from kludge or rfc header
     */
    p = hdr((char *)"CHRS", kmsg);
    if (p == NULL)
	p = hdr((char *)"CHARSET", kmsg);
    if (p == NULL)
	p = hdr((char *)"CODEPAGE", kmsg);
    if (p) {
	while (*p && isspace(*p))
	    p++;
	Striplf(p);
	charset = xstrcpy(p);
	Syslog('m', "Charset from ftn \"%s\"", printable(charset, 0));
    } else {
	p=hdr((char *)"Content-Type",msg);
	if (p == NULL)
	    p=hdr((char *)"RFC-Content-Type",kmsg);
	if (p == NULL)
	    p=hdr((char *)"Content-Type",kmsg);
	if (p) {
	    q = strtok(p, " \n\0");
	    q = strtok(NULL, " \n\0");
	    while (*q && isspace(*q))
		q++;
	    Syslog('m', "charset part: %s", printable(q, 0));
	    if (q && (strncasecmp(q, "charset=", 8) == 0)) {
		charset = xstrcpy(q + 8);
		Syslog('m', "Charset from rfc \"%s\"", printable(charset, 0));
	    }
	} else {
	    charset = xstrcpy((char *)"iso-8859-1");
	    Syslog('m', "No charset, setting default to iso-8859-1");
	}
    }

    if (kmsg && !strcmp(kmsg->key,"AREA")) {
	/*
	 * The msgs record is already loaded.
	 */
	newsgroup = xstrcpy(msgs.Newsgroup);
	newsmode = TRUE;
    } else 
	newsmode = FALSE;
    Syslog('m', "Got %s message", newsmode?"echo":"netmail");

    /*
     * fsc-0038 defines "^aDOMAIN: othernet 99:12/34 fidonet 2:293/2219"
     */
    if ((p=hdr((char *)"DOMAIN",kmsg)) && (!strchr(p,'@'))) {
	strncpy(buf,p,sizeof(buf)-1);
	buf[sizeof(buf)-1]='\0';
	l=strtok(buf," \n");
	p=strtok(NULL," \n");
	r=strtok(NULL," \n");
	q=strtok(NULL," \n");
	if ((ta=parsefnode(p))) {
	    t->point=ta->point;
	    t->node=ta->node;
	    t->net=ta->net;
	    t->zone=ta->zone;
	    tidy_faddr(ta);
	}
	t->domain=xstrcpy(l);
	if ((ta=parsefnode(q))) {
	    f->point=ta->point;
	    f->node=ta->node;
	    f->net=ta->net;
	    f->zone=ta->zone;
	    tidy_faddr(ta);
	}
	f->domain=xstrcpy(r);
    } else if ((p=hdr((char *)"INTL",kmsg))) {
	strncpy(buf,p,sizeof(buf)-1);
	buf[sizeof(buf)-1]='\0';
	l=strtok(buf," \n");
	r=strtok(NULL," \n");
	if ((ta=parsefnode(l))) {
	    t->point=ta->point;
	    t->node=ta->node;
	    t->net=ta->net;
	    t->zone=ta->zone;
	    if (ta->domain) {
		if (t->domain) 
		    free(t->domain);
		t->domain=ta->domain;
		ta->domain=NULL;
	    }
	    tidy_faddr(ta);
	}
	if ((ta=parsefnode(r))) {
	    f->point=ta->point;
	    f->node=ta->node;
	    f->net=ta->net;
	    f->zone=ta->zone;
	    if (ta->domain) {
		if (f->domain) 
		    free(f->domain);
		f->domain=ta->domain;
		ta->domain=NULL;
	    }
	    tidy_faddr(ta);
	}
    }

    /*
     * fidogate generates "^aDOMAIN: Z2@fidonet"
     */
    if ((f->domain==NULL) && ((p=hdr((char *)"DOMAIN",kmsg)) && (q=strchr(p,'@')))) {
	*q='\0';
	f->domain=xstrcpy(q+1);
	*q='@';
    }

    if ((p=hdr((char *)"FMPT",kmsg))) 
	f->point=atoi(p);
    if ((p=hdr((char *)"TOPT",kmsg))) 
	t->point=atoi(p);

    if (!newsmode) {
	Syslog('m', "final from: %s",ascfnode(f,0xff));
	Syslog('m', "final   to: %s",ascfnode(t,0xff));
    }

    if (!newsmode) {
	p=hdr((char *)"Resent-To",msg);
	if (p == NULL) 
	    p=hdr((char *)"To",msg);
	if (p == NULL) 
	    p=hdr((char *)"RFC-Resent-To",kmsg);
	if (p == NULL) 
	    p=hdr((char *)"RFC-To",kmsg);
	if (p && is_local(t)) {
	    while (*p == ' ') 
		p++;
	    strncpy(buf, p, sizeof(buf) -1);
	    if (*(p = buf + strlen(buf) -1) == '\n') 
		*p='\0';
	} else
	    snprintf(buf,4096,"%s",ascinode(t,0x7f));
	substitute(buf,4096);
	Syslog('+', "mail from %s to %s",ascfnode(f,0x7f),buf);
	To = xstrcpy(buf);

	p = NULL;
	p = hdr((char *)"Return-Path",msg);
	if (p == NULL) 
	    p=hdr((char *)"RFC-Return-Path",kmsg);
	if (p == NULL) 
	    p=hdr((char *)"Return-Path",kmsg);
	if ((CFG.EmailMode == E_PRMISP) && (p == NULL))
	    p=hdr((char *)"From",msg);
	if (p)
	    snprintf(MailFrom, 128, "%s", p);
	else
	    snprintf(MailFrom, 128, "%s", ascinode(f,0x7f));
	Syslog('m', "MailFrom: %s", MailFrom);

	if (To)
	    snprintf(MailTo, 128, "%s", To);
	else
	    snprintf(MailTo, 128, "%s", t->name);
	Syslog('m', "MailTo: %s", MailTo);

	/*
	 * Because we need the same stream for news and email
	 * we need to check if the newsfile is already open.
	 */
	if (newsopen) {
	    fclose(nfp);
	    newsopen = FALSE;
	}

	if ((nfp = tmpfile()) == NULL) {
	    WriteError("$Unable to open temporary file");
	    return 4;
	}

	Syslog('m', "Prepare is ready");
    }

    Syslog('m', "ftn2rfc: charset in: %s charset out: %s", charset, getrfcchrs(msgs.Charset));

    /*
     * Setup charset conversion
     */
    chartran_init(charset, getrfcchrs(msgs.Charset), 'm');

    if (newsmode) {
	/*
	 *  Open temporary newsfile, append messages if it already exists.
	 */
	if (!newsopen) {
	    p = calloc(PATH_MAX, sizeof(char));
	    snprintf(p, PATH_MAX, "%s/tmp/newsout", getenv("MBSE_ROOT"));
	    if ((nfp = fopen(p, "a")) == NULL) {
		WriteError("$Can't open %s", p);
		free(p);
		return 2;
	    }
	    free(p);
	    newsopen = TRUE;
	}

	if ((p=hdr((char *)"Path",msg)) == NULL)
	    p=hdr((char *)"RFC-Path",kmsg);
	rlist=NULL;
	fill_rlist(&rlist, p);
	for (qmsg = kmsg; qmsg; qmsg = qmsg->next)
	    if (strcasecmp(qmsg->key, "SPTH") == 0)
		fill_list(&ftnpath, qmsg->val, &rlist);
	for (qmsg = kmsg; qmsg; qmsg = qmsg->next)
	    if (strcasecmp(qmsg->key, "PATH") == 0)
		fill_list(&ftnpath, qmsg->val, &rlist);
	tidy_falist(&rlist);

	/*
	 *  Build Path: headerline
	 */
	if (CFG.newsfeed != FEEDINN) {
	    q = xstrcpy((char *)"Path: ");
	    if (CFG.newsfeed == FEEDUUCP) {
		/*
		 *  If we don't run our own newsserver we have to simulate and
		 *  add the UUCP nodename here.
		 */
		memset(&utsbuf, 0, sizeof(utsbuf));
		if (uname(&utsbuf)) {
		    WriteError("Can't get system nodename");
		} else {
		    q = xstrcat(q, utsbuf.nodename);
		    q = xstrcat(q, (char *)"!");
		}
	    }
	    tfaddr = fido2faddr(msgs.Aka);
	    q = xstrcat(q, ascinode(tfaddr, 0x07));
	    tidy_faddr(tfaddr);
	    q = xstrcat(q, (char *)"!");
	    if (ftnpath)
		for (tfa=ftnpath->next;tfa;tfa=tfa->next) {
		    /* FIXME: possible memory leak */
		    q = xstrcat(q, ascinode(tfa->addr,0x1f));
		    q = xstrcat(q, (char *)"!");
		}
	    tidy_falist(&ftnpath);

	    if (p) {
		while (isspace(*p)) 
		    p++;
		q = xstrcat(q, p);
	    } else 
		q = xstrcat(q, (char *)"not-for-mail");
	    snprintf(temp, 32768, "%s\n", q);
	    Send(newsmode, temp);
	    free(q);
	}

	if ((p = hdr((char *)"Newsgroups",msg))) {
	    /*
	     * The gate at puddle.fidonet.org put spaces in Newsgroups header
	     */
	    if ((strstr(p,", "))) {
		while ((r = strchr(p, ' '))) {
		    *r = '\0';
		    strcat(p,r+1);
		}
	    }
	}
	if (p == NULL) 
	    p=hdr((char *)"RFC-Newsgroups",kmsg);
	if (p == NULL) 
	    p=hdr((char *)"Newsgroups",kmsg);
	if (p) {
	    while (*p && isspace(*p)) 
		p++;
	    snprintf(temp,32768,"Newsgroups: %s\n",newsgroup);
	    Send(newsmode, temp);
	    snprintf(temp,32768,"X-Origin-Newsgroups: %s",p);
	    Send(newsmode, temp);
	} else {
	    snprintf(temp,32768,"Newsgroups: %s\n",newsgroup);
	    Send(newsmode, temp);
	}

	p = hdr((char *)"Comment-To",msg);
	if (p == NULL)
	    p=hdr((char *)"X-Comment-To",msg);
	if (p == NULL)
	    p=hdr((char *)"To",msg);
	if ((p) && (strcasecmp(p,"All\n"))) {
	    snprintf(temp,32768,"X-Comment-To:%s", p);
	    Send(newsmode, temp);
	} else {
	    if (p == NULL) 
		p=hdr((char *)"RFC-X-Comment-To",kmsg);
	    if (p == NULL) 
		p=hdr((char *)"RFC-Comment-To",kmsg);
	    if (p == NULL) 
		p=hdr((char *)"RFC-To",kmsg);
	    if ((p) && (strcasecmp(p,"All\n"))) {
		snprintf(temp,32768,"X-Comment-To: %s", p);
		Send(newsmode, temp);
	    } else if ((t) && (t->name) && (strcasecmp(t->name,"All"))) {
		snprintf(temp,32768,"X-Comment-To: %s\n", t->name);
		Send(newsmode, temp);
	    } else {
		snprintf(temp,32768,"X-Comment-To: All\n");
		Send(newsmode, temp);
	    }
	}

	if ((p=hdr((char *)"Approved",msg))) {
	    snprintf(temp,32768,"Approved:%s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"RFC-Approved",kmsg))) {
	    snprintf(temp,32768,"Approved: %s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"Approved",kmsg))) {
	    snprintf(temp,32768,"Approved: %s",p);
	    Send(newsmode, temp);
	}

    } else { /* if newsmode */
	now = time(NULL);
	Syslog('m', "Should send Received: header for mbfido");
	snprintf(temp, 32768,"Received: from %s\n", ascinode(f, 0x3f));
	Send(FALSE, temp);
	snprintf(temp, 32768,"\tby %s with FTN (mbfido v.%s) id AA%u\n", ascinode(bestaka,0x3f), VERSION, getpid());
	Send(FALSE, temp);
	snprintf(temp, 32768,"\t%s\n", rfcdate(now));
	Send(FALSE, temp);
	Syslog('m', "Is done now");

	for (qmsg = kmsg; qmsg; qmsg = qmsg->next)
	    if (!strcasecmp(qmsg->key,"RFC-Received")) {
		snprintf(temp, 32768, "%s: %s", qmsg->key+4, qmsg->val);
		Send(FALSE, temp);
	    }
	for (qmsg = msg; qmsg; qmsg = qmsg->next)
	    if (!strcasecmp(qmsg->key,"Received")) {
		snprintf(temp, 32768, "%s:%s", qmsg->key, qmsg->val);
		Send(FALSE, temp);
	    }

	if ((p=hdr((char *)"Apparently-To",msg))) {
	    snprintf(temp, 32768, "Apparently-To: %s\n",p);
	    Send(FALSE, temp);
	} else if ((p=hdr((char *)"RFC-Apparently-To",kmsg))) {
	    snprintf(temp, 32768, "Apparently-To: %s\n",p);
	    Send(FALSE, temp);
	} else if ((p=hdr((char *)"Apparently-To",kmsg))) {
	    snprintf(temp, 32768, "Apparently-To: %s\n",p);
	    Send(FALSE, temp);
	} else if ((is_local(t))) {
	    snprintf(temp, 32768, "Apparently-To: %s\n",buf);
	    Send(FALSE, temp);
	}

	if (flags & M_RRQ) 
	    rrq=TRUE;
	else 
	    rrq=FALSE;
	if (rrq && !hdr((char *)"RFC-Return-Receipt-To",kmsg) &&
		   !hdr((char *)"Return-Receipt-To",msg) &&
		   !hdr((char *)"RFC-Notice-Requested-Upon-Delivery-To",kmsg) &&
		   !hdr((char *)"Notice-Requested-Upon-Delivery-To",msg)) {
	    snprintf(temp,32768,"Notice-Requested-Upon-Delivery-To: %s\n",buf);
	    Send(FALSE, temp);
	}

	if (t->name == NULL) 
	    t->name=xstrcpy((char *)"Postmaster");
	p=hdr((char *)"Resent-To",msg);
	if (p == NULL) 
	    p=hdr((char *)"To",msg);
	if (p) {
	    snprintf(temp,32768,"To:%s",p);
	    Send(FALSE, temp);
	} else {
	    if (p == NULL) 
		p=hdr((char *)"RFC-Resent-To",kmsg);
	    if (p == NULL) 
		p=hdr((char *)"RFC-To",kmsg);
	    if (p) {
		Syslog('m', "2");
		snprintf(temp,32768,"To: %s\n",p);
		Send(FALSE, temp);
	    } else if (is_local(t)) {
		Syslog('m', "3");
		snprintf(temp, 32768, "To: %s <%s>\n", t->name, buf);
		Send(FALSE, temp);
	    } else {
		Syslog('m', "4");
		snprintf(temp,32768,"To: %s\n",ascinode(t,0xff));
		Send(FALSE, temp);
	    }
	}
    }

    if ((p = hdr((char *)"From",msg))) {
	snprintf(temp, 32768, "From:%s", p);
	Send(newsmode, temp);
    } else if ((p = hdr((char *)"RFC-From",kmsg))) {
	Syslog('m', "b");
	snprintf(temp, 32768, "From: %s", p);
	Send(newsmode, temp);
    } else if ((p = hdr((char *)"From\n",kmsg))) {
	Syslog('m', "c");
	snprintf(temp, 32768, "From: %s", p);
	Send(newsmode, temp);
    } else if ((p = hdr((char *)"X-PcBoard-FROM",msg))) {
        if (f->name) {
            while (isspace(*p)) 
		p++;
            p[strlen(p)-1] = '\0';
            snprintf(temp,32768,"From: %s <%s>\n", f->name, p);
	} else {
	    snprintf(temp,32768,"From:%s\n", p);
	}
	Send(newsmode, temp);
    } else if ((hdr((char *)"REPLYADDR",kmsg)) && (p=xstrcpy(hdr((char *)"REPLYADDR",kmsg)))) {
	if (*(r=p+strlen(p)-1) == '\n') 
	    *(r--)='\0';
	while (isspace(*r)) 
	    *(r--)='\0';
	q=xstrcpy(hdr((char *)"X-RealName",msg));
	if (q == NULL) 
	    q=xstrcpy(hdr((char *)"RealName",msg));
	if (q == NULL) 
	    q=xstrcpy(hdr((char *)"X-RealName",kmsg));
	if (q == NULL) 
	    q=xstrcpy(hdr((char *)"RealName",kmsg));
	if (q) {
	    if (*(r=q+strlen(q)-1) == '\n') 
		*(r--)='\0';
	    while (isspace(*r)) 
		*(r--)='\0';
	    for (l=q; isspace(*l); ) 
		l++;
	    if ((*l == '\"') && (*r == '\"')) {
		l++;
		*r--='\0';
	    }
	    Syslog('m', "d");
	    snprintf(temp,32768,"From: \"%s\" <%s>\n", l, p);
	    Send(newsmode, temp);
	    free(q);
	} else if (f->name) {
	    Syslog('m', "e");
	    snprintf(temp,32768,"From: \"%s\" <%s>\n", f->name, p);
	    Send(newsmode, temp);
	} else {
	    Syslog('m', "f");
	    snprintf(temp,32768,"From: %s\n",p);
	    Send(newsmode, temp);
	}
	free(p);
    }

    /*
     * If post was done with an external editor that doesn't supply
     * From: (some GoldED versions, not all) then add one here.
     */
    if (p) 
	snprintf(temp,32768,"X-FTN-Sender: %s\n", ascinode(f,0xff));
    else 
	snprintf(temp,32768,"From: %s\n", ascinode(f,0xff));
    Send(newsmode, temp);

    if ((p=hdr((char *)"Reply-To",msg))) {
	snprintf(temp,32768,"Reply-To:%s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"RFC-Reply-To",kmsg))) {
	snprintf(temp,32768,"Reply-To: %s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"Reply-To",kmsg))) {
	snprintf(temp,32768,"Reply-To: %s",p);
	Send(newsmode, temp);
    } else if (((p=backalias(f))) && strlen(CFG.sysdomain)) {
	snprintf(temp,32768,"Reply-To: %s@%s\n",p,CFG.sysdomain);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"REPLYADDR",kmsg))) {
	snprintf(temp,32768,"Reply-To: %s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"REPLYTO",kmsg))) {
	ta = parsefaddr(p);
	snprintf(temp,32768,"Reply-To: %s\n",ascinode(ta, 0xff));
	tidy_faddr(ta);
	Send(newsmode, temp);
    }
	
    if ((p=hdr((char *)"Date",msg))) {
	snprintf(temp,32768,"Date:%s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"RFC-Date",kmsg))) {
	snprintf(temp,32768,"Date: %s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"Date",kmsg))) {
	snprintf(temp,32768,"Date: %s",p);
	Send(newsmode, temp);
    } else if (newsmode) {
	/*
	 * Restamp future postings
	 */
	now = time(NULL);
	if (mdate > now) {
	    Syslog('+', "Future posting: %s", rfcdate(mdate));
	    snprintf(temp,32768,"Date: %s\n", rfcdate(now));
	    Send(newsmode, temp);
	    snprintf(temp,32768,"X-Origin-Date: %s\n", rfcdate(mdate));
	    Send(newsmode, temp);
	} else if ((mdate < now-14*24*60*60) && (mdate > time(&now)-21*24*60*60)) {
	    /*
	     * Restamp old postings
	     */
	    Syslog('+', "Article too old, restamped: %s", rfcdate(mdate));
	    snprintf(temp,32768,"Date: %s\n", rfcdate(now));
	    Send(newsmode, temp);
	    snprintf(temp,32768,"X-Origin-Date: %s\n", rfcdate(mdate));
	    Send(newsmode, temp);
	} else {
	    snprintf(temp,32768,"Date: %s\n",rfcdate(mdate));
	    Send(newsmode, temp);
	}
    } else {
	snprintf(temp,32768,"Date: %s\n",rfcdate(mdate));
	Send(newsmode, temp);
    }

    if ((p = hdr((char *)"Subject",msg))) 
	snprintf(temp, 32768, "Subject:%s", p);
    else if ((p = hdr((char *)"RFC-Subject",kmsg))) 
	snprintf(temp, 32768, "Subject: %s", p);
    else if ((p = hdr((char *)"Subject",kmsg))) 
	snprintf(temp, 32768, "Subject: %s", p);
    else if ((p = hdr((char *)"X-PcBoard-SUBJECT",msg))) 
	snprintf(temp, 32768, "Subject:%s", p);
    else if (subj && (strspn(subj," \t\n\r") != strlen(subj)))
	snprintf(temp, 32768, "Subject: %s\n", subj);
    else 
	snprintf(temp, 32768, "Subject: <none>\n");
    Send(newsmode, temp);

    if ((p=hdr((char *)"Message-ID",msg)))
	snprintf(temp,32768, "Message-ID:%s",p);
    else if ((p=hdr((char *)"RFC-Message-ID",kmsg)))
	snprintf(temp,32768, "Message-ID: %s",p);
    else if ((p=hdr((char *)"Message-ID",kmsg)))
	snprintf(temp,32768, "Message-ID: %s",p);
    else if ((p=hdr((char *)"RFCID",kmsg))) {
	if ((p[0]=='<')) {
	    /* "^aRFCID: <local@machine>" */
	    if ((p[strlen(p)-2]=='>')) {
		snprintf(temp,32768, "Message-ID: %s",p);
		/* "^aRFCID: <local@machine" */
		/* I saw it on some IntToss gated articles
		 * it seems to be a bug on the program or something
		 * like that, because in the majority of IntToss gated
		 * articles it is "^aRFCID: local@machine"
		 */
	    } else { 
		p[strlen(p)-1]='\0';
                snprintf(temp,32768, "Message-ID: %s>\n",p);
	    }
	    /* "^aRFCID: local@machine" */
	} else { 
	    p[strlen(p)-1]='\0'; 
	    snprintf(temp,32768, "Message-ID: <%s>\n",p);
	}
    } else if ((p=hdr((char *)"ORIGID",kmsg))) {
	    snprintf(temp,32768, "Message-ID: %s",p);
    } else if ((p = hdr((char *)"MSGID",kmsg))) {
	q = rfcmsgid(p, bestaka);
	snprintf(temp,32768, "Message-ID: %s\n", q);
        free(q);
    } else {
	snprintf(temp,32768, "Message-ID: <%lu@%s.ftn>\n", mdate^(subj?str_crc32(subj):0L), ascinode(f,0x1f));
    }
    Send(newsmode, temp);

    if (newsmode) {
	if ((p=hdr((char *)"References",msg))) {
	    snprintf(temp,32768, "References:%s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"RFC-References",kmsg))) {
	    snprintf(temp,32768, "References: %s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"References",kmsg))) {
	    snprintf(temp,32768, "References: %s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"ORIGREF",kmsg))) {
	    snprintf(temp,32768, "References: %s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"REPLY",kmsg))) {
	    q = rfcmsgid(p, bestaka);
	    snprintf(temp,32768, "References: %s\n", q);
	    Send(newsmode, temp);
	    free(q);
	}
    } else {
	if ((p=hdr((char *)"In-Reply-To",msg))) {
	    snprintf(temp,32768, "In-Reply-To:%s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"RFC-In-Reply-To",kmsg))) {
	    snprintf(temp,32768, "In-Reply-To: %s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"REPLY",kmsg))) {
	    q = rfcmsgid(p,bestaka);
	    snprintf(temp,32768, "In-Reply-To: %s\n", q);
	    Send(newsmode, temp);
	    free(q);
	}
    }

    if ((p=hdr((char *)"Organization",msg))) {
	snprintf(temp,32768, "Organization:%s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"Organisation",msg))) {
	snprintf(temp,32768, "Organization:%s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"RFC-Organization",kmsg))) {
	snprintf(temp,32768, "Organization: %s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"RFC-Organisation",kmsg))) {
	snprintf(temp,32768, "Organization: %s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"Organization",kmsg))) {
	snprintf(temp,32768, "Organization: %s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"Organisation",kmsg))) {
	snprintf(temp,32768, "Organization: %s",p);
	Send(newsmode, temp);
    } else if (origline) {
	snprintf(temp,32768, "Organization: %s\n",origline);
	Send(newsmode, temp);
    }
	
    if ((p=hdr((char *)"Supersedes",msg))) {
	snprintf(temp,32768, "Supersedes:%s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"RFC-Supersedes",kmsg))) {
	snprintf(temp,32768, "Supersedes: %s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"Supersedes",kmsg))) {
	snprintf(temp,32768, "Supersedes: %s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"ACUPDATE",kmsg)) && (strstr(p,"MODIFY"))) {
	q = rfcmsgid(p+8,bestaka);
	snprintf(temp,32768, "Supersedes: %s\n", q);
	Send(newsmode, temp);
	free(q);
    }

    if (CFG.allowcontrol) {
	if ((p=hdr((char *)"Control",msg))) {
	    snprintf(temp,32768, "Control:%s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"RFC-Control",kmsg))) {
	    snprintf(temp,32768, "Control: %s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"Control",kmsg))) {
	    snprintf(temp,32768, "Control: %s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"ACUPDATE",kmsg)) && (strstr(p,"DELETE"))) {
	    q = rfcmsgid(p+8,bestaka);
	    snprintf(temp,32768, "Control: cancel %s\n", q);
	    Send(newsmode, temp);
	    free(q);
	}
    }

    if ((p=hdr((char *)"Mime-Version",msg))) {
	snprintf(temp,32768, (char *)"Mime-Version:%s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"RFC-Mime-Version",kmsg))) {
	snprintf(temp,32768, (char *)"Mime-Version: %s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"Mime-Version",kmsg))) {
	snprintf(temp,32768, (char *)"Mime-Version: %s",p);
	Send(newsmode, temp);
    }

    /*
     * We have setup translation, send the right charset name
     */
    if ((p=hdr((char *)"Content-Type",msg))) {
	snprintf(temp, 32768, "Content-Type: text/plain; charset=%s\n", getrfcchrs(msgs.Charset));
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"RFC-Content-Type",kmsg))) {
	snprintf(temp, 32768, "Content-Type: text/plain; charset=%s\n", getrfcchrs(msgs.Charset));
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"Content-Type",kmsg))) {
	snprintf(temp, 32768, "Content-Type: text/plain; charset=%s\n", getrfcchrs(msgs.Charset));
	Send(newsmode, temp);
    }

    if ((p=hdr((char *)"Content-Length",msg))) {
	snprintf(temp,32768, "Content-Length%s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"RFC-Content-Length",kmsg))) {
	snprintf(temp,32768, "Content-Length: %s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"Content-Length",kmsg))) {
	snprintf(temp,32768, "Content-Length: %s",p);
	Send(newsmode, temp);
    }

    if ((p=hdr((char *)"Content-Transfer-Encoding",msg))) {
	snprintf(temp,32768, "Content-Transfer-Encoding:%s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"RFC-Content-Transfer-Encoding",kmsg))) {
	snprintf(temp,32768, "Content-Transfer-Encoding: %s",p);
	Send(newsmode, temp);
    } else if ((p=hdr((char *)"Content-Transfer-Encoding",kmsg))) {
	snprintf(temp,32768, "Content-Transfer-Encoding: %s",p);
	Send(newsmode, temp);
    }

    if (newsmode) {
	if ((p=hdr((char *)"X-Newsreader",msg))) {
	    snprintf(temp,32768, "X-Newsreader: %s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"RFC-X-Newsreader",kmsg))) {
	    snprintf(temp,32768, "X-Newsreader: %s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"X-Newsreader",kmsg))) {
	    snprintf(temp,32768, "X-Newsreader: %s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"PID",kmsg))) {
	    snprintf(temp,32768, "X-Newsreader: %s",p);
	    Send(newsmode, temp);
	}
    } else {
	if ((p=hdr((char *)"X-Mailer",msg))) {
	    snprintf(temp,32768, "X-Mailer:%s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"RFC-X-Mailer",kmsg))) {
	    snprintf(temp,32768, "X-Mailer: %s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"X-Mailer",kmsg))) {
	    snprintf(temp,32768, "X-Mailer: %s",p);
	    Send(newsmode, temp);
	} else if ((p=hdr((char *)"PID",kmsg))) {
	    snprintf(temp,32768, "X-Mailer: %s",p);
	    Send(newsmode, temp);
	}
    }

    /*
     * Convert some ftn kludges to rfc. We should not have these but
     * GoldED posts news with plain ftn kludges as rfc headers.
     */
    if ((p = hdr((char *)"CHRS", msg))) {
	snprintf(temp, 32768, "X-FTN-CHRS:%s", p);
	Send(newsmode, temp);
    }
    if ((p = hdr((char *)"MSGID", msg))) {
	snprintf(temp, 32768, "X-FTN-MSGID:%s", p);
	Send(newsmode, temp);
    }
    if ((p = hdr((char *)"PID", msg))) {
	snprintf(temp, 32768, "X-FTN-PID:%s", p);
	Send(newsmode, temp);
    }
    if ((p = hdr((char *)"TZUTC", msg))) {
	snprintf(temp, 32768, "X-FTN-TZUTC:%s", p);
	Send(newsmode, temp);
    }

    for (qmsg = msg; qmsg; qmsg = qmsg->next) {
	if (strcasecmp(qmsg->key,"CHRS") &&
	    strcasecmp(qmsg->key,"MSGID") &&
	    strcasecmp(qmsg->key,"PID") &&
	    strcasecmp(qmsg->key,"TZUTC") &&
	    strcasecmp(qmsg->key,"X-Body-Start") &&
	    strcasecmp(qmsg->key,"X-PcBoard-FROM") &&
	    strcasecmp(qmsg->key,"X-PcBoard-SUBJECT") &&
	    strcasecmp(qmsg->key,"X-PcBoard-PACKOUT") &&
            (strcasecmp(qmsg->key,"Control") || !CFG.allowcontrol) &&
            strcasecmp(qmsg->key,"Supersedes") &&
            strcasecmp(qmsg->key,"Mime-Version") &&
            strcasecmp(qmsg->key,"Content-Type") &&
            strcasecmp(qmsg->key,"Content-Length") &&
            strcasecmp(qmsg->key,"Content-Transfer-Encoding") &&
            strcasecmp(qmsg->key,"Lines") &&
            strcasecmp(qmsg->key,"Path") &&
            strcasecmp(qmsg->key,"Received") &&
            strcasecmp(qmsg->key,"From") &&
            strcasecmp(qmsg->key,"To") &&
            strcasecmp(qmsg->key,"Comment-To") &&
            strcasecmp(qmsg->key,"X-Comment-To") &&
            strcasecmp(qmsg->key,"Date") &&
            strcasecmp(qmsg->key,"Subject") &&
            strcasecmp(qmsg->key,"Reply-To") &&
            strcasecmp(qmsg->key,"In-Reply-To") &&
            strcasecmp(qmsg->key,"References") &&
            strcasecmp(qmsg->key,"Organization") &&
	    strcasecmp(qmsg->key,"Organisation") &&
            strcasecmp(qmsg->key,"X-Mailer") &&
            strcasecmp(qmsg->key,"X-Newsreader") &&
            (strcasecmp(qmsg->key,"Newsgroups") || !newsmode) &&
            strcasecmp(qmsg->key,"Apparently-To") &&
            strcasecmp(qmsg->key,"Distribution") &&
            strcasecmp(qmsg->key,"Approved") &&
            strcasecmp(qmsg->key,"Message-ID")) {
	    snprintf(temp,32768, "%s:%s",qmsg->key,qmsg->val);
	    Send(newsmode, temp);
	}
    }

    if ((p=compose_flags(flags,hdr((char *)"FLAGS",kmsg)))) {
	snprintf(temp,32768, "X-FTN-FLAGS:%s\n",p);
	Send(newsmode, temp);
	free(p);
    }

    for (qmsg = kmsg; qmsg; qmsg = qmsg->next) {
	if (strcasecmp(qmsg->key,"INTL") &&
	    strcasecmp(qmsg->key,"FMPT") &&
            strcasecmp(qmsg->key,"TOPT") &&
            strcasecmp(qmsg->key,"FLAGS") &&
            strcasecmp(qmsg->key,"CHARSET") &&
            strcasecmp(qmsg->key,"CHRS") &&
            strcasecmp(qmsg->key,"CODEPAGE") &&
            strcasecmp(qmsg->key,"ORIGCHRS") &&
	    /*
	     * RFC: is used by fidogate to tell how completly RFC headers were
	     * gated (0=no headers at all; 1=some headers; 2=all headers)
	    */
            strcasecmp(qmsg->key,"RFC") &&  
            strcasecmp(qmsg->key,"RFCID") &&
            strcasecmp(qmsg->key,"ORIGID") &&
            strcasecmp(qmsg->key,"ORIGREF") &&
            strcasecmp(qmsg->key,"X-GATEWAY") &&
            strcasecmp(qmsg->key,"Lines") &&
	    /* strcmp(qmsg->key,"Path") &&         */
            strcasecmp(qmsg->key,"PATH") &&
            strcasecmp(qmsg->key,"Received") &&
            strcasecmp(qmsg->key,"From") &&
            strcasecmp(qmsg->key,"To") &&
            strcasecmp(qmsg->key,"Comment-To") &&
            strcasecmp(qmsg->key,"X-Comment-To") &&
            strcasecmp(qmsg->key,"Date") &&
            strcasecmp(qmsg->key,"Subject") &&
            strcasecmp(qmsg->key,"Reply-To") &&
            strcasecmp(qmsg->key,"In-Reply-To") &&
            strcasecmp(qmsg->key,"References") &&
            strcasecmp(qmsg->key,"Organization") &&
	    strcasecmp(qmsg->key,"Organisation") &&
	    strcasecmp(qmsg->key,"X-Mailer") &&
            strcasecmp(qmsg->key,"X-Newsreader") &&
            (strcasecmp(qmsg->key,"Newsgroups") || !newsmode) &&
            strcasecmp(qmsg->key,"Apparently-To") &&
            strcasecmp(qmsg->key,"Message-ID") &&
            strcasecmp(qmsg->key,"Mime-Version") &&
            strcasecmp(qmsg->key,"Content-Type") &&
            strcasecmp(qmsg->key,"Content-Lenght") &&
            strcasecmp(qmsg->key,"Content-Transfer-Encoding") &&
            (strcasecmp(qmsg->key,"RFC-Control") || !CFG.allowcontrol) &&
            strcasecmp(qmsg->key,"RFC-Supersedes") &&
            strcasecmp(qmsg->key,"RFC-Mime-Version") &&
            strcasecmp(qmsg->key,"RFC-Content-Type") &&
            strcasecmp(qmsg->key,"RFC-Content-Lenght") &&
            strcasecmp(qmsg->key,"RFC-Content-Transfer-Encoding") &&
            strcasecmp(qmsg->key,"RFC-Lines") &&
            strcasecmp(qmsg->key,"RFC-Path") &&
            strcasecmp(qmsg->key,"RFC-Received") &&
            strcasecmp(qmsg->key,"RFC-From") &&
            strcasecmp(qmsg->key,"RFC-To") &&
            strcasecmp(qmsg->key,"RFC-Comment-To") &&
            strcasecmp(qmsg->key,"RFC-X-Comment-To") &&
            strcasecmp(qmsg->key,"RFC-Date") &&
            strcasecmp(qmsg->key,"RFC-Subject") &&
            strcasecmp(qmsg->key,"RFC-Reply-To") &&
            strcasecmp(qmsg->key,"RFC-In-Reply-To") &&
            strcasecmp(qmsg->key,"RFC-References") &&
            strcasecmp(qmsg->key,"RFC-Organization") &&
            strcasecmp(qmsg->key,"RFC-X-Mailer") &&
            strcasecmp(qmsg->key,"RFC-X-Newsreader") &&
            (strcasecmp(qmsg->key,"RFC-Newsgroups") || !newsmode) &&
            strcasecmp(qmsg->key,"RFC-Apparently-To") &&
            strcasecmp(qmsg->key,"RFC-Distribution") &&
            strcasecmp(qmsg->key,"RFC-Approved") &&
            strcasecmp(qmsg->key,"RFC-Message-ID")) {
	    if (!strncmp(qmsg->key,"RFC-",4)) {
		snprintf(temp,32768, "%s: %s",qmsg->key+4,qmsg->val);
		Send(newsmode, temp);
	    } else if ((!strncasecmp(qmsg->key,"X-",2)) || (!strncasecmp(qmsg->key,"NNTP-",5))) {
		snprintf(temp,32768, "%s: %s",qmsg->key,qmsg->val);
		Send(newsmode, temp);
	    } else if ((!strncasecmp(qmsg->key,"ZC-",3))) {
		snprintf(temp,32768, "X-%s: %s",qmsg->key,qmsg->val);
		Send(newsmode, temp);
	    } else if ((!strcasecmp(qmsg->key,"Origin")) || (!strcasecmp(qmsg->key,"MOOD"))) {
		snprintf(temp,32768, "X-FTN-%s: %s",qmsg->key,qmsg->val);
		Send(newsmode, temp);
	    } else {
		snprintf(temp,32768, "X-FTN-%s: %s",qmsg->key,qmsg->val);
		Send(newsmode, temp);
	    }
	}
    }

    if (newsmode) {
	fa_list	*tmpl,*ptl=NULL;
	char	sbe[16];
	int	seenlen=0,oldnet;

	for (qmsg = kmsg; qmsg; qmsg = qmsg->next)
	    if (!strcmp(qmsg->key, "PATH")) {
		fill_path(&ptl, qmsg->val);
	    }

	uniq_list(&ptl);

        /*
	 * ensure it will not match for the first entry
	 */
	oldnet = ptl->addr->net-1;
	q = xstrcpy((char*)"X-FTN-PATH:");
	for (tmpl = ptl; tmpl; tmpl = tmpl->next) {
	    if (tmpl->addr->net == oldnet)
		snprintf(sbe,16," %u",tmpl->addr->node);
	    else
		snprintf(sbe,16," %u/%u",tmpl->addr->net, tmpl->addr->node);
	    oldnet=tmpl->addr->net;
	    seenlen+=strlen(sbe);
	    if (seenlen > MAXPATH) {
		seenlen=0;
		snprintf(temp, 32768, "%s\n", q);
		Send(newsmode, temp);
		free(q);
		q = xstrcpy((char *)"X-FTN-PATH:");
		snprintf(sbe,16," %u/%u",tmpl->addr->net, tmpl->addr->node);
		seenlen=strlen(sbe);
	    }
	    q = xstrcat(q, sbe);
	}
	snprintf(temp,32768, "%s\n", q);
	Send(newsmode, temp);
	free(q);
	tidy_falist(&ptl);

	if ((hdr((char *)"X-FTN-SPTH", msg))) {
	    snprintf(temp,32768, "X-FTN-SPTH: %s\n", ascfnode(bestaka,0x1f));
	    Send(newsmode, temp);
	}
    }

    /*
     * Search past RFC headers.
     */
    while (fgets(buf,sizeof(buf)-1,fp)) {
	if ((strlen(buf) == 1) && (buf[0] == '\n')) {
	    break;
	}
    }

    /*
     * Send the message body
     */
    pass=1;
    count = lines = 0;
    first = TRUE;

    Syslog('m', "Start sending message body");
    while (fgets(buf,sizeof(buf)-1,fp) && pass) {
	if (first) {
	    p = xstrcpy((char *)"\n");
	    Send(newsmode, p);
	    free(p);
	    first = FALSE;

	    if ((p=hdr((char *)"X-Body-Start",msg))) {
		lines++;
		q = xstrcpy(p);
		Send(newsmode, q);
		free(q);
	    }
	}

	if (ftell(fp) > endmsg_off) {
	    Syslog('m', "line \"%s\" past message end %d %d", buf,(int)endmsg_off, ftell(fp));
	    pass=0;
	}
	if (pass) {
	    p=buf;
	    b=NULL;
	    while ((c=*p++)) {
		switch (c) {
		    case ' ':       b=p-1; break;
		    case '\n':      b=NULL; count=0; lines++; break;
		}
		if ((count++ > BOUNDARY) /* && (!pgpsigned) */ ) {
		    if (b) {
			*b++='\n';  // Replace space.
			p = b + 1;
			b=NULL;
			lines++;
			count=0;
		    }
		}
	    }
	    if ((strncmp(buf, ".\r\n", 3)) && (strncmp(buf, ".\n", 2)))
		q = xstrcpy(buf);
	    else
		q = xstrcpy((char *)" .\n");
	    Send(newsmode, q);
	    free(q);
	}
    }
    Syslog('m', "End sending message body");

    if (charset)
	free(charset);

    tidyrfc(msg);
    fclose(fp);
    tidyrfc(kmsg);

    if (!newsmode) {
	result = postemail(nfp, MailFrom, MailTo);
	fclose(nfp);
    } else {
	news_in++;
	/*
	 * The newsfile stays open and will be closed later after processing
	 * all echomail.
	 */
	fprintf(nfp, ".\n");
    }

    chartran_close();
    if (newsgroup)
	free(newsgroup);
    rbuf = NULL;
    free(temp);
    return result;
}


