Closed ftoledo closed 3 years ago
//Patch to get original message date/time get imported at mhsrtx() function
/***************************************************************************
* *
* GALMHS.C *
* *
* Copyright (c) 1992-1997 Galacticomm, Inc. All Rights Reserved. *
* *
* This is online portion of the Worldgroup MHS importer/exporter. The *
* message format used is based on MHS v1.5 and the SMF-70 *
* specifications. Only a subset is being supported. (was MHSHDL.C) *
* *
* - R. Skurnick 2/8/92 *
* -File Attachment Support - C. Robert 2/1/93 *
* - C. Kotacka 2/1/93 *
* -Separate into DLL using GME - J. Alvrus 9/25/94 *
* *
***************************************************************************/
#include "gcomm.h"
#include "fcntl.h"
#include "share.h"
#include "sys\stat.h"
#include "majorbbs.h"
#include "gme.h"
#include "galmhs.h"
#include "mhsalias.h"
#include "dntapi.h"
#define FILREV "$Revision: 8 $"
#define NONDEL 0 /* send non-delivery notice */
#define RETREC 1 /* send return receipt notice */
#define MAXKWD 20 /* max size of incoming message keywords*/
#define MAXLIN 79 /* max message text line length */
#define MHSDSZ 80 /* MHS date information field size */
/* exporter functions */
const CHAR *mhshlp(VOID);
const CHAR *mhsasp(const CHAR *to,const struct message *msg);
INT sndmhs(const CHAR *to,const struct message *msg,const CHAR *text,
const CHAR *filatt);
VOID outxt(FILE *fp,const CHAR *cp);
/* importer functions */
VOID mhsproc(INT taskid);
VOID mhsscn2(VOID);
GBOOL mhsscn(VOID);
GBOOL mhsrhd(VOID);
GBOOL mhschkh(VOID);
GBOOL mhsrtxt(VOID);
GBOOL mhssnd(VOID);
GBOOL chk4bad(CHAR *fname);
struct mhskar *keywdok(CHAR *stgptr);
VOID mhsfpst(VOID);
VOID mhsbad(VOID);
VOID bad2sy(VOID);
GBOOL sndbad(VOID);
VOID sndnod(VOID);
VOID sndnot(INT wchtyp);
VOID delimp(VOID);
/* keyword processing functions */
GBOOL attmnt(CHAR *s);
GBOOL touid(CHAR *s);
GBOOL frmadr(CHAR *s);
GBOOL msgsub(CHAR *s);
GBOOL hdlsum(CHAR *s);
GBOOL nottyp(CHAR *s);
GBOOL retrec(CHAR *s);
GBOOL nodnot(CHAR *s);
GBOOL errnum(CHAR *s);
GBOOL msgdte(CHAR *s);
GBOOL nulrou(CHAR *s);
/* miscellaneous functions */
VOID inimhs(VOID);
GBOOL mhscfl(VOID *work,USHORT forum,LONG msgid);
VOID clsmhs(VOID);
VOID clnmhs(VOID);
VOID bldrfl(CHAR *msgpth);
CHAR *makpth(CHAR *pthpre,CHAR *filnam);
VOID zapbck(CHAR *dir);
CHAR *skpspc(CHAR *s);
CHAR *xltcrs(CHAR *s);
struct mhsalias mhsexp={ /* alias block for MHS */
{ /* (begin MHS exporter control block) */
"", /* address prefix for this exporter */
"", /* name of exporter */
"", /* description of exporter */
"", /* example address to this exporter */
"", /* key required to use this exporter */
0, /* per-message surcharge */
"", /* key required for file attachments */
0, /* attachment surcharge */
0, /* attachment per-kbyte surcharge */
"", /* key required to request return recp*/
0, /* return receipt request surcharge */
"", /* key required to send priority msg */
0, /* priority surcharge */
(EXPATT|EXPRRR), /* supported features flags */
mhshlp, /* get help message for this exporter */
valmhs, /* is this a valid address vector */
mhsasp, /* path+file name for attachments */
sndmhs /* send message vector */
}, /* (end MHS exporter control block) */
NULL, /* outgoing message directory */
NULL, /* outgoing attachment directory */
NULL, /* incoming message directory */
NULL, /* incoming attachment directory */
"", /* outgoing message address prefix */
"" /* outgoing message address suffix */
};
VOID *mhswrk; /* GME work area for importing */
struct message *mhsmsg; /* message header for importing */
CHAR *mhstxt; /* message text buffer for importing */
INT scnmhs, /* how often to scan for incoming msgs */
lastalias=-1, /* index of last alias imported for */
mhscur, /* MHS current state for incoming mail */
mhstsk; /* MHS importing task ID */
ULONG mhsidly; /* per-CYCLE MHS import: maximum delay */
GBOOL impact=FALSE, /* at least one MHS importer is active */
badmhs, /* bad import E-mail to Sysop flag */
moremsg; /* this message continues */
CHAR *gtwnme, /* server gateway name */
mhsfnm[GCMAXPTH], /* file name hold area */
mhsfn2[GCMAXPTH]; /* file name hold area #2 */
FILE *filfp=NULL; /* current import message file stream */
HMCVFILE mhsmb=NULL; /* MHS message file pointer */
struct mhsalias *curalias; /* pointer to alias being imported */
INT naliases=0; /* number of MHS aliases registered */
struct mhsalias **aliasarr=NULL; /* array of MHS alias control blocks */
INT numrfd; /* number of files referenced in msgs */
CHAR **refdfl; /* "referenced in msgs" file list */
/* MHS importing states */
#define MHSIGNORE -1 /* no cycle needed, ignore it */
#define MHSSCN 0 /* dispatch to mhsscn() */
#define MHSRHD 1 /* dispatch to mhsrhd() */
#define MHSRHD2 2 /* dispatch to mhsrhd() */
#define MHSCHKH 3 /* dispatch to mhschkh() */
#define MHSTXT 4 /* dispatch to mhsrtxt() */
#define MHSTXT2 5 /* dispatch to mhsrtxt() */
#define MHSSND 6 /* dispatch to mhssnd() */
#define SNDBAD 7 /* dispatch to sndbad() */
struct mhskar { /* struct for dealing with keywords */
CHAR *hdrwrd; /* keyword name */
GBOOL (*routine)(CHAR *); /* routine to execute */
};
#define HDRSIZ (sizeof(mhskwd)/sizeof(struct mhskar))
struct mhskar mhskwd[]={
{"ATTACHMENT", attmnt},
{"DATE", msgdte},
{"ERC", errnum},
{"FROM", frmadr},
{"NDN", nodnot},
{"ROC", nulrou},
{"RRN", retrec},
{"SUBJECT", msgsub},
{"SUMMARY", hdlsum},
{"TO", touid},
{"TYPE", nottyp}
};
#define CONTSTR "\r<< Continued in next Message >>\r"
#define ATTBGN "Attachment-name:" /* attachment line in msg begins w/ this*/
struct mhsimp { /* current message import control data */
USHORT forum; /* forum ID to which message is going */
LONG lastmsg; /* last message number for TBC */
CHAR from[MAXADR]; /* from address - for replys */
CHAR subject[TPCSIZ]; /* message subject */
CHAR to[UIDSIZ]; /* on-system destination for msg */
CHAR auxto[MAXADR]; /* who forum message was addressed to */
CHAR date[MHSDSZ]; /* date information */
CHAR filatt[GCMAXPTH]; /* file attachment path+file name */
CHAR attname[GCMAXFNM]; /* file attachment name */
INT errcode; /* errcode if notification */
CHAR flags; /* misc flags */
} mhsimp;
/* bit definitions for mhsimp.flags */
#define HASSUB 0x01 /* Subject has been defined */
#define ISNOTI 0x02 /* This is only a notification */
#define REQREC 0x04 /* Return Receipt Requested */
#define REQNOD 0x08 /* Request Non-Delivery Notice */
#define FILEAT 0x10 /* File attachment present */
#define FNDFOR 0x20 /* Forum message going to found */
#define FNDUID 0x40 /* User-ID to whom message going found*/
VOID EXPORT
init__galmhs(VOID) /* initialize MHS */
{
if (mhsmb == NULL) {
mhsmb=opnmsg("GALMHS.MCV");
}
else {
setmbk(mhsmb);
}
mhscur=MHSIGNORE;
hook_shutdown(clsmhs);
hook_cleanup(clnmhs);
if (!ynopt(MHSACT)) {
return;
}
stlcpy(mhsexp.exp.prefix,getMsgBlk(MHSPFX),PFXSIZ);
stlcpy(mhsexp.exp.name,getMsgBlk(MHSNAM),EXPNSZ);
stlcpy(mhsexp.exp.desc,getMsgBlk(MHSDSC),EXPDSZ);
stlcpy(mhsexp.exp.exmp,getMsgBlk(MHSXMP),MAXADR);
stlcpy(mhsexp.exp.wrtkey,getMsgBlk(MHSKEY),KEYSIZ);
mhsexp.exp.wrtchg=numopt(MHSCHG,-32767,32767);
stlcpy(mhsexp.exp.attkey,getMsgBlk(MHSATKY),KEYSIZ);
mhsexp.exp.attchg=numopt(MHSATCH,-32767,32767);
mhsexp.exp.apkchg=numopt(MHSPKCH,-32767,32767);
stlcpy(mhsexp.exp.rrrkey,getMsgBlk(MHSRRKY),KEYSIZ);
mhsexp.exp.rrrchg=numopt(MHSRRCH,-32767,32767);
mhsexp.outmsg=stgopt(OUTMSG);
if (*(mhsexp.outfil=stgopt(OUTFIL)) == '\0') {
free(mhsexp.outfil);
mhsexp.outfil=NULL;
}
mhsexp.inmsg=stgopt(INMSG);
if (*(mhsexp.infil=stgopt(INFIL)) == '\0') {
free(mhsexp.infil);
mhsexp.infil=NULL;
}
if (!register_mhsalias(&mhsexp)) {
usrnum=-1;
shocst("MHS: Inactive","MHS: Directory Structure Incomplete!");
free(mhsexp.outmsg);
if (mhsexp.outfil != NULL) {
free(mhsexp.outfil);
}
free(mhsexp.inmsg);
if (mhsexp.infil != NULL) {
free(mhsexp.infil);
}
return;
}
}
VOID
inimhs(VOID) /* initialize MHS import/export */
{
static GBOOL initted=FALSE;
if (initted) {
return;
}
if (mhsmb == NULL) {
mhsmb=opnmsg("GALMHS.MCV");
}
else {
setmbk(mhsmb);
}
mhswrk=(VOID *)alczer(GMEWRKSZ);
mhsmsg=(struct message *)alcmem(sizeof(struct message));
mhstxt=(CHAR *)alcmem(txtlen());
gtwnme=stgopt(GTWNME);
if (*gtwnme == '\0') {
catastro("GALMHS: gateway name not configured");
}
scnmhs=numopt(SCNMHS,5,3600);
badmhs=ynopt(BADMHS);
mhsidly=numopt(MHSIDLY,1,100)*655L;
if (!setcfl(mhscfl)) {
catastro("GALMHS: unable to register conflict checker");
}
initted=TRUE;
rstmbk();
}
GBOOL /* returns TRUE if MHS has conflict */
mhscfl( /* MHS conflict checker */
VOID *work, /* work area being checked */
USHORT forum, /* forum to check */
LONG msgid) /* message ID to check */
{
if (work != mhswrk && msgid == 0L) {
return((mhscur == MHSSND || mhscur == SNDBAD)
&& forum == mhsmsg->forum);
}
return(FALSE);
}
VOID
clsmhs(VOID) /* shutdown MHS processing */
{
while (mhscur == MHSSND) {
mhssnd();
}
while (mhscur == SNDBAD) {
sndbad();
}
if (filfp != NULL) {
fclose(filfp);
filfp=NULL;
}
clsmsg(mhsmb);
mhsmb=NULL;
}
VOID
clnmhs(VOID) /* clean out old MHS file attachments */
{
INT i,aliasidx;
CHAR *curfil;
struct ffblk fb;
for (aliasidx=0 ; aliasidx < naliases ; ++aliasidx) {
curalias=aliasarr[aliasidx];
if (curalias->outmsg != NULL) {
bldrfl(curalias->outmsg);
curfil=makpth(curalias->outfil,STAR);
if (fnd1st(&fb,curfil,0)) {
do {
curfil=makpth(curalias->outfil,fb.ff_name);
if (curfil[strlen(curfil)-1] == '.') {
curfil[strlen(curfil)-1]='\0';
}
for (i=0 ; i < numrfd ; ++i) {
if (sameas(curfil,refdfl[i])) {
break;
}
}
if (i == numrfd) {
unlink(curfil);
}
} while (fndnxt(&fb));
}
if (numrfd > 0) {
for (i=0 ; i < numrfd ; ++i) {
free(refdfl[i]);
}
free(refdfl);
}
}
}
}
VOID
bldrfl( /* build "referenced in msgs" file list */
CHAR *msgpth) /* path to find outgoing MHS msgs */
{
FILE *fp;
CHAR *curfil;
struct ffblk fb;
numrfd=0;
refdfl=NULL;
curfil=makpth(msgpth,STAR);
cntdir(curfil);
if (numfils == 0L || !fnd1st(&fb,curfil,0)) {
return;
}
refdfl=(CHAR **)alczer(sizeof(CHAR *)*(INT)numfils);
do {
curfil=makpth(msgpth,fb.ff_name);
if ((fp=fopen(curfil,FOPRA)) != NULL) {
while (fgets(vdatmp,vdasiz,fp) != NULL) {
if (sameto(ATTBGN,vdatmp)) {
refdfl[numrfd]=
alcdup(unpad(skpwht(&vdatmp[sizeof(ATTBGN)-1])));
++numrfd;
break;
}
}
fclose(fp);
}
} while (fndnxt(&fb));
}
CHAR *
makpth( /* make a path out of prefix and file */
CHAR *pthpre, /* path prefix to use */
CHAR *filnam) /* file name to use */
{
static CHAR retbuf[GCMAXPTH];
stlcpy(retbuf,pthpre,GCMAXPTH);
if (retbuf[strlen(retbuf)-1] != SL) {
stlcat(retbuf,SLS,GCMAXPTH);
}
stlcat(retbuf,filnam,GCMAXPTH);
return(retbuf);
}
/* The following functions deal with MHS aliases: */
GBOOL /* returns FALSE if bad directories */
register_mhsalias ( /* set up an MHS alias */
struct mhsalias *alias) /* alias definition block */
{
INT i;
GBOOL impflg,expflg;
CHAR newpth[GCMAXPTH],oldpth[GCMAXPTH];
ASSERT(alias != NULL);
impflg=FALSE;
if (alias->inmsg != NULL) {
if (*alias->inmsg == '\0') {
return(FALSE);
}
zapbck(alias->inmsg);
for (i=0 ; i < naliases ; ++i) {
if (aliasarr[i]->inmsg != NULL
&& sameas(normspec(newpth,alias->inmsg),
normspec(oldpth,aliasarr[i]->inmsg))) {
catastro("GALMHS: inbound message directory conflict\n"
"Importer \"%s:\" conflicts with \"%s:\"",
alias->exp.prefix,aliasarr[i]->exp.prefix);
}
}
if (alias->infil == NULL || *alias->infil == '\0') {
alias->infil=alcdup(spr("%s" SLS "PARCEL",alias->inmsg));
}
else {
zapbck(alias->infil);
}
if (!fmdir(alias->inmsg) || !fmdir(alias->infil)) {
return(FALSE);
}
impflg=TRUE;
}
expflg=FALSE;
if (alias->outmsg != NULL) {
if (*alias->outmsg == '\0') {
return(FALSE);
}
zapbck(alias->outmsg);
if (alias->outfil == NULL || *alias->outfil == '\0') {
alias->outfil=alcdup(spr("%s" SLS "PARCEL",alias->outmsg));
}
else {
zapbck(alias->outfil);
}
if (!fmdir(alias->outmsg) || !fmdir(alias->outfil)) {
return(FALSE);
}
alias->exp.flags&=(EXPATT|EXPRRR);
if (alias->exp.sndmsg == NULL || alias->exp.attspc == NULL) {
catastro("GALMHS: invalid exporter alias (prefix: \"%s:\")",
alias->exp.prefix);
}
if (alias->exp.helpmsg == NULL) {
alias->exp.helpmsg=mhshlp;
}
if (alias->exp.valadr == NULL) {
alias->exp.valadr=valmhs;
}
expflg=TRUE;
}
if (!alcpar(&aliasarr,naliases,SMLBLK)) {
catastro("GALMHS: not enough memory to register MHS alias\n"
"(prefix: \"%s:\")",alias->exp.prefix);
}
aliasarr[naliases]=alias;
++naliases;
inimhs();
if (impflg && !impact) {
impact=TRUE;
rtkick(5,mhsscn2);
}
if (expflg) {
register_exp(&alias->exp);
}
return(TRUE);
}
CHAR *
aliasasp( /* get outbound att file path+name */
struct mhsalias *alias, /* for this exporter alias */
const CHAR *to, /* address to which message being sent*/
const struct message *msg) /* header of message being sent */
{
UINT ctr;
static CHAR attpath[GCMAXPTH];
(VOID)to;
(VOID)msg;
ctr=0U;
do {
stlcpy(attpath,alias->outfil,GCMAXPTH);
stlcat(attpath,SLS,GCMAXPTH);
stlcat(attpath,tmpnam(NULL),GCMAXPTH);
if (++ctr == TMP_MAX) {
catastro("Too many temporary files in outbound attachment\n"
"directory: %s",alias->outfil);
}
} while (isfile(attpath));
return(attpath);
}
INT /* returns GME error codes */
sndalias( /* send a message for an MHS alias */
struct mhsalias *alias, /* exporter alias being used */
const CHAR *to, /* to field (MHS address) */
const struct message *msg, /* header of message to send off */
const CHAR *text, /* message text buffer */
const CHAR *filatt) /* path+file name of attachment */
{
INT handle,savusn;
FILE *fp;
CHAR sumlin[MAXADR];
CHAR outnam[GCMAXPTH];
strcpy(outnam,alias->outmsg);
strcat(outnam,SLS);
if ((handle=creattemp(outnam,0)) != -1) {
close(handle);
if ((fp=fopen(outnam,FOPWA)) != NULL) {
fprintf(fp,"SMF-70\n");
fprintf(fp,"To: %s%s%s\n",alias->outpfx,to,alias->outsfx);
fprintf(fp,"From: MBBS@%s {MBBS: %s}\n",gtwnme,msg->from);
fprintf(fp,"Subject: %s\n",msg->topic);
fprintf(fp,"Date: %s %s\n",ncdatel(msg->crdate), nctime(msg->crtime));
if (msg->forum != EMLID && !sameas(msg->to,ALLINF)) {
stlcpy(sumlin,msg->to,MAXADR);
if (strchr(sumlin,'@') == NULL && uidxst(sumlin)) {
stlcat(sumlin,"@",MAXADR);
stlcat(sumlin,gtwnme,MAXADR);
}
fprintf(fp,"Summary: MBBS: %s\n",sumlin);
}
if (msg->flags&FILATT) {
fprintf(fp,"Attachment-name: %s\n",filatt);
}
fprintf(fp,"MCB-options: %s\n\n",
(msg->flags&RECREQ) ? "NYYNPNP" : "NNYNPNP");
outxt(fp,text);
fclose(fp);
return(GMEOK);
}
}
savusn=usrnum;
usrnum=-1;
shocst("MHS FILE OPEN ERROR",
"Couldn't create file in %s",alias->outmsg);
usrnum=savusn;
return(GMEERR);
}
const CHAR *
mhsGatewayName(VOID) /* get MHS gateway name */
{ /* (replaces exported gtwnme variable) */
return(gtwnme);
}
/* The following functions deal with exporting messages using MHS: */
const CHAR *
mhshlp(VOID) /* get help on MHS exporter */
{
if (mhsmb != NULL) {
setmbk(mhsmb);
sprintf(vdatmp,getMsgBlk(MHSHLP),mhsexp.exp.prefix);
rstmbk();
return(vdatmp);
}
return("");
}
GBOOL
valmhs( /* does addr contain valid MHS '@' char */
const CHAR *adr) /* ('!' is considered valid for MG/I) */
{
return(strchr(adr,'@') != NULL || strchr(adr,'!') != NULL);
}
const CHAR *
mhsasp( /* outbound att file path+name for MHS */
const CHAR *to, /* address to which message being sent*/
const struct message *msg) /* header of message being sent */
{
return(aliasasp(&mhsexp,to,msg));
}
INT /* returns GME error codes */
sndmhs( /* send MHS message */
const CHAR *to, /* to field (MHS address) */
const struct message *msg, /* header of message to send off */
const CHAR *text, /* message text buffer */
const CHAR *filatt) /* path+file name of attachment */
{
return(sndalias(&mhsexp,to,msg,text,filatt));
}
VOID
outxt( /* output msg text (trans '\r' to '\n') */
FILE *fp, /* into this file */
const CHAR *cp) /* from this string */
{
for ( ; *cp != '\0' ; ++cp) {
if (*cp == '\r') {
fputc('\n',fp);
}
else {
fputc(*cp,fp);
}
}
}
VOID
zapbck( /* remove trailing backslash if present */
CHAR *dir) /* from this directory name */
{
INT pos;
if (dir[pos=strlen(dir)-1] == SL) {
dir[pos]='\0';
}
}
/* The following routines deal with background importing of MHS messages: */
VOID
mhsproc( /* incoming mail process dispatcher */
INT taskid) /* task ID in use */
{
GBOOL cont;
ULONG begintim,interval;
static ULONG debtim=0L;
if (debtim >= mhsidly) {
debtim-=mhsidly;
return;
}
begintim=hrtval()-debtim;
do {
switch (mhscur) {
case MHSIGNORE:
cont=FALSE;
break;
case MHSSCN:
cont=mhsscn();
break;
case MHSRHD:
case MHSRHD2:
cont=mhsrhd();
break;
case MHSCHKH:
cont=mhschkh();
break;
case MHSTXT:
case MHSTXT2:
cont=mhsrtxt();
break;
case MHSSND:
cont=mhssnd();
break;
case SNDBAD:
cont=sndbad();
break;
default:
catastro("GALMHS: Invalid mhsproc() substate: %d",mhscur);
}
} while ((interval=hrtval()-begintim) < mhsidly && cont);
if (!cont) {
debtim=0L;
mfytask(taskid,NULL);
}
else {
debtim=(interval > mhsidly ? interval-mhsidly : 0L);
}
}
VOID
mhsscn2(VOID) /* rtkick'able version of mhsscn() */
{
mhsscn();
}
GBOOL
mhsscn(VOID) /* scan for incoming MHS messages */
{
INT nchecked;
struct ffblk fb;
for (nchecked=0 ; nchecked < naliases ; ++nchecked) {
if (++lastalias >= naliases) {
lastalias=0;
}
curalias=aliasarr[lastalias];
if (curalias->inmsg != NULL) {
stlcpy(mhsfnm,curalias->inmsg,GCMAXPTH);
stlcat(mhsfnm,SLS STAR,GCMAXPTH);
if (fnd1st(&fb,mhsfnm,0)) {
do {
if (fb.ff_fsize != 0L && !chk4bad(fb.ff_name)) {
stlcpy(mhsfnm,curalias->inmsg,GCMAXPTH);
stlcat(mhsfnm,SLS,GCMAXPTH);
stlcat(mhsfnm,fb.ff_name,GCMAXPTH);
filfp=gcfsopen(mhsfnm,FOPRA,GSH_DENYRW);
if (filfp != NULL) {
if (mhscur == MHSIGNORE) {
mhstsk=initask(mhsproc);
}
mhscur=MHSRHD;
return(TRUE);
}
}
} while (fndnxt(&fb));
}
}
}
mhscur=MHSIGNORE;
rtkick(scnmhs,mhsscn2);
return(FALSE);
}
GBOOL
mhsrhd(VOID) /* read and process the incoming header */
{
static struct mhskar *kptr;
static CHAR *sptr,*dptr;
static CHAR keywd[MAXKWD];
if (mhscur == MHSRHD) {
setmem(&mhsimp,sizeof(struct mhsimp),0);
}
if ((sptr=fgets(vdatmp,vdasiz,filfp)) != NULL) {
if (*sptr == '\n') {
mhscur=MHSCHKH;
return(TRUE);
}
dptr=keywd;
while (*sptr != ':' && *sptr != '\0' && dptr-keywd < MAXKWD-1) {
*dptr++=*sptr++;
}
if (*sptr != ':') {
mhsbad();
return(TRUE);
}
*dptr='\0';
if ((kptr=keywdok(keywd)) == NULL) {
shocst("MHS Bad: keywd null", "keywd null %s", keywd);
mhsbad();
return(TRUE);
}
sptr++;
while (isspace(*sptr)) {
sptr++;
}
if (!(*(kptr->routine))(sptr)) {
if (mhscur != SNDBAD) {
mhscur=MHSSCN;
}
return(TRUE);
}
mhscur=MHSRHD2;
return(TRUE);
}
shocst("MHS Bad: fgets", "fgets");
mhsbad();
return(TRUE);
}
GBOOL
mhschkh(VOID) /* check header components */
{
if (!(*curalias->exp.valadr)(mhsimp.from)) {
mhsbad();
}
else if ((mhsimp.flags&FNDFOR)
&& ((mhsimp.flags&FNDUID) || mhsimp.forum != EMLID)) {
moremsg=FALSE;
mhscur=MHSTXT;
}
else {
sndnod();
unlink(mhsimp.filatt);
}
return(TRUE);
}
GBOOL
mhsrtxt(VOID) /* read and process the incoming text */
{
const CHAR *cp;
static INT cnt;
static UINT totbyt,maxsiz;
static CHAR *ptr,buf[MAXLIN+1];
static INT c;
CHAR decdate[MHSDSZ];
CHAR dectime[MHSDSZ];
if (mhscur == MHSTXT) {
setmem(mhsmsg,sizeof(struct message),0);
mhsmsg->forum=mhsimp.forum;
stlcat(mhsmsg->from,":",MAXADR);
stlcat(mhsmsg->from,mhsimp.from,MAXADR);
//Patch to get original message date/time get imported
//you must use MM/DD/YYYY HH:II::SS format
sscanf(mhsimp.date, "%s %s", decdate, dectime);
shocst("MHS", "date: %s", decdate);
shocst("MHS", "time: %s", dectime);
mhsmsg->crdate = dcdate(decdate);
mhsmsg->crtime = dctime(dectime);
if (mhsmsg->forum == EMLID) {
stlcpy(mhsmsg->to,mhsimp.to,UIDSIZ);
}
else {
if (mhsimp.flags&FNDUID) {
stlcpy(mhsmsg->to,mhsimp.auxto,MAXADR);
}
else {
stlcpy(mhsmsg->to,ALLINF,MAXADR);
}
}
stlcpy(mhsmsg->topic,(mhsimp.flags&HASSUB) ? mhsimp.subject
: "<< None >>",TPCSIZ);
if (mhsimp.flags&FILEAT) {
cp=tpcfnm(mhsmsg->topic);
if (cp != NULL) {
stlcpy(mhsmsg->attname,cp,GCMAXFNM);
}
mhsmsg->flags|=FILATT;
if (mhsmsg->forum == EMLID) {
mhsmsg->flags|=FILAPV;
}
mhsimp.flags&=~FILEAT;
}
cnt=0;
if (moremsg) {
sprintf(mhstxt,"\r<< Continued from Message #%ld >>\r\r",
mhsimp.lastmsg);
}
else {
strcpy(mhstxt,"\r");
}
moremsg=FALSE;
totbyt=strlen(mhstxt);
maxsiz=TXTLEN-sizeof(CONTSTR);
}
if (totbyt+MAXLIN+1 < maxsiz) {
ptr=NULL;
while (cnt < MAXLIN && (c=fgetc(filfp)) != EOF) {
if (c == '\n' || c == '\r') {
buf[cnt++]='\r';
buf[cnt]='\0';
strcat(mhstxt,buf);
totbyt=strlen(mhstxt);
cnt=0;
mhscur=MHSTXT2;
return(TRUE);
}
else {
if (c == ' ') {
ptr=&buf[cnt];
}
buf[cnt++]=c;
}
}
if (c == EOF) {
buf[cnt]='\0';
stlcat(mhstxt,buf,TXTLEN);
}
if (cnt >= MAXLIN) {
if (ptr != NULL) {
*ptr='\0';
buf[cnt]='\0';
stlcat(mhstxt,buf,TXTLEN);
stlcat(mhstxt,"\r",TXTLEN);
cnt=strlen(++ptr);
movmem(ptr,buf,cnt+1);
}
else {
buf[cnt++]='\r';
buf[cnt]='\0';
cnt=0;
stlcat(mhstxt,buf,TXTLEN);
}
totbyt=strlen(mhstxt);
mhscur=MHSTXT2;
return(TRUE);
}
}
if (c != EOF) {
moremsg=TRUE;
stlcat(mhstxt,CONTSTR,TXTLEN);
}
else {
moremsg=FALSE;
}
inigmerq(mhswrk);
mhscur=MHSSND;
return(TRUE);
}
GBOOL
mhssnd(VOID) /* submit message to GME */
{
switch (impmsg(mhswrk,mhsmsg,mhstxt,mhsimp.filatt)) {
case GMEAGAIN:
break;
case GMEAFWD:
case GMEOK:
shocst("MHS", "Imported from %s to %s", mhsimp.from, mhsimp.to);
if (moremsg) {
mhsimp.lastmsg=mhsmsg->msgid;
mhscur=MHSTXT;
}
else {
mhsfpst();
}
break;
default:
mhsbad();
break;
}
return(TRUE);
}
/* The following functions process incoming MHS message keywords: */
GBOOL
touid( /* process "TO" keyword data */
CHAR *s) /* string to process */
{
INT i,siz,spc;
CHAR uid[UIDSIZ];
shocst("MHS","To %s", s);
s=strchr(s,'{');
if (s != NULL) {
s++;
if (sameto("MBBS:",s=skpspc(s))) {
s=skpspc(s+5);
}
else if (sameto("WG:",s)) {
s=skpspc(s+3);
}
i=0;
siz=(*s == FORIDC ? FORNSZ : UIDSIZ-1);
do {
uid[i++]=*s++;
} while (i < siz && *s != '\0' && *s != '}');
uid[i]='\0';
for (spc = i-1; spc > 0 ; --spc) {
if (isspace(uid[spc])) {
uid[spc]='\0';
}
else {
break;
}
}
stlcpy(mhsimp.to,uid,UIDSIZ); /* for NDN's */
if (uid[0] == FORIDC) {
mhsimp.forum=getfid(&uid[1]);
if (mhsimp.forum != EMLID) {
mhsimp.flags|=FNDFOR;
}
}
else {
if (uidxst(uid)) {
mhsimp.forum=EMLID;
mhsimp.flags|=(FNDUID|FNDFOR);
}
}
}
return(TRUE);
}
GBOOL
frmadr( /* process "FROM" keyword data */
CHAR *s) /* string to process */
{
CHAR *ptr;
ptr=strchr(s,'\n');
if (ptr != NULL) {
*ptr='\0';
}
ptr=strchr(s,'\r');
if (ptr != NULL) {
*ptr='\0';
}
if (*s != '\0') {
stlcpy(mhsimp.from,s,MAXADR);
}
return(TRUE);
}
GBOOL
msgsub( /* process "SUBJECT" keyword data */
CHAR *s) /* string to process */
{
INT len;
stlcpy(mhsimp.subject,s,TPCSIZ);
len=strlen(mhsimp.subject);
if (len != 0 && mhsimp.subject[len-1] == '\n') {
mhsimp.subject[len-1]='\0';
}
mhsimp.flags|=HASSUB;
return(TRUE);
}
GBOOL
hdlsum( /* process "SUMMARY" keyword data */
CHAR *s) /* string to process */
{
CHAR *ptr;
s=skpwht(s);
if (sameto("MBBS: ",s)) {
s+=strlen("MBBS: ");
ptr=strchr(s,'\n'); /* Zap the NL */
if (ptr!= NULL) {
*ptr='\0';
}
ptr=strchr(s,'\r'); /* Zap the CR */
if (ptr!= NULL) {
*ptr='\0';
}
if ((ptr=strchr(s,'@')) != NULL) {
if (sameas(ptr+1,gtwnme)) {
*ptr='\0';
}
}
mhsimp.flags|=FNDUID;
stlcpy(mhsimp.auxto,s,MAXADR);
}
return(TRUE);
}
GBOOL
nottyp( /* process "TYPE" keyword data */
CHAR *s) /* string to process */
{ /* 0=Message 1=Some notification */
if (*s == '1') {
mhsimp.flags|=ISNOTI;
}
return(TRUE);
}
GBOOL
retrec( /* process "RRN" keyword data */
CHAR *s) /* string to process */
{ /* Return Receipt Requested? */
if (*s != 'Y' && *s != 'N') {
mhsbad();
return(FALSE);
}
if (*s == 'Y') {
mhsimp.flags|=REQREC;
}
return(TRUE);
}
GBOOL
attmnt( /* process "ATTACHMENT" line */
CHAR *s) /* string to process */
{
if (*s != '\0') {
stlcpy(mhsimp.filatt,curalias->infil,GCMAXPTH);
stlcat(mhsimp.filatt,SLS,GCMAXPTH);
stlcat(mhsimp.filatt,s,GCMAXPTH);
unpad(mhsimp.filatt);
if (isfile(mhsimp.filatt)) {
mhsimp.flags|=FILEAT;
}
else {
*mhsimp.filatt='\0';
}
}
return(TRUE);
}
GBOOL
nodnot( /* process "NDN" keyword data */
CHAR *s) /* string to process */
{ /* Non-delivery note Requested? */
if (*s != 'Y' && *s != 'N') {
mhsbad();
return(FALSE);
}
else if (*s == 'Y') {
mhsimp.flags|=REQNOD;
}
return(TRUE);
}
GBOOL
errnum( /* process "ERC" keyword data */
CHAR *s) /* string to process */
{ /* What's wrong if this is non-delivery */
mhsimp.errcode=atoi(s);
return(TRUE);
}
GBOOL
msgdte( /* process "DATE" keyword data */
CHAR *s) /* string to process */
{
CHAR *ddptr;
ddptr=strchr(s,'\n');
if (ddptr != NULL) {
*ddptr='\0';
}
ddptr=strchr(s,'\r');
if (ddptr != NULL) {
*ddptr='\0';
}
if (*s != '\0') {
stlcpy(mhsimp.date,s,MHSDSZ);
shocst("MHS", "set date %s", mhsimp.date);
}
return(TRUE);
}
GBOOL
nulrou( /* dummy keyword processor function */
CHAR *s) /* string to process */
{
(VOID)s;
return(TRUE);
}
/* miscellaneous importing utility functions follow: */
VOID
mhsfpst(VOID) /* finish up posting messages */
{
if (onsys(mhsimp.to)) {
setmbk(mhsmb);
clrmlt();
if (mhsimp.forum == EMLID) {
prfmlt(MHSEML);
}
else {
prfmlt(MHSFOR,getfnm(mhsimp.forum));
}
injoth();
}
if (mhsimp.flags&REQREC) {
sndnot(RETREC);
}
delimp();
mhscur=MHSSCN;
}
VOID
mhsbad(VOID) /* something wrong with msg to import */
{
CHAR *ptr;
fclose(filfp);
filfp=NULL;
stlcpy(mhsfn2,mhsfnm,GCMAXPTH);
ptr=strchr(mhsfn2,'.');
if (ptr == NULL) {
stlcat(mhsfn2,".BAD",GCMAXPTH);
}
else {
stlcpy(ptr,".BAD",GCMAXPTH);
}
if (mhsimp.flags&ISNOTI) {
delimp();
}
else if (rename(mhsfnm,mhsfn2) == 0) {
if (badmhs) {
bad2sy();
return;
}
}
mhscur=MHSSCN;
}
VOID
bad2sy(VOID) /* send email to Sysop about a .BAD message */
{
setmem(mhsmsg,sizeof(struct message),0);
mhsmsg->forum=EMLID;
strcpy(mhsmsg->from,"Sysop");
strcpy(mhsmsg->to,"Sysop");
strcpy(mhsmsg->topic,"* MHS Import Notice *");
setmbk(mhsmb);
prfmsg(INVMHS,mhsfnm);
stlcpy(mhstxt,xltcrs(stpans(prfbuf)),TXTLEN);
clrprf();
inigmerq(mhswrk);
mhscur=SNDBAD;
}
GBOOL
sndbad(VOID) /* send bad import message */
{
if (gsndmsg(mhswrk,mhsmsg,mhstxt,NULL) != GMEAGAIN) {
mhscur=MHSSCN;
}
return(TRUE);
}
GBOOL
chk4bad(fname) /* check for ".BAD" extension */
CHAR *fname;
{
CHAR *ptr;
ptr=strchr(fname,'.');
if (ptr != NULL) {
return(sameas(ptr,".BAD"));
}
return(FALSE);
}
struct mhskar *
keywdok( /* check valid keyword list */
CHAR *stgptr) /* in this string */
{
INT cond;
struct mhskar *low,*mid,*high;
low=&mhskwd[0];
high=&mhskwd[HDRSIZ-1];
while (low <= high) {
mid=low+((INT)(high-low))/2;
if ((cond=stricmp(stgptr,mid->hdrwrd)) < 0) {
if (mid == low) {
break;
}
high=mid-1;
}
else if (cond > 0) {
if (mid == high) {
break;
}
low=mid+1;
}
else {
return(mid);
}
}
return(NULL);
}
VOID
sndnod(VOID) /* NDN requested? Delete MHS import */
{
if (mhsimp.flags&REQNOD) {
sndnot(NONDEL);
}
delimp();
mhscur=MHSSCN;
}
VOID
sndnot( /* send a return notice */
INT wchtyp) /* 0=Non Delivery 1=Return Receipt */
{
INT handle;
struct message *msg;
FILE *fp;
if (curalias->outmsg != NULL) {
stlcpy(mhsfn2,curalias->outmsg,GCMAXPTH);
stlcat(mhsfn2,SLS,GCMAXPTH);
if ((handle=creattemp(mhsfn2,0)) != -1) {
close(handle);
if ((fp=fopen(mhsfn2,FOPWA)) != NULL) {
fprintf(fp,"SMF-70\n");
fprintf(fp,"MCB-Type: 1\n");
fprintf(fp,"To: %s\n", mhsimp.from);
fprintf(fp,"From: MBBS@%s {MBBS: %s}\n", gtwnme,mhsimp.to);
fprintf(fp,"Subject: %s\n",
wchtyp == NONDEL ? "Non-Delivery Notification"
: "Return Receipt Notification");
setmbk(mhsmb);
prfmsg(wchtyp == NONDEL ? MHSNOD : MHSREC,
*mhsimp.date == '\0' ? "Unknown" : mhsimp.date,
mhsimp.to);
rstmbk();
fputc('\n',fp);
fputs(xltcrs(stpans(prfbuf)),fp);
clrprf();
fclose(fp);
}
}
}
else if (curalias->exp.sndmsg != NULL) {
msg=(struct message *)vdatmp;
setmem(msg,sizeof(struct message),0);
msg->forum=EMLID;
stlcpy(msg->to,mhsimp.from,MAXADR);
sprintf(msg->from,"MBBS@%s {MBBS: %s}",gtwnme,mhsimp.to);
strcpy(msg->topic,wchtyp == NONDEL ? "Non-Delivery Notification"
: "Return Receipt Notification");
setmbk(mhsmb);
prfmsg(wchtyp == NONDEL ? MHSNOD : MHSREC,
*mhsimp.date == '\0' ? "Unknown" : mhsimp.date,
mhsimp.to);
rstmbk();
(*curalias->exp.sndmsg)(msg->to,msg,xltcrs(stpans(prfbuf)),NULL);
}
}
CHAR * /* ptr to first non-whitespace char */
skpspc( /* skip all whitespace characters */
CHAR *s) /* in this string */
{
while (isspace(*s)) {
++s;
}
return(s);
}
CHAR * /* copy of pointer to string */
xltcrs( /* translate '\r' to '\n' */
CHAR *s) /* in this string */
{
CHAR *cp;
cp=s;
while ((cp=strchr(cp,'\r')) != NULL) {
*cp='\n';
}
return(s);
}
VOID
delimp(VOID) /* delete a message from import dir */
{
fclose(filfp);
filfp=NULL;
chmod(mhsfnm,S_IWRITE);
unlink(mhsfnm);
}
whitout patched DLL, WG will import with NOW() as datetime
WG set the NOW() for date when import to MHs, i need to learm the MHS source code of WG to see if are possible to save the original msg date/time