/****************************************************************************/
/*                                                                          */
/*    Qwkspt.c    :QWK format routines for MaxMail                          */
/*                                                                          */
/****************************************************************************/

#include "MaxMail.h"

/* Some QWK specifics */

struct QWKmsghd {		/* Messages.dat header */
   char  Msgstat;    		/* message status byte */
   char  Msgnum[7];  		/* message number in ascii */
   char  Msgdate[8]; 		/* date in ascii */
   char  Msgtime[5]; 		/* time in ascii */
   char  Msgto[25];  		/* Person addressed to */
   char  Msgfrom[25];		/* Person who wrote message */
   char  Msgsubj[25];		/* Subject of message */
   char  Msgpass[12];		/* password */
   char  Msgrply[8]; 		/* message # this refers to */
   char  Msgrecs[6];		   /* # of 128 byte recs in message,inc header */
   char  Msglive; 		   /* always 0xe1 */
   char  Msgarealo;     	/* area number, low byte */
   char  Msgareahi;     	/* area number, hi byte */
   char  Msgfiller[3];		/* fill out to 128 bytes */
};

union Converter {
   unsigned char  uc[10];
   unsigned int   ui[5];
   unsigned long  ul[2];
   float           f[2];
   double          d[1];
};

struct repmsg {
   int count;
   int areano;
   word flags;
   struct repmsg _far *next;
};

#define RP_CMDFLAG  0x0001

static int Indx;		/* Message NDX file */
static int PIndx;		/* Personal NDX file */
static int upmsgs;
static int repfile;
static int msgrecs;
static int confreqs;
static word lastarea;

static struct repmsg _far *RP1;
static struct repmsg _far *rp;
static struct repmsg _far *RPprev;

static FILE *MsgFile; /* Messages.dat file */
static TotRecs;
extern char msg_line[];
static int Aindex;
static struct _aidx IDX;

static char *monthstr[] =  {  {"Jan"},{"Feb"},{"Mar"},{"Apr"},
                            {"May"},{"Jun"},{"Jul"},{"Aug"},
                            {"Sep"},{"Oct"},{"Nov"},{"Dec"}
                         };                         


static struct QWKmsghd *QMsgHead;
extern struct _msg   amsg;

extern char _far  *msgbuffer;
extern int fido_init;
extern int HaveUpl;

/* Create the control.dat file for QWK packets, this only called
   once per session. It also does some other initialization for
   QWK handling.. */

void _pascal qwkinit(void)
{
   static First = TRUE;
   struct find_t fbuf;

   if (First) {		/* Do this only once */
      Indx = -1;
      PIndx = -1;
      if (!fido_init)
         fidomsg_init();

      if (tdir[0])
         switch_dir(tdir);		/* Switch to temp dir */

      sprintf(QWKDir,"QWK%04x",Task);
      if(mkdir(QWKDir) != 0) {
         if(chdir(QWKDir) != 0)
            QWKDir[0] = 0;
         else {		/* We are in QWKDir, let's cleanup */
            if (!_dos_findfirst("*.*",_A_NORMAL,&fbuf)) {	/* Kill everything */
               unlink(fbuf.name);
               while (!_dos_findnext(&fbuf)) 
                  unlink(fbuf.name);
            }
            chdir("..");		/* Restore back to parent */
         }
      }

      if (tdir[0])
         switch_dir(PRM(sys_path));

      First = FALSE;
   }
   lastarea = 0xffff;
}


