
/* **** Includes *********************************************************** */

#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 <math.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 <HBBS/release.h>
char *versionstr="$VER: AccountEdit "RELEASE_STR;

/* **** Variables ********************************************************** */

/* Common */

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

struct BBSGlobalData *BBSGlobal = NULL;
struct NodeData *N_ND           = NULL;
int    N_NodeNum                = -1;
char   outstr[1024];

long __stack=16*1024; // increse this in 4k incrments if you suffer from
                      // random/suprious crashings after or during the running
                      // of your door.

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

/* Used By This Door Only */

BOOL SysopMode=FALSE;
BOOL CallDataOnly=TRUE;
ULONG GLFlags=GL_EDIT + GL_DISPLAY;



/* **** Functions ********************************************************** */


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

/* **** DoorMain *********************************************************** */

void DisplayUserDetails ( struct UserData *UserDataPtr)
{

    DOOR_WriteText(ANSI_RESET ANSI_CLS);

    strNcpy(outstr,gargv[0],(PathPart(gargv[0])-gargv[0])+1);
    strcat(outstr,"AccountEdit.SCR");
    DOOR_DisplayScreen(outstr);

    sprintf(outstr,ANSI_FG_CYAN" 1) "ANSI_FG_YELLOW"Handle           "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%s"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->Handle);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN" 2) "ANSI_FG_YELLOW"Password         "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%s"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->Password);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN" 3) "ANSI_FG_YELLOW"Status           "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%c"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->Status);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN" 4) "ANSI_FG_YELLOW"Group            "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%s"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->Group);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN" 5) "ANSI_FG_YELLOW"Access Level     "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%d"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->Access);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN" 6) "ANSI_FG_YELLOW"Bytes Ratio      "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%d"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->BytesRatio);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN" 7) "ANSI_FG_YELLOW"Files Ratio      "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%d"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->FilesRatio);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN" 8) "ANSI_FG_YELLOW"Bytes Upload     "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%1.0f"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->UploadBytes);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN" 9) "ANSI_FG_YELLOW"Files Upload     "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%d"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->UploadFiles);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN"10) "ANSI_FG_YELLOW"Bytes Download   "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%1.0f"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->DownloadBytes);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN"11) "ANSI_FG_YELLOW"Files Download   "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%d"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->DownloadFiles);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN"12) "ANSI_FG_YELLOW"ConfAcs File     "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%s"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->ConfAcsDataFile);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN"13) "ANSI_FG_YELLOW"SentBy           "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%s"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->SentBy);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN"14) "ANSI_FG_YELLOW"Time Allowed     "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%d"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->TimeAllowed);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN"15) "ANSI_FG_YELLOW"Time Used        "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%d"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->TimeUsed);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN"16) "ANSI_FG_YELLOW"Extra Time       "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%d"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->ExtraTimeLimit);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN"17) "ANSI_FG_YELLOW"Preferred Conf   "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%d"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->PreferedConf);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN"18) "ANSI_FG_YELLOW"Last Conf        "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%d"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->LastConf);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN"19) "ANSI_FG_YELLOW"Calls Made       "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%d"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->CallsMade);
    DOOR_WriteText(outstr);
    sprintf(outstr,ANSI_FG_CYAN"20) "ANSI_FG_YELLOW"Messages Written "ANSI_FG_WHITE":"ANSI_FG_YELLOW"\""ANSI_FG_GREEN"%d"ANSI_FG_YELLOW"\"\r\n",UserDataPtr->MessagesWritten);
    DOOR_WriteText(outstr);

}

