
/*

   Mail_Scan.HBBS
   ==============

   Door for scanning new mail.


   ideas
   -----
     copy mail to another user
     forward mail to another user
     allow editing of header (from, to etc..)


   todo
   ----

   create a savemsglist() and loadmsg() list

   put routines into a shared lib.


*/

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>

#include <HBBS/ANSI_Codes.h>
#include <HBBS/Defines.h>
#include <HBBS/types.h>
#include <HBBS/structures.h>
#include <HBBS/hbbscommon_protos.h>
#include <HBBS/hbbscommon_pragmas.h>
#include <HBBS/Hbbsnode_protos.h>
#include <HBBS/Hbbsnode_pragmas.h>

#include "/Mail_Common.h"


struct Library *HBBSCommonBase=NULL;
struct Library *HBBSNodeBase=NULL;

struct BBSGlobalData *BBSGlobal=NULL;
struct NodeData *N_ND=NULL;
int N_NodeNum=-1;
char outstr[1024]; // temp string for displaying text..

int    gargc;         // these are just copies of main()'s argc and argv..
char   **gargv;

LONG __stack=16384;

struct List *MsgList=NULL;
V_BIGNUM Msgs=0;
struct MsgNode *ListNode=NULL;

#include "/maillib.i"

#ifdef __SASC
int CXBRK(void) { return(0); }
int _CXBRK(void) { return(0); }
void chkabort(void) {}
#endif


static VOID cleanup(ULONG num)
{
  if (HBBSNodeBase)
  {
    HBBS_CleanUpDoor();
    CloseLibrary (HBBSNodeBase);
  }

  if (HBBSCommonBase)
  {
    HBBS_CleanUpCommon();
    CloseLibrary (HBBSCommonBase);
  }

  if (num) printf("Door Error = %d\n",num);

  exit(0);
}

static VOID init(char *name)
{
  if(!(HBBSCommonBase = OpenLibrary("HBBSCommon.library",0)))
  {
    cleanup(1);
  }

  if (!(HBBS_InitCommon()))
  {
    cleanup(2);
  }

  if(!(HBBSNodeBase = OpenLibrary("HBBSNode.library",0)))
  {
    cleanup(3);
  }

  if (!(HBBS_InitDoor(N_NodeNum,name)))
  {
    cleanup(4);
  }
  SetProgramName(name);
}

V_BIGNUM CreateMsgListSpecial(char *MailPath, struct List **MsgList,V_BOOL DisplayWibble,V_SMALLNUM Type,V_BIGNUM ConfNum)
{
  V_BIGNUM FirstMessage,LastMessage;
  V_BIGNUM Msgs=0;
  V_BIGNUM loop,wibbleloop=0;

  char wibblestr[]="/-\\|/-\\|";
  #define wibblelen 8
/*
  char wibblestr[]="-+*+ ";
  #define wibblelen 5
*/
  char wibbleout[]="[\x44 ";


  struct MsgNode *ListNode;
  struct MailData *MailNode;
  BOOL DisplayedWibble=FALSE,AddOK;

  if ( (*MsgList) || ( (*MsgList==NULL) && (*MsgList=HBBS_CreateList()) ) )
  {
    if (PathOK(MailPath))
    {
      if (GetMailDirInfo(MailPath,&FirstMessage,&LastMessage))
      {
        // if public or conference mail then we need to
        // take note of what message the user
        // last scanned upto.

        if (DisplayWibble) DOOR_WriteText(" ");
        for (loop=FirstMessage;loop<=LastMessage;loop++)
        {
          if ((DisplayWibble) && (loop % 10==0))
          {
            wibbleout[3]=wibblestr[wibbleloop];
            DOOR_WriteText(wibbleout);
            wibbleloop++;
            if (wibbleloop==wibblelen) wibbleloop=0;
            DisplayedWibble=TRUE;
          }
          if (MailNode=GetMailMessage(MailPath,loop))
          {

            // read message ONLY if addressed to the user
            // OR if it's to another user, but is public
            // OR if the user is a Co-Sysop or better! :-)
            // OR is the user wrote the message in the first place!

            AddOK=FALSE;

            // sysop ?
            if (N_ND->User.CallData.Access>=250)
            {
              AddOK=TRUE;
            }
            else
            {
              // written by the user who wants to read it
              if (MailNode->FromID==N_ND->User.CallData.UserID)
              {
                AddOK=TRUE;
              }
              else
              {
                // to the user, an eall or an all ?
                if ( (MailNode->ToID==N_ND->User.CallData.UserID) ||   // USER
                     (stricmp("ALL",MailNode->To)==0)             ||   // ALL
                     (stricmp("EVERYBODY",MailNode->To)==0)         )  // EVERYBODY
                {
                  AddOK=TRUE;
                }
                else
                {
                  // public message to someone else ?
                  if (!(MailNode->Flags & MSGF_PRIVATE))
                  {
                    AddOK=TRUE;
                  }
                }
              }
            }
            if (AddOK)
            {
              if (ListNode=AllocVec(sizeof(struct MsgNode),MEMF_CLEAR))
              {
                if (ListNode->From=DupStr(MailNode->From))
                {
                  ListNode->FromID=MailNode->FromID;
                  if (ListNode->To=DupStr(MailNode->To))
                  {
                    if (ListNode->node.ln_Name=DupStr(MailNode->Subject))
                    {
                      ListNode->ToID=MailNode->ToID;
                      ListNode->Flags=MailNode->Flags;
                      ListNode->Number=loop;
                      ListNode->Type=Type;
                      ListNode->ConfNum=ConfNum;
                      AddTail(*MsgList,(struct Node *)ListNode);
                      Msgs++;
                    }
                    else
                    {
                      FreeVec(ListNode->To);  // *?* change to FreeStr
                      FreeVec(ListNode->From);
                    }
                  } else FreeVec(ListNode->From);
                }
              }
            }
            FreeMailMessage(MailNode);
          }
        }
        if (DisplayWibble && DisplayedWibble) DOOR_WriteText("[\x44 [\x44"); //return cursor to start position
      }
    }
    else
    {
      sprintf(outstr,"Could not find a directory needed for mail (%s)\r\n",MailPath);
//      DOOR_WriteText(outstr);
      HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_GENERAL,outstr,TYPE_WARNING);
    }
  }
  return(Msgs);
}