int _pascal openqwk(void)
{
   int code=0;
   int x,keys,totals;
   char *p;
   FILE *datfile;
   time_t     aclock;
   struct tm  *newtime;
   char fname[_MAX_FNAME];
   char fext[_MAX_EXT];


   QMsgHead = (struct QWKmsghd *) malloc(sizeof(struct QWKmsghd));
   if (QMsgHead == NULL)
      return 1;

/* Fill out some defaults in the Messages.dat file header */
   memset(QMsgHead->Msgpass,' ',12);
   memset(QMsgHead->Msgfiller,' ',3);
   QMsgHead->Msglive = 0xe1;

   tempdir();
   datfile = _fsopen("Control.dat","wt",SH_DENYRW);
   if (datfile != NULL) {
      setcolor(TextAttr[HILITE_TEXT]);
      strout("\r\nCreating the Control.Dat file for your QWK packet...\r\n");
      totals = 0;
      strcpy(temp,PRM(system_name));
      p = strtok(temp," \r\n");
      fputs(p,datfile);		/* Line #1 */
      fputs("\n",datfile);
      fputs("               \n",datfile);
      fputs(BBSphone,datfile);
      fputs("\n",datfile);
      fputs(PRM(sysop),datfile);
      fputs("\n",datfile);
      if (!BBSid[0]) {
         strncpy(BBSid,PRM(system_name),8);
         BBSid[8] = 0;
      }
      sprintf(temp,"00000,%s\n",BBSid);		/* Line #5 */
      fputs(temp,datfile);
      sprintf(temp,"%s.qwk",BBSid);
      unlink(temp);
      time(&aclock);
      newtime = localtime(&aclock);
      sprintf(temp,"%02d-%02d-19%02d,%02d:%02d:%02d\n",
         newtime->tm_mon+1,newtime->tm_mday,newtime->tm_year,
         newtime->tm_hour,newtime->tm_min,newtime->tm_sec);
      fputs(temp,datfile);		/* Line #6 */
      fputs(strupr(USERCFG.name),datfile);
      fputs("\n",datfile);
      fputs(" \n",datfile);		/* Line #8 */
      fputs("0\n",datfile);
      fputs("0\n",datfile);		/* Line #10 */
      Aindex = sopen(PRM(aidx_name),O_BINARY | O_RDONLY,SH_DENYNO,S_IREAD);
      if (Aindex == -1)
         aborterror(FILEOPEN,"Error opening Area index file");
      for (x=0; x < 1000; x++) {	/* Display the first 1000 msg areas */
         if((read(Aindex,(char *)&IDX,sizeof(struct _aidx))) != sizeof(struct _aidx))
            break;
         fseek(afile,IDX.offset,SEEK_SET);
         fread(&AREA,astrlen,1,afile);
         keys = testlock();
         if (!isskiparea(x)) {
            if (AREA.msgpath[0] && (LastUser.priv >= AREA.msgpriv) && keys) {
               if(check_barareas(&AREA,-1)) 
                  totals++;
            }
         }
      }
      sprintf(temp,"%d\n",totals-1);
      fputs(temp,datfile);
      lseek(Aindex,0L,SEEK_SET);		/* Rewind again */
      for (x=0; x < 1000; x++) {	/* Display the first 1000 msg areas */
         if((read(Aindex,(char *)&IDX,sizeof(struct _aidx))) != sizeof(struct _aidx))
            break;
         fseek(afile,IDX.offset,SEEK_SET);
         fread(&AREA,astrlen,1,afile);
         keys = testlock();
         if (!isskiparea(x)) {
            if (AREA.msgpath[0] && (LastUser.priv >= AREA.msgpriv) && keys) {
               if(check_barareas(&AREA,-1)) {
                  sprintf(temp,"%d\n",x);
                  fputs(temp,datfile);
                  memset(temp,0,11);
                  strncpy(temp,AREA.msginfo,10);
                  fputs(temp,datfile);
                  fputs("\n",datfile);
               }
            }
         }
      }
      close(Aindex);

      if (QWKWelcome[0]) {
         _splitpath(QWKWelcome,temp,temp,fname,fext);
         sprintf(temp,"%s%s\n",fname,fext);
         fputs(temp,datfile);		/* This is QWK welcome file */
      }
      else fputs("WELCOME\n",datfile);		/* This is QWK welcome file */

      if (QWKnews[0]) {
         _splitpath(QWKnews,temp,temp,fname,fext);
         sprintf(temp,"%s%s\n",fname,fext);
         fputs(temp,datfile);		/* This is QWK news file */
      }
      else fputs("WELCOME\n",datfile);		/* This is QWK news file */

      if (QWKbye[0]) {
         _splitpath(QWKbye,temp,temp,fname,fext);
         sprintf(temp,"%s%s\n",fname,fext);
         fputs(temp,datfile);		/* This is QWK bye file */
      }
      else fputs("GOODBYE\n",datfile);		/* This is QWK bye file */

      fclose(datfile);
      datfile = _fsopen("DOOR.ID","wt",SH_DENYRW);
      if (datfile != NULL) {
         sprintf(temp,"DOOR = MaxMail   \n");
         fputs(temp,datfile);		/* Line #1 */

         sprintf(temp,"VERSION = %2.2f  \n",Version);
         fputs(temp,datfile);		/* Line #2 */

         sprintf(temp,"SYSTEM = Maximus   \n");
         fputs(temp,datfile);		/* Line #3 */

         sprintf(temp,"CONTROLNAME = MAXMAIL\n");
         fputs(temp,datfile);		/* Line #4 */

         sprintf(temp,"CONTROLTYPE = ADD\n");
         fputs(temp,datfile);		/* Line #5 */

         sprintf(temp,"CONTROLTYPE = DROP\n");
         fputs(temp,datfile);		/* Line #6 */
         sprintf(temp,"CONTROLTYPE = REQUEST\n");
         fputs(temp,datfile);		/* Line #6 */
         fclose(datfile);
      }

      MsgFile = _fsopen("Messages.dat","wb",SH_DENYNO);
      if (MsgFile != NULL) {		/* Write out the header */
         fwrite("Produced by Qmail...",20,1,MsgFile);
         fwrite("Copywright (c) 1987 by Sparkware.  ",35,1,MsgFile);
         fwrite("All Rights Reserved",19,1,MsgFile);
         for (x=0; x < 54; x++)
            fwrite(" ",1,1,MsgFile);		/* Fill out rest of 128 byte record */
      }
      else code = 1;
   }
   else code = 1;

   homedir();

   TotRecs = 1;
   return code;
}