void HandleOption(int OptionNum,struct UserData *UserDataPtr)
{
  V_SMALLNUM SmallNum;
    V_BIGNUM BigNum;
    V_HUGENUM HugeNum;

  switch (OptionNum)
  {
    case 1: // handle
      DOOR_WriteText("New Handle >");
      DOOR_GetLine(GLFlags,0,LEN_HANDLE,0,UserDataPtr->Handle);
      if (N_ND->CurrentLine[0])
      {
        strcpy(UserDataPtr->Handle,N_ND->CurrentLine);
      }
      break;
    case 2: // Password
      DOOR_WriteText("New Password >");
      DOOR_GetLine(GLFlags,0,0,0,UserDataPtr->Password);
      if (N_ND->CurrentLine[0])
      {
        strcpy(UserDataPtr->Password,N_ND->CurrentLine);
      }
      break;
    case 3: //status
      sprintf(outstr,"%c",UserDataPtr->Status);
      DOOR_WriteText("New Status >");
      DOOR_GetLine(GLFlags,0,1,0,outstr);
      if (N_ND->CurrentLine[0])
      {
        UserDataPtr->Status=N_ND->CurrentLine[0];
      }
      break;
    case 4: // Password
      DOOR_WriteText("New Group >");
      DOOR_GetLine(GLFlags,0,LEN_GROUP,0,UserDataPtr->Group);
      if (N_ND->CurrentLine[0])
      {
        strcpy(UserDataPtr->Group,N_ND->CurrentLine);
      }
      break;
    case 5: //access level
      sprintf(outstr,"%ld",UserDataPtr->Access);
      DOOR_WriteText("New Access >");
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
      {
        // validate access level!
        if (HBBS_FindNodeNum(BBSGlobal->AcsLevelList,N_ND->CurrentLine)!=-1)
        {
          UserDataPtr->Access=SmallNum;
        }
        else
        {
          DOOR_PausePrompt("Invalid Access Level, check HBBS:Access/Levels/Level_List for valid ones");
        }
      }
      break;
    case 6: // bytes ratio
      sprintf(outstr,"%ld",UserDataPtr->BytesRatio);
      DOOR_WriteText("New Bytes Ratio >");
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
      {
        UserDataPtr->BytesRatio=SmallNum;
      }
      break;
    case 7: // files ratio
      DOOR_WriteText("New Files Ratio >");
      sprintf(outstr,"%ld",UserDataPtr->FilesRatio);
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
      {
        UserDataPtr->FilesRatio=SmallNum;
      }
      break;
    case 8: //bytes uploaded
      DOOR_WriteText("New Bytes Uploaded >");
      sprintf(outstr,"%1.0f",UserDataPtr->UploadBytes);
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      UserDataPtr->UploadBytes=atof(N_ND->CurrentLine);
/*
      if (sscanf(N_ND->CurrentLine,"%f",&HugeNum))
      {
        UserDataPtr->UploadBytes=HugeNum;
      }
*/
      break;
    case 9: //files uploaded
      DOOR_WriteText("New Files Uploaded >");
      sprintf(outstr,"%ld",UserDataPtr->UploadFiles);
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      if (sscanf(N_ND->CurrentLine,"%d",&BigNum))
      {
        UserDataPtr->UploadFiles=BigNum;
      }
      break;
    case 10: //bytes downloaded
      DOOR_WriteText("New Bytes Downloaded >");
      sprintf(outstr,"%1.0f",UserDataPtr->DownloadBytes);
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      UserDataPtr->DownloadBytes=atof(N_ND->CurrentLine);
/*
      if (sscanf(N_ND->CurrentLine,"%f",&HugeNum))
      {
        UserDataPtr->DownloadBytes=HugeNum;
      }
*/
      break;
    case 11: //files downloaded
      DOOR_WriteText("New Files Downloaded >");
      sprintf(outstr,"%ld",UserDataPtr->DownloadFiles);
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      if (sscanf(N_ND->CurrentLine,"%d",&BigNum))
      {
        UserDataPtr->DownloadFiles=BigNum;
      }
      break;
    case 12: // ConfAcs File
      DOOR_WriteText("Access File >");
      DOOR_GetLine(GLFlags,0,LEN_CONFACCESSFILE,0,UserDataPtr->ConfAcsDataFile);
      if (N_ND->CurrentLine[0])
      {
        strcpy(outstr,"HBBS:System/Data/ConfAcs");
        AddPart(outstr,N_ND->CurrentLine,1024);
        strcat(outstr,".CFG");
        if (PathOK(outstr))
        {
          strcpy(UserDataPtr->ConfAcsDataFile,N_ND->CurrentLine);
        }
      }
      break;
    case 13: // Sentby File
      DOOR_WriteText("SentBy >");
      DOOR_GetLine(GLFlags,0,LEN_SENTBY,0,UserDataPtr->SentBy);
      strcpy(UserDataPtr->SentBy,N_ND->CurrentLine);
      break;
    case 14: // Time Allowed
      DOOR_WriteText("Time Allowed >");
      sprintf(outstr,"%ld",UserDataPtr->TimeAllowed);
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
      {
        UserDataPtr->TimeAllowed=SmallNum;
      }
      break;
    case 15: // Time Used
      DOOR_WriteText("Time Used >");
      sprintf(outstr,"%ld",UserDataPtr->TimeUsed);
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
      {
        UserDataPtr->TimeUsed=SmallNum;
      }
      break;
    case 16: // Extra Time Limit
      DOOR_WriteText("Extra Time Limit >");
      sprintf(outstr,"%ld",UserDataPtr->ExtraTimeLimit);
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
      {
        UserDataPtr->ExtraTimeLimit=SmallNum;
      }
      break;
    case 17: // Preferred Conf
      DOOR_WriteText("Preferred Conf >");
      sprintf(outstr,"%ld",UserDataPtr->PreferedConf);
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
      {
        UserDataPtr->PreferedConf=SmallNum;
      }
      break;
    case 18: // Last Conf
      DOOR_WriteText("Last Conf >");
      sprintf(outstr,"%ld",UserDataPtr->LastConf);
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
      {
        UserDataPtr->LastConf=SmallNum;
      }
      break;
    case 19: // Calls Made
      DOOR_WriteText("Calls Made >");
      sprintf(outstr,"%ld",UserDataPtr->CallsMade);
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
      {
        UserDataPtr->CallsMade=SmallNum;
      }
      break;
    case 20: // MessagesWritten
      DOOR_WriteText("Messages Written >");
      sprintf(outstr,"%ld",UserDataPtr->MessagesWritten);
      DOOR_GetLine(GLFlags,0,0,0,outstr);
      if (sscanf(N_ND->CurrentLine,"%d",&SmallNum))
      {
        UserDataPtr->MessagesWritten=SmallNum;
      }
      break;

    Default :
      DOOR_WriteText("Unknown Option!\r\n");
      break;
  }
}

LONG EditUser ( struct UserData *UserDataPtr,LONG EUFlags)
{
  // Return Values

  #define EU_Save 1
  #define EU_Cancel 0

  // Flags

  #define EUF_None 0


  V_BIGNUM BigNum,OptionNum;
  BOOL Done=FALSE,ChangesMade=FALSE;
  LONG Retval=EU_Cancel;
  struct UserData User;

  CopyMem(UserDataPtr,&User,sizeof(struct UserData));

  do
  {
    DisplayUserDetails(&User);

    DOOR_WriteText("\r\n");

    DOOR_MenuPrompt("[S]ave, [Q]uit, [H]elp, [V]alidate or # of option : ",' ');
    if (DOOR_GetLine(GLFlags,'\0',0,0,NULL)==IN_GOTLINE)
    {
      RemoveSpaces(N_ND->CurrentLine);
      if (stricmp("S",N_ND->CurrentLine)==0)
      {
        DOOR_WriteText("Save\r\n");
        Retval=EU_Save;
        Done=TRUE;
      }
      else
      if (stricmp("Q",N_ND->CurrentLine)==0)
      {
        DOOR_WriteText("Quit\r\n");
        if (ChangesMade && DOOR_ContinuePrompt("Save changes first ",DEFAULT_NO|DCP_ADDYN))
        {
          Retval=EU_Save;
        }
        Done=TRUE;
      }
      else
      if (stricmp("H",N_ND->CurrentLine)==0)
      {
        DOOR_WriteText("To use the Validate option, just set the access level for the user\r\n"
                       "Then use the V option and the rest of the users settings will be changed\r\n");
        DOOR_PausePrompt(NULL);
      }
      else
      if (stricmp("V",N_ND->CurrentLine)==0)
      {
        // Set VALIDATED status
        User.Status=USER_VALIDATED;

        sprintf(outstr,"%d",User.Access);
        if ((BigNum=HBBS_FindNodeNum(BBSGlobal->AcsLevelList,outstr))>=0)
        {
          strcpy(User.ConfAcsDataFile,HBBS_ListName(BBSGlobal->AcsLevelConfAcsDef,BigNum));
        }
      }
      else
      {
        DOOR_WriteText("\r\n");
        OptionNum=0;
        if (sscanf(N_ND->CurrentLine,"%d",&OptionNum))
        {
          HandleOption(OptionNum,&User);
          ChangesMade=TRUE;
        }
      }
    }
    else
    {
      Done=TRUE;
    }
  } while (!Done);

  if (Retval==EU_Save)
  {
    CopyMem(&User,UserDataPtr,sizeof(struct UserData));
  }

  return(Retval);
}