void DoorMain( void )
{
  char ScanDir[1024];
  char tmpstr[1024],tmpfilename[1024];
  V_BIGNUM Msgs=0,MsgNum;
  struct List *MsgList=NULL;

  // User
  //
  //

//  sprintf(tmpstr,"argc=%d\r\n",gargc);
//  DOOR_WriteText(tmpstr);

  if ((gargc==2) || ((gargc>=3) && (toupper(gargv[2][0])=='C')))
  {
    // Conference
    DOOR_WriteText("Scanning for mail ");
    sprintf(ScanDir,"%sMail/",N_ND->CurrentConf->ConfPath,N_ND->User.CallData.UserID);
    Msgs+=CreateMsgListSpecial(ScanDir,&MsgList,TRUE,MSGT_CONFERENCE,N_ND->CurrentConf->ConfNum);
    DOOR_WriteText("Ok!\r\n");
  }
  else
  if (gargc>=3 && toupper(gargv[2][0])=='U')
  {
    // Private Mail

    DOOR_WriteText("Scanning for private mail ");
    sprintf(ScanDir,"%s%ld/",MAILDIR_USER,N_ND->User.CallData.UserID);
    Msgs+=CreateMsgListSpecial(ScanDir,&MsgList,TRUE,MSGT_PRIVATE,0);
    DOOR_WriteText("Ok!\r\n");
  }
  else
  if (gargc>=3 && toupper(gargv[2][0])=='P')
  {
    // Public Mail

    DOOR_WriteText("Scanning for public mail ");
    Msgs+=CreateMsgListSpecial(MAILDIR_PUBLIC,&MsgList,TRUE,MSGT_PUBLIC,0);
    DOOR_WriteText("Ok!\r\n");
  }
  else
  if (gargc>=3 && toupper(gargv[2][0])=='S')
  {
    // Sysop Mail

    if (N_ND->User.CallData.Access>=250)
    {
      DOOR_WriteText("Scanning for sysop mail ");
      Msgs+=CreateMsgListSpecial(MAILDIR_SYSOP,&MsgList,TRUE,MSGT_SYSOP,0);
      DOOR_WriteText("Ok!\r\n");
    }
  }
  else
  if (gargc>=3 && toupper(gargv[2][0])=='?')
  {
    DOOR_WriteText("This mail read command accepts the following parameters\r\n"
                   "?    = Displays this screen\r\n\r\n"
                   "U    = Read All Your Private Mail\r\n"
                   "P    = Read All The Public Mail\r\n"
                   "C    = Read Conference Mail\r\n"
                   "#    = Read Conference Message Number #\r\n");
    if (N_ND->User.CallData.Access>=250)
    {
      DOOR_WriteText("S    = Read all Sysop mail\r\n");
    }
  }
  else
  if (gargc>=3)
  {
    if (sscanf(gargv[2],"%ld",&MsgNum))
    {
      // msgnum, type, confnum
      sprintf(tmpstr,"MSG %d %d %d",MsgNum,MSGT_CONFERENCE,N_ND->CurrentConf->ConfNum);
      DOOR_SystemDoor("MailRead",tmpstr);
    }
    else
    {
      DOOR_WriteText("Invalid Paramater! use ? for help!\r\n");
    }
  }


  if (Msgs)
  {
    sprintf(tmpfilename,"%sWork/MailTemp.DAT",N_ND->NodeLocation);
    if (SaveMsgList(MsgList,tmpfilename,SML_ALL))
    {
      sprintf(tmpstr,"MSGLIST %s%s",tmpfilename,N_ND->User.CallData.Access>=250 ? " NOAUTODELETE" : "" );
      DOOR_SystemDoor("MailRead",tmpstr);
      DeleteFile(tmpfilename);
    }
    FreeMsgList(MsgList);
  }
}

int main(int argc,char *argv[])
{
  gargc=argc;
  gargv=argv;

  if (sscanf(argv[1],"%d",&N_NodeNum)==0)
  {
    printf("Invalid/No Paramaters for door!\n");
    exit (20);
  }
  init("Checking Mail");

  if (BBSGlobal=HBBS_GimmeBBS())
  {
    if (N_ND=HBBS_NodeDataPtr(N_NodeNum)) // this should not fail in normal circumstances..
    {
      DoorMain();
    }
  }
  cleanup(0);
}