/* This function is called whenever a new message
   area to scan is started */
void _pascal qwk_newarea(struct msgupd_st *msgupd)
{

   char tname[10];
   if (Indx != -1)
      close(Indx);

   tempdir();
   sprintf(tname,"%03d.ndx",msgupd->areano);
   Indx = sopen(tname,O_CREAT | O_TRUNC | O_BINARY | O_RDWR,SH_DENYRW,S_IWRITE);
   homedir();
}

/* This function is called whenever a new message
    needs to be imported to QWK */
int _pascal qwk_fidomsg(int i,int flags,struct msgupd_st *msgupd,struct msghead *MSGHD)
{
   char        c;
   int         j,n,recs,start,origin;
   int         newline,IsOurs = FALSE;
   struct      find_t c_file;
   long	      size,filepos;
   float       in,out;

   j = n = 0;
   sprintf(temp1,"%s%u%s",msgupd->msgpath,i,".MSG");
   if (_dos_findfirst(temp1,0,&c_file) !=0) 
      return(FILE_SRCH_ERR);

   if (c_file.size >= (long) MAXFMSGSIZ) 		/* Message is too big! */
      return(FILE_SIZE_ERR);

   size=c_file.size - ((long) sizeof(struct _msg));
   recs=sopen(temp1,O_RDONLY|O_BINARY,SH_DENYNO,S_IREAD);
   if (recs < 0) 
      return(FILE_OPEN_ERR);

   j = read(recs,(char *) &amsg,sizeof(struct _msg));
   if (j != sizeof(struct _msg)) 
      return(FILE_READ_ERR);

   _dos_read(recs,msgbuffer,(unsigned)size,&j);
   if (j != (int)size) 
      return(FILE_READ_ERR);

   close(recs);		/* Close the fido message */


   if (strcmpi(amsg.to,MSGHD->ourname) == 0) {
      IsOurs = TRUE;
      MSGHD->ourmail++;
      if (PIndx == -1) {		/* Start the Personal Index file */
         tempdir();
         PIndx = sopen("Personal.ndx",O_CREAT | O_TRUNC | O_BINARY | O_RDWR,SH_DENYRW,S_IWRITE);
         homedir();
       }
   }
   else {		/* Not ours */
      if ((flags & PRIVATE) && (amsg.attr & MSGPRIVATE)) 
         return(PVTMSG_ERR);		/* No messages to read */
      IsOurs = FALSE;
   }

   if (recs >= 0) {		/* We had a valid MSG file, here's the main stuff */
      if (lastarea != msgupd->areano) {		/* A new area */
         qwk_newarea(msgupd);
         lastarea = msgupd->areano;
      }
      recs = 1;		/* Becomes # of 128 byte records */
      TotRecs++;
/* First write out the index position */
      sprintf(msg_line,"%u",TotRecs);	/* Stringized version of current position */
      in = (float) atof(msg_line);
      out = IEEToMSBIN(in);
      write(Indx,&out,sizeof(float));


      c = 0;
      write(Indx,&c,sizeof(char));		/* Conference # */

      if (IsOurs && PIndx != -1)	{	/* Set up PERSONAL area */
         write(PIndx,&out,sizeof(float));
         write(PIndx,&c,sizeof(char));		/* Conference # */
      }

/* Now build the messages.dat msg header */
      if (amsg.attr & MSGPRIVATE)
         QMsgHead->Msgstat = '*';
      else {
         if (!(msgupd->attribute & ECHOMAIL)) {		/* Local area */
            if ((amsg.attr & MSGREAD) && IsOurs)
               QMsgHead->Msgstat = '-';
            else QMsgHead->Msgstat = ' ';
         }
         else QMsgHead->Msgstat = ' ';
      }
      sprintf(msg_line,"%d",i);
      ljstring(QMsgHead->Msgnum,msg_line,7);
      sprintf(msg_line,"%02d-%02d-%02d",amsg.date_written.date.mo,amsg.date_written.date.da,
         amsg.date_written.date.yr+80);
      memcpy(QMsgHead->Msgdate,msg_line,8);
      sprintf(msg_line,"%02d:%02d",amsg.date_written.time.hh,amsg.date_written.time.mm);
      memcpy(QMsgHead->Msgtime,msg_line,5);

      ljstring(QMsgHead->Msgto,strupr(amsg.to),25);
      ljstring(QMsgHead->Msgfrom,strupr(amsg.from),25);
      ljstring(QMsgHead->Msgsubj,amsg.subj,25);
      sprintf(msg_line,"%d",amsg.reply);
      ljstring(QMsgHead->Msgrply,msg_line,8);

      QMsgHead->Msgarealo = (char) (msgupd->areano % 255); /* Lo byte area # */
      QMsgHead->Msgareahi = (char) (msgupd->areano / 255); /* Hi byte area # */

      filepos = ftell(MsgFile);		/* save position for later */
      fwrite(QMsgHead,128,1,MsgFile);		/* Write out the header */

/* Ok, now the tough part. We have to plunge thru the message buffer
   strip hidden lines, translate cr's to 0xe3, write out
   messge text in 128 byte record chunks. */

	   j=0;
	   start=0;
      while (msgbuffer[j] == '\0') {
         j++;
         start++;
      }

      n = 0;
      origin = FALSE;
      newline = TRUE;
      for (j = start; j < (int) size; j++) {
         switch ((byte) msgbuffer[j]) {
            case 1:		/* Hidden line */
               while (msgbuffer[j] != 0x0d && msgbuffer[j] != 0x8d) 	/* Skip special lines */
                  j++;
               newline = FALSE;
               break;

            case 'S':		/* Maybe a seenby? */
               if (newline) {
                  _fstrncpy((char _far *)temp1,msgbuffer+j,8);
                  temp1[8] = 0;
                  if (strcmpi(temp1,"SEEN-BY:") == 0) {
                     while (msgbuffer[j] != 0x0d)		/* Skip special lines */
                        j++;
                  }
                  else msg_line[n++] = msgbuffer[j];
                  newline = FALSE;
               }
               else msg_line[n++] = msgbuffer[j];
               break;

            case ' ':		/* Maybe an origin line? */
               if (newline) {
                  _fstrncpy((char _far *)temp1,msgbuffer+j,10);
                  temp1[10] = 0;
                  if (strcmpi(temp1," * Origin:") == 0) {
                     msg_line[n++] = msgbuffer[j];
                     origin = TRUE;
                  }
                  else msg_line[n++] = msgbuffer[j];
                  newline = FALSE;
               }
               else msg_line[n++] = msgbuffer[j];
               break;

            case 'P':
               if (newline) {
                  _fstrncpy((char _far *)temp1,msgbuffer+j,4);
                  temp1[4] = 0;
                  if (strcmpi(temp1,"PATH") == 0) {
                     while (msgbuffer[j] != 0x0d)		/* Skip special lines */
                        j++;
                  }
                  else msg_line[n++] = msgbuffer[j];
                  newline = FALSE;
               }
               else msg_line[n++] = msgbuffer[j];
               break;

            case 0x8d:		/* Soft c/r */
            case 0x0d:		/* Standard c/r */
               msg_line[n] = 0xe3;
               n++;
               newline = TRUE;
               if (origin) /* Eliminate further copying after origin line */
                  j = (int) size;
               break;

            case 0x0a:		/* Skip linefeeds */
               newline = TRUE;
               break;

            case 0:
            case 0x80:
               newline = FALSE;
               break;

            default:
               newline = FALSE;
               msg_line[n++] = msgbuffer[j];
               break;
         }
         if (n >= 128) {
            msg_line[128] = 0;
            fwrite(msg_line,128,1,MsgFile); 	/* Write out a record */
            n = 0;
            TotRecs++;
            recs++;
            memset(msg_line,' ',128);
         }
      }
      if (n) {		/* Partial record */
         recs++;
         msg_line[128] = 0;
         fwrite(msg_line,128,1,MsgFile); 	/* Write out a record */
         TotRecs++;
      }

/* Now update with record count */
      fseek(MsgFile,filepos,SEEK_SET);		/* Restore back to header start */
      sprintf(msg_line,"%d",recs);
      ljstring(QMsgHead->Msgrecs,msg_line,6);
      fwrite(QMsgHead,128,1,MsgFile);		/* Write out the header */
      fseek(MsgFile,0L,SEEK_END);		/* Bump back to end of file */
   }
   return(i);		/* No errors!, return message number */
}

/* QWK handling cleanup */
void _pascal closeqwk(void)
{
   if (Indx != -1) {
      close(Indx);
      Indx = -1;
   }

   if (PIndx != -1) {
      close(PIndx);
      PIndx = -1;
   }

   if (MsgFile != NULL) {
      fclose(MsgFile);
      MsgFile = NULL;
   }
}

/* Convert an IEEE floating point number to MSBIN
   floating point decimal */

float _pascal IEEToMSBIN(float f)
{
   union Converter t;
   int   sign,exp;

   t.f[0] = f;

/* Extract sign & change exponent bias from 0x7f to 0x81 */

   sign = t.uc[3] / 0x80;
   exp  = ((t.ui[1] >> 7) - 0x7f + 0x81) & 0xff;

/* reassemble them in MSBIN format */
   t.ui[1] = (t.ui[1] & 0x7f) | (sign << 7) | (exp << 8);
   return t.f[0];
}


/* Fetch REP packet from user and import if ok */
void _pascal getrep(void)
{
   int x,y,z,msgfile,RDONLY;
   int endspace;
   char  *msgbuff,*p;
   struct dostime_t time;
   struct dosdate_t date;
   struct QWKmsghd *MsgHead;
   struct msgupd_st *msgupd;
   FILE   *tosslog;

   if (repupload() > 0) {		/* We have received a REP packet perhaps */
      Aindex = sopen(PRM(aidx_name),O_BINARY | O_RDONLY,SH_DENYNO,S_IREAD);
      if (Aindex == -1)
         aborterror(FILEOPEN,"Error opening Area index file");
      tempdir();
      sprintf(temp,"%s.rep",BBSid);
      if(!extractarc(temp)) {		/* Parse the bbs.msg file and import */
         upmsgs = 0;
         confreqs = 0;
         sprintf(temp,"%s.msg",BBSid);
         repfile = sopen(temp,O_BINARY | O_RDONLY,SH_DENYRW,S_IREAD);
         if (repfile >= 0) {
            MsgHead = (struct QWKmsghd *) malloc(sizeof(struct QWKmsghd));
            if (MsgHead == NULL)
               aborterror(BADALLOC,NULL);
            msgbuff = (char *) malloc(150);
            if (msgbuff == NULL)
               aborterror(BADALLOC,NULL);
            read(repfile,msgbuff,128);		/* Ignore first record */
            msgbuff[8] = 0;
            stripwhite(msgbuff);
            RP1 = NULL;
            if (strcmpi(BBSid,msgbuff) == 0) {		/* Make sure it's ours! */
               setcolor(TextAttr[STD_TEXT]);
               strout("\r\nHang on while I import the messages.\r\n\r\n");
               setcolor(TextAttr[HILITE_TEXT]);
               x = read(repfile,(struct QWKmsghd *) MsgHead,128);
               while (x == 128) {		/* This is the BBS.MSG import loop */
         /* Build the Fidonet message head */
                  x = atoi(MsgHead->Msgnum);		/* Area number */
                  rp = RP1;
                  RPprev = RP1;
                  while (rp != NULL) {		/* Search for same area */
                     if (rp->areano == x)
                        break;
                     else {
                        RPprev = rp;
                        rp = rp->next;
                     }
                  }
                  if (rp == NULL) {		/* New message area */
                     rp = (struct repmsg _far *) _fmalloc(sizeof(struct repmsg));
                     if (rp == NULL)
                        aborterror(BADALLOC,NULL);
                     rp->count = 0;
                     rp->next = NULL;
                     rp->areano = x;
                     rp->flags = 0;
                     if (RP1 == NULL) {		/* First one */
                        RP1 = rp;
                     }
                     else RPprev->next = rp;		/* Link it in */
                  }
                  msgupd = MSGUPD_1;
                  while (msgupd != NULL) {		/* Is it selected area? */
                     if (msgupd->areano == (word) x)
                        break;
                     else msgupd = msgupd->next;
                  }
                  if (msgupd == NULL) { /* Not user selected area, create a fake one */
                     msgupd = (struct msgupd_st *) malloc(sizeof(struct msgupd_st));
                     if (msgupd != NULL) {
                        msgupd->areano = x;
                        if ((lseek(Aindex,(long) (x * sizeof(struct _aidx)),SEEK_SET)) != -1L) {
                           if((read(Aindex,(char *)&IDX,sizeof(struct _aidx))) == sizeof(struct _aidx)) {
                              fseek(afile,IDX.offset,SEEK_SET);
                              fread(&AREA,astrlen,1,afile);
                              msgupd->attribute = (word) AREA.attrib[UserClass];
                              msgupd->next = NULL;
                              if (AREA.msgpath[0] && (AREA.areano == IDX.area)) {
                                 strcpy(msgupd->msgpath,AREA.msgpath);
                                 msgupd->update = -2;		/* Flag that its fake */
                                 msgupd->readmsgs = 0;		/* # of replies */
                              }
                              else {
                                 free(msgupd);
                                 msgupd = NULL;
                              }
                           }
                           else {
                              free(msgupd);
                              msgupd = NULL;
                           }
                        }
                        else {
                           free(msgupd);
                           msgupd = NULL;
                        }
                     }
                  }
                  upmsgs++;
                  sprintf(temp,"Importing message # %d\r",upmsgs);
                  strout(temp);
                  if ((msgupd->attribute & NOPUBLIC) && (msgupd->attribute & NOPRIVATE)
                     && LastUser.priv < ASSTSYSOP)
                        RDONLY = TRUE;
                  else RDONLY = FALSE;
                  if (msgupd != NULL && !RDONLY) { /* Create the fidonet message */
                     msgrecs = atoi(MsgHead->Msgrecs) - 1;
                  /* Parse date and time junk */
                     strncpy(temp,MsgHead->Msgdate,8);
                     temp[8] = 0;
                     p = strtok(temp,"-");		/* Fetch month */
                     x = amsg.date_written.date.mo = atoi(p);
                     p = strtok(NULL,"-");		/* Fetch day */
                     z = amsg.date_written.date.da = atoi(p);
                     p = strtok(NULL," \0-");		/* Fetch year */
                     y = amsg.date_written.date.yr = (atoi(p) - 80);

                     strncpy(temp,MsgHead->Msgtime,5);
                     temp[5] = 0;
                     sprintf(amsg.date,"%d %s %d %s:00",z,monthstr[x-1],y+80,temp);

                     p = strtok(temp,":");		/* Fetch hour */
                     amsg.date_written.time.hh = atoi(p);
                     p = strtok(NULL,"\0:");		/* Fetch minutes */
                     amsg.date_written.time.mm = atoi(p);
                     amsg.date_written.time.ss = 0; /* Clear seconds */

                     _dos_getdate(&date);
                     _dos_gettime(&time);

                     amsg.date_arrived.date.mo = date.month;
                     amsg.date_arrived.date.da = date.day;
                     amsg.date_arrived.date.yr = date.year - 1980;
                     amsg.date_arrived.time.hh = time.hour;
                     amsg.date_arrived.time.mm = time.minute;
                     amsg.date_arrived.time.ss = time.hsecond;
                     amsg.attr = 0;
                     if (MsgHead->Msgstat == '*') {
                        if (!(msgupd->attribute & NOPRIVATE))
                           amsg.attr |= MSGPRIVATE;
                     }
                     amsg.orig = prm.address[0].Node;	 /* Original node number */
                     amsg.orig_net = prm.address[0].Net; /* Original net number */
                     amsg.dest = prm.address[0].Node;	 /* Original node number */
                     amsg.dest_net = prm.address[0].Net; /* Original net number */
                     amsg.reply = atoi(MsgHead->Msgrply);
                     amsg.times = 1;
                     amsg.up = 0;
                     amsg.cost = 0;
   
                     memset(amsg.from,0,36);
                     memset(amsg.to,0,36);
                     memset(amsg.subj,0,72);
                     strcpy(amsg.to,namefixup(MsgHead->Msgto));
                     strcpy(amsg.from,namefixup(MsgHead->Msgfrom));
                     strcpy(amsg.subj,namefixup(MsgHead->Msgsubj));

                     if(!qwkfunct(msgupd,msgbuff)) {		/* A genuine message */
                     /* Ok write out the fidonet header */
                        lseek(Aindex,(long) (msgupd->areano * sizeof(struct _aidx)),SEEK_SET);
                        read(Aindex,(char *)&IDX,sizeof(struct _aidx));
                        fseek(afile,IDX.offset,SEEK_SET);
                        fread(&AREA,astrlen,1,afile);
                        switch (AREA.area_type) {
                           case 0:		/* Fido 1.msg style */
                              msgupd->himsg = find_fidohigh(AREA.msgpath);
                              break;

                           default:
                              msgupd->himsg = find_fidohigh(AREA.msgpath);
                              break;
                        }
                        if (msgupd->himsg == 0xffff )
                           msgupd->himsg = 0;
                        msgupd->startmsg = get_lastread(msgupd->msgpath);
                        sprintf(temp1,"%s%d.msg",msgupd->msgpath,msgupd->himsg+1);
                        msgfile = sopen(temp1,O_TRUNC | O_CREAT | O_BINARY | O_RDWR,SH_DENYRW,S_IWRITE);
                        y = sizeof(struct _msg);
                        write(msgfile,(char *) &amsg,y);
                        rp->count += 1;

                  /* Now prepare to read in the REP msg and convert to fidonet */
                        for (x=0; x < msgrecs; x++) {
                           read(repfile,msgbuff,128);
                           msgbuff[128] = 0;
                           p = strchr(msgbuff,0xe3);		/* Look for special linefeeds */
                           while (p) {
                              *p = 0x0d;		/* Replace as a cr */
                              p = strchr(p+1,0xe3);
                           }
                           p = msgbuff + 127;
                           endspace = TRUE;
                  /* Now go backwards and strip out '---' after a c/r */
                           while (p > msgbuff) {
                              if (*p == '-' && StripTags && (msgupd->attribute & ECHOMAIL)) {
                                 endspace = FALSE;
                                 p--;
                                 if (*p == '-') {
                                    p--;
                                    if (*p == '-') {
                                       if (*(p-1) == '\r') {
                                          *p = ' ';
                                          *(p+1) = ' ';
                                          *(p+2) = ' ';
                                       }
                                       break;
                                    }
                                 }
                              }
                              if (*p & 0x80) {	/* Hi bit set? */
                                 if(!(msgupd->attribute & HIGHBIT))
                                    *p &= 0x7f;		/* Make it harmless */
                                 endspace = FALSE;
                              }
                              if ((x == (msgrecs - 1)) && *p == ' ' && endspace && *(p-1) == ' ') 
                                 *p = 0;
                              else endspace = FALSE;
                              p--;
                           }
                           y = strlen(msgbuff);
                           write(msgfile,msgbuff,y);
                        }
                        strcpy(msgbuff,"\r\n");
                        write(msgfile,msgbuff,3);
                        close(msgfile);
                        msgupd->startmsg++;
                        msgupd->himsg++;
                        adjust_lastread(msgupd->msgpath,msgupd->himsg);
                        if (msgupd->update == -2) 	/* A fake one? */
                           free(msgupd);
                     }
                  }
                  else {		/* Invalid message, skip to next one */
                     msgrecs = atoi(MsgHead->Msgrecs) - 1;
                     for (x=0; x < msgrecs; x++) 
                        read(repfile,msgbuff,128);
                  }
                  x = read(repfile,(struct QWKmsghd *) MsgHead,128);
               }
               free(MsgHead);
               free(msgbuff);
               close(repfile);
            }
            else {
               setcolor(TextAttr[ATTN_TEXT]);
               strout("\r\nSorry, but this REP packet is not addressed to us!\r\n\r\n");
               logit("REP packet upload has invalid BBS id",'!');
            }
         }
         else {
            setcolor(TextAttr[ATTN_TEXT]);
            strout("\r\nSorry but the REP pack can not be opened.\r\n");
            logit("REP open file error",'!');
         }
      }
      else {
         setcolor(TextAttr[ATTN_TEXT]);
         strout("\r\nSorry but the REP pack can not be extracted.\r\n");
         logit("REP packet extraction error",'!');
      }
   /* Cleanup */
      sprintf(temp,"%s.rep",BBSid);
      unlink(temp);
      sprintf(temp,"%s.msg",BBSid);
      unlink(temp);
      homedir();
      if (upmsgs) {
         Exitcode = 6;
         HaveUpl = TRUE;
         sprintf(temp,"Total of %d messages were uploaded",upmsgs);
         setcolor(TextAttr[MENU_KEY]);
         strout("\r\n");
         strout(temp);
         strout("\r\n");
         logit(temp,'#');
         setcolor(TextAttr[HILITE_TEXT]);
         rp = RP1;
         tosslog = NULL;
         while (rp) {
            if (rp->count) {		/* A valid import message */
               lseek(Aindex,(long) (rp->areano * sizeof(struct _aidx)),SEEK_SET);
               read(Aindex,(char *)&IDX,sizeof(struct _aidx)); 
               fseek(afile,IDX.offset,SEEK_SET);
               fread(&AREA,astrlen,1,afile);
               strncpy(temp1,AREA.msginfo,25);
               temp1[25] = 0;
               stripwhite(temp1);
               sprintf(temp,"Importing %d messages into [%s]",rp->count,temp1);
               strout(temp);
               strout("\r\n");
               logit(temp,'#');
               if (tosslog == NULL && (AREA.attrib[UserClass] & ECHOMAIL)
                  && AREA.msgname[0])
                     tosslog = _fsopen(PRM(echotoss_name),"at+",SH_DENYNO);
               if (tosslog != NULL && (AREA.attrib[UserClass] & ECHOMAIL)
                  && AREA.msgname[0]) {
                  sprintf(temp,"%s\n",AREA.msgname);
                  fputs(temp,tosslog);
               }
            }
            else {
               if (rp->flags == 0) 
                  sprintf(temp,"Messages to area # %d were ignored",rp->areano);
               else sprintf(temp,"Messages to area # %d were MaxMail commands",rp->areano);
               strout(temp);
               strout("\r\n");
               logit(temp,'#');
            }
            RPprev = rp;
            rp = rp->next;
            _ffree(RPprev);
         }
         if (tosslog != NULL)
            fclose(tosslog);
      }
      setcolor(TextAttr[HILITE_TEXT]);
      strout("\r\n");
      if (confreqs) {
         sprintf(temp,"User made %d requests for area changes",confreqs);
         strout(temp);
         strout("\r\n");
         logit(temp,'#');
      }
      close(Aindex);
   }
}

/* Test and process special door functions from QWK messages.
   return FALSE if none */
int _pascal qwkfunct(struct msgupd_st *msgupd,char *msgbuff)
{
   char *p;

   if ((strcmpi(amsg.to,"QMAIL") == 0)  ||		/* Default */
         (strcmpi(amsg.to,"MAXMAIL") == 0)) {		/* Uh oh, its for us! */
      rp->flags |=  RP_CMDFLAG;
      if (strcmpi(amsg.subj,"CONFIG") == 0) {		/* Sometimes its this one */
         read(repfile,msgbuff,128);
         msgbuff[128] = 0;
         stripwhite(msgbuff);
         p = strtok(msgbuff," \n\r");
         if (strcmpi(p,"ADD") == 0) {		/* Add this conference */
            if(!isskiparea(msgupd->areano)) {
               if(is_selarea(msgupd->areano)) {
                  sprintf(temp,"You already have Conference #%03d enabled\r\n",msgupd->areano);
                  setcolor(TextAttr[ATTN_TEXT]);
                  strout(temp);
               }
               else {
                  sprintf(temp,"Adding conference #%03d",msgupd->areano);
                  strout(temp);
                  logit(temp,'#');
                  strout("\r\n");
                  msgmark(msgupd->areano);
                  confreqs++;
                  upmsgs--;
               }
            }
         }
         else if (strcmpi(p,"DROP") == 0) {		/* Remove this conference */
            if(!isForcearea(msgupd->areano)) {
               if (!is_selarea(msgupd->areano)) {
                  sprintf(temp,"Conference #%03d was not enabled\r\n",msgupd->areano);
                  setcolor(TextAttr[ATTN_TEXT]);
                  strout(temp);
               }
               else {
                  sprintf(temp,"Dropping conference #%03d",msgupd->areano);
                  strout(temp);
                  logit(temp,'#');
                  strout("\r\n");
                  confreqs++;
                  msgunmark(msgupd->areano);
                  upmsgs--;
               }
            }
         }
      }
      else if (strcmpi(amsg.subj,"DROP") == 0) {		/* But usually this way */
         read(repfile,msgbuff,128);		/* Drop a conference */
         if(!isForcearea(msgupd->areano)) {
            if(!is_selarea(msgupd->areano)) {
               sprintf(temp,"Conference #%03d was not enabled\r\n",msgupd->areano);
               setcolor(TextAttr[ATTN_TEXT]);
               strout(temp);
            }
            else {
               sprintf(temp,"Dropping conference #%03d",msgupd->areano);
               strout(temp);
               logit(temp,'#');
               strout("\r\n");
               confreqs++;
               msgunmark(msgupd->areano);
               upmsgs--;
            }
         }
      }
      else if (strcmpi(amsg.subj,"ADD") == 0) {
         read(repfile,msgbuff,128);		/* Add a conference */
         if(!isskiparea(msgupd->areano)) {
            if(is_selarea(msgupd->areano)) {
               sprintf(temp,"You already have Conference #%03d enabled\r\n",msgupd->areano);
               setcolor(TextAttr[ATTN_TEXT]);
               strout(temp);
            }
            else {
               sprintf(temp,"Adding conference #%03d",msgupd->areano);
               strout(temp);
               logit(temp,'#');
               strout("\r\n");
               msgmark(msgupd->areano);
               confreqs++;
               upmsgs--;
            }
         }
      }
      return TRUE;
   }
   else return FALSE;
}

char * _pascal namefixup(char *name)
{
   int x,y;
   static char tname[81];

   strncpy(tname,name,80);
   tname[20] = 0;
   stripwhite(tname);
   strlwr(tname);

   tname[0] = (char) toupper((int) tname[0]);
   y = (int) strlen(tname);

   for (x = 0; x < y; x++) {
      if (isspace(tname[x])) {
         x++;
         tname[x] = (char) toupper((int) tname[x]);
      }
   }
   return (&tname[0]);
}