#define EDIT_NONE   0
#define EDIT_BROWSE 1
#define EDIT_NEW    2

void DoorMain( void )
{
  struct UserData UserDat;
//  struct UserData *User=NULL;
  BOOL Done2,Done=FALSE;
  char defaultopt;
  struct List *UserList;
  struct Node *node,*CurrentUser;
  V_BIGNUM UserID,UsersInList;
  short ListMode;

  if ((gargc>=3) && (iposition("SYSOPONLY",gargv[2])>=0))
  {
    SysopMode=TRUE;
    CallDataOnly=FALSE;
    DOOR_WriteText(ANSI_RESET ANSI_CLS "Wait while the sysop changes your account settings!\r\n");

    /* Block Output to the serial port so the user doesn't see what we're doing.. */

    N_ND->NodeFlags+=NFLG_BLOCKSERIAL;


    GLFlags+=GL_SYSOP;

    if ((gargc>=4) && (iposition("CALLONLY",gargv[3])>=0))
    {
      CallDataOnly=TRUE;
    }

    if (N_ND->User.Valid)
    {
      if (EditUser(&N_ND->User.CallData,EUF_None)==EU_Save)
      {

        if (!CallDataOnly)
        {
          CopyMem(&N_ND->User.CallData,&N_ND->User.NormalData,sizeof(struct UserData));
        }

        if (SysopMode && CallDataOnly) DOOR_WriteText("Changes only last for this call!\r\n");
      }
    }
    else
    {
      DOOR_SysopText("No User is Logged On Yet!\r\n");
    }
    N_ND->NodeFlags-=NFLG_BLOCKSERIAL;

    HBBS_SetAccess();

  }
  else
  {
    do
    {
      DOOR_WriteText(ANSI_CLS ANSI_RESET ANSI_FG_YELLOW "Account Editor\r\n" ANSI_FG_WHITE);
      strcpy(N_ND->CharsAllowed,"SsNnQqBbIi");
      DOOR_MenuPrompt("[N]ew Users, [S]pecific User, [I]d, [B]rowse, [Q]uit >",'Q');
      DOOR_GetLine(GLFlags | GL_IMMEDIATE | GL_USECHARS,0,1,0,NULL);
      if (N_ND->OnlineStatus==OS_ONLINE && N_ND->CurrentLine[0])
      {
        ListMode=EDIT_NONE;

        switch(toupper(N_ND->CurrentLine[0]))
        {
          case 'I':
            DOOR_WriteText("Enter User ID :");
            DOOR_GetLine(GLFlags,0,LEN_HANDLE,0,NULL);
            RemoveSpaces(N_ND->CurrentLine);
            if (N_ND->CurrentLine[0]) // anything left in the line ?
            {
              UserID=atoi(N_ND->CurrentLine);

              if (UserID>0 && UserID<=BBSGlobal->TotalUsers)
              {
                if (HBBS_LoadUser(UserID,NULL,NULL,&UserDat))
                {
                  if (EditUser(&UserDat,EUF_None)==EU_Save)
                  {
                    HBBS_SaveUserData(&UserDat);
                  }
                }
                else DOOR_WriteText("Error loading that user's data!");
              }
              else DOOR_WriteText("That user ID does not exist!\r\n");
            }
            break;

          case 'S':
            DOOR_WriteText("Enter Handle :");
            DOOR_GetLine(GLFlags,0,LEN_HANDLE,0,NULL);
            RemoveSpaces(N_ND->CurrentLine);
            if (N_ND->CurrentLine[0])
            {
              if (HBBS_ValidUserHandle(N_ND->CurrentLine,&UserDat))
              {
//                User=&UserDat;

                if (EditUser(&UserDat,EUF_None)==EU_Save)
                {
                  HBBS_SaveUserData(&UserDat);
                }

              }
              else
              {
                DOOR_WriteText("Could Not Find That User!\r\n");
              }
            }
            break;
          case 'B':
            ListMode=EDIT_BROWSE;
            break;
          case 'N':
            ListMode=EDIT_NEW;
            break;
          case 'Q':
            Done=TRUE;
            break;
        }

        if (ListMode!=EDIT_NONE)
        {
          defaultopt='E';
          DOOR_WriteText("Searching...");

          /*
            Build linked list of users in memory, just needs to contain userid of user
            this way we can go [N]ext and [P]rev even after you have validated a user
            (the user's status may have been changed so we couldn't search backwards
            from current to find the last userwith a status of N)
          */

          if (UserList=HBBS_CreateList())
          {
            UsersInList=0;
            CurrentUser=0;
            for (UserID=1;UserID<=BBSGlobal->TotalUsers;UserID++)
            {
              if (HBBS_LoadUser(UserID,NULL,NULL,&UserDat))
              {
                if ((ListMode==EDIT_NEW && UserDat.Status==USER_NEW) || (ListMode==EDIT_BROWSE))
                {
                  if (node=HBBS_CreateNode(0,NULL)) // *C* could change NULL to UserDat->Handle..
                  {
                    node->ln_Pri=UserID;
                    AddTail(UserList,node);
                    UsersInList++;
                  }
                }
              }
            }

            sprintf(outstr,"OK.\r\nFound %d %suser%s\r\n",UsersInList,ListMode==EDIT_NEW ? "new " : "",UsersInList==1 ? "" : "s");
            DOOR_WriteText(outstr);
            DOOR_PausePrompt(NULL);

            if (UsersInList)
            {
              CurrentUser=UserList->lh_Head;

              Done2=FALSE;

              do
              {
                if (HBBS_LoadUser(CurrentUser->ln_Pri,NULL,NULL,&UserDat))
                {
                  DOOR_WriteText(ANSI_CLS ANSI_RESET ANSI_FG_YELLOW "Account Editor\r\n");
                  sprintf(outstr,ANSI_FG_CYAN "Current User "ANSI_FG_BLUE": "ANSI_FG_YELLOW"%s"ANSI_FG_BLUE" / "ANSI_FG_YELLOW"%s \r\n"ANSI_FG_WHITE,UserDat.Handle,UserDat.Group);
                  DOOR_WriteText(outstr);
                  DOOR_MenuPrompt("Options: [E]dit, [D]elete, [N]ext, [P]rev, [Q]uit >",defaultopt);
                  strcpy(N_ND->CharsAllowed,"EeDdNnPpQq");
                  DOOR_GetLine(GLFlags | GL_IMMEDIATE | GL_USECHARS,0,1,0,NULL);
                  if (N_ND->OnlineStatus==OS_ONLINE)
                  {
                    if (N_ND->CurrentLine[0]==0) N_ND->CurrentLine[0]=defaultopt;
                    switch(toupper(N_ND->CurrentLine[0]))
                    {
                      case 'D':
                        if (DOOR_ContinuePrompt("Are you sure!",DCP_ADDYN))
                        {
                          UserDat.Status=USER_DELETED;
                          HBBS_SaveUserData(&UserDat);
                        }
                        break;
                      case 'P':
                        if ((struct Node **)CurrentUser->ln_Pred != &UserList->lh_Head)
                        {
                          CurrentUser=CurrentUser->ln_Pred;
                        }
                        else DOOR_PausePrompt("No More! - Press Return");
                        break;
                      case 'N':
                        if ((struct Node **)CurrentUser->ln_Succ != &UserList->lh_Tail)
                        {
                          CurrentUser=CurrentUser->ln_Succ;
                          defaultopt='E';
                        }
                        else DOOR_PausePrompt("No More! - Press Return");
                        break;
                      case 'Q':
                        Done2=TRUE;
                        break;
                      case 'E':
                        if (EditUser(&UserDat,EUF_None)==EU_Save)
                        {
                          HBBS_SaveUserData(&UserDat);
                        }
                        defaultopt='N';

                        break;
                    }

                  } else Done2=TRUE;

                }
                else Done2=TRUE;

              } while (!Done2);
              HBBS_FreeListNodes(UserList);
            }
            FreeVec(UserList);
          } else DOOR_WriteText("No Mem\r\n");

        }
      }
      if (N_ND->OnlineStatus==OS_OFFLINE) Done=TRUE;
    } while (!Done);
  }

  DOOR_WriteText("Done.\r\n");
}

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

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

/* **** End Of File ******************************************************** */
