/***************************************************************************** * * $Id$ * 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; Syslog('N' ,"fill_rlist %s",str); 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) Syslog('N', "fill_rlist returns: %s",ascfnode(tmp->addr,0x06)); 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__" 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$" */ else if (!strncmp(p, "wgmid$<", 7)) snprintf(rbuf, bufsize, "%s", p+6); /* in case we have "" */ 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; } Syslog('M', "Message input start ============="); 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 (strlen(buf) > 200) { Syslog('M', "FTN: Next line should be %d characters", strlen(buf)); Syslogp('M', printable(buf, 200)); } else { Syslogp('M', printable(buf, 0)); } 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); Syslog('M', "origin \"%s\" at offset %d", buf,(int)orig_off); 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); } } Syslog('M', "Message input end ==============="); 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); Syslog('M', "newsgroup %s", printable(newsgroup, 0)); 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: \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: " */ if ((p[strlen(p)-2]=='>')) { snprintf(temp,32768, "Message-ID: %s",p); /* "^aRFCID: \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; }