
/*

   Mail_Add.HBBS
   ===============

   Door for adding a file to the messagebase

   todo
   ====

     Default access level for public mail, when writing to ALL and EVERYBODY

     Add support for posting to handles with a space in the middle!

*/

#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 <HBBS/ANSI_Codes.h>
#include <HBBS/Defines.h>
#include <HBBS/types.h>
#include <HBBS/Access.h>
#include <HBBS/structures.h>
#include <HBBS/Hbbscommon_protos.h>
#ifdef __SASC
#include <HBBS/hbbscommon_pragmas_sas.h>
#else
#include <HBBS/hbbscommon_pragmas_stc.h>
#endif

#include <HBBS/Hbbsnode_protos.h>
#ifdef __SASC
#include <HBBS/Hbbsnode_pragmas_sas.h>
#else
#include <HBBS/Hbbsnode_pragmas_stc.h>
#endif
#include <HBBS/release.h>
char *versionstr="$VER: Mail_Write "RELEASE_STR;

#include "HBBS:Source/Mail/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=32768;

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

#include "HBBS:Source/Mail/maillib.i"

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);
}

void DoorMain( void )
{
  long nextparam;

  struct MailData *NewMail;
  struct UserData *ToUser,*FromUser;
  V_BIGNUM FromID,FromAccess;
  char datestr[12];
  V_BIGNUM NewMailAccess,NewMailFlags=MSGF_NORMAL;
  V_BOOL ToUserValid,error=FALSE,Posted=FALSE,Verbose=FALSE;
  V_SMALLNUM NewMailType=MSGT_CONFERENCE;

  char *FromHandle=NULL;
  char *MessageTextFile=NULL;
  char *ToHandles=NULL;
  char *ToHandle=NULL;
  char Subject[BIG_STR] = "<No Subject Defined>";
  char *TempToHandlesList=NULL;
  int where;
  BOOL Done;

  V_SMALLNUM  NewMailConf    = 0;
  char        expirydate[40] = "";

  // set defaults

  FromHandle=N_ND->User->CallData->Handle;
  FromID=N_ND->User->CallData->UserID;
  FromAccess=N_ND->User->NormalData->Access;

  NewMailFlags=MSGF_NORMAL;
  NewMailAccess=0; // needs same or higher for <ToHandles> to read   *C* default access level
  NewMailConf=N_ND->CurrentConf ? N_ND->CurrentConf->ConfNum : 0;

  LoadMailSystemConfig();


  // Parse command line.

  if (gargc>=2)
  {
    MessageTextFile=gargv[2];

    nextparam=3;

    while (nextparam < gargc)
    {
      if (Verbose)
      {
        sprintf(outstr,"%d = %s\r\n",nextparam,gargv[nextparam]);
        DOOR_SysopText(outstr);
      }

      if (stricmp(gargv[nextparam],"TO")==0)
      {
        nextparam++;
        if (nextparam < gargc) ToHandles=gargv[nextparam];
      }
      else
      {
        if (stricmp(gargv[nextparam],"FROM")==0)
        {
          nextparam++;
          if (nextparam < gargc)
          {
            if (ToEALLType(gargv[nextparam]))  // message to ALL or EVERYBODY
            {
              FromHandle=gargv[nextparam];
              FromID=0;
              FromAccess=0;
            }
            else
            {
              // nope, so check the handle..

              if (FromUser = (struct UserData *)AllocVec(sizeof (struct UserData ),MEMF_PUBLIC|MEMF_CLEAR))
              {
                if (HBBS_ValidUserHandle(gargv[nextparam],FromUser))
                {
                  // and set the FromID accordingly.

                  FromID=FromUser->UserID;
                  FromAccess=FromUser->Access;
                  FromHandle=gargv[nextparam];
                }
                FreeVec(FromUser);
              }

              // note: if the from handle specified does not exist then it will default to the
              // currently logged on user's handle.
            }
          }
        }
        else
        {
          if (stricmp(gargv[nextparam],"SUBJECT")==0)
          {
            nextparam++;
            Subject[0]=0;
            // the rest of the line is the subject
            while (nextparam < gargc)
            {
              strcat(Subject,gargv[nextparam++]);
              if (nextparam < gargc) strcat(Subject," ");
            }
          }
          else
          {
            if (stricmp(gargv[nextparam],"ACCESS")==0)
            {
              nextparam++;
              if (nextparam < gargc) sscanf(gargv[nextparam],"%d",&NewMailAccess);
            }
            else
            {
              if (stricmp(gargv[nextparam],"FLAGS")==0)
              {
                nextparam++;
                if (nextparam < gargc) sscanf(gargv[nextparam],"%d",&NewMailFlags);
              }
              else
              {
                if (stricmp(gargv[nextparam],"TYPE")==0)
                {
                  nextparam++;
                  if (nextparam < gargc)
                  switch(gargv[nextparam][0])
                  {
                    case 'S':
                      NewMailType=MSGT_SYSOP;
                      if (Verbose) DOOR_SysopText("Sysop Comment\r\n");
                      break;
                    case 'U':
                      NewMailType=MSGT_PRIVATE;
                      if (Verbose) DOOR_SysopText("Private User Mail\r\n");
                      break;
                    case 'C':
                      NewMailType=MSGT_CONFERENCE;
                      if (Verbose) DOOR_SysopText("Conference Mail\r\n");
                      break;
                    case 'P':
                      NewMailType=MSGT_PUBLIC;
                      if (Verbose) DOOR_SysopText("Public Mail\r\n");
                      break;
                  }
                }
                else
                {
                  if (stricmp(gargv[nextparam],"EXPIRY")==0)
                  {
                    nextparam++;
                    if (nextparam < gargc) strNcpy(expirydate,gargv[nextparam],11);
                  }
                  else
                  {
                    if (stricmp(gargv[nextparam],"CONF")==0)
                    {
                      nextparam++;
                      if (nextparam < gargc) sscanf(gargv[nextparam],"%d",&NewMailConf);
                    }
                    else
                    {
                      if (stricmp(gargv[nextparam],"VERBOSE")==0)
                      {
                        Verbose=TRUE;
                      }
                      else
                      {
                        sprintf(outstr,"Invalid Option Specified %s\r\n",gargv[nextparam]);
                        DOOR_SysopText(outstr);
                      }
                    }
                  }
                }
              }
            }
          }

        }

      }

      nextparam++;
    }
  }

  if (ToHandles == NULL) // default the user to the logged on user
  {
    if (N_ND->User->Valid)
    {
      ToHandles=N_ND->User->CallData->Handle;
    }
  }

  // have we got required parameters ?

  if (ToHandles && MessageTextFile)
  {

    // create a copy of the ToHandles (as we don't want to modify things we've pointed to)

    if (TempToHandlesList = DupStr(ToHandles))
    {
      // allocate some memory the same size as the HandlesList
      if (ToHandle = AllocVec(strlen(TempToHandlesList)+1,MEMF_PUBLIC))
      {
        Done=FALSE;
        while (!Done)
        {
          // get the first handle from the comma seperated list.

          where=position(",",TempToHandlesList);
          if (where>0)
          {
            strNcpy(ToHandle,TempToHandlesList,where);

            // copy the rest of the string over itself so we can get the next handle from the list.
            // (this is why we use a copy of ToHandles..)
            strftcpy(TempToHandlesList,TempToHandlesList,where+1,strlen(TempToHandlesList));
            if (TempToHandlesList[0]==0) Done=TRUE;
          }
          else // no comma, so it's a single handle..
          {
            strcpy(ToHandle,TempToHandlesList);
            Done=TRUE;
          }

          // ToHandle now contains a single handle. which we use for the remainder of this loop.

          if (NewMailType == MSGT_CONFERENCE)
          {
            if (NewMailConf == 0)
            {
              DOOR_SysopText("CONF Not Specified/Invalid or THISCONF specified but not in a conf yet\r\n");
              error=TRUE;
            }
          }
          else
          {
            NewMailConf=0; // reset back to 0 to make sure (e.g. if user selected a mail type other than conference but specified
                           // a conference by mistake.
          }

          if (stricmp(ToHandle,"SYSOP")==0) ToHandle = BBSGlobal->SysopAccount;

          if (NewMailType == MSGT_SYSOP) ToHandle = BBSGlobal->SysopAccount;

          if (!error)
          {
            if (Verbose)
            {
              sprintf(outstr,"Writing Mail\r\nTo %s\r\nFrom %s %d\r\nSubject %s\r\nAccess %d\r\nFlags %d\r\nType %d\r\nConference %d\r\n",ToHandle,FromHandle,FromID,Subject,NewMailAccess,NewMailFlags,NewMailType,NewMailConf);
              DOOR_SysopText(outstr);
            }

            if (ToUser = (struct UserData *)AllocVec(sizeof (struct UserData ),MEMF_PUBLIC|MEMF_CLEAR))
            {

              // Check the handle is valid!

              ToUserValid=FALSE; // Set flag, in case message is to ALL or EVERYBODY

              if (HBBS_ValidUserHandle(ToHandle,ToUser))
              {
                ToUserValid=TRUE;
              }

              if (ToUserValid || ToEALLType(ToHandle))
              {
                // Does <ToHandle> has access to conf if message is a conference message ?

                if ( ((NewMailType == MSGT_CONFERENCE) && (HBBS_CheckConfAccess(ToHandle,NewMailConf)))
                     ||
                     (NewMailType != MSGT_CONFERENCE) )
                {

                  // Allocate message

                  if (NewMail=AllocVec(sizeof(struct MailData ),MEMF_PUBLIC|MEMF_CLEAR))
                  {

                    // set message stuff..

                    NewMail->Type=NewMailType;
                    NewMail->Subject=DupStr(Subject);

                    NewMail->From=DupStr( FromHandle );
                    NewMail->FromID= FromID;

                    NewMail->To=DupStr( ToHandle );
                    if (ToUserValid) NewMail->ToID=ToUser->UserID; else NewMail->ToID=0;

                    HBBS_GetDate(datestr);
                    NewMail->CreateDate=DupStr(datestr);

                    // checks valid expriy date and that it is in the future

                    if (expirydate[0] && (HBBS_DateStrToAmigaTime(expirydate) > HBBS_GetAmigaTime()))
                    {
                      NewMail->ExpiryDate=DupStr(expirydate);
                    }
                    else
                    {
                      NewMail->ExpiryDate=DupStr("DD-MMM-YYYY"); // set message not to expire
                    }

                    NewMail->Flags=NewMailFlags;
                    NewMail->AttachedFiles=0;
                    NewMail->AccessLevel=NewMailAccess;
                    NewMail->UserAccessLevel=FromAccess;


                    if (PostNewMail(NewMail,NewMailConf,MessageTextFile))
                    {
                      N_ND->User->MsgsWritten++; //this call
                      N_ND->User->CallData->MessagesWritten++; //ever
                      N_ND->User->NormalData->MessagesWritten++;
                      N_ND->Actions[ACTN_WROTEMAIL]=ACTC_WROTEMAIL;

                      Posted=TRUE;
                    }
                    FreeMailMessage(NewMail);
                  }
                }
              }
              FreeVec(ToUser);
            }
            if (Posted && Verbose) DOOR_SysopText("Posted Mail Message\r\n");
          }
        }
        FreeVec(ToHandle);
      }
      FreeVec(TempToHandlesList);
    }
  }
  else
  {
    DOOR_SysopText("ToHandles and/or MessageTextFile was not set\r\n");
  }
  
  if (Posted)
  {
    DOOR_Return("POSTED");
  }
  else
  {
    DOOR_Return("FAILED");
  }
}

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("Adding Mail");

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