home *** CD-ROM | disk | FTP | other *** search
- /*
- * MSGBASE.C - Message handling
- *
- * Msged/Q message editor for QuickBBS Copyright 1990 by P.J. Muller
- *
- */
-
- #include <stdlib.h>
- #include <io.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #ifdef __MSC__
- #include <sys/types.h>
- #endif
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <time.h>
-
- #include "msged.h"
- #include "p2c.h"
- #include "screen.h"
- #include "qmsgbase.h"
-
- #include <assert.h>
-
- #ifdef EIDS
- #include "eidcrc.h"
- #endif
-
- #define TEXTLEN 200 /* changed when added * Origin scanning */
-
- static BOOLEAN checkrecvd(MSG *m);
- static int tputs(char *s, char **buf);
- static void remap(MSG *m);
- static void stripline(char *s);
- static void addid(MSG *m, ADDRESS ofrom /*, char *origtext*/ );
-
- /*
- * Display activity light
- */
-
- void working(BOOLEAN on)
- {
- int x,y;
- static char state = 1;
-
- x = wherex(); y = wherey();
- gotoxy(maxx,1);
- if (on)
- bputc(state = state ^ 3);
- else
- bputc(' ');
- gotoxy(x,y);
-
- } /* working */
-
- /*
- * Scan the message for kludge lines and set the addressing fields
- * Sets m->to and m->from
- * Note: m->*.domain de-allocated if not NULL
- * In msged there was something about 'thread' here which I removed
- *
- * Addressing information comes from the last INTL, DOMAIN or MSGID that
- * was found. If none was found, looks in the Origin line for the address.
- * If no origin line was found, use the address from the message header and
- * a FMPT line if present.
- */
-
- static void parsekludge(MSG *m, BUFFER *msg)
- {
- #ifdef EIDS
- EID seid; /* EID */
- #endif
- MSGID msgid;
- char dst[31], src[31], ddom[31], sdom[31];
- int fmpt, topt;
- LINE *t; /* used for scanning text */
-
- if (m->to.domain != NULL) /* this could be dangerous */
- ptrfree(m->to.domain); /* if m.to = thisnode was done */
-
- if (m->from.domain != NULL)
- ptrfree(m->from.domain);
-
- m->from.zone = m->header.origzone;
- m->from.net = m->header.orig_net;
- m->from.node = m->header.orig;
- m->from.point = 0;
- m->from.domain = NULL;
-
- m->to.zone = m->header.destzone;
- m->to.net = m->header.dest_net;
- m->to.node = m->header.dest;
- m->to.point = 0;
- m->to.domain = NULL;
-
- #ifdef EIDS
- memset(&(m->eid),0,sizeof(m->eid));
- memset(&seid,0,sizeof(seid));
- #endif
- memset(&msgid,0,sizeof(msgid));
-
- *dst = *src = EOS; /* clear all the scan variables */
- fmpt = topt = 0;
- memset(ddom,0,sizeof(ddom));
- memset(sdom,0,sizeof(sdom));
- memset(dst,0,sizeof(dst));
- memset(src,0,sizeof(src));
-
- /* now scan for kludge lines */
-
- t = msg->first; /* first line of text */
-
- while (t != NULL) {
- msg->last = t; /* set last line */
-
- if ((t->text != NULL) && (*(t->text) == '\01')) { /* is hidden line */
- sscanf(t->text, "\01FMPT %i\n", &(fmpt));
- sscanf(t->text, "\01TOPT %i\n", &(topt));
- sscanf(t->text, "\01INTL %30s %30s\n", dst, src);
- sscanf(t->text, "\01DOMAIN %30s %30s %30s %30s\n",ddom,dst,sdom,src);
- sscanf(t->text, "\01MSGID: %30s %X\n", src, &(msgid.st));
- #ifdef EIDS
- sscanf(t->text, "\01EID: %x %X", &(seid.crc), &(seid.st));
- #endif
- } /* if */
-
- if (strncmp(" * Origin: ",t->text,10) == 0) { /* origin line */
-
- if (*src == EOS) { /* no source found yet */
- char line2[TEXTLEN]; /* temporary origin line from msg */
- char *l;
-
- strcpy(line2,t->text);
-
- if ((strchr(line2,'\n') == NULL) && (t->next != NULL))
- strcat(line2,t->next->text); /* origin line was split */
-
- if ((l = strrchr(line2,'(')) != NULL) {
- char *m;
- while (!isdigit(*l) && (*l != EOS)) l++;
- m = src;
- while ((*l != ')') && (m-src < 30))
- *m++ = *l++;
- *m = EOS; /* copy to src */
- } /* if */
- } /* if */
-
- } /* if */
-
- t = t->next; /* step on */
- } /* while */
-
- if (*src != EOS) /* INTL or DOMAIN line found */
- m->from = parsenode(src);
-
- if (*dst != EOS)
- m->to = parsenode(dst);
-
- if (fmpt && (m->from.point == 0)) /* if we already know the point */
- m->from.point = fmpt; /* number don't add it */
-
- if (topt && (m->to.point == 0))
- m->to.point = topt;
-
- #ifdef EIDS
- if (seid.st != 0) /* found EID */
- m->eid = seid;
- #endif
-
- if (msgid.st != 0) /* found MSGID */
- m->msgid = msgid;
-
- if (*ddom != EOS) {
- m->to.domain = strdup(ddom);
- assert(m->to.domain);
- } /* if */
-
- if (*sdom != EOS) {
- m->from.domain = strdup(sdom);
- assert(m->from.domain);
- } /* if */
-
- } /* parsekludge */
-
- /*
- * Read a message and set the addressing fields
- * Text is read into global 'msgbuf'
- * Return TRUE if ok
- */
-
- BOOLEAN readmsg(MSG *m, int msgnum)
- {
- char *text;
-
- clearbuffer(&msgbuf); /* clear global msg buffer */
-
- if (!readheader(msgnum, &m->header)) /* read the header */
- return FALSE;
-
- if (arealist[area].netmail && protectnet && /* protect netmail */
- (strnicmp(username, m->header.from, strlen(username)) != 0) &&
- (strnicmp(username, m->header.to, strlen(username)) != 0)) {
-
- if ((text = strdup(" * Private\r")) == NULL)
- return FALSE;
-
- } else
- if ((text = readtext(&m->header)) == NULL) { /* read the text */
- text = strdup(" * Read Error\r"); /* was too big or something */
- if (text == NULL)
- return FALSE;
- }
-
- if (*text == EOS) { /* read an empty message */
- ptrfree(text);
- text = strdup(" * Empty message\r");
- } /* if */
-
- msgbuf = buffer(&text);
- ptrfree(text);
- if (msgbuf.first == NULL)
- return FALSE; /* maybe TRUE? */
-
- parsekludge(m, &msgbuf); /* fill in addressing fields */
-
- if (!checkrecvd(m)) return FALSE; /* set 'received' bit if neccessary */
-
- if (msgnum > highmsgread)
- highmsgread = msgnum;
-
- return TRUE;
-
- } /* readmsg */
-
- /*
- * Set received bit
- * Return TRUE if ok
- */
-
- static BOOLEAN checkrecvd(MSG *m)
- {
- int fmsg;
- char *s = NULL, *t = NULL;
- BOOLEAN result = FALSE;
-
- if (m->header.bits.is_rcvd) /* already received! */
- return TRUE;
-
- if ((fmsg = filemsg(m->header.msgnum)) == -1)
- return FALSE;
-
- if ((s = strdup(username)) == NULL)
- goto leave;
- if ((t = (char *) calloc(1, sizeof(m->header.to)+1)) == NULL)
- goto leave;
- memcpy(t, m->header.to, sizeof(m->header.to)+1);
-
- if (memicmp(s, t, strlen(s)) == 0) {
- m->header.bits.is_rcvd = 1;
- if (!writeheader(&m->header))
- goto leave;
- if (!writetoidx(fmsg,"* Received *"))
- goto leave;
- } /* if */
-
- result = TRUE;
- leave:
- ptrfree(s);
- ptrfree(t);
-
- return(result);
- } /* checkrecvd */
-
- /*
- * Do the addressing of the message before writing
- */
-
- static void remap(MSG *m)
- {
- #ifdef GATE
- int i;
- #endif
-
- m->header.dest_net = m->to.net;
- m->header.dest = m->to.node;
- m->header.destzone = m->to.zone;
-
- /*
- * we really only want to remap crash mail if a point... the boss
- * node can (and probably will) handle remapping the rest
- */
-
- if ((m->from.point) && (pointnet != 0)) { /* is a point */
-
- if (strnicmp(m->header.to,"Areafix",7) == 0) { /* to Areafix */
- m->from.net = pointnet;
- m->from.node = m->from.point;
- } /* if */
- /* should remove this if FMPT is desired (only netmail really) */
- if (!arealist[area].netmail)
- m->from.point = 0; /* no .n number, i.e. now 4921/4.0 or 7102/1.0 */
- } /* if */
-
- m->header.origzone = m->from.zone;
- m->header.orig_net = m->from.net;
- m->header.orig = m->from.node;
-
- /*
- * don't zone gate a message if it's going somewhere in your own zone
- */
-
- #ifdef GATE
- if ((thisnode[CurAKA].zone != m->to.zone) && (!m->header.is_crash) && (arealist[area].netmail) && ((gate & GZONES) == GZONES)) {
- m->header.dest_net = thisnode[CurAKA].zone;
- m->header.dest = m->to.zone;
- } /* if */
-
- if (((m->to.domain != NULL) && (m->from.domain != NULL)) &&
- (stricmp(m->to.domain,m->from.domain)) && ((gate & GDOMAINS) == GDOMAINS))
- for (i = 0; i < domains; i++)
- if (stricmp(domain_list[i].domain,m->to.domain) == 0) {
- m->header.dest = domain_list[i].node;
- m->header.dest_net = domain_list[i].net;
- }
- #endif
- } /* remap */
-
- /*
- * Search through MSGTOIDX.BBS for name
- * Starts at msgnum and stops at last message in board
- * Returns msgnum found or -1 if error or not found
- */
-
- int searchto(BYTE board, int msgnum, char *name)
- {
- int fmsg, old;
- char *get;
-
- for (;;) {
- if ((fmsg = filemsg(msgnum)) == -1) return(-1);
- if ((get = readtoidx(fmsg)) == NULL) return(-1);
-
- if (strnicmp(name,get,strlen(name)) == 0)
- return(msgnum);
-
- if ((msgnum = msgnext(board,old = msgnum)) == old)
- return(-1); /* last message */
- } /* forever */
- } /* searchto */
-
- /*
- * Mutilate bad lines without changing their length
- */
-
- static void stripline(char *s)
- {
- char *p;
-
- while ((p = strstr(s,"SEEN-BY:")) != NULL)
- p[0] = '!'; /* comes out as "!EEN-BY:" */
-
- for (p=s; *p != EOS; p++)
- if (*p == '\01')
- *p = '@';
-
- } /* stripline */
-
- /*
- * Read the MSGID kludge line contents
- * Return a pointer to a static buffer or NULL if nothing
- */
-
- static char *readkludge(int num)
- {
- MSGHEADER header;
- char *text, *msgid;
- static char buf[101];
-
- buf[0] = EOS;
-
- if (!readheader(num, &header))
- return NULL;
-
- if (header.numrecs == 0)
- return NULL;
-
- header.numrecs = min(header.numrecs, 2); /* 2 blocks max */
-
- if ((text = readtext(&header)) == NULL) /* read the text */
- return NULL;
-
- if ((msgid = strstr(text,"\01MSGID:")) != NULL)
- if (sscanf(msgid, "\01MSGID: %100[^\r\n\215]", &buf[0]) == 1)
- msgid = buf;
- else
- msgid = NULL;
-
- ptrfree(text);
- return msgid;
- } /* readkludge */
-
- /*
- * Add the ^a kludges
- */
-
- static void addid(MSG *m, ADDRESS ofrom /*, char *origtext*/ )
- {
- char buffer[TEXTLEN];
- #ifdef EIDS
- EID rid;
- memset(&rid,0,sizeof(rid));
- #endif
-
- #ifdef PID /* JoHo's Baby */
- if (arealist[area].netmail) {
- sprintf(buffer, "\01PID: %s %s\n", PID, PIDVER); /* serial # opt. */
- (void)insertline(&msgbuf, msgbuf.first, buffer);
- }
- #endif
-
- if (msgids) {
- static BYTE counter=0;
- time_t t;
-
- if (m->header.reply != 0) { /* message is a reply */
- char *replyid = readkludge(m->header.reply);
- if (replyid != NULL) {
- sprintf(buffer,"\01REPLY: %s\n", replyid);
- (void)insertline(&msgbuf, msgbuf.first, buffer);
- } /* if */
- } /* if */
-
- (void)time(&t); /* could use time from message too */
- t = (t<<4) | (counter++ & 15); /* for more than message/s (cc:) */
-
- sprintf(buffer,"\01MSGID: %s %lx\n", formaddr(ofrom,Z_A|N_A|P_O|D_O),t);
- (void)insertline(&msgbuf, msgbuf.first, buffer);
- } /* if */
-
- /* Add EID line here */
-
- #ifdef EIDS
- if ((eids) && (arealist[area].echomail)) {
- m->eid.crc = eidcrc(origtext, m->header.from, m->header.to, m->header.subj);
- m->eid.st = dostime(m->header.posttime,m->header.postdate,TRUE);
-
- if (m->eid.st != 0) { /* EID computed ok */
- if (rid.st != 0) {
- sprintf(buffer, "\01EID:%04x %08lx %04x %08lx\n", m->eid.crc,
- m->eid.st, rid.crc, rid.st);
- (void)insertline(&msgbuf, msgbuf.first, buffer);
- } else {
- sprintf(buffer, "\01EID:%04x %08lx\n", m->eid.crc, m->eid.st);
- (void)insertline(&msgbuf, msgbuf.first, buffer);
- } /* else */
- } /* if */
- } /* if */
- #endif
-
- } /* addid */
-
- /*
- * Format the origin line
- * The buffer must be big enough (say char[200]) to accept the origin line
- */
-
- void formatorigin(char *buffer, char *origin, ADDRESS thisnode)
- {
- if (origin == NULL)
- origin = username;
- sprintf(buffer, " * Origin: %s (%s)\n", origin, formaddr(thisnode,Z_A|N_A|P_O|D_O));
- } /* formatorigin */
-
- /*
- * Write the current message from the global text buffer
- * Add origin line and remap the message
- * Return TRUE if ok
- *
- * Steps for writing a QuickBBS message:
- *
- * * Search MSGIDX to see if message number already exists.
- * * Modify or add receiver's name to MSGTOIDX
- * * if new message: highmsg++, totalactive++, activemessages++ in MSGINFO
- * * Modify or add msgnum and board to MSGIDX
- * * if more text than old message, add text to end of MSGTXT, else overwrite
- * * change startrec and numrec fields and write to MSGHDR
- *
- */
-
- int writemsg(MSG *m)
- {
- char buffer[TEXTLEN];
- LINE *t;
- BOOLEAN newtear = (arealist[area].echomail);
- BOOLEAN neworig = newtear;
- char *textbuf = NULL; /* temporary buffer for text */
- BOOLEAN result = FALSE;
- #ifdef EIDS
- char *origtext = NULL; /* origin line text */
- #endif
- ADDRESS ofrom = m->from;
-
- remap(m); /* change addressing */
-
- /* remove the current kludge lines */
-
- t = msgbuf.first; /* in global msgbuf */
- while (t != NULL) {
- if (strip && (t->text[0] == '\01')) { /* remove current hidden lines */
- LINE *temp = t;
- t = t->next; /* step to next line */
- deleteline(&msgbuf,temp); /* and delete current line */
- continue;
- } /* if */
-
- stripline(t->text); /* mutilate the rest */
-
- if (newtear)
- newtear = (strncmp(t->text,"--- ",4) != 0);
-
- if (neworig) {
- neworig = (strncmp(t->text," * Origin: ",11) != 0);
- #ifdef EIDS
- if (!neworig)
- origtext = (t->text+11); /* old origin line */
- #endif
- } /* if */
-
- t = t->next;
- } /* while */
-
- /* now add new tearline and/or origin line */
-
- if (newtear) {
- sprintf(buffer, "\n\n--- %s\n", PID " " PIDVER);
- (void)insertline(&msgbuf, NULL, buffer);
- }
-
- if (neworig) { /* add origin line */
- char *corigin = origin; /* default origin line */
-
- if (!override)
- if (arealist[area].areaorig != NULL) /* from ECHOORIG.CTL */
- corigin = arealist[area].areaorig;
-
- formatorigin(buffer, corigin, thisnode[CurAKA]);
-
- t = insertline(&msgbuf, NULL, buffer);
- #ifdef EIDS
- origtext = (t->text+11);
- #endif
- } /* if */
-
- #ifdef GATE
- if ((m->from.zone != m->to.zone) && (arealist[area].netmail)) {
- sprintf(buffer, "\01INTL %d:%d/%d %d:%d/%d\n",
- m->to.zone, m->to.net, m->to.node,
- m->from.zone, m->from.net, m->from.node);
- (void)insertline(&msgbuf, msgbuf.first, buffer);
- } /* if */
-
- if (((m->to.domain != NULL) && (m->from.domain != NULL)) &&
- (stricmp(m->to.domain,m->from.domain))) {
- sprintf(buffer, "\01DOMAIN %s %d:%d/%d %s %d:%d/%d\n",
- strupr(m->to.domain),m->to.zone, m->to.net, m->to.node,
- strupr(m->from.domain),m->from.zone, m->from.net, m->from.node);
- (void)insertline(&msgbuf, msgbuf.first, buffer);
- } /* if */
- #endif
-
- addid(m, ofrom /*, origtext*/ ); /* add id lines */
-
- /* Here the IFNA TOPT/FMPT kludge lines are added, in front */
-
- #ifdef TOFMPT
- if (arealist[area].netmail) {
- if (m->from.point) {
- sprintf(buffer,"\01FMPT %d\n", m->from.point);
- (void)insertline(&msgbuf, msgbuf.first, buffer);
- } /* if */
-
- if (m->to.point) {
- sprintf(buffer,"\01TOPT %d\n", m->to.point);
- (void)insertline(&msgbuf, msgbuf.first, buffer);
- } /* if */
- } /* if */
- #endif
-
- /* write out the lines */
-
- /* global msgbuf */
- for (t = msgbuf.first; (t != NULL); t = t->next) {
- char *d = buffer;
- char *s = t->text;
- if (s == NULL) continue;
-
- while (*s != EOS) { /* write the message text to the buffer */
- if (*s == '\n') {
- *d++ = '\r';
- /* *d++ = '\n'; */ /* linefeed after CR */
- } else {
- *d++ = *s;
- } /* else */
- s++;
- } /* while */
-
- if (arealist[area].softcr && (strchr(t->text,'\n') == NULL))
- *d++ = 0x8d;
-
- *d = EOS;
-
- tputs(buffer, &textbuf); /* write the line */
- } /* for */
-
- /* add: check here if memory overflowed during message text building */
-
- /* now write the header and text of the message */
-
- writebase(&m->header,arealist[area].board,textbuf,
- arealist[area].echomail,arealist[area].netmail);
-
- arealist[area].new = 1;
- result = TRUE;
-
- if (textbuf != NULL)
- ptrfree(textbuf);
-
- if (curmsg(CurBoard) == 0)
- setcur(CurBoard,m->header.msgnum);
-
- #ifdef PARANOID
- flushmsgbase();
- #endif
-
- return(result);
-
- } /* writemsg */
-
- /*
- * Return current number of characters in buffer or -1 if error
- */
-
- static int tputs(char *s, char **buf)
- {
- int blen, slen;
-
- if (s == NULL)
- if (*buf == NULL)
- return(0);
- else
- return(strlen(*buf));
-
- slen = strlen(s);
-
- if (*buf == NULL) { /* allocate first piece of memory */
- if ((*buf = malloc(slen+1)) == NULL)
- return(-1); /* no memory available */
- strcpy(*buf,s);
- return(slen);
- } /* if */
-
- blen = strlen(*buf); /* current length */
-
- if ((*buf = realloc(*buf, blen+slen+1)) == NULL)
- return(-1); /* allocate more bytes */
-
- strcat(*buf,s); /* add to end */
-
- return(blen+slen); /* new length */
-
- } /* tputs */
-
- /*
- * Look for a user in USERS.BBS
- * If 'create' is TRUE, add the user
- * Return user number from 0 or -1 if error or not found
- */
-
- int searchuser(char *name, BOOLEAN create)
- {
- USERRECORD user;
- int uf;
- int count;
- BOOLEAN found = FALSE;
- int access = O_RDWR|O_BINARY;
-
- if (name == NULL)
- return(-1);
-
- if (create)
- access |= O_CREAT;
-
- if ((uf = open(expandbbs("users.bbs"),access,S_IREAD|S_IWRITE)) == -1)
- return(-1);
-
- count = -1;
- while (!found && (eof(uf) == 0)) {
- read(uf,(char *)&user,sizeof(user));
- p2c_strn(user.name,35);
- found = (stricmp(user.name,name) == 0);
- count++;
- } /* while */
-
- if (!found && create) {
- memset(&user,0,sizeof(user));
- strncpy(user.name,name,35);
- c2p_str(user.name);
- strcpy(user.pwd,"*no password*");
- c2p_str(user.pwd);
- timestr(user.lasttime,user.lastdate);
- c2p_str(user.lasttime);
- c2p_str(user.lastdate);
- user.attrib = U_NOKILL;
- if (write(uf,(char *)&user,sizeof(user)) == sizeof(user)) {
- found = TRUE;
- count++;
- } /* if */
- } /* if */
-
- highmsgread = user.highmsgread; /* set global */
-
- close(uf);
-
- if (found)
- return(count);
- else
- return(-1);
- } /* searchuser */
-
- BOOLEAN updatehigh(int usernum, int high)
- {
- USERRECORD user;
- int uf;
-
- if ((uf = open(expandbbs("users.bbs"),O_RDWR|O_BINARY)) == -1)
- return FALSE;
-
- if ((lseek(uf,(long)usernum*sizeof(user),SEEK_SET)) == -1) {
- close(uf);
- return FALSE;
- } /* if */
-
- read(uf,(char *)&user,sizeof(user));
- if (high > user.highmsgread) {
- user.highmsgread = high;
- lseek(uf,(long)usernum*sizeof(user),SEEK_SET);
- write(uf,(char *)&user,sizeof(user));
- } /* if */
-
- close(uf);
-
- return TRUE;
- } /* updatehigh */