diff --git a/mbfido/ftn2rfc.c b/mbfido/ftn2rfc.c new file mode 100644 index 00000000..d98179e5 --- /dev/null +++ b/mbfido/ftn2rfc.c @@ -0,0 +1,1499 @@ +/***************************************************************************** + * + * File ..................: mbfido/ftn2rfc.c + * Purpose ...............: Gate netmail->email or echomail->news + * Last modification date : 14-Aug-2001 + * + ***************************************************************************** + * Copyright (C) 1997-2001 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "../lib/libs.h" +#include "../lib/structs.h" +#include "../lib/records.h" +#include "../lib/dbftn.h" +#include "../lib/dbdupe.h" +#include "../lib/dbuser.h" +#include "../lib/common.h" +#include "../lib/clcomm.h" +#include "rollover.h" +#include "aliasdb.h" +#include "postemail.h" +#include "backalias.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 long id = 0L; + faddr *ta = NULL; + + if (msgid == NULL) + return NULL; + + /* + * +40 for the additionnal stuff we need to write, should be enough + */ + rbuf = malloc(strlen(msgid) + 40); + 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, "%lx", &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)) { + sprintf(rbuf, "<%lu@%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)) { + sprintf(rbuf, "%s", p+6); + while ((q = strstr(rbuf, ">_<"))) + *(q+1) = ' '; + } + /* "mid__local@domain" are also generated by gigo */ + else if (!strncmp(p, "mid__", 5)) + sprintf(rbuf, "<%s>", p+5); + /* "wgmid$" */ + else if (!strncmp(p, "wgmid$<", 7)) + sprintf(rbuf, "%s", p+6); + /* in case we have "" */ + else if (!strncmp(p, "<", 1)) + sprintf(rbuf, "%s", p); + /* or "local@domain" */ + else + sprintf(rbuf, "<%s>", p); + while ((q = strchr(rbuf, '@')) != strrchr(rbuf, '@')) { + /* we (still) have more than one @ */ + *q = '%'; + } + } else { + sprintf(rbuf, "<%lu@%s>", id, p); + } + free(p); + } + } else { + sprintf(rbuf, "<%lu@%s.ftn>", (unsigned long)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 *); +void substitute(char *buf) +{ + 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"); + sprintf(buf,"%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)) + sprintf(buf, "%s@%s", usr.Name, CFG.sysdomain); + else if (!strcasecmp(buf,"sysop")) + strcpy(buf,"postmaster"); + else + sprintf(buf,"%s",ascinode(fa,0x7f)); + } + } else { + WriteError("substitute(%s) it is not local, may not happen", buf); + sprintf(buf,"%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, const char *, ...); +void Send(int newsmode, const char *format, ...) +{ + char *outstr, *p; + va_list va_ptr; + unsigned long crc; + + outstr = calloc(2048, sizeof(char)); + + va_start(va_ptr, format); + vsprintf(outstr, format, va_ptr); + va_end(va_ptr); + + fwrite(outstr, 1, strlen(outstr), nfp); + + 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); + } + } + + free(outstr); +} + + + +/* + * 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, modtype = 0; + int incode = CHRS_NOTSET, outcode = CHRS_NOTSET; + int waskludge = FALSE, badkludge, pgpsigned = FALSE; + int bNeedToGetAddressFromMsgid = (int)NULL; + int newsmode = 0, lines, pass, count, first; + char *newsgroup = NULL, *distribution = NULL, *moderator = NULL; + char *temp, *p, *q, *r, *l, *b; + char *To = NULL, buf[4096], *charset, c; + 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; + int dirtyoutcode = CHRS_NOTSET; + struct utsname utsbuf; + char MailFrom[128], MailTo[128]; + + temp = calloc(2048, 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('+', "Possible bufferoverflow: line read %d bytes", strlen(buf)); + if (strlen(buf) > 200) { + Syslog('m', "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 %ld", printable(buf, 0), (long)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,PGP_SIGNED_BEGIN, strlen(PGP_SIGNED_BEGIN))) + pgpsigned = TRUE; + else if ((!strncmp(buf,"---",3)) && ((buf[3] == '\r') || (buf[3] == ' ') || (buf[3] == '\n'))) { + 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); + } + Syslog('M', "tearline \"%s\" at offset %ld", buf,(long)tear_off); + } 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 %ld", buf,(long)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; + Syslog('M', "end message offset %ld",(long)endmsg_off); + + rewind(fp); + msg = parsrfc(fp); + bestaka = bestaka_s(f); + rewind(fp); + + p = hdr((char *)"CHRS", kmsg); + if (p == NULL) + p = hdr((char *)"CHARSET", kmsg); + if (p == NULL) + p = hdr((char *)"CODEPAGE", kmsg); + if (p) + outcode = readchrs(p); + 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) + outcode=readcharset(p); + else { + q = rfcmsgid(hdr((char *)"MSGID",kmsg),bestaka); + Syslog('m', "start headers checking 1j"); + if ((hdr((char *)"Message-ID",msg)) || (hdr((char *)"RFC-Message-ID",kmsg)) || + (hdr((char *)"Message-ID",kmsg)) || (hdr((char *)"RFCID",kmsg)) || + (hdr((char *)"ORIGID",kmsg)) || ((hdr((char *)"MSGID",kmsg)) && (!chkftnmsgid(q)))) + outcode = defaultrfcchar; + else + outcode = defaultftnchar; + if (q) + free(q); + q = NULL; + } + } + + /* + * A hack for TerMail + */ + p = hdr((char *)"PID", kmsg); + if ((p) && (!strncmp(p, "TerMail", 7)) && (outcode == defaultrfcchar)) + outcode = defaultftnchar; + + if (dirtyoutcode != CHRS_NOTSET) + outcode = dirtyoutcode; + if (pgpsigned) + incode = outcode; + + if (kmsg && !strcmp(kmsg->key,"AREA")) { + /* + * The msgs record is already loaded. + */ + newsgroup = xstrcpy(msgs.Newsgroup); + if (strlen(msgs.Distribution)) + distribution = xstrcpy(msgs.Distribution); + if (strlen(msgs.Moderator)) { + moderator = xstrcpy(msgs.Moderator); + if (msgs.MsgKinds == USEMOD) + modtype = 1; + } + Syslog('m', "newsgroup %s, distribution %s, moderator %s modtype %d", + printable(newsgroup, 0), printable(distribution, 0), printable(moderator, 0), modtype); + newsmode = TRUE; + if ((modtype == 1) && (!hdr((char *)"Approved",msg)) && + (!hdr((char *)"RFC-Approved",kmsg)) && (!hdr((char *)"Approved",kmsg))) + newsmode = TRUE; + } else + newsmode = FALSE; + Syslog('m', "Got %s message", newsmode?"echo":"netmail"); + + if ((outcode == CHRS_NOTSET) && (hdr((char *)"MSGID", kmsg))) { + p = rfcmsgid(hdr((char *)"MSGID",kmsg),bestaka); + if ((hdr((char *)"Message-ID",msg)) || (hdr((char *)"RFC-Message-ID",kmsg)) || + (hdr((char *)"Message-ID",kmsg)) || (hdr((char *)"RFCID",kmsg)) || + (hdr((char *)"ORIGID",kmsg)) || ((hdr((char *)"MSGID",kmsg)) && (!chkftnmsgid(p)))) + outcode = defaultrfcchar; + else + outcode = defaultftnchar; + free(p); + } + if (pgpsigned) + incode = outcode; + else if (incode == CHRS_NOTSET) + incode = getincode(outcode); + + + /* + * 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); + + 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 if (modtype == 1) + sprintf(buf,"%s",moderator); + else + sprintf(buf,"%s",ascinode(t,0x7f)); + substitute(buf); + Syslog('+', "mail from %s to %s",ascfnode(f,0x7f),buf); + To = xstrcpy(buf); + } + + + if (!newsmode) { + Syslog('m', "Preparing email"); +// if (p) +// free(p); + 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 (p) + sprintf(MailFrom, "%s", p); + else + sprintf(MailFrom, "%s", ascinode(f,0x7f)); + Syslog('m', "MailFrom: %s", MailFrom); + + if (To) + sprintf(MailTo, "%s", To); + else + sprintf(MailTo, "%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"); + + if (modtype == 1) + newsmode = TRUE; + } + + if (newsmode) { + /* + * Open temporary newsfile, append messages if it already exists. + */ + if (!newsopen) { + p = calloc(PATH_MAX, sizeof(char)); + sprintf(p, "%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 + */ + 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"); + Send(newsmode, "%s\n", 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++; + Send(newsmode,"Newsgroups: %s\n",newsgroup); + Send(newsmode,"X-Origin-Newsgroups: %s",p); + } else + Send(newsmode,"Newsgroups: %s\n",newsgroup); + + if ((p=hdr((char *)"Distribution",msg))) + Send(newsmode,"Distribution:%s",p); + else if ((p=hdr((char *)"RFC-Distribution",kmsg))) + Send(newsmode,"Distribution: %s",p); + else if ((p=hdr((char *)"Distribution",kmsg))) + Send(newsmode,"Distribution: %s",p); + else if (distribution) + Send(newsmode,"Distribution: %s\n",distribution); + + 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"))) + Send(newsmode,"X-Comment-To:%s",hdrconv(p,outcode,incode)); + 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"))) + Send(newsmode,"X-Comment-To: %s",hdrconv(p,outcode,incode)); + else if ((t) && (t->name) && (strcasecmp(t->name,"All"))) + Send(newsmode,"X-Comment-To: %s\n",hdrconv(t->name,outcode,incode)); + else + Send(newsmode,"X-Comment-To: All\n"); + } + +// for (tmpml=approve;tmpml;tmpml=tmpml->next) { +// if ((strncmp(newsgroup,tmpml->prefix, strlen(tmpml->prefix)) == 0)) { +// modtype=2; +// moderator=xstrcpy(tmpml->address); +// break; +// } +// } + + if ((p=hdr((char *)"Approved",msg))) + Send(newsmode,"Approved:%s",p); + else if ((p=hdr((char *)"RFC-Approved",kmsg))) + Send(newsmode,"Approved: %s",p); + else if ((p=hdr((char *)"Approved",kmsg))) + Send(newsmode,"Approved: %s",p); + else if (modtype==2) + Send(newsmode,"Approved: %s\n",moderator); + + } else { /* if newsmode */ + time(&now); + if (CFG.EmailMode == E_NOISP) { + /* + * Probaly not needed as messages for systems without ISP never get here. + * Perhaps only news to moderators. + */ + Send(FALSE, "From: %s!", ascinode(f,0x3f)); + Send(FALSE, "%s %s", ascinode(f,0x40), ctime(&mdate)); + } + for (qmsg = kmsg; qmsg; qmsg = qmsg->next) + if (!strcasecmp(qmsg->key,"RFC-Received")) + Send(FALSE, "%s: %s", qmsg->key+4, qmsg->val); + for (qmsg = msg; qmsg; qmsg = qmsg->next) + if (!strcasecmp(qmsg->key,"Received")) + Send(FALSE, "%s:%s", qmsg->key, qmsg->val); + + if ((p=hdr((char *)"Apparently-To",msg))) + Send(FALSE, "Apparently-To: %s\n",p); + else if ((p=hdr((char *)"RFC-Apparently-To",kmsg))) + Send(FALSE, "Apparently-To: %s\n",p); + else if ((p=hdr((char *)"Apparently-To",kmsg))) + Send(FALSE, "Apparently-To: %s\n",p); + else if ((is_local(t))) + Send(FALSE, "Apparently-To: %s\n",buf); + + 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)) { + Send(FALSE,"Notice-Requested-Upon-Delivery-To: %s\n",buf); + } + + 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) { + Send(FALSE,"To:%s",p); + } 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"); + Send(FALSE,"To: %s\n",p); + } else if (modtype == 1) + Send(FALSE,"To: %s\n",moderator); + else if (is_local(t)) { + Syslog('m', "3"); + Send(FALSE, "To: %s <%s>\n", t->name, buf); + } else { + Syslog('m', "4"); + Send(FALSE,"To: %s\n",ascinode(t,0xff)); + } + } + } + + if ((p = hdr((char *)"From",msg))) { + Send(newsmode, "From:%s", hdrconv(p,outcode,incode)); + } else if ((p = hdr((char *)"RFC-From",kmsg))) { + Syslog('m', "b"); + Send(newsmode, "From: %s", hdrconv(p,outcode,incode)); + } else if ((p = hdr((char *)"From\n",kmsg))) { + Syslog('m', "c"); + Send(newsmode, "From: %s", hdrconv(p,outcode,incode)); + } else if ((p = hdr((char *)"X-PcBoard-FROM",msg))) { + if (f->name) { + while (isspace(*p)) + p++; + p[strlen(p)-1] = '\0'; + Send(newsmode,"From: %s <%s>\n", hdrconv(f->name,outcode,incode), p); + } else { + Send(newsmode,"From:%s\n", p); + } + } 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"); + Send(newsmode,"From: \"%s\" <%s>\n",hdrconv(l,outcode,incode),p); + free(q); + } else if (f->name) { + Syslog('m', "e"); + Send(newsmode,"From: \"%s\" <%s>\n",hdrconv(f->name,outcode,incode),p); + } else { + Syslog('m', "f"); + Send(newsmode,"From: %s\n",p); + } + free(p); + } + + if (p) + Send(newsmode,"X-FTN-Sender: %s\n",hdrconv(ascinode(f,0xff),outcode,incode)); + else + Send(newsmode,"From: %s\n",hdrconv(ascinode(f,0xff),outcode,incode)); + + if ((p=hdr((char *)"Reply-To",msg))) + Send(newsmode,"Reply-To:%s",p); + else if ((p=hdr((char *)"RFC-Reply-To",kmsg))) + Send(newsmode,"Reply-To: %s",p); + else if ((p=hdr((char *)"Reply-To",kmsg))) + Send(newsmode,"Reply-To: %s",p); + else if (((p=backalias(f))) && strlen(CFG.sysdomain)) + Send(newsmode,"Reply-To: %s@%s\n",p,CFG.sysdomain); + else if ((p=hdr((char *)"REPLYADDR",kmsg))) + Send(newsmode,"Reply-To: %s",p); + else if ((p=hdr((char *)"REPLYTO",kmsg))) + Send(newsmode,"Reply-To: %s\n",ascinode(parsefaddr(p),0xff)); + + if ((p=hdr((char *)"Date",msg))) + Send(newsmode,"Date:%s",p); + else if ((p=hdr((char *)"RFC-Date",kmsg))) + Send(newsmode,"Date: %s",p); + else if ((p=hdr((char *)"Date",kmsg))) + Send(newsmode,"Date: %s",p); + else if (newsmode) { + /* + * Restamp future postings + */ + if(mdate > time(&now)) { + Syslog('+', "Future posting: %s", rfcdate(mdate)); + Send(newsmode,"Date: %s\n", rfcdate(now)); + Send(newsmode,"X-Origin-Date: %s\n", rfcdate(mdate)); + } else if((mdate < time(&now)-14*24*60*60) && (mdate > time(&now)-RESTAMP_OLD_POSTINGS*24*60*60)) { + /* + * Restamp old postings + */ + Syslog('+', "Article too old, restamped: %s", rfcdate(mdate)); + Send(newsmode,"Date: %s\n", rfcdate(now)); + Send(newsmode,"X-Origin-Date: %s\n", rfcdate(mdate)); + } else + Send(newsmode,"Date: %s\n",rfcdate(mdate)); + } else + Send(newsmode,"Date: %s\n",rfcdate(mdate)); + + if ((p = hdr((char *)"Subject",msg))) + Send(newsmode, "Subject:%s", hdrconv(p,outcode,incode)); + else if ((p = hdr((char *)"RFC-Subject",kmsg))) + Send(newsmode, "Subject: %s", hdrconv(p,outcode,incode)); + else if ((p = hdr((char *)"Subject",kmsg))) + Send(newsmode, "Subject: %s", hdrconv(p,outcode,incode)); + else if ((p = hdr((char *)"X-PcBoard-SUBJECT",msg))) + Send(newsmode, "Subject:%s", hdrconv(p,outcode,incode)); + else if (subj && (strspn(subj," \t\n\r") != strlen(subj))) + Send(newsmode, "Subject: %s\n", hdrconv(subj,outcode,incode)); + else + Send(newsmode, "Subject: \n"); + + if ((p=hdr((char *)"Message-ID",msg))) + Send(newsmode,"Message-ID:%s",p); + else if ((p=hdr((char *)"RFC-Message-ID",kmsg))) + Send(newsmode,"Message-ID: %s",p); + else if ((p=hdr((char *)"Message-ID",kmsg))) + Send(newsmode,"Message-ID: %s",p); + else if ((p=hdr((char *)"RFCID",kmsg))) + if ((p[0]=='<')) { + /* "^aRFCID: " */ + if ((p[strlen(p)-2]=='>')) + Send(newsmode,"Message-ID: %s",p); + /* "^aRFCID: \n",p); + } + } + /* "^aRFCID: local@machine" */ + else { + p[strlen(p)-1]='\0'; + Send(newsmode,"Message-ID: <%s>\n",p); + } else if ((p=hdr((char *)"ORIGID",kmsg))) + Send(newsmode,"Message-ID: %s",p); + else if ((p = hdr((char *)"MSGID",kmsg))) { + q = rfcmsgid(p, bestaka); + Send(newsmode,"Message-ID: %s\n", q); + free(q); + } else + Send(newsmode,"Message-ID: <%lu@%s.ftn>\n", mdate^(subj?str_crc32(subj):0L), ascinode(f,0x1f)); + + if (newsmode) { + if ((p=hdr((char *)"References",msg))) + Send(newsmode,"References:%s",p); + else if ((p=hdr((char *)"RFC-References",kmsg))) + Send(newsmode,"References: %s",p); + else if ((p=hdr((char *)"References",kmsg))) + Send(newsmode,"References: %s",p); + else if ((p=hdr((char *)"ORIGREF",kmsg))) + Send(newsmode,"References: %s",p); + else if ((p=hdr((char *)"REPLY",kmsg))) { + q = rfcmsgid(p, bestaka); + Send(newsmode,"References: %s\n", q); + free(q); + } + } else { + if ((p=hdr((char *)"In-Reply-To",msg))) + Send(newsmode,"In-Reply-To:%s",p); + else if ((p=hdr((char *)"RFC-In-Reply-To",kmsg))) + Send(newsmode,"In-Reply-To: %s",p); + else if ((p=hdr((char *)"REPLY",kmsg))) { + q = rfcmsgid(p,bestaka); + Send(newsmode,"In-Reply-To: %s\n", q); + free(q); + } + } + + if ((p=hdr((char *)"Organization",msg))) + Send(newsmode,"Organization:%s",hdrconv(p,outcode,incode)); + else if ((p=hdr((char *)"Organisation",msg))) + Send(newsmode,"Organization:%s",hdrconv(p,outcode,incode)); + else if ((p=hdr((char *)"RFC-Organization",kmsg))) + Send(newsmode,"Organization: %s",hdrconv(p,outcode,incode)); + else if ((p=hdr((char *)"RFC-Organisation",kmsg))) + Send(newsmode,"Organization: %s",hdrconv(p,outcode,incode)); + else if ((p=hdr((char *)"Organization",kmsg))) + Send(newsmode,"Organization: %s",hdrconv(p,outcode,incode)); + else if ((p=hdr((char *)"Organisation",kmsg))) + Send(newsmode,"Organization: %s",hdrconv(p,outcode,incode)); + else if (origline) + Send(newsmode,"Organization: %s\n",hdrconv(origline,outcode,incode)); + + if ((p=hdr((char *)"Supersedes",msg))) + Send(newsmode,"Supersedes:%s",p); + else if ((p=hdr((char *)"RFC-Supersedes",kmsg))) + Send(newsmode,"Supersedes: %s",p); + else if ((p=hdr((char *)"Supersedes",kmsg))) + Send(newsmode,"Supersedes: %s",p); + else if ((p=hdr((char *)"ACUPDATE",kmsg)) && (strstr(p,"MODIFY"))) { + q = rfcmsgid(p+8,bestaka); + Send(newsmode,"Supersedes: %s\n", q); + free(q); + } + if (CFG.allowcontrol) { + if ((p=hdr((char *)"Control",msg))) + Send(newsmode,"Control:%s",p); + else if ((p=hdr((char *)"RFC-Control",kmsg))) + Send(newsmode,"Control: %s",p); + else if ((p=hdr((char *)"Control",kmsg))) + Send(newsmode,"Control: %s",p); + else if ((p=hdr((char *)"ACUPDATE",kmsg)) && (strstr(p,"DELETE"))) { + q = rfcmsgid(p+8,bestaka); + Send(newsmode,"Control: cancel %s\n", q); + free(q); + } + } + + Send(newsmode, "X-FTN-CHRS: %s\n", getchrs(incode)); + if (incode != outcode) + Send(newsmode, "X-FTN-ORIGCHRS: %s\n", getchrs(outcode)); + charset = getcharset(incode); + + if ((p=hdr((char *)"Mime-Version",msg))) + Send(newsmode,(char *)"Mime-Version:%s",p); + else if ((p=hdr((char *)"RFC-Mime-Version",kmsg))) + Send(newsmode,(char *)"Mime-Version: %s",p); + else if ((p=hdr((char *)"Mime-Version",kmsg))) + Send(newsmode,(char *)"Mime-Version: %s",p); + else if ((charset) && (incode != CHRS_NOTSET)) + Send(newsmode,"Mime-Version: 1.0\n"); + + temp[0] = '\0'; + if ((p=hdr((char *)"Content-Type",msg))) + Send(newsmode,"Content-Type:%s",p); + else if ((p=hdr((char *)"RFC-Content-Type",kmsg))) + Send(newsmode,"Content-Type: %s",p); + else if ((p=hdr((char *)"Content-Type",kmsg))) + Send(newsmode,"Content-Type: %s",p); + else if ((charset) && (incode != CHRS_NOTSET)) { + if ((p=hdr((char *)"FSCHTML",kmsg)) || (p=hdr((char *)"HTML",kmsg))) + Send(newsmode,"Content-Type: text/html; charset=%s\n",charset); + else + Send(newsmode,"Content-Type: text/plain; charset=%s\n",charset); + } + + if ((p=hdr((char *)"Content-Length",msg))) + Send(newsmode,"Content-Length%s",p); + else if ((p=hdr((char *)"RFC-Content-Length",kmsg))) + Send(newsmode,"Content-Length: %s",p); + else if ((p=hdr((char *)"Content-Length",kmsg))) + Send(newsmode,"Content-Length: %s",p); + + temp[0] = '\0'; + if ((p=hdr((char *)"Content-Transfer-Encoding",msg))) + sprintf(temp,"Content-Transfer-Encoding:%s",p); + else if ((p=hdr((char *)"RFC-Content-Transfer-Encoding",kmsg))) + sprintf(temp,"Content-Transfer-Encoding: %s",p); + else if ((p=hdr((char *)"Content-Transfer-Encoding",kmsg))) + sprintf(temp,"Content-Transfer-Encoding: %s",p); + else if ((charset) && (incode == CHRS_ISO_8859_1_QP)) + sprintf(temp,"Content-Transfer-Encoding: quoted-printable\n"); + else if ((charset) && (incode != CHRS_NOTSET)) { + if ((incode == CHRS_ASCII || incode == CHRS_UTF_7)) + sprintf(temp,"Content-Transfer-Encoding: 7bit\n"); + else if (strncasecmp(charset,"iso-2022-",9) == 0) + sprintf(temp,"Content-Transfer-Encoding: 7bit\n"); + else + sprintf(temp,"Content-Transfer-Encoding: 8bit\n"); /* all others are 8 bit */ + } + if (temp[0]) + Send(newsmode, temp); + + if (newsmode) { + if ((p=hdr((char *)"X-Newsreader",msg))) + Send(newsmode,"X-Newsreader: %s",p); + else if ((p=hdr((char *)"RFC-X-Newsreader",kmsg))) + Send(newsmode,"X-Newsreader: %s",p); + else if ((p=hdr((char *)"X-Newsreader",kmsg))) + Send(newsmode,"X-Newsreader: %s",p); + else if ((p=hdr((char *)"PID",kmsg))) + Send(newsmode,"X-Newsreader: %s",p); + } else { + if ((p=hdr((char *)"X-Mailer",msg))) + Send(newsmode,"X-Mailer:%s",p); + else if ((p=hdr((char *)"RFC-X-Mailer",kmsg))) + Send(newsmode,"X-Mailer: %s",p); + else if ((p=hdr((char *)"X-Mailer",kmsg))) + Send(newsmode,"X-Mailer: %s",p); + else if ((p=hdr((char *)"PID",kmsg))) + Send(newsmode,"X-Mailer: %s",p); + } + + for (qmsg=msg;qmsg;qmsg=qmsg->next) { + if (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-Lenght") && + 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")) + Send(newsmode,"%s:%s",qmsg->key,hdrconv(qmsg->val,outcode,incode)); + } + + if ((p=compose_flags(flags,hdr((char *)"FLAGS",kmsg)))) { + Send(newsmode,"X-FTN-FLAGS:%s\n",p); + 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)) + Send(newsmode,"%s: %s",qmsg->key+4,hdrconv(qmsg->val,outcode,incode)); + else if ((!strncasecmp(qmsg->key,"X-",2)) || (!strncasecmp(qmsg->key,"NNTP-",5))) + Send(newsmode,"%s: %s",qmsg->key,hdrconv(qmsg->val,outcode,incode)); + else if ((!strncasecmp(qmsg->key,"ZC-",3))) + Send(newsmode,"X-%s: %s",qmsg->key,qmsg->val); + else if ((!strcasecmp(qmsg->key,"Origin")) || (!strcasecmp(qmsg->key,"MOOD"))) + Send(newsmode,"X-FTN-%s: %s",qmsg->key,hdrconv(qmsg->val,outcode,incode)); + else + Send(newsmode,"X-FTN-%s: %s",qmsg->key,qmsg->val); + } + } + + 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) + sprintf(sbe," %u",tmpl->addr->node); + else + sprintf(sbe," %u/%u",tmpl->addr->net, tmpl->addr->node); + oldnet=tmpl->addr->net; + seenlen+=strlen(sbe); + if (seenlen > MAXPATH) { + seenlen=0; + Send(newsmode, "%s\n", q); + free(q); + q = xstrcpy((char *)"X-FTN-PATH:"); + sprintf(sbe," %u/%u",tmpl->addr->net, tmpl->addr->node); + seenlen=strlen(sbe); + } + q = xstrcat(q, sbe); + } + Send(newsmode,"%s\n", q); + free(q); + tidy_falist(&ptl); + + if ((hdr((char *)"X-FTN-SPTH", msg))) + Send(newsmode,"X-FTN-SPTH: %s\n", ascfnode(bestaka,0x1f)); + } + + /* + * 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) { + Send(newsmode, (char *)"\n"); + first = FALSE; + +/* FIXME: Maybe scan now for repeating headers and drop them as they will appear in the message text */ + + if ((p=hdr((char *)"X-Body-Start",msg))) { + lines++; + Send(newsmode, "%s", strkconv(p, outcode, incode)); + } + } + + if (ftell(fp) > endmsg_off) { + Syslog('M', "line \"%s\" past message end %ld %ld", buf,(long)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++='\r'; + *b = '\n'; + p=b+2; + b=NULL; + lines++; + count=0; + } + } + } + if (strncmp(buf, ".\r\n", 3)) + Send(newsmode, strkconv(buf, outcode, incode)); + else + Send(newsmode, (char *)" .\n"); + } + } + Syslog('M', "End sending message body"); + + if ((modtype==1) && (!hdr((char *)"Approved",msg)) && + (!hdr((char *)"RFC-Approved",kmsg)) && (!hdr((char *)"Approved",kmsg))) + newsmode = FALSE; + + 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"); + } + +// if (p) Geeft segfault +// free(p); + if (newsgroup) + free(newsgroup); + if (distribution) + free(distribution); + if (moderator) + free(moderator); + rbuf = NULL; + free(temp); + return result; +} + + diff --git a/mbfido/ftn2rfc.h b/mbfido/ftn2rfc.h new file mode 100644 index 00000000..d52d4e5a --- /dev/null +++ b/mbfido/ftn2rfc.h @@ -0,0 +1,8 @@ +#ifndef _FTN2RFC_H +#define _FTN2RFC_H + + +int ftn2rfc(faddr *, faddr *, char *, char *, time_t, int, FILE *); + +#endif + diff --git a/mbfido/postecho.c b/mbfido/postecho.c new file mode 100644 index 00000000..cc773b4f --- /dev/null +++ b/mbfido/postecho.c @@ -0,0 +1,584 @@ +/***************************************************************************** + * + * File ..................: mbfido/postecho.c + * Purpose ...............: Post echomail message. + * Last modification date : 25-Aug-2001 + * + ***************************************************************************** + * Copyright (C) 1997-2001 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "../lib/libs.h" +#include "../lib/structs.h" +#include "../lib/records.h" +#include "../lib/common.h" +#include "../lib/clcomm.h" +#include "../lib/msg.h" +#include "../lib/msgtext.h" +#include "../lib/dbcfg.h" +#include "../lib/dbnode.h" +#include "../lib/dbmsgs.h" +#include "../lib/dbdupe.h" +#include "../lib/dbuser.h" +#include "../lib/dbftn.h" +#include "ftn2rfc.h" +#include "postecho.h" +#include "storeecho.h" +#include "addpkt.h" +#include "rollover.h" + + + +/* + * External declarations + */ +extern int do_quiet; /* No tty output */ +extern int do_unsec; /* Toss unsecure */ +extern int check_dupe; /* Check dupes */ +extern time_t t_start; /* Reference time */ +extern int most_debug; /* Heavy debugging */ +extern int echo_in; /* Echomail processed */ +extern int echo_out; /* Echomail forwarded */ +extern int echo_bad; /* Bad echomail */ + + +#define MAXPATH 73 +#define MAXSEEN 70 + + +void tidy_qualify(qualify **); +void fill_qualify(qualify **, fidoaddr, int, int); +void dlog_qualify(qualify **, char *); +int EchoOut(fidoaddr, char *, char *, char *, FILE *, int, int, time_t); + + + + +/* + * Add echomail mesage to the queue. + */ +int EchoOut(fidoaddr aka, char *toname, char *fromname, char *subj, FILE *fp, int flags, int cost, time_t date) +{ + char *buf; + FILE *qp; + faddr *From, *To; + int rc; + + if ((qp = OpenPkt(msgs.Aka, aka, (char *)"qqq")) == NULL) { + WriteError("EchoOut(): OpenPkt failed"); + return 1; + } + + From = fido2faddr(msgs.Aka); + To = fido2faddr(aka); + rc = AddMsgHdr(qp, From, To, flags, cost, date, toname, fromname, subj); + tidy_faddr(To); + tidy_faddr(From); + if (rc) { + WriteError("EchoOut(): AddMsgHdr failed"); + return 1; + } + + rewind(fp); + buf = calloc(2048, sizeof(char)); + + while ((fgets(buf, 2048, fp)) != NULL) { + Striplf(buf); + fprintf(qp, "%s\r", buf); + } + + free(buf); + putc(0, qp); + fsync(fileno(qp)); + fclose(qp); + return 0; +} + + + +void tidy_qualify(qualify **qal) +{ + qualify *tmp, *old; + + for (tmp = *qal; tmp; tmp = old) { + old = tmp->next; + free(tmp); + } + *qal = NULL; +} + + + +void fill_qualify(qualify **qal, fidoaddr aka, int orig, int insb) +{ + qualify *tmp; + + tmp = (qualify *)malloc(sizeof(qualify)); + tmp->next = *qal; + tmp->aka = aka; + tmp->inseenby = insb; + tmp->send = ((!insb) && (!orig)); + tmp->orig = orig; + *qal = tmp; +} + + + +void dlog_qualify(qualify **qal, char *msg) +{ + qualify *tmpl; + + for (tmpl = *qal; tmpl; tmpl = tmpl->next) { + Syslog('m', "%s InSB=%s Snd=%s Org=%s", + aka2str(tmpl->aka), tmpl->inseenby ? "True":"False", + tmpl->send ? "True":"False", + tmpl->orig ? "True":"False"); + } +} + + + +/* + * Post echomail message, forward if needed. + * pkt_from, from, to, subj, orig, mdate, flags, cost, file + * The msgs record must be in memory. + * + * 1 - Cannot open message base. + * 4 - Rejected echomail message. + * + * For echomail, the crc32 is calculated over the ^AREA kludge, subject, + * message date, origin line, message id. + */ +int postecho(faddr *p_from, faddr *f, faddr *t, char *orig, char *subj, + time_t mdate, int flags, int cost, FILE *fp, int tonews) +{ + char *buf, *msgid = NULL, *reply = NULL, *p, *q, sbe[16]; + int First = TRUE, rc = 0, i, kludges = TRUE; + int dupe = FALSE, bad = TRUE, seenlen, oldnet; + faddr *Faddr; + unsigned long crc; + sysconnect Link; + fa_list *sbl = NULL, *ptl = NULL, *tmpl; + qualify *qal = NULL, *tmpq; + FILE *nfp, *qp; + + Syslog('M', "Entering postecho, area %s %s", msgs.Tag, msgs.Name); + Syslog('M', "p_from: %s", ascfnode(p_from, 0xff)); + Syslog('M', "from : %s", ascfnode(f, 0xff)); + Syslog('M', "to : %s", ascfnode(t, 0xff)); + Syslog('M', "subj : %s", printable(subj, 0)); + Syslog('M', "origin: %s", orig); + Syslog('M', "date : %s", rfcdate(mdate)); + Syslog('M', "flags : %08x", flags); + Syslog('M', "cost : %d", cost); + Syslog('M', "tonews: %s", tonews ? "True":"False"); + + memset(&Link, 0, sizeof(Link)); + crc = 0xffffffff; + echo_in++; + + /* + * p_from is set for tossed echomail, it is NULL for local posted echomail and gated news. + */ + if (p_from) { + while (GetMsgSystem(&Link, First)) { + First = FALSE; + if ((p_from->zone == Link.aka.zone) && (p_from->net == Link.aka.net) && (p_from->node == Link.aka.node)) { + bad = FALSE; + break; + } + } + if (bad && (msgs.UnSecure || do_unsec)) { + bad = FALSE; + memset(&Link, 0, sizeof(Link)); + } + if (bad) { + Syslog('+', "Node %s not connected to area %s", ascfnode(p_from, 0x1f), msgs.Tag); + echo_bad++; + return 4; + } + if (Link.cutoff && !bad) { + Syslog('+', "Echomail from %s in %s refused, cutoff", ascfnode(p_from, 0x1f), msgs.Tag); + bad = TRUE; + echo_bad++; + return 4; + } + if (!Link.receivefrom && !bad) { + Syslog('+', "Echomail from %s in %s refused, read only", ascfnode(p_from, 0x1f), msgs.Tag); + bad = TRUE; + echo_bad++; + return 4; + } + } else { + /* + * Fake the zone entry to be our own zone, this prevents + * zonegate behaviour. It's also not a bad message yet. + */ + Link.aka.zone = msgs.Aka.zone; + bad = FALSE; + } + + if (CFG.toss_old && ((t_start - mdate) / 86400) > CFG.toss_old) { + Syslog('+', "Rejecting msg: too old, %s", rfcdate(mdate)); + bad = TRUE; + echo_bad++; + return 4; + } + + /* + * Read the message for kludges we need. + */ + buf = calloc(2048, sizeof(char)); + First = TRUE; + rewind(fp); + while ((fgets(buf, 2048, fp)) != NULL) { + + Striplf(buf); + Syslogp('M', printable(buf, 0)); + + if (First && (!strncmp(buf, "AREA:", 5))) { + crc = upd_crc32(buf, crc, strlen(buf)); + First = FALSE; + } + if (!strncmp(buf, "\001MSGID: ", 8)) + msgid = xstrcpy(buf + 8); + if (!strncmp(buf, "\001REPLY: ", 8)) + reply = xstrcpy(buf + 8); + if (!strncmp(buf, "SEEN-BY:", 8)) { + if (Link.aka.zone == msgs.Aka.zone) { + p = xstrcpy(buf + 9); + fill_list(&sbl, p, NULL); + free(p); + } else + Syslog('m', "Strip zone SB lines"); + } + if (!strncmp(buf, "\001PATH:", 6)) { + p = xstrcpy(buf + 7); + fill_path(&ptl, p); + free(p); + } + } /* end of checking kludges */ + + + /* + * Further dupe checking. + */ + crc = upd_crc32(subj, crc, strlen(subj)); + if (orig == NULL) + Syslog('!', "No origin line found"); + else + crc = upd_crc32(orig, crc, strlen(orig)); + crc = upd_crc32((char *)&mdate, crc, sizeof(mdate)); + if (msgid != NULL) { + crc = upd_crc32(msgid, crc, strlen(msgid)); + } else { + if (check_dupe) { + /* + * If a MSGID is missing it is possible that dupes from some offline + * readers slip through because these readers use the same date for + * each message. In this case the message text is included in the + * dupecheck. Redy Rodriguez. + */ + rewind(fp); + while ((fgets(buf, 2048, fp)) != NULL) { + Striplf(buf); + if (strncmp(buf, "---", 3) == 0) + break; + if ((strncmp(buf, "\001", 1) != 0 ) && (strncmp(buf,"AREA:",5) != 0 )) + crc = upd_crc32(buf, crc , strlen(buf)); + } + } + } + if (check_dupe) + dupe = CheckDupe(crc, D_ECHOMAIL, CFG.toss_dupes); + else + dupe = FALSE; + + + if (!dupe && !msgs.UnSecure && !do_unsec) { + /* + * Check if the message is for us. Don't check point address, + * echomail messages don't have point destination set. + */ + if ((msgs.Aka.zone != t->zone) || (msgs.Aka.net != t->net) || (msgs.Aka.node != t->node)) { + bad = TRUE; + /* + * If we are a hub or host and have all our echomail + * connected to the hub/host aka, echomail from points + * under a nodenumber aka isn't accepted. The match + * must be further tested. + */ + if ((msgs.Aka.zone == t->zone) && (msgs.Aka.net == t->net)) { + for (i = 0; i < 40; i++) { + if ((CFG.akavalid[i]) && + (CFG.aka[i].zone == t->zone) && + (CFG.aka[i].net == t->net) && + (CFG.aka[i].node == t->node)) + bad = FALSE; /* Undo the result */ + } + } + } + if (bad) { + echo_bad++; + WriteError("Msg in %s not for us (%s) but for %s", msgs.Tag, aka2str(msgs.Aka), ascfnode(t,0x1f)); + free(buf); + if (msgid) + free(msgid); + if (reply) + free(reply); + return 4; + } + } + + + /* + * The echomail message is accepted for post/forward/gate + */ + if (!dupe) { + + if (msgs.Aka.zone != Link.aka.zone) { + /* + * If it is a zonegated echomailmessage the SEEN-BY lines + * are stripped off including that of the other zone's + * gate. Add the gate's aka to the SEEN-BY + */ + Syslog('m', "Gated echomail, clean SB"); + tidy_falist(&sbl); + sprintf(sbe, "%u/%u", Link.aka.net, Link.aka.node); + Syslog('m', "Add gate SB %s", sbe); + fill_list(&sbl, sbe, NULL); + } + + /* + * Add more aka's to SEENBY if in the same zone as our system. + * When ready filter dupe's, there is at least one. + */ + for (i = 0; i < 40; i++) { + if (CFG.akavalid[i] && (msgs.Aka.zone == CFG.aka[i].zone) && + !((msgs.Aka.net == CFG.aka[i].net) && (msgs.Aka.node == CFG.aka[i].node))) { + sprintf(sbe, "%u/%u", CFG.aka[i].net, CFG.aka[i].node); + fill_list(&sbl, sbe, NULL); + } + } + uniq_list(&sbl); + } + + + /* + * Add our system to the path for later export. + */ + sprintf(sbe, "%u/%u", msgs.Aka.net, msgs.Aka.node); + fill_path(&ptl, sbe); + uniq_list(&ptl); /* remove possible duplicate own aka */ + + /* + * Build a list of qualified systems to receive this message. + * Complete the SEEN-BY lines. + */ + First = TRUE; + while (GetMsgSystem(&Link, First)) { + First = FALSE; + if ((Link.aka.zone) && (Link.sendto) && (!Link.pause) && (!Link.cutoff)) { + Faddr = fido2faddr(Link.aka); + if (p_from == NULL) { + fill_qualify(&qal, Link.aka, FALSE, in_list(Faddr, &sbl, FALSE)); + } else { + fill_qualify(&qal, Link.aka, ((p_from->zone == Link.aka.zone) && + (p_from->net == Link.aka.net) && (p_from->node == Link.aka.node) && + (p_from->point == Link.aka.point)), in_list(Faddr, &sbl, FALSE)); + } + tidy_faddr(Faddr); + } + } + + + /* + * Add SEEN-BY for nodes qualified to receive this message. + * When ready, filter the dupes and sort the SEEN-BY entries. + */ + for (tmpq = qal; tmpq; tmpq = tmpq->next) { + if (tmpq->send) { + sprintf(sbe, "%u/%u", tmpq->aka.net, tmpq->aka.node); + fill_list(&sbl, sbe, NULL); + } + } + uniq_list(&sbl); + sort_list(&sbl); + + + /* + * Create a new tmpfile with a copy of the message + * without original PATH and SEENBY lines, add the + * new PATH and SEENBY lines. + */ + rewind(fp); + if ((nfp = tmpfile()) == NULL) + WriteError("$Unable to open tmpfile"); + while ((fgets(buf, 2048, fp)) != NULL) { + Striplf(buf); + fprintf(nfp, "%s", buf); + /* + * Don't write SEEN-BY and PATH lines + */ + if (strncmp(buf, " * Origin:", 10) == 0) + break; + fprintf(nfp, "\n"); + } + + + /* + * Now add new SEEN-BY and PATH lines + */ + seenlen = MAXSEEN + 1; + /* + * Ensure that it will not match for the first entry. + */ + oldnet = sbl->addr->net - 1; + for (tmpl = sbl; tmpl; tmpl = tmpl->next) { + if (tmpl->addr->net == oldnet) + sprintf(sbe, " %u", tmpl->addr->node); + else + sprintf(sbe, " %u/%u", tmpl->addr->net, tmpl->addr->node); + oldnet = tmpl->addr->net; + seenlen += strlen(sbe); + if (seenlen > MAXSEEN) { + seenlen = 0; + fprintf(nfp, "\nSEEN-BY:"); + sprintf(sbe, " %u/%u", tmpl->addr->net, tmpl->addr->node); + seenlen = strlen(sbe); + } + fprintf(nfp, "%s", sbe); + } + + seenlen = MAXPATH + 1; + /* + * Ensure it will not match for the first entry + */ + oldnet = ptl->addr->net - 1; + for (tmpl = ptl; tmpl; tmpl = tmpl->next) { + if (tmpl->addr->net == oldnet) + sprintf(sbe, " %u", tmpl->addr->node); + else + sprintf(sbe, " %u/%u", tmpl->addr->net, tmpl->addr->node); + oldnet = tmpl->addr->net; + seenlen += strlen(sbe); + if (seenlen > MAXPATH) { + seenlen = 0; + fprintf(nfp, "\n\001PATH:"); + sprintf(sbe, " %u/%u", tmpl->addr->net, tmpl->addr->node); + seenlen = strlen(sbe); + } + fprintf(nfp, "%s", sbe); + } + fprintf(nfp, "\n"); + fflush(nfp); + rewind(nfp); + + + /* + * Import this echomail, even if it's bad or a dupe. + */ + if (storeecho(f, t, mdate, flags, subj, msgid, reply, bad, dupe, nfp) || bad || dupe) { + /* + * Store failed or it was bad or a dupe. + */ + WriteError("Store echomail in JAM base failed"); + tidy_falist(&sbl); + tidy_falist(&ptl); + tidy_qualify(&qal); + free(buf); + if (msgid) + free(msgid); + if (reply) + free(reply); + return 0; + } + + /* + * Forward to other links + */ + for (tmpq = qal; tmpq; tmpq = tmpq->next) { + if (tmpq->send) { + if (SearchNode(tmpq->aka)) { + StatAdd(&nodes.MailSent, 1L); + UpdateNode(); + SearchNode(tmpq->aka); + } + echo_out++; + if (EchoOut(tmpq->aka, t->name, f->name, subj, nfp, flags, cost, mdate)) + WriteError("Forward echomail to %s failed", aka2str(tmpq->aka)); + } + } + + /* + * Gate to newsserver + */ + if (strlen(msgs.Newsgroup) && tonews) { + rewind(nfp); + qp = tmpfile(); + while ((fgets(buf, 2048, nfp)) != NULL) { + Striplf(buf); + if (kludges && (buf[0] != '\001') && strncmp(buf, "AREA:", 5)) { + kludges = FALSE; + q = xstrcpy(Msg.From); + for (i = 0; i < strlen(q); i++) + if (q[i] == ' ') + q[i] = '_'; + fprintf(qp, "From: %s@%s\n", q, ascinode(f, 0x1f)); + fprintf(qp, "Subject: %s\n", Msg.Subject); + fprintf(qp, "To: %s\n", Msg.To); + + // FIXME: hier nog X-...-To: ?? + + fprintf(qp, "\n"); + } + fprintf(qp, "%s\n", buf); + } + rewind(qp); + most_debug = TRUE; + ftn2rfc(f, t, subj, orig, mdate, flags, qp); + most_debug = FALSE; + fclose(qp); + } + fclose(nfp); + + /* + * Free memory used by SEEN-BY, ^APATH and Qualified lines. + */ + tidy_falist(&sbl); + tidy_falist(&ptl); + tidy_qualify(&qal); + + if (rc < 0) + rc =-rc; + free(buf); + if (msgid) + free(msgid); + if (reply) + free(reply); + return rc; +} + + + diff --git a/mbfido/postecho.h b/mbfido/postecho.h new file mode 100644 index 00000000..47c4556b --- /dev/null +++ b/mbfido/postecho.h @@ -0,0 +1,21 @@ +#ifndef _POSTECHO_H +#define _POSTECHO_H + + +/* + * Structure for qualified systems to receive a echomail message + */ +typedef struct _qualify { + struct _qualify *next; /* Linked list */ + fidoaddr aka; /* AKA of the linked system */ + unsigned inseenby : 1; /* System is in SEEN-BY */ + unsigned send : 1; /* Send message to link */ + unsigned orig : 1; /* Is originator of message */ +} qualify; + + +int postecho(faddr *, faddr *, faddr *, char *, char *, time_t, int, int, FILE *, int); + + +#endif + diff --git a/mbfido/rfc2ftn.c b/mbfido/rfc2ftn.c new file mode 100644 index 00000000..955c71ca --- /dev/null +++ b/mbfido/rfc2ftn.c @@ -0,0 +1,987 @@ +/***************************************************************************** + * + * File ..................: mbfido/rfc2ftn.c + * Purpose ...............: Convert RFC to FTN + * Last modification date : 14-Aug-2001 + * + ***************************************************************************** + * Copyright (C) 1997-2001 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "../lib/libs.h" +#include "../lib/structs.h" +#include "../lib/records.h" +#include "../lib/common.h" +#include "../lib/clcomm.h" +#include "../lib/mbinet.h" +#include "../lib/dbdupe.h" +#include "../lib/dbnode.h" +#include "../lib/dbmsgs.h" +#include "../lib/msg.h" +#include "../lib/msgtext.h" +#include "mkftnhdr.h" +#include "hash.h" +#include "rollover.h" +#include "pack.h" +#include "postnetmail.h" +#include "postecho.h" +#include "rfc2ftn.h" + + +#define MAXHDRSIZE 2048 +#define MAXSEEN 70 +#define MAXPATH 73 + + +/* + * Global variables + */ +static int ftnorigin; +static int removemime; +static int removemsgid; +static int removeref; +static int removeinreply; +static int removesupersedes; +static int removeapproved; +static int removereplyto; +static int removereturnto; +static int dirtyoutcode = CHRS_NOTSET; + + + +/* + * External variables + */ +extern int do_quiet; +extern int do_learn; +extern int most_debug; +extern int news_in; +extern int email_in; +extern char *replyaddr; + + + +/* + * Internal functions + */ +int needputrfc(rfcmsg *); + + + +int charwrite(char *, FILE *); +int charwrite(char *s, FILE *fp) +{ + if ((strlen(s) >= 3) && (strncmp(s,"---",3) == 0) && (s[3] != '-')) { + putc('-',fp); + putc(' ',fp); + } + while (*s) { + putc(*s, fp); + s++; + } + return 0; +} + + + +/* + * write (multiline) header to kluge: change \n to ' ' and end line with \n + */ +int kludgewrite(char *, FILE *); +int kludgewrite(char *s, FILE *fp) +{ + while (*s) { + if (*s == '\r') + putc('\n', fp); + else { + if (*s != '\n') + putc(*s, fp); + else if (*(s+1)) + putc(' ',fp); + } + s++; + } + putc('\n',fp); + return 0; +} + + + +/* + * Input a RFC message. + */ +int rfc2ftn(FILE *fp, faddr *recipient) +{ + char sbe[16], *p, *q, *temp, *origin; + int i, rc, incode, outcode, pgpsigned, newsmode; + int seenlen, oldnet; + rfcmsg *msg = NULL, *tmsg, *tmp; + ftnmsg *fmsg = NULL; + FILE *ofp; + fa_list *sbl = NULL, *ptl = NULL, *tmpl; + faddr *ta; + unsigned long svmsgid, svreply; + int sot_kludge = FALSE, eot_kludge = FALSE, qp_or_base64 = FALSE, tinyorigin = FALSE; + int needsplit, hdrsize, datasize, splitpart, forbidsplit, rfcheaders; + char newsubj[4 * (MAXSUBJ+1)], *oldsubj, *acup_a = NULL; + unsigned long acup_n = 0; + int html_message = FALSE; + time_t Now; + + temp = calloc(4096, sizeof(char)); + Syslog('m', "Entering rfc2ftn"); + if (recipient) + Syslog('m', "Recipient: %s", ascfnode(recipient, 0xff)); + rewind(fp); + Syslog('m', "========== RFC Start"); + while ((fgets(temp, 4095, fp)) != NULL) { + Syslogp('m', printable(temp, 0)); + } + Syslog('m', "========== RFC end"); + rewind(fp); + msg = parsrfc(fp); + incode = outcode = CHRS_NOTSET; + pgpsigned = FALSE; + + newsmode = hdr((char *)"Newsgroups", msg) ?TRUE:FALSE; + Syslog('m', "RFC message is %s", newsmode ? "news article":"e-mail message"); + + if (newsmode) + news_in++; + else + email_in++; + + p = hdr((char *)"Content-Type",msg); + if (p) + incode = readcharset(p); + if (incode == CHRS_NOTSET) { + p = hdr((char *)"X-FTN-CHRS",msg); + if (p == NULL) + p = hdr((char *)"X-FTN-CHARSET", msg); + if (p == NULL) + p = hdr((char *)"X-FTN-CODEPAGE", msg); + if (p) + incode = readchrs(p); + } + + if ((p = hdr((char *)"Content-Type",msg)) && ((strcasestr(p,(char *)"multipart/signed")) || + (strcasestr(p,(char *)"application/pgp")))) { + pgpsigned = TRUE; + outcode = incode; + } else if ((p = hdr((char *)"X-FTN-ORIGCHRS", msg))) + outcode = readchrs(p); + else if (dirtyoutcode != CHRS_NOTSET) + outcode = dirtyoutcode; + else + outcode = getoutcode(incode); + + if (!CFG.allowcontrol) { + if (hdr((char *)"Control",msg)) { + Syslog('n', "skipping news message"); + tidyrfc(msg); + return 1; + } + } + + if ((fmsg = mkftnhdr(msg, incode, outcode, newsmode, recipient)) == NULL) { + WriteError("Unable to create FTN headers from RFC ones, aborting"); + tidyrfc(msg); + return 1; + } + + if (newsmode) + fmsg->area = xstrcpy(msgs.Tag); + svmsgid = fmsg->msgid_n; + svreply = fmsg->reply_n; + if ((p = hdr((char *)"Message-ID",msg))) { + ftnmsgid(p, &fmsg->msgid_a, &fmsg->msgid_n, fmsg->area); + hash_update_s(&fmsg->msgid_n, fmsg->area); + } + + if ((p = hdr((char *)"References",msg))) { + p = strrchr(p,' '); + ftnmsgid(p,&fmsg->reply_a, &fmsg->reply_n,fmsg->area); + if (!chkftnmsgid(p)) { + hash_update_s(&fmsg->reply_n, fmsg->area); + } + } else if ((p = hdr((char *)"In-Reply-To",msg))) { + ftnmsgid(p,&fmsg->reply_a, &fmsg->reply_n,fmsg->area); + if (!chkftnmsgid(p)) { + hash_update_s(&fmsg->reply_n, fmsg->area); + } + } + + if (incode == CHRS_NOTSET && newsmode) + incode = msgs.Rfccode; + if (outcode == CHRS_NOTSET) { + if (newsmode) + outcode = msgs.Ftncode; + else + outcode = CHRS_DEFAULT_FTN; + } + if ((incode == CHRS_NOTSET) && (hdr((char *)"Message-ID",msg))) { + if (chkftnmsgid(hdr((char *)"Message-ID",msg))) + incode = CHRS_DEFAULT_FTN; + else + incode = CHRS_DEFAULT_RFC; + } + removemime = FALSE; + removemsgid = FALSE; + removeref = FALSE; + removeinreply = FALSE; + removesupersedes = FALSE; + removeapproved = FALSE; + removereplyto = TRUE; + removereturnto = TRUE; + ftnorigin = fmsg->ftnorigin; + if ((hdr((char *)"X-PGP-Signed",msg))) + pgpsigned = TRUE; + if (pgpsigned) + Syslog('n', "pgpsigned = %s", pgpsigned ? "True":"False"); + + q = hdr((char *)"Content-Transfer-Encoding",msg); + if (q) + while (*q && isspace(*q)) + q++; + if (!(q)) + q = (char *)"8bit"; + if ((p = hdr((char *)"Content-Type",msg))) { + while (*p && isspace(*p)) + p++; + + /* + * turn the quoted-printable decode mode on; remember FTN is virtually 8-bit clean + */ + if ((strncasecmp(p, "text/plain", 10) == 0) && (strncasecmp(q, "quoted-printable", 16) == 0)) + qp_or_base64 = 1; + /* + * turn the base64 decode mode on + */ + else if ((strncasecmp(p, "text/plain", 10) == 0) && (strncasecmp(q, "base64", 6) == 0)) + qp_or_base64 = 2; + + /* + * text/html support from FSC-HTML 001 proposal of Odinn Sorensen (2:236/77) + */ + if (strncasecmp(p, "text/html", 9) == 0) + html_message = TRUE; + for (tmp = msg; tmp; tmp = tmp->next) + if (((strcasecmp(tmp->key,"X-FTN-KLUDGE") == 0) && (strcasecmp(tmp->val,"FSCHTML") == 0)) || + (strcasecmp(tmp->key,"X-FTN-HTML") == 0)) + html_message = FALSE; + + if ((readcharset(p) != CHRS_NOTSET ) && ((q == NULL) || (strncasecmp(q,"7bit",4) == 0) || + ((!pgpsigned) && (qp_or_base64==1)) || ((!pgpsigned) && (qp_or_base64==2)) || (strncasecmp(q,"8bit",4) == 0))) + removemime=1; /* no need in MIME headers */ + /* + * some old MUA puts "text" instead of "text/plain; charset=..." + */ + else if ((strcasecmp(p,"text\n") == 0)) + removemime = TRUE; + } + if (removemime || qp_or_base64 || html_message) + Syslog('n', "removemime=%s, qp_or_base64 = %d, html_message=%s", removemime ? "True":"False", qp_or_base64, + html_message ? "True":"False"); + + if ((p = hdr((char *)"Message-ID",msg))) { + if (!removemsgid) + removemsgid = chkftnmsgid(p); + } + Syslog('n', "removemsgid = %s", removemsgid ? "True":"False"); + + if ((!removeref) && (p = hdr((char *)"References",msg))) { + p = xstrcpy(p); + q = strtok(p," \t\n"); + if ((q) && (strtok(NULL," \t\n") == NULL)) + removeref = chkftnmsgid(q); + free(p); + } + if (removeref) + Syslog('n', "removeref = %s", removeref ? "True":"False"); + + if ((p = hdr((char *)"Supersedes",msg))) + removesupersedes = chkftnmsgid(p); + if (removesupersedes) + Syslog('n', "removesupersedes = %s", removesupersedes ? "True":"False"); + + if ((p = hdr((char *)"Approved",msg))) { + while (*p && isspace(*p)) + p++; + if ((q = strchr(p,'\n'))) + *q='\0'; + if (newsmode && strlen(msgs.Moderator) && (strcasestr(msgs.Moderator,p))) + removeapproved = TRUE; + if (q) + *q='\n'; + } + if (removeapproved) + Syslog('n', "removeapproved = %s", removeapproved ? "True":"False"); + + if ((p = hdr((char *)"Reply-To",msg))) { + removereplyto = FALSE; + if ((q = hdr((char *)"From",msg))) { + char *r; + r = xstrcpy(p); + p = r; + while(*p && isspace(*p)) + p++; + if (p[strlen(p)-1] == '\n') + p[strlen(p)-1]='\0'; + if (strcasestr(q,p)) + removereplyto = TRUE; +// free(r); + } + } + Syslog('n', "removereplyto = %s", removereplyto ? "True":"False"); + + if ((p = hdr((char *)"Return-Receipt-To",msg))) { + removereturnto = FALSE; + if ((q = hdr((char *)"From",msg))) { + char *r; + + r = xstrcpy(p); + p = r; + while (*p && isspace(*p)) + p++; + if (p[strlen(p)-1] == '\n') + p[strlen(p)-1]='\0'; + if (strcasestr(q,p)) + removereturnto = TRUE; +// free(r); + } + } + if (!removereturnto) + Syslog('n', "removereturnto = %s", removereturnto ? "True":"False"); + + p = ascfnode(fmsg->from,0x1f); + i = 79-11-3-strlen(p); + if (ftnorigin && fmsg->origin && (strlen(fmsg->origin) > i)) { + /* This is a kludge... I don't like it too much. But well, + if this is a message of FTN origin, the original origin (:) + line MUST have been short enough to fit in 79 chars... + So we give it a try. Probably it would be better to keep + the information about the address format from the origin + line in a special X-FTN-... header, but this seems even + less elegant. Any _good_ ideas, anyone? */ + + /* OK, I am keeping this, though if should never be used + al long as X-FTN-Origin is used now */ + + p = ascfnode(fmsg->from,0x0f); + Syslog('n', "checkorigin 3"); + i = 79-11-3-strlen(p); + tinyorigin = TRUE; + } + if (tinyorigin) + Syslog('n', "tinyorigin = %s", tinyorigin ? "True":"False"); + + if ((fmsg->origin) && (strlen(fmsg->origin) > i)) + fmsg->origin[i]='\0'; + forbidsplit = (ftnorigin || (hdr((char *)"X-FTN-Split",msg))); + needsplit = 0; + splitpart = 0; + hdrsize = 20; + hdrsize += (fmsg->subj)?strlen(fmsg->subj):0; + if (fmsg->from) + hdrsize += (fmsg->from->name)?strlen(fmsg->from->name):0; + if (fmsg->to) + hdrsize += (fmsg->to->name)?strlen(fmsg->to->name):0; + do { + Syslog('n', "split loop, splitpart = %d", splitpart); + datasize = 0; + + if (splitpart) { + sprintf(newsubj,"[part %d] ",splitpart+1); + strncat(newsubj,fmsg->subj,MAXSUBJ-strlen(newsubj)); + } else { + strncpy(newsubj,fmsg->subj,MAXSUBJ); + } + strcpy(newsubj, hdrnconv(newsubj, incode, outcode, MAXSUBJ)); + newsubj[MAXSUBJ]='\0'; + + if (splitpart) { + hash_update_n(&fmsg->msgid_n,splitpart); + } + oldsubj = fmsg->subj; + fmsg->subj = newsubj; + + /* + * Create a new temp message in FTN style format + */ + if ((ofp = tmpfile()) == NULL) { + WriteError("$Can't open second tmpfile"); + tidyrfc(msg); + return 1; + } + + if (newsmode) { + fprintf(ofp, "AREA:%s\n", msgs.Tag); + } else { + if (fmsg->to->point != 0) + fprintf(ofp, "\001TOPT %d\n", fmsg->to->point); + if (fmsg->from->point != 0) + fprintf(ofp, "\001FMPT %d\n", fmsg->from->point); + fprintf(ofp, "\001INTL %d:%d/%d %d:%d/%d\n", fmsg->to->zone, fmsg->to->net, fmsg->to->node, + fmsg->from->zone, fmsg->from->net, fmsg->from->node); + } + + fprintf(ofp, "\001MSGID: %s %08lx\n", MBSE_SS(fmsg->msgid_a),fmsg->msgid_n); + if (fmsg->reply_s) + fprintf(ofp, "\1REPLY: %s\n", fmsg->reply_s); + else if (fmsg->reply_a) + fprintf(ofp, "\1REPLY: %s %08lx\n", fmsg->reply_a, fmsg->reply_n); + Now = time(NULL) - (gmt_offset((time_t)0) * 60); + fprintf(ofp, "\001TZUTC: %s\n", gmtoffset(Now)); + fmsg->subj = oldsubj; + if ((p = hdr((char *)"X-FTN-REPLYADDR",msg))) { + Syslog('n', "replyaddr 1 %s", p); + hdrsize += 10+strlen(p); + fprintf(ofp,"\1REPLYADDR:"); + kludgewrite(p,ofp); + } else if (replyaddr) { + Syslog('n', "replyaddr 2"); + hdrsize += 10+strlen(replyaddr); + fprintf(ofp,"\1REPLYADDR: "); + kludgewrite(replyaddr,ofp); + } + if ((p = hdr((char *)"X-FTN-REPLYTO",msg))) { + hdrsize += 8+strlen(p); + fprintf(ofp,"\1REPLYTO:"); + kludgewrite(p,ofp); + } else if (replyaddr) { + hdrsize += 15; + if (newsmode) + fprintf(ofp,"\1REPLYTO: %s UUCP\n", aka2str(msgs.Aka)); + else + fprintf(ofp,"\1REPLYTO: %s UUCP\n", ascfnode(bestaka_s(fmsg->to), 0x1f)); + } else if ((p = hdr((char *)"Reply-To",msg))) { + if ((ta = parsefaddr(p))) { + if ((q = hdr((char *)"From",msg))) { + if (!strcasestr(q,p)) { + fprintf(ofp,"\1REPLYTO: %s %s\n", ascfnode(ta,0x1f), ta->name); + } + tidy_faddr(ta); + } + } + } + if ((p=strip_flags(hdr((char *)"X-FTN-FLAGS",msg)))) { + hdrsize += 15; + fprintf(ofp,"\1FLAGS:%s\n",p); + free(p); + } + if (!hdr((char *)"X-FTN-PID", msg)) { + p = hdr((char *)"User-Agent", msg); + if (p == NULL) + p = hdr((char *)"X-Newsreader", msg); + if (p == NULL) + p = hdr((char *)"X-Mailer", msg); + if (p) { + hdrsize += 4 + strlen(p); + fprintf(ofp, "\1PID:"); + kludgewrite(p, ofp); + } else { + fprintf(ofp, "\001PID: MBSE-FIDO %s\n", VERSION); + } + } + + hdrsize += 8 + strlen(getchrs(outcode)); + fprintf(ofp, "\001CHRS: %s\n", getchrs(outcode)); + if (html_message) { + hdrsize += 9; + fprintf(ofp, "\1HTML: 5\n"); + } + + if (CFG.allowcontrol && (!hdr((char *)"X-FTN-ACUPDATE",msg)) && (p=hdr((char *)"Control",msg))) { + if (strstr(p,"cancel")) { + ftnmsgid(p,&acup_a,&acup_n,fmsg->area); + if (acup_a) { + hash_update_s(&acup_n,fmsg->area); + hdrsize += 26 + strlen(acup_a); + fprintf(ofp,"\1ACUPDATE: DELETE %s %08lx\n", acup_a,acup_n); + } + } + } + if ((!hdr((char *)"X-FTN-ACUPDATE",msg)) && (p=hdr((char *)"Supersedes",msg))) { + ftnmsgid(p,&acup_a,&acup_n,fmsg->area); + if (acup_a) { + hash_update_s(&acup_n,fmsg->area); + hdrsize += 26 + strlen(acup_a); + fprintf(ofp,"\1ACUPDATE: MODIFY %s %08lx\n", acup_a,acup_n); + } + } +#ifdef FSC_0070 + /* FSC-0070 */ + if((p = hdr((char *)"Message-ID", msg)) && !(hdr((char *)"X-FTN-RFCID", msg))) { + q = strdup(p); + fprintf(ofp,"\1RFCID:"); + if ((l = strrchr(q, '<')) && (r = strchr(q, '>')) && (l < r)) { + *l++ = ' '; + while(*l && isspace(*l)) + l++; + l--; /* leading ' ' */ + *r-- = '\0'; + while(*r && isspace(*r)) + *r-- = '\0'; + } else + l = q; + kludgewrite(l, ofp); + hdrsize += 6 + strlen(l); + free(q); + } +#endif /* FSC_0070 */ + + if (!(hdr((char *)"X-FTN-Tearline", msg)) && !(hdr((char *)"X-FTN-TID", msg))) { + sprintf(temp, " MBSE-FIDO %s", VERSION); + hdrsize += 4 + strlen(temp); + fprintf(ofp, "\1TID:"); + kludgewrite(temp, ofp); + } + if ((splitpart == 0) || (hdrsize < MAXHDRSIZE)) { + for (tmp = msg; tmp; tmp = tmp->next) { + if ((!strncmp(tmp->key,"X-Fsc-",6)) || + (!strncmp(tmp->key,"X-FTN-",6) && + strcasecmp(tmp->key,"X-FTN-Tearline") && + strcasecmp(tmp->key,"X-FTN-Origin") && + strcasecmp(tmp->key,"X-FTN-Sender") && + strcasecmp(tmp->key,"X-FTN-Split") && + strcasecmp(tmp->key,"X-FTN-FLAGS") && + strcasecmp(tmp->key,"X-FTN-AREA") && + strcasecmp(tmp->key,"X-FTN-MSGID") && + strcasecmp(tmp->key,"X-FTN-REPLY") && + strcasecmp(tmp->key,"X-FTN-SEEN-BY") && + strcasecmp(tmp->key,"X-FTN-PATH") && + strcasecmp(tmp->key,"X-FTN-REPLYADDR") && + strcasecmp(tmp->key,"X-FTN-REPLYTO") && + strcasecmp(tmp->key,"X-FTN-To") && + strcasecmp(tmp->key,"X-FTN-From") && + strcasecmp(tmp->key,"X-FTN-CHARSET") && + strcasecmp(tmp->key,"X-FTN-CHRS") && + strcasecmp(tmp->key,"X-FTN-CODEPAGE") && + strcasecmp(tmp->key,"X-FTN-ORIGCHRS") && + strcasecmp(tmp->key,"X-FTN-SOT") && + strcasecmp(tmp->key,"X-FTN-EOT") && + strcasecmp(tmp->key,"X-FTN-Via"))) { + if ((strcasecmp(tmp->key,"X-FTN-KLUDGE") == 0)) { + if (!strcasecmp(tmp->val," SOT:\n")) + sot_kludge = TRUE; + else if (!strcasecmp(tmp->val," EOT:\n")) + eot_kludge = TRUE; + else { + hdrsize += strlen(tmp->val); + fprintf(ofp,"\1"); + /* we should have restored the original string here... */ + kludgewrite((tmp->val)+1,ofp); + } + } else { + hdrsize += strlen(tmp->key)+strlen(tmp->val); + fprintf(ofp,"\1%s:",tmp->key+6); + kludgewrite(tmp->val,ofp); + } + } + } + /* ZConnect are X-ZC-*: in usenet, \1ZC-*: in FTN */ + for (tmp=msg;tmp;tmp=tmp->next) + if ((!strncmp(tmp->key,"X-ZC-",5))) { + hdrsize += strlen(tmp->key)+strlen(tmp->val); + fprintf(ofp,"\1%s:",tmp->key+2); + kludgewrite(tmp->val,ofp); + } + + /* mondo.org gateway uses ".MSGID: ..." in usenet */ + for (tmp=msg;tmp;tmp=tmp->next) + if ((!strncmp(tmp->key,".",1)) && (strcasecmp(tmp->key,".MSGID"))) { + hdrsize += strlen(tmp->key)+strlen(tmp->val); + fprintf(ofp,"\1%s:",tmp->key+1); + kludgewrite(tmp->val,ofp); + } + + /* + * Add the Received: header from this system to the mesage. + */ + if (!newsmode) { + Now = time(NULL); + fprintf(ofp, "\1RFC-Received: by %s (mbfido) via RFC2FTN; %s\n", CFG.sysdomain, rfcdate(Now)); + hdrsize += 72+strlen(CFG.sysdomain); + } + + for (tmp = msg; tmp; tmp = tmp->next) { + if ((needputrfc(tmp) == 1)) { + if (strcasestr((char *)"X-Origin-Newsgroups",tmp->key)) { + hdrsize += 10+strlen(tmp->val); + fprintf(ofp,"\1RFC-Newsgroups:"); + } else { + hdrsize += strlen(tmp->key)+strlen(tmp->val); + fprintf(ofp,"\1RFC-%s:",tmp->key); + } + kludgewrite(hdrconv(tmp->val, incode, outcode),ofp); + } + } + + rfcheaders=0; + for (tmp=msg;tmp;tmp=tmp->next) { + if ((needputrfc(tmp) > 1)) { + rfcheaders++; + if (strcasestr((char *)"X-Origin-Newsgroups",tmp->key)) { + hdrsize += 10+strlen(tmp->val); + fprintf(ofp,"Newsgroups:"); + } else { + hdrsize += strlen(tmp->key)+strlen(tmp->val); + fprintf(ofp,"%s:",tmp->key); + } + charwrite(hdrconv(tmp->val, incode, outcode),ofp); + } + } + if (rfcheaders) + charwrite((char *)"\n",ofp); + if ((hdr((char *)"X-FTN-SOT",msg)) || (sot_kludge)) + fprintf(ofp,"\1SOT:\n"); + if ((splitpart == 0) && (hdr((char *)"X-PGP-Signed",msg))) + fprintf(ofp,PGP_SIGNED_BEGIN"\n"); + } + if (replyaddr) { +// free(replyaddr); /* Gives SIGSEGV */ + replyaddr = NULL; + } + if (needsplit) { + fprintf(ofp," * Continuation %d of a split message *\n\n", splitpart); + needsplit = FALSE; + } else if ((p=hdr((char *)"X-Body-Start",msg))) { + datasize += strlen(p); + if (qp_or_base64==1) + charwrite(strkconv(qp_decode(p), incode, outcode), ofp); + else if (qp_or_base64==2) + charwrite(strkconv(b64_decode(p), incode, outcode), ofp); + else + charwrite(strkconv(p, incode, outcode), ofp); + } + while (!(needsplit=(!forbidsplit) && (((splitpart && (datasize > (CFG.new_split * 1024))) || + (!splitpart && ((datasize+hdrsize) > (CFG.new_split * 1024)))))) && (bgets(temp,4096-1,fp))) { + datasize += strlen(temp); + if (qp_or_base64==1) + charwrite(strkconv(qp_decode(temp), incode, outcode), ofp); + else if (qp_or_base64==2) + charwrite(strkconv(b64_decode(temp), incode, outcode), ofp); + else + charwrite(strkconv(temp, incode, outcode), ofp); + } + if (needsplit) { + fprintf(ofp,"\n * Message split, to be continued *\n"); + splitpart++; + } else if ((p=hdr((char *)"X-PGP-Signed",msg))) { + fprintf(ofp,PGP_SIG_BEGIN"\n"); + if ((q=hdr((char *)"X-PGP-Version",msg))) { + fprintf(ofp,"Version:"); + charwrite(q,ofp); + } + if ((q=hdr((char *)"X-PGP-Charset",msg))) { + fprintf(ofp,"Charset:"); + charwrite(q,ofp); + } + if ((q=hdr((char *)"X-PGP-Comment",msg))) { + fprintf(ofp,"Comment:"); + charwrite(q,ofp); + } + fprintf(ofp,"\n"); + p=xstrcpy(p); + q=strtok(p," \t\n"); + fprintf(ofp,"%s\n",q); + while ((q=(strtok(NULL," \t\n")))) + fprintf(ofp,"%s\n",q); + fprintf(ofp,PGP_SIG_END"\n"); + } + if ((p=hdr((char *)"X-FTN-EOT",msg)) || (eot_kludge)) + fprintf(ofp,"\1EOT:\n"); + + if ((p=hdr((char *)"X-FTN-Tearline",msg))) { + fprintf(ofp,"---"); + if (strcasecmp(p," (none)\n") == 0) + charwrite((char *)"\n",ofp); + else + charwrite(p,ofp); + } else + fprintf(ofp,"--- MBSE BBSv.%s\n",VERSION); + + if ((p = hdr((char *)"X-FTN-Origin",msg))) { + if (*(q=p+strlen(p)-1) == '\n') + *q='\0'; + origin = xstrcpy((char *)" * Origin: "); + origin = xstrcat(origin, hdrconv(p, incode, outcode)); + } else { + origin = xstrcpy((char *)" * Origin: "); + if (fmsg->origin) + origin = xstrcat(origin, hdrconv(fmsg->origin, incode, outcode)); + else + origin = xstrcat(origin, CFG.origin); + origin = xstrcat(origin, (char *)" ("); + origin = xstrcat(origin, ascfnode(fmsg->from,tinyorigin?0x0f:0x1f)); + origin = xstrcat(origin, (char *)")"); + } + fprintf(ofp, "%s", origin); + + if (newsmode) { + /* + * Setup SEEN-BY lines, first SEEN-BY from RFC message, then all matching AKA's + */ + for (tmsg = msg; tmsg; tmsg = tmsg->next) + if (strcasecmp(tmsg->key, "X-FTN-SEEN-BY") == 0) + fill_list(&sbl, tmsg->val, NULL); + for (i = 0; i < 40; i++) { + if (CFG.akavalid[i] && (CFG.aka[i].point == 0) && (msgs.Aka.zone == CFG.aka[i].zone) && + !((msgs.Aka.net == CFG.aka[i].net) && (msgs.Aka.node == CFG.aka[i].node))) { + sprintf(sbe, "%u/%u", CFG.aka[i].net, CFG.aka[i].node); + fill_list(&sbl, sbe, NULL); + } + } + if (msgs.Aka.point == 0) { + sprintf(sbe, "%u/%u", msgs.Aka.net, msgs.Aka.node); + fill_list(&sbl, sbe, NULL); + } + + /* + * Only add SEEN-BY lines if there are any + */ + if (sbl != NULL) { + uniq_list(&sbl); + sort_list(&sbl); + seenlen = MAXSEEN + 1; + memset(&sbe, 0, sizeof(sbe)); + /* ensure it will not match for the first entry */ + oldnet = sbl->addr->net-1; + for (tmpl = sbl; tmpl; tmpl = tmpl->next) { + if (tmpl->addr->net == oldnet) + sprintf(sbe," %u",tmpl->addr->node); + else + sprintf(sbe," %u/%u",tmpl->addr->net, tmpl->addr->node); + oldnet = tmpl->addr->net; + seenlen += strlen(sbe); + if (seenlen > MAXSEEN) { + seenlen = 0; + fprintf(ofp,"\nSEEN-BY:"); + sprintf(sbe," %u/%u",tmpl->addr->net, tmpl->addr->node); + seenlen = strlen(sbe); + } + fprintf(ofp,"%s",sbe); + } + tidy_falist(&sbl); + } + + /* + * Setup PATH lines + */ + for (tmp = msg; tmp; tmp = tmp->next) + if (!strcasecmp(tmp->key,"X-FTN-PATH")) + fill_path(&ptl,tmp->val); + if (msgs.Aka.point == 0) { + sprintf(sbe,"%u/%u",msgs.Aka.net, msgs.Aka.node); + fill_path(&ptl,sbe); + } + + /* + * Only add PATH line if there is something + */ + if (ptl != NULL) { + uniq_list(&ptl); + seenlen = MAXPATH+1; + /* ensure it will not match for the first entry */ + oldnet = ptl->addr->net-1; + for (tmpl = ptl; tmpl; tmpl = tmpl->next) { + if (tmpl->addr->net == oldnet) + sprintf(sbe," %u",tmpl->addr->node); + else + sprintf(sbe," %u/%u",tmpl->addr->net, tmpl->addr->node); + oldnet = tmpl->addr->net; + seenlen += strlen(sbe); + if (seenlen > MAXPATH) { + seenlen = 0; + fprintf(ofp,"\n\1PATH:"); + sprintf(sbe," %u/%u",tmpl->addr->net, tmpl->addr->node); + seenlen = strlen(sbe); + } + fprintf(ofp,"%s",sbe); + } + tidy_falist(&ptl); + } + } /* if (newsmode) */ + + /* + * Add newline and message is ready. + */ + fprintf(ofp,"\n"); + fflush(ofp); + rewind(ofp); + + Syslog('n', "========== Fido start"); + while (fgets(temp, 4096, ofp) != NULL) { + /* + * Only log kludges, skip the body + */ +// if ((temp[0] == '\001') || !strncmp(temp, "AREA:", 5) || !strncmp(temp, "SEEN-BY", 7)) { +// Striplf(temp); + Syslogp('n', printable(temp, 0)); +// } + } + Syslog('n', "========== Fido end"); + + if (newsmode) + rc = postecho(NULL, fmsg->from, fmsg->to, origin, fmsg->subj, fmsg->date, fmsg->flags, 0, ofp, FALSE); + else + rc = postnetmail(ofp, fmsg->from, fmsg->to, origin, fmsg->subj, fmsg->date, fmsg->flags, FALSE); + + free(origin); + fclose(ofp); + } while (needsplit); + free(temp); + tidyrfc(msg); + tidy_ftnmsg(fmsg); + UpdateMsgs(); + + return 0; +} + + + +/* + * Test which kludges to add; + * <1 junk + * 1 make kludge + * >1 pass + */ +int needputrfc(rfcmsg *msg) +{ + faddr *ta; + +// Syslog('M', "needputrfc(%s)", printable(msg->key,0)); + if ((msg->key == NULL) || (strlen(msg->key) == 0)) return 0; + + if (!strcasecmp(msg->key,"X-UUCP-From")) return -1; + if (!strcasecmp(msg->key,"X-Body-Start")) return -1; + if (!strncasecmp(msg->key,".",1)) return 0; + if (!strncasecmp(msg->key,"X-FTN-",6)) return 0; + if (!strncasecmp(msg->key,"X-Fsc-",6)) return 0; + if (!strncasecmp(msg->key,"X-ZC-",5)) return 0; + if (!strcasecmp(msg->key,"X-Gateway")) return 0; + if (!strcasecmp(msg->key,"Path")) return 0; + if (!strcasecmp(msg->key,"Newsgroups")) { + if ((hdr((char *)"X-Origin-Newsgroups",msg))) + return 0; + else if (strstr(msg->val,",")) + return 1; + else + return 0; + } + + if (!strcasecmp(msg->key,"X-Origin-Newsgroups")) { + if (strstr(msg->val,",")) + return 1; + else + return 0; + } + + if (!strcasecmp(msg->key,"Control")) { + if (CFG.allowcontrol) { + if (strstr(msg->val,"cancel")) + return 1; + else + return 0; + } else + return 0; + } + if (!strcasecmp(msg->key,"Return-Path")) return 1; + if (!strcasecmp(msg->key,"Xref")) return 0; + if (!strcasecmp(msg->key,"Approved")) return removeapproved ? -1:2; + if (!strcasecmp(msg->key,"X-URL")) return 0; + if (!strcasecmp(msg->key,"Return-Receipt-To")) return removereturnto? 0:1; + if (!strcasecmp(msg->key,"Notice-Requested-Upon-Delivery-To")) return 0; + if (!strcasecmp(msg->key,"Received")) return ftnorigin ?0:1; + if (!strcasecmp(msg->key,"From")) { + if ((ta = parsefaddr(msg->val))) { + tidy_faddr(ta); + return 0; + } else { + return 1; /* 28-Jul-2001 MB (was 2) */ + } + } + if (!strcasecmp(msg->key,"To")) { + if ((ta=parsefaddr(msg->val))) { + tidy_faddr(ta); + return 0; + } else + return 2; + } + if (!strcasecmp(msg->key,"Cc")) return 2; + if (!strcasecmp(msg->key,"Bcc")) return 0; + if (!strcasecmp(msg->key,"Reply-To")) { + if ((ta = parsefaddr(msg->val))) { + tidy_faddr(ta); + return -1; + } else + return removereplyto ?0:4; + } + if (!strcasecmp(msg->key,"Lines")) return 0; + if (!strcasecmp(msg->key,"Date")) return 0; + if (!strcasecmp(msg->key,"Subject")) { + if ((msg->val) && (strlen(msg->val) > MAXSUBJ)) + return 2; + else + return 0; + } + if (!strcasecmp(msg->key,"Organization")) return 1; + if (!strcasecmp(msg->key,"Organisation")) return 1; + if (!strcasecmp(msg->key,"Comment-To")) return 0; + if (!strcasecmp(msg->key,"X-Comment-To")) return 0; + if (!strcasecmp(msg->key,"X-Apparently-To")) return 0; + if (!strcasecmp(msg->key,"Apparently-To")) return 0; + if (!strcasecmp(msg->key,"X-Fidonet-Comment-To")) return 0; + if (!strcasecmp(msg->key,"Keywords")) return 2; + if (!strcasecmp(msg->key,"Summary")) return 2; + if (!strcasecmp(msg->key,"MIME-Version")) return removemime ?0:1; + if (!strcasecmp(msg->key,"Content-Type")) return removemime ?0:1; + if (!strcasecmp(msg->key,"Content-Length")) return removemime ?0:1; + if (!strcasecmp(msg->key,"Content-Transfer-Encoding")) return removemime ?0:1; + if (!strcasecmp(msg->key,"Content-Name")) return 2; + if (!strcasecmp(msg->key,"Content-Description")) return 2; + if (!strcasecmp(msg->key,"Message-ID")) return removemsgid ?0:1; + if (!strcasecmp(msg->key,"References")) return removeref ?0:1; + if (!strcasecmp(msg->key,"Supersedes")) return removesupersedes ?0:1; + if (!strcasecmp(msg->key,"Distribution")) return ftnorigin ?0:0; + if (!strcasecmp(msg->key,"X-Newsreader")) return 0; + if (!strcasecmp(msg->key,"X-Mailer")) return 0; + if (!strcasecmp(msg->key,"User-Agent")) return 0; + if (!strncasecmp(msg->key,"NNTP-",5)) return 0; + if (!strncasecmp(msg->key,"X-Trace",7)) return 0; + if (!strncasecmp(msg->key,"X-Complaints",12)) return 0; + if (!strncasecmp(msg->key,"X-MSMail",9)) return 0; + if (!strncasecmp(msg->key,"X-MimeOLE",9)) return 0; + if (!strncasecmp(msg->key,"X-MIME-Autoconverted",20)) return 0; + if (!strcasecmp(msg->key,"X-Origin-Date")) return 0; + if (!strncasecmp(msg->key,"X-PGP-",6)) return 0; + if (!strncasecmp(msg->key,"Resent-",7)) return 0; + if (!strcasecmp(msg->key,"X-Mailing-List")) return 0; + if (!strcasecmp(msg->key,"X-Loop")) return 0; + if (!strcasecmp(msg->key,"Precedence")) return 0; + /*if (!strcasecmp(msg->key,"")) return ;*/ + return 1; +} + + diff --git a/mbfido/rfc2ftn.h b/mbfido/rfc2ftn.h new file mode 100644 index 00000000..77e0f74e --- /dev/null +++ b/mbfido/rfc2ftn.h @@ -0,0 +1,7 @@ +#ifndef _RFC2FTN_H +#define _RFC2FTN_H + +int rfc2ftn(FILE *fp, faddr *); + +#endif + diff --git a/mbfido/storeecho.c b/mbfido/storeecho.c new file mode 100644 index 00000000..4557439d --- /dev/null +++ b/mbfido/storeecho.c @@ -0,0 +1,172 @@ +/***************************************************************************** + * + * File ..................: tosser/storenet.c + * Purpose ...............: Import a netmail message + * Last modification date : 28-Jul-2001 + * + ***************************************************************************** + * Copyright (C) 1997-2001 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "../lib/libs.h" +#include "../lib/structs.h" +#include "../lib/records.h" +#include "../lib/common.h" +#include "../lib/clcomm.h" +#include "../lib/msg.h" +#include "../lib/msgtext.h" +#include "../lib/dbmsgs.h" +#include "../lib/dbuser.h" +#include "rollover.h" +#include "storeecho.h" + + + +extern int echo_in; /* Total echomails */ +extern int echo_imp; /* Imported echomails */ +extern int echo_dupe; /* Dupe echomails */ +extern int echo_bad; /* Bad echomails */ +extern int do_quiet; /* Quiet flag */ + + + +/* + * Store echomail into the JAM base. + * + * 0 - All seems well. + * 1 - Can't access messagebase. + * + */ +int storeecho(faddr *f, faddr *t, time_t mdate, int flags, char *subj, char *msgid, char *reply, int bad, int dupe, FILE *fp) +{ + int result; + unsigned long crc2; + char *buf; + + /* + * Update import counters + */ + if (!bad && !dupe) { + StatAdd(&msgs.Received, 1L); + time(&msgs.LastRcvd); + StatAdd(&mgroup.MsgsRcvd, 1L); + time(&mgroup.LastDate); + UpdateMsgs(); + } + + if (bad) { + if (strlen(CFG.badboard) == 0) { + Syslog('+', "Killing bad message"); + return 0; + } else { + if ((result = Msg_Open(CFG.badboard))) + Syslog('+', "Tossing in bad board"); + } + } else if (dupe) { + if (strlen(CFG.dupboard) == 0) { + Syslog('+', "Killing dupe message"); + return 0; + } else { + if ((result = Msg_Open(CFG.dupboard))) + Syslog('+', "Tossing in dupe board"); + } + } else { + result = Msg_Open(msgs.Base); + } + if (!result) { + WriteError("Can't open JAMmb %s", msgs.Base); + return 1; + } + + if (Msg_Lock(30L)) { + if (dupe) + echo_dupe++; + else if (bad) + echo_bad++; + else + echo_imp++; + + if (!do_quiet) { + colour(3, 0); + printf("\r%6u => %-40s\r", echo_in, msgs.Name); + fflush(stdout); + } + + Msg_New(); + + /* + * Fill subfields + */ + strcpy(Msg.From, f->name); + strcpy(Msg.To, t->name); + strcpy(Msg.FromAddress, ascfnode(f,0x1f)); + strcpy(Msg.Subject, subj); + Msg.Written = mdate; + Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60); + Msg.Echomail = TRUE; + + /* + * These are the only usefull flags in echomail + */ + if ((flags & M_PVT) && ((msgs.MsgKinds == BOTH) || (msgs.MsgKinds == PRIVATE))) + Msg.Private = TRUE; + if (flags & M_FILE) + Msg.FileAttach = TRUE; + + /* + * Set MSGID and REPLY crc. + */ + if (msgid != NULL) { + crc2 = -1; + Msg.MsgIdCRC = upd_crc32(msgid, crc2, strlen(msgid)); + } + if (reply != NULL) { + crc2 = -1; + Msg.ReplyCRC = upd_crc32(reply, crc2, strlen(reply)); + } + + /* + * Start write the message + * If not a bad or dupe message, eat the first + * line (AREA:tag). + */ + buf = calloc(2048, sizeof(char)); + rewind(fp); + if (!dupe && !bad) + fgets(buf , 2048, fp); + Msg_Write(fp); + Msg_AddMsg(); + Msg_UnLock(); + Msg_Close(); + free(buf); + return 0; + } else { + Syslog('+', "Can't lock msgbase %s", msgs.Base); + Msg_UnLock(); + Msg_Close(); + return 1; + } +} + + diff --git a/mbfido/storeecho.h b/mbfido/storeecho.h new file mode 100644 index 00000000..5c588fa1 --- /dev/null +++ b/mbfido/storeecho.h @@ -0,0 +1,7 @@ +#ifndef _STOREECHO_H +#define _STOREECHO_H + +int storeecho(faddr *, faddr *, time_t, int, char *, char *, char *, int, int, FILE *); + +#endif + diff --git a/mbfido/storenet.c b/mbfido/storenet.c new file mode 100644 index 00000000..4efbb207 --- /dev/null +++ b/mbfido/storenet.c @@ -0,0 +1,171 @@ +/***************************************************************************** + * + * File ..................: tosser/storenet.c + * Purpose ...............: Import a netmail message + * Last modification date : 27-Jul-2001 + * + ***************************************************************************** + * Copyright (C) 1997-2001 + * + * 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, 675 Mass Ave, Cambridge, MA 02139, USA. + *****************************************************************************/ + +#include "../lib/libs.h" +#include "../lib/structs.h" +#include "../lib/records.h" +#include "../lib/common.h" +#include "../lib/clcomm.h" +#include "../lib/msg.h" +#include "../lib/msgtext.h" +#include "../lib/dbmsgs.h" +#include "../lib/dbuser.h" +#include "rollover.h" +#include "storenet.h" + + + +/* + * Global variables + */ +extern int net_imp; /* Netmails imported */ +extern int net_bad; /* Bad netmails (tracking errors */ + + + +/* + * Store netmail into the JAM base. + * + * 0 - All seems well. + * 1 - Can't access messagebase. + * 2 - Can't find a netmail board. + * + */ +int storenet(faddr *f, faddr *t, time_t mdate, int flags, char *Subj, char *msgid, char *reply, FILE *fp) +{ + int result, i, empty = TRUE; + unsigned long crc2; + char *Buf; + + if (SearchNetBoard(t->zone, t->net)) { + StatAdd(&msgs.Received, 1L); + time(&msgs.LastRcvd); + UpdateMsgs(); + + result = Msg_Open(msgs.Base); + if (!result) { + WriteError("Can't open msgbase %s", msgs.Base); + net_bad++; + return 1; + } + + if (Msg_Lock(30L)) { + Msg_New(); + + Syslog('m', "Flagfield 0x%04x", flags); + strcpy(Msg.From, f->name); + strcpy(Msg.To, usr.sUserName); + strcpy(Msg.FromAddress, ascfnode(f,0x1f)); + strcpy(Msg.ToAddress, ascfnode(t,0x1f)); + strcpy(Msg.Subject, Subj); + Msg.Written = mdate; + Msg.Arrived = time(NULL) - (gmt_offset((time_t)0) * 60); + Msg.Netmail = TRUE; + + /* + * These are the only usefull flags in netmail + */ + if ((msgs.MsgKinds == BOTH) || (msgs.MsgKinds == PRIVATE)) + Msg.Private = (flags & M_PVT) ? TRUE:FALSE; + else + Msg.Private = TRUE; /* Allways */ + if (flags & M_CRASH) + Msg.Crash = TRUE; + if (flags & M_FILE) + Msg.FileAttach = TRUE; + if (flags & M_TRANSIT) + Msg.Intransit = TRUE; + if (flags & M_REQ) + Msg.FileRequest = TRUE; + if (flags & M_RRQ) + Msg.ReceiptRequest = TRUE; + + /* + * Set MSGID and REPLY crc. + */ + if (msgid != NULL) { + crc2 = -1; + Msg.MsgIdCRC = upd_crc32(msgid, crc2, strlen(msgid)); + } + if (reply != NULL) { + crc2 = -1; + Msg.ReplyCRC = upd_crc32(reply, crc2, strlen(reply)); + } + + /* + * Check if this is an empty netmail + */ + rewind(fp); + Buf = calloc(2049, sizeof(char)); + while ((fgets(Buf, 2048, fp)) != NULL) { + + for (i = 0; i < strlen(Buf); i++) { + if (*(Buf + i) == '\0') + break; + if (*(Buf + i) == '\n') + *(Buf + i) = '\0'; + if (*(Buf + i) == '\r') + *(Buf + i) = '\0'; + } + if (*(Buf) != '\0') { + if ((*(Buf) != '\001') && + (strcmp(Buf, (char *)"--- "))) + empty = FALSE; + } + } + free(Buf); + + if (!empty) { + Syslog('+', "Import netmail to %s", usr.sUserName); + rewind(fp); + Msg_Write(fp); + Msg_AddMsg(); + net_imp++; + } else { + Syslog('+', "Empty netmail for %s dropped", usr.sUserName); + } + Msg_UnLock(); + Msg_Close(); + + return 0; + } else { + WriteError("Can't lock msgbase %s", msgs.Base); + Msg_Close(); + return 1; + } + } else { + WriteError("Can't find a netmail board"); + net_bad++; + return 2; + } /* if SearchNetBoard() */ +} + + diff --git a/mbfido/storenet.h b/mbfido/storenet.h new file mode 100644 index 00000000..4ad6ff61 --- /dev/null +++ b/mbfido/storenet.h @@ -0,0 +1,8 @@ +#ifndef _STORENET_H +#define _STORENET_H + + +int storenet(faddr *, faddr *, time_t, int, char *, char *, char *, FILE *); + +#endif +