This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-mbse/mbfido/mkftnhdr.c
2005-10-11 20:49:41 +00:00

598 lines
16 KiB
C

/*****************************************************************************
*
* $Id$
* Purpose ...............: MBSE BBS Mail Gate
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
/* Base on E.C. Crosser's ifmail.
*
* ### Modified by P.Saratxaga on 19 Sep 1995 ###
* - Added X-FTN-From and X-FTN-To support
* - added code by T.Tanaka, dated 13 Mar 1995, to put the freename in the ftn
* header, instead of the userid, when the address is fido parseable
* - modified ^aREPLY: code, to look in In-Reply-To:
* - support to decode MSGID from fidogate "Message-ID: <MSGID_....>"
* - suport for X-Apparently-To: (generated by the french fido->usenet gate)
* - added don't regate code by Wim Van Sebroeck <vsebro@medelec.uia.ac.be>
* - corriged a bug when Organization: has only blanks
*/
#include "../config.h"
#include "../lib/mbselib.h"
#include "../lib/users.h"
#include "../lib/mbsedb.h"
#include "atoul.h"
#include "hash.h"
#include "msgflags.h"
#include "aliasdb.h"
#include "mkftnhdr.h"
#ifndef ULONG_MAX
#define ULONG_MAX 4294967295
#endif
char *replyaddr=NULL;
char *ftnmsgidstyle=NULL;
faddr *bestaka;
int ftnmsgid(char *msgid, char **s, unsigned int *n, char *areaname)
{
char *buf, *l, *r, *p;
unsigned int nid = 0L;
faddr *tmp;
static int ftnorigin = 0;
Syslog('m', "Make ftn msgid from \"%s\"", MBSE_SS(msgid));
if (msgid == NULL) {
*s = NULL;
*n = 0L;
return ftnorigin;
}
buf = malloc(strlen(msgid)+65);
strcpy(buf, msgid);
if ((l = strchr(buf,'<')))
l++;
else
l = buf;
while (isspace(*l))
l++;
if ((r = strchr(l,'>')))
*r = '\0';
r = l + strlen(l) - 1;
while (isspace(*r) && (r > l))
(*r--)='\0';
if ((tmp = parsefaddr(l))) {
if (tmp->name) {
if (strspn(tmp->name,"0123456789") == strlen(tmp->name))
nid = atoul(tmp->name);
else
nid = ULONG_MAX;
if (nid == ULONG_MAX) {
hash_update_s(&nid, tmp->name);
} else
ftnorigin = 1;
} else {
hash_update_s(&nid,l);
}
*s = xstrcpy(ascfnode(tmp, 0x1f));
tidy_faddr(tmp);
} else {
if ((r=strchr(l,'@')) == NULL) { /* should never happen */
Syslog('!', "ftnmsgid: should never happen");
*s = xstrcpy(l);
hash_update_s(&nid,l);
/* <MSGID_mimeanything_abcd1234@ftn.domain> */
} else if (strncmp(l,"MSGID_",6) == 0) {
*r = '\0';
r = strrchr(l+6,'_');
if (r)
*r++ = '\0';
*s = xstrcpy(l+6);
if (r)
sscanf(r,"%x",&nid);
ftnorigin = 1;
/* <NOMSGID_mimeanything_abcd1234@ftn.domain> */
} else if (strncmp(l,"NOMSGID_",8) == 0) {
*s = NULL;
*n = 0L;
ftnorigin = 1;
return ftnorigin;
/* <ftn_2.204.226$fidonet_1d17b3b3_Johan.Olofsson@magnus.ct.se> */
} else if (strncmp(l,"ftn_",4) == 0) {
*r = '\0';
if ((r = strchr(l+4,'$')) || (r=strchr(l+4,'#'))) {
if (*r=='$')
*r='@';
if ((r=strchr(l+4,'.')))
*r=':';
if ((r=strchr(l+4,'.')))
*r='/';
}
while ((r=strrchr(l+4,'_')) != strchr(l+4,'_'))
*r='\0';
r=strchr(l+4,'_');
*r++='\0';
*s=xstrcpy(l+4);
sscanf(r,"%x",&nid);
ftnorigin=1;
/* <wgcid$3$g712$h610$i22$kfidonet$j6596dbf5@brazerko.com> */
} else if (strncmp(l,"wgcid$",6) == 0) {
*r='\0';
if ((r=strstr(l+6,"$g"))) {
*r='\0';
*s=xstrcpy(l+6);
*s=xstrcat(*s,(char *)":");
l=r+2;
}
if ((r=strstr(l,"$h"))) {
*r++='\0';
*s=xstrcat(*s,l);
*s=xstrcat(*s,(char *)"/");
l=r+2;
}
if ((r=strstr(l,"$i"))) {
*r='\0';
*s=xstrcat(*s,l);
*s=xstrcat(*s,(char *)".");
l=r+2;
}
if ((r=strstr(l,"$k"))) {
*r='\0';
*s=xstrcat(*s,l);
*s=xstrcat(*s,(char *)"@");
l=r+2;
}
if ((r=strstr(l,"$j"))) {
*r='\0';
*s=xstrcat(*s,l);
sscanf(r+2,"%x",&nid);
}
} else {
*r='\0';
if ((p=strchr(l,'%'))) {
*p='\0';
if (strspn(l,"0123456789") == strlen(l)) {
*r='@';
r=p;
} else
*p='%';
}
r++;
if (strspn(l,"0123456789") == strlen(l))
nid = atoul(l);
else
nid = ULONG_MAX;
if (nid == ULONG_MAX)
hash_update_s(&nid,l);
*s=xstrcpy(r);
}
}
*n=nid;
free(buf);
return ftnorigin;
}
ftnmsg *mkftnhdr(rfcmsg *msg, int newsmode, faddr *recipient)
{
char *freename = NULL, *rfcfrom = NULL, *p, *q, *l, *r;
char *fbuf = NULL, *ftnfrom=NULL;
static ftnmsg *tmsg;
int needreplyaddr = 1;
faddr *tmp, *tmp2;
tmsg=(ftnmsg *)malloc(sizeof(ftnmsg));
memset(tmsg, 0, sizeof(ftnmsg));
if (newsmode) {
p = xstrcpy(hdr((char *)"Comment-To",msg));
if (p == NULL)
p = xstrcpy(hdr((char *)"X-Comment-To",msg));
if (p == NULL)
p = xstrcpy(hdr((char *)"X-FTN-To",msg));
if (p == NULL)
p = xstrcpy(hdr((char *)"X-Fidonet-Comment-To",msg));
if (p == NULL)
p = xstrcpy(hdr((char *)"X-Apparently-To",msg));
if (p == NULL)
p = xstrcpy(hdr((char *)"To", msg)); /* 14-Aug-2001 MB */
if (p) {
Syslog('m', "Getting `to' address from \"%s\"", MBSE_SS(p));
if ((tmsg->to = parsefaddr(p)) == NULL)
tmsg->to = parsefaddr((char *)"All@p0.f0.n0.z0");
if ((l = strrchr(p,'<')) && (r = strchr(p,'>')) && (l < r)) {
r = l;
*r-- = '\0';
if ((l = strchr(p,'"')) && (r = strrchr(p,'"')) && (l < r)) {
l++;
*r-- = '\0';
}
while (isspace(*r))
*r-- = '\0';
if (!l)
l = p;
while (isspace(*l))
l++;
} else if ((l = strrchr(p,'(')) && (r = strchr(p,')')) && (l < r)) {
*r-- = '\0';
while (isspace(*r))
*r-- = '\0';
l++;
while (isspace(*l))
l++;
} else {
l = p;
while (isspace(*l))
l++;
r = p + strlen(p) -1;
if (*r == '\n')
*r-- = '\0';
while (isspace(*r))
*r-- = '\0';
}
if (*l) {
if (strlen(l) > MAXNAME)
l[MAXNAME]='\0';
free(tmsg->to->name);
tmsg->to->name=xstrcpy(l);
}
free(p);
/*
* It will become echomail, the destination FTN address must
* be our address. 14-Aug-2001 MB.
*/
tmsg->to->zone = msgs.Aka.zone;
tmsg->to->net = msgs.Aka.net;
tmsg->to->node = msgs.Aka.node;
tmsg->to->point = msgs.Aka.point;
tmsg->to->domain = xstrcpy(msgs.Aka.domain);
} else {
/*
* Filling a default To: address.
*/
tmsg->to = (faddr*)malloc(sizeof(faddr));
tmsg->to->name = xstrcpy((char *)"All");
tmsg->to->zone = msgs.Aka.zone;
tmsg->to->net = msgs.Aka.net;
tmsg->to->node = msgs.Aka.node;
tmsg->to->point = msgs.Aka.point;
tmsg->to->domain = xstrcpy(msgs.Aka.domain);
}
Syslog('N', "TO: %s",ascfnode(tmsg->to,0xff));
} else {
if (recipient) {
/*
* In mbmail mode the recipient is valid and must be used
* as the destination address. The To: field is probably
* an RFC address an cannot be used to route the message.
*/
tmsg->to = (faddr *)malloc(sizeof(faddr));
tmsg->to->point = recipient->point;
tmsg->to->node = recipient->node;
tmsg->to->net = recipient->net;
tmsg->to->zone = recipient->zone;
tmsg->to->name = xstrcpy(recipient->name);
if (tmsg->to->name && (strlen(tmsg->to->name) > MAXNAME))
tmsg->to->name[MAXNAME]='\0';
tmsg->to->domain = xstrcpy(recipient->domain);
Syslog('m', "Recipient TO: %s", ascfnode(tmsg->to,0xff));
} else {
p = xstrcpy(hdr((char *)"To",msg));
if (p == NULL)
p = xstrcpy(hdr((char *)"X-Apparently-To",msg));
if (p) {
if ((tmsg->to = parsefaddr(p)) == NULL)
WriteError("Unparsable destination address");
else
Syslog('m', "RFC parsed TO: %s",ascfnode(tmsg->to,0xff));
}
}
} /* else (newsmode) */
p = fbuf = xstrcpy(hdr((char *)"Reply-To", msg));
if (fbuf == NULL)
p = fbuf = xstrcpy(hdr((char *)"From", msg));
if (fbuf == NULL)
p = fbuf = xstrcpy(hdr((char *)"X-UUCP-From", msg));
if (p) {
q = p;
while (isspace(*q))
q++;
fbuf = parserfcaddr(q).remainder;
if (parserfcaddr(q).target) {
fbuf = xstrcat(fbuf, (char *)"@");
fbuf = xstrcat(fbuf, parserfcaddr(q).target);
}
rfcfrom = fbuf;
}
if (p)
free(p);
p = NULL;
if (!rfcfrom)
rfcfrom = xstrcpy((char *)"postmaster");
p = fbuf = xstrcpy(hdr((char *)"From", msg));
if (fbuf == NULL)
p = fbuf = xstrcpy(hdr((char *)"X-UUCP-From", msg));
if (p) {
q = p;
while (isspace(*q))
q++;
if ((q) && (*q != '\0'))
freename = parserfcaddr(q).comment;
else
freename = NULL;
} else
freename = xstrcpy((char *)"Unidentified User");
if (freename) {
while (isspace(*freename))
freename++;
}
if (rfcfrom) {
while (isspace(*rfcfrom))
rfcfrom++;
p = rfcfrom + strlen(rfcfrom) -1;
while ((isspace(*p)) || (*p == '\n'))
*(p--)='\0';
}
if ((freename) && (*freename != '\0')) {
while (isspace(*freename))
freename++;
p = freename + strlen(freename) -1;
while ((isspace(*p)) || (*p == '\n'))
*(p--)='\0';
if ((*freename == '\"') && (*(p=freename+strlen(freename)-1) == '\"')) {
freename++;
*p='\0';
}
}
// if (*freename == '\0') freename=rfcfrom;
if ((!freename) || ((freename) && (*freename == '\0')) || (strcmp(freename,".")==0))
freename=rfcfrom;
if (newsmode)
Syslog('M', "FROM: %s <%s>", freename, rfcfrom);
else
Syslog('+', "from: %s <%s>",freename,rfcfrom);
needreplyaddr = 1;
if ((tmsg->from=parsefaddr(rfcfrom)) == NULL) {
if (freename && rfcfrom)
if (!strchr(freename,'@') && !strchr(freename,'%') &&
strncasecmp(freename,rfcfrom,MAXNAME) &&
strncasecmp(freename,"uucp",4) &&
strncasecmp(freename,"usenet",6) &&
strncasecmp(freename,"news",4) &&
strncasecmp(freename,"super",5) &&
strncasecmp(freename,"admin",5) &&
strncasecmp(freename,"postmaster",10) &&
strncasecmp(freename,"sys",3))
needreplyaddr=registrate(freename,rfcfrom);
} else {
tmsg->ftnorigin = 1;
tmsg->from->name = xstrcpy(freename);
if (strlen(tmsg->from->name) > MAXNAME)
tmsg->from->name[MAXNAME]='\0';
}
if (replyaddr) {
free(replyaddr);
replyaddr=NULL;
}
if (needreplyaddr && (tmsg->from == NULL)) {
Syslog('M', "fill replyaddr with \"%s\"",rfcfrom);
replyaddr=xstrcpy(rfcfrom);
}
if (tmsg->from)
Syslog('m', "From address was%s distinguished as ftn", tmsg->from ? "" : " not");
if (newsmode) {
tmp2 = fido2faddr(msgs.Aka);
bestaka = bestaka_s(tmp2);
tidy_faddr(tmp2);
} else
bestaka = bestaka_s(tmsg->to);
if ((tmsg->from == NULL) && (bestaka)) {
if (CFG.dontregate) {
p = xstrcpy(hdr((char *)"X-FTN-Sender",msg));
if (p == NULL) {
if ((p = hdr((char *)"X-FTN-From",msg))) {
tmp = parsefnode(p);
p = xstrcpy(ascinode(tmp, 0xff));
tidy_faddr(tmp);
}
}
if (p) {
q = p;
while (isspace(*q))
q++;
ftnfrom = parserfcaddr(q).remainder;
if (parserfcaddr(q).target) {
ftnfrom = xstrcat(ftnfrom,(char *)"@");
ftnfrom = xstrcat(ftnfrom,parserfcaddr(q).target);
}
Syslog('m', "Ftn gateway: \"%s\"", ftnfrom);
Syslog('+', "Ftn sender: %s",ftnfrom);
if (ftnfrom)
tmsg->from = parsefaddr(ftnfrom);
if ((tmsg->from) && (!tmsg->from->name))
tmsg->from->name = xstrcpy(rfcfrom);
}
if (p)
free(p);
p = NULL;
if (tmsg->from == NULL) {
tmsg->from=(faddr *)malloc(sizeof(faddr));
tmsg->from->name=xstrcpy(freename);
if (tmsg->from->name && (strlen(tmsg->from->name) > MAXNAME))
tmsg->from->name[MAXNAME]='\0';
tmsg->from->point=bestaka->point;
tmsg->from->node=bestaka->node;
tmsg->from->net=bestaka->net;
tmsg->from->zone=bestaka->zone;
tmsg->from->domain=xstrcpy(bestaka->domain);
}
} else {
tmsg->from=(faddr *)xmalloc(sizeof(faddr));
tmsg->from->name=xstrcpy(freename);
if (tmsg->from->name && (strlen(tmsg->from->name) > MAXNAME))
tmsg->from->name[MAXNAME]='\0';
tmsg->from->point=bestaka->point;
tmsg->from->node=bestaka->node;
tmsg->from->net=bestaka->net;
tmsg->from->zone=bestaka->zone;
tmsg->from->domain=xstrcpy(bestaka->domain);
}
}
if (fbuf)
free(fbuf);
fbuf = NULL;
p = hdr((char *)"Subject", msg);
if (p) {
while (isspace(*p))
p++;
tmsg->subj = xstrcpy(p);
if (*(p=tmsg->subj+strlen(tmsg->subj)-1) == '\n')
*p='\0';
if (strlen(tmsg->subj) > MAXSUBJ)
tmsg->subj[MAXSUBJ]='\0';
} else {
tmsg->subj = xstrcpy((char *)" ");
}
Syslog('M', "SUBJ: \"%s\"", tmsg->subj);
if ((p = hdr((char *)"X-FTN-FLAGS",msg)))
tmsg->flags |= flagset(p);
if (hdr((char *)"Return-Receipt-To",msg))
tmsg->flags |= M_RRQ;
if (hdr((char *)"Notice-Requested-Upon-Delivery-To",msg))
tmsg->flags |= M_RRQ;
if (!newsmode) {
tmsg->flags |= M_PVT;
tmsg->flags |= M_KILLSENT;
}
if ((p = hdr((char *)"X-Origin-Date",msg)))
tmsg->date = parsedate(p, NULL);
else if ((p = hdr((char *)"Date",msg)))
tmsg->date = parsedate(p, NULL);
else
tmsg->date = time((time_t *)NULL);
/*
* SunMail 1.0 creates invalid date formats like: Wed, 19 Jun 2002 18:21:07 GMT-08:00
* ^---- not allowed.
*/
if (tmsg->date == -1) {
Syslog('!', "Parsing date \"%s\" failed, using current date", p);
tmsg->date = time((time_t *)NULL);
}
if ((p = hdr((char *)"X-FTN-MSGID", msg))) {
tmsg->ftnorigin &= 1;
while (isspace(*p))
p++;
tmsg->msgid_s = xstrcpy(p);
if (*(p = tmsg->msgid_s + strlen(tmsg->msgid_s) -1) == '\n')
*p='\0';
} else if ((p = hdr((char *)".MSGID",msg))) {
tmsg->ftnorigin &= 1;
while (isspace(*p))
p++;
tmsg->msgid_s = xstrcpy(p);
if (*(p = tmsg->msgid_s + strlen(tmsg->msgid_s) -1) == '\n')
*p='\0';
} else if ((p = hdr((char *)"Message-ID",msg))) {
tmsg->ftnorigin &= ftnmsgid(p,&(tmsg->msgid_a),&(tmsg->msgid_n),tmsg->area);
} else
tmsg->msgid_a = NULL;
if ((p = hdr((char *)"X-FTN-REPLY",msg))) {
while (isspace(*p))
p++;
tmsg->reply_s = xstrcpy(p);
if (*(p=tmsg->reply_s + strlen(tmsg->reply_s) -1) == '\n')
*p='\0';
} else {
if (newsmode) {
p = hdr((char *)"References",msg);
if (p) {
l = xstrcpy(p);
r = strtok(l," \t\n");
while ((l=strtok(NULL," \t\n")) != NULL)
r = l;
p = r;
free(l);
}
} else
p = hdr((char *)"In-Reply-To",msg);
}
if (p)
(void)ftnmsgid(p,&(tmsg->reply_a),&(tmsg->reply_n),NULL);
else
tmsg->reply_a=NULL;
Syslog('M', "DATE: %s, MSGID: %s %lx, REPLY: %s %lx",
ftndate(tmsg->date), MBSE_SS(tmsg->msgid_a),tmsg->msgid_n, MBSE_SS(tmsg->reply_a),tmsg->reply_n);
p = hdr((char *)"Organization",msg);
if (p == NULL)
p = hdr((char *)"Organisation",msg);
if (p) {
while (isspace(*p))
p++;
tmsg->origin = xstrcpy(p);
if (tmsg->origin)
if (*(p = tmsg->origin + strlen(tmsg->origin)-1) == '\n')
*p='\0';
} else {
/*
* No Organization header, insert the default BBS origin.
*/
tmsg->origin = xstrcpy(CFG.origin);
}
Syslog('M', "ORIGIN: %s", MBSE_SS(tmsg->origin));
return tmsg;
}