
#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <utility/date.h>

#include <utility/date.h>
#include <resources/battclock.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <clib/battclock_protos.h>
#include <clib/utility_protos.h>

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


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

#include <HBBS/ANSI_Codes.h>
#include <HBBS/Defines.h>
#include <HBBS/types.h>
#include <HBBS/structures.h>
#include <HBBS/Access.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: FileList "RELEASE_STR;

struct Library *HBBSCommonBase=NULL;
struct Library *HBBSNodeBase=NULL;
struct Library *UtilityBase = NULL;
struct Library *BattClockBase; // dont need to close this so skip initialisation

struct BBSGlobalData *BBSGlobal=NULL;
struct NodeData *N_ND=NULL;
int N_NodeNum=-1;

char tmpstr[BIG_STR];
char outstr[BIG_STR];
char searchstr[BIG_STR];
V_SMALLNUM LinesOutput=0;
BOOL Quit=FALSE,NonStop=FALSE,NonStopCLS=FALSE,SearchMode=FALSE,GotSearch=FALSE;
V_BIGNUM CurrentFileNumber;

#define FLM_NONE          0
#define FLM_NEW           1
#define FLM_REVERSE       2
#define FLM_LIST          3
#define FLM_REVERSESEARCH 4
#define FLM_SEARCH        5

ULONG Mode=FLM_NONE;

int gargc;
char **gargv;

struct List *FileNames=NULL;

char monthstr[12][4]={"JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"};
ULONG todaytime,fromtime;
struct ClockData todayDT,fromDT;

#define BUFFERSIZE 1024  // *C* Increase to 32k



ULONG FH;
ULONG FL;
UBYTE Buffer[BUFFERSIZE];
ULONG BytesInBuffer;
ULONG BufferOffset;

#define DIR_FORWARDS TRUE
#define DIR_REVERSE FALSE

static VOID cleanup(ULONG num)
{
  if (UtilityBase) CloseLibrary(UtilityBase);

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

  if (!(UtilityBase = (struct Library *)OpenLibrary("utility.library",33)))
  {
    cleanup(5);
  }
  if (!(BattClockBase= OpenResource(BATTCLOCKNAME)))
  {
    cleanup(6);
  }

  SetProgramName(name);
}

void strpad(char *buffer, int requiredlen, UBYTE PadChar)
{
  int many;
  int loop;
  int clen=strlen(buffer);

  if (clen<requiredlen)
  {
    many=requiredlen-clen;
    for (loop=0;loop<=many;loop++) buffer[clen+loop]=PadChar;
    buffer[requiredlen]=0;
  }
}

void PrintLine( char *Buffer)
{
  // Depending on the ID at the start of the buffer different things happen to the
  // output of the reset of the buffer..

  UBYTE buffer[256];
  strNcpy(buffer,Buffer,255); // max 255 chars..

  if (buffer[1]==' ')
  {
    switch (buffer[0])
    {
      case 'F' :
        CurrentFileNumber++;


        // first we print a little divider out..

        DOOR_WriteText(ANSI_RESET ANSI_FG_BLUE);
        sprintf(tmpstr,"-- "ANSI_FG_YELLOW"["ANSI_FG_WHITE" %d "ANSI_FG_YELLOW"]"ANSI_FG_WHITE" - "ANSI_FG_YELLOW"["ANSI_FG_WHITE" %s "ANSI_FG_YELLOW"]"ANSI_FG_WHITE" - "ANSI_FG_YELLOW"["ANSI_FG_WHITE" Node %d "ANSI_FG_YELLOW"]"ANSI_FG_BLUE" ",CurrentFileNumber,BBSGlobal->BBSName,N_ND->NodeNum);
        strpad(tmpstr,79+60,'-'); // +60 for the ansi!
        strcat(tmpstr,"\r\n");
        DOOR_WriteText(tmpstr);

        // then we need to print out the line of text itself..

        // first part of line needs to be CYAN

        DOOR_WriteText(ANSI_FG_CYAN);
        strNcpy(tmpstr,&buffer[2],34);
        DOOR_WriteText(tmpstr);

        // last part of line needs to be WHITE

        DOOR_WriteText(ANSI_FG_WHITE);
        strfcpy(tmpstr,&buffer[2],34); // index at 0, so use 34 instead of 35 for the 34th char..
        DOOR_WriteText(tmpstr);
        DOOR_WriteText("\r\n");
        LinesOutput+=2;
        break;
      case 'I' :
        DOOR_WriteText(ANSI_FG_WHITE);
        DOOR_WriteText(&buffer[2]);
        DOOR_WriteText("\r\n");
        LinesOutput++;
        break;
      case 'U' : // uploader (sentby)
        DOOR_WriteText(ANSI_FG_CYAN ANSI_BOLD);
        DOOR_WriteText(&buffer[2]);
        DOOR_WriteText("\r\n");
        LinesOutput++;
        break;
      case 'X' :
        strpad(buffer,81,' '); // make sure it's 81 chars long.. 79 are printed.. *C* won't work if ansi colours are used!!
        DOOR_WriteText(ANSI_BG_BLUE ANSI_FG_WHITE);
        DOOR_WriteText(&buffer[2]);
        DOOR_WriteText("\r\n");
        DOOR_WriteText(ANSI_RESET);
        LinesOutput++;
        break;
      case 'L' :
        DOOR_WriteText(ANSI_FG_YELLOW);
        DOOR_WriteText(&buffer[2]);
        DOOR_WriteText("\r\n");
        DOOR_WriteText(ANSI_RESET);
        LinesOutput++;
        break;
      case 'P' :
        DOOR_WriteText(ANSI_RESET);
        DOOR_WriteText(&buffer[2]);
        DOOR_WriteText("\r\n");
        DOOR_WriteText(ANSI_RESET);
        LinesOutput++;
        break;
      case 'T' :
        if (strlen(buffer)>=25)
        {
          strNcpy(tmpstr,&buffer[2],25);
          DOOR_WriteText(tmpstr);
          DOOR_WriteText(ANSI_FG_YELLOW);
          strNcpy(tmpstr,&buffer[27],8);
          DOOR_WriteText(tmpstr);
          DOOR_WriteText(ANSI_FG_WHITE);
          DOOR_WriteText(&buffer[35]);
          DOOR_WriteText("\r\n");
          LinesOutput++;
        }
        break;
      case 'N' :
        if (strlen(buffer)>=25)
        {
          strNcpy(tmpstr,&buffer[2],25);
          DOOR_WriteText(tmpstr);
          DOOR_WriteText(ANSI_FG_GREEN);
          strNcpy(tmpstr,&buffer[27],8);
          DOOR_WriteText(tmpstr);
          DOOR_WriteText(ANSI_FG_WHITE);
          DOOR_WriteText(&buffer[35]);
          DOOR_WriteText("\r\n");
          LinesOutput++;
        }
        break;
    }
  }
}

BOOL ScreenPausePrompt( BOOL ReachedEOF )
{
  BOOL retval=FALSE;
  V_BOOL Help;

  if ((!NonStop) || (NonStop && ReachedEOF) || (DOOR_CheckRaw(CR_NONE) && N_ND->CurrentLine[0]==3))
  {
    do
    {
      Help=FALSE;

      if (ReachedEOF)
      {
        strcpy(N_ND->CharsAllowed,"YyNnQqFfRr? ");
        DOOR_MenuPrompt("End-Of-File [Y/N/F/R/?] : ",' ');
//        DOOR_WriteText(ANSI_RESET "End-Of-File "ANSI_FG_YELLOW"["ANSI_FG_WHITE"Y/N/F/R/?"ANSI_FG_YELLOW"]"ANSI_FG_WHITE " : ");
      }
      else
      {
        strcpy(N_ND->CharsAllowed,"LlYyNnCcAaFfRr?Qq ");
        DOOR_MenuPrompt("Paused, More ? [Y/N/C/A/F/R/?] : ",' ');
//        DOOR_WriteText(ANSI_RESET "More "ANSI_FG_YELLOW"["ANSI_FG_WHITE"Y/N/C/A/F/R/?"ANSI_FG_YELLOW"]"ANSI_FG_WHITE " : ");
      }


      DOOR_GetLine(GL_EDIT|GL_DISPLAY|GL_USECHARS|GL_IMMEDIATE|GL_NORETURN,'\0',1,0,NULL);
      if (N_ND->OnlineStatus==OS_ONLINE)
      {
        DOOR_WriteText("\r[K"); // erase line
        if (stricmp("F",N_ND->CurrentLine)==0)
        {
          DOOR_WriteText(ANSI_FG_CYAN "Enter Filenames To Tag > "ANSI_FG_WHITE);
          DOOR_GetLine(GL_EDIT|GL_DISPLAY|GL_HISTORY|GL_NORETURN,'\0',0,0,NULL);
          if (N_ND->OnlineStatus==OS_ONLINE)
          {
            DOOR_WriteText("\r[K"); // erase line
            RemoveSpaces(N_ND->CurrentLine);
            if (N_ND->CurrentLine[0])
            {
              strcpy(tmpstr,N_ND->CurrentLine);
              DOOR_UserDoor("A",tmpstr);
              Help=TRUE;
            }
          }
        }
        else
        if (stricmp("R",N_ND->CurrentLine)==0)
        {
          DOOR_WriteText(ANSI_FG_CYAN"Enter FileNumbers To Tag > "ANSI_FG_WHITE);
          DOOR_GetLine(GL_EDIT|GL_DISPLAY|GL_HISTORY|GL_NORETURN,'\0',0,0,NULL);
          RemoveSpaces(N_ND->CurrentLine);
          if (N_ND->CurrentLine[0])
          {
            // this (horrible) code is nicked from ben's Zippy program
            // hence the horrible varialbe names and huge amount of them..

            LONG i,where;
            UBYTE filename[BIG_STR],rp[BIG_STR],*filenames;


            DOOR_WriteText("\r[K"); // erase line

            tmpstr[0]=0;

            for( i=0; i<strlen( N_ND->CurrentLine ); i++ )
            {
              if( N_ND->CurrentLine[i] == ',' )
              {
                rp[i] = ' ';
              }
              else
              {
                rp[i] = N_ND->CurrentLine[i];
              }
            }
            rp[i] = 0;


            filenames = rp;

            // but this bit is mine...

            while (filenames[0]) // any chars left ?
            {
              while ((filenames[0]==' ') && (filenames[0])) filenames++; //skip spaces..

              if (filenames[0])
              {
                if (((where=position(" ",filenames))>=0) )
                {
                  strNcpy(filename,filenames,where);
                  filenames+=where;
                }
                else
                {
                  strcpy(filename,filenames);
                  filenames+=strlen(filename);
                }

                // and this isn't mine..

                i = atol( filename );
                if (i>0 && i<=CurrentFileNumber)
                {
                  sprintf( tmpstr+strlen(tmpstr), "%s ", HBBS_ListName(FileNames, i-1) );
                }

              }
            }
            // but this is..
            if (tmpstr[0]) DOOR_UserDoor("A",tmpstr);
            Help=TRUE;
          }
        }
        else
        if (stricmp("C",N_ND->CurrentLine)==0)
        {
          DOOR_WriteText(ANSI_CLS);
        }
        else
        if (stricmp("L",N_ND->CurrentLine)==0)
        {
          NonStop=TRUE;
          NonStopCLS=TRUE;
          DOOR_WriteText(ANSI_CLS);
        }
        else
        if ((stricmp("N",N_ND->CurrentLine)==0) || (stricmp("Q",N_ND->CurrentLine)==0))
        {
          retval=TRUE;
        }
        else
        if (stricmp("A",N_ND->CurrentLine)==0)
        {
          NonStop=TRUE;
        }
        if (stricmp("?",N_ND->CurrentLine)==0)
        {
          DOOR_WriteText(ANSI_FG_WHITE
                         "Help\r\n~~~~\r\n\r\n"
                         "?    "ANSI_FG_CYAN"-"ANSI_FG_WHITE"  This Help Page\r\n"
                         "C    "ANSI_FG_CYAN"-"ANSI_FG_WHITE"  Clear Screen And Continue\r\n"
                         "N/Q  "ANSI_FG_CYAN"-"ANSI_FG_WHITE"  No More Please (QUIT)\r\n"
                         "A    "ANSI_FG_CYAN"-"ANSI_FG_WHITE"  Display All of remaining files (same as /X's NS)\r\n"
                         "L    "ANSI_FG_CYAN"-"ANSI_FG_WHITE"  Display All of remaining files with CLS's!\r\n"
                         "F    "ANSI_FG_CYAN"-"ANSI_FG_WHITE"  Flag File By NAME\r\n"
                         "R    "ANSI_FG_CYAN"-"ANSI_FG_WHITE"  Flag File By NUMBER\r\n");
          Help=TRUE;
        }
      }
    }
    while ((N_ND->OnlineStatus==OS_ONLINE) && (Help));
  }
  LinesOutput=0;

  if (N_ND->OnlineStatus==OS_ONLINE)
  {
    if (NonStopCLS && !ReachedEOF) DOOR_WriteText( ANSI_CLS );
  }
  else
  {
    retval=TRUE; // cancel!
  }


  return(retval);
}

void DisplayHelp( void )
{
  switch(Mode) // display different help depending on the mode!
  {
    case FLM_LIST:
      DOOR_WriteText("Example: F T\r\n\r\n"
                     "Supported options are:\r\n\r\n"
                     "T      [List]    - Scan Todays Files\r\n"
                     "S      [List]    - Scan since last call\r\n"
                     "<days> [List]    - Scan from <days> ago\r\n");
      break;
    case FLM_NEW:
      DOOR_WriteText("Example: N -3\r\n\r\n"
                     "Supported options are:\r\n\r\n"
                     "T      [List]    - Scan Todays Files\r\n"
                     "S      [List]    - Scan since last call\r\n"
                     "<days> [List]    - Scan from <days> ago\r\n");
      break;
    case FLM_REVERSE:
      DOOR_WriteText("Example: FR 2\r\n\r\n"
                     "Supported options are:\r\n\r\n"
                     "[List]           - Reverse Scan Files\r\n");
      break;
    case FLM_SEARCH:
      DOOR_WriteText("Example: Z searchtext A\r\n\r\n"
                     "Try using REVERSE SEARCH mode to display new files first\r\n"
                     "(ZFR from the BBS prompt)\r\n"
                     "To search for single letters, don't specify the search text on the command line\r\n"
                     "Supported options are:\r\n\r\n"
                     "[List]           - Reverse Scan Files\r\n");

      break;
    case FLM_REVERSESEARCH:
      DOOR_WriteText("Example: ZFR searchtext A\r\n\r\n"
                     "in REVERSE SEARCH mode, you'll see newer files first!\r\n"
                     "To search for single letters, don't specify the search text on the command line\r\n"
                     "Supported options are:\r\n\r\n"
                     "[List]           - Reverse Scan Files\r\n");

      break;
  }

  // display common options

  DOOR_WriteText("CFG              - Configure Scanner!\r\n"
                 "A                - Scan all file lists\r\n");


  // display sysop options

  if (N_ND->User->CallData->Access>=255) // *C* Configurable access level.
  {
    DOOR_WriteText(  "H                - Scan HOLD list\r\n");
    DOOR_WriteText(  "B                - Scan BADFILES list\r\n");
  }
}

void stripCR(UBYTE *String)
{
  ULONG Len;
  if (String && (Len=strlen(String)))
  {
    Len--; // Len now = character index..

    while (Len && (String[Len]=='\r' || String[Len]=='\n'))
    {
      String[Len--]=0;
    }
  }
}

void PrintFileInfo(struct List *FileInfo)
{
  struct Node *node;
  UBYTE tmpstr[20];
  if (FileInfo)
  {
    strftcpy( tmpstr,FileInfo->lh_Head->ln_Name,  2, 14 );
    NewStrNode( tmpstr, FileNames ); // *C* errorcheck!

    for (node=FileInfo->lh_Head;node->ln_Succ;node=node->ln_Succ)
    {
      PrintLine(node->ln_Name);
    }
  }
}

/*
BOOL FGetsR(BPTR FH,UBYTE *Buffer,LONG BufferLen)
{

  LONG nr,startpos,where,back,foundpos=0;
  BOOL retval=TRUE,sof=FALSE,error=FALSE;

  UBYTE *strptr=NULL;


  Buffer[0]=0;
  BufferLen--;

  where=Seek(FH,0,OFFSET_CURRENT);  // start of file already ?
  if (where<=0) //start of file or error
  {
    retval=FALSE;
  }
  else
  {
    startpos=where; // make a note of where we started from.
    do
    {
      back=255;
      if (where<255) back=where;

      if (back>BufferLen) back=BufferLen;

      if ((where=Seek(FH,0-back,OFFSET_CURRENT))!=-1)
      {
        where-=back;

        if (nr=Read(FH,Buffer,back))
        {
          Buffer[nr]=0;
          if (strptr=strrchr(Buffer,'\n'))
          {
            foundpos=where+(strptr-Buffer);
            if (Seek(FH,foundpos+1,OFFSET_BEGINNING)==-1)
            {
              error=TRUE;
            }
          }
          else
          {
            if (where==0)
            {
              if (Seek(FH,0,OFFSET_BEGINNING)==-1)
              {
                error=TRUE;
              }
              else
              {
                sof=TRUE;
                foundpos=1;
              }
            }
            else
            {

              if (Seek(FH,0-nr,OFFSET_CURRENT)!=-1)
              {
                where-=nr;
              }
              else
              {
                error=TRUE;
              }
            }

          }
        }
        else
        {
          error=TRUE;
        }

      }
    } while (strptr==NULL && !error && !sof);

    Buffer[0]=0;
    if (strptr || sof )
    {
      FGets(FH,Buffer,BufferLen);
      Seek(FH,foundpos ? foundpos-1 : 0,OFFSET_BEGINNING);
    }
  }

  return(retval);

}

BOOL FGetsR(BPTR FH,UBYTE *Buffer,LONG BufferLen)
{

  LONG nr,BufferPos=0;
  BOOL retval=TRUE,First=TRUE,Done=FALSE;
  char c;


  Buffer[0]=0;
  BufferLen--;

  if ((nr=Seek(FH,0,OFFSET_CURRENT))==0)  // start of file already ?
  {
    retval=FALSE;
  }
  else
  {
    do
    {
      if (Seek(FH,First ? -1 : -2 ,OFFSET_CURRENT)!=-1)
      {
        if (Read(FH,&c,1))
        {
          if (c=='\n')
          {
            Done=TRUE;
            Seek(FH,-1,OFFSET_CURRENT);
          }
          else
          {
            Buffer[BufferPos++]=c;
          }

        }
        else
        {
          Done=TRUE;
        }
        First=FALSE;
      }
      else
      {
        if (First)
        {
          retval=FALSE; // error, beginning of file or file error as seek() failed!
        }
        else
        {
          Seek(FH,-1,OFFSET_CURRENT);
                       // beginning of file..
        }
        Done=TRUE;
      }
    }
    while(BufferPos<BufferLen && !Done);

    Buffer[BufferPos]=0;

    if (BufferPos) strrev(Buffer); // reverse the string.
  }
  return(retval);

}
*/


struct List *GetFileInfoReverse( void )
{
  UBYTE Buffer[255];
  struct List *FileInfo=NULL;
  struct Node *node;

  BOOL Done=FALSE;

  if (FileInfo=HBBS_CreateList())
  {
    do
    {
      if (FGetsR(FH,Buffer,255))
      {
        stripCR(Buffer);
        switch(Buffer[0])
        {
          case 'F':
            Done=TRUE;
          case 'T':
          case 'N':
          case 'I':
          case 'U':
          case 'C':
          case 'L':
          case 'X':
          case 'P':

            if (node=HBBS_CreateNode(Buffer,0))
            {
              AddHead(FileInfo,node); //note: addHEAD() rather than addTAIL()
            }
            else
            {
              Done=TRUE;
            }
            break;
        }
      }
      else
      {
        Done=TRUE;
      }
    } while (!Done);

    if (HBBS_NodesInList(FileInfo)==0)
    {
      FreeStrList(FileInfo);
      FileInfo=NULL;
    }
  }
  return(FileInfo);
}

struct List *GetFileInfo( void )
{
  UBYTE Buffer[255];
  struct List *FileInfo=NULL;
  ULONG cpos,oldpos=0;

  BOOL Done=FALSE,KeepAdding=FALSE;

  if (FileInfo=HBBS_CreateList())
  {
    do
    {
      oldpos=Seek(FH,0,OFFSET_CURRENT);
      if (FGets(FH,Buffer,255))
      {
        stripCR(Buffer);
        switch(Buffer[0])
        {
          case 'F':
            if (KeepAdding)
            {
              cpos=Seek(FH,0,OFFSET_CURRENT);
              Seek(FH,0-(cpos-oldpos),OFFSET_CURRENT);
              KeepAdding=FALSE;
              Done=TRUE;
            }
            else
            {
              KeepAdding=TRUE;
            }
            // note: the lack of a "break" here!
          case 'T':
          case 'N':
          case 'I':
          case 'U':
          case 'C':
          case 'X':
          case 'L':
          case 'P':
            if (KeepAdding)
            {
              if (NewStrNode(Buffer,FileInfo))
              {
                Done=TRUE;
              }
            }
            break;
          default:
            if (KeepAdding) Done=TRUE;
            break;
        }
      }
      else
      {
        Done=TRUE;
      }
    } while (!Done);


    if (HBBS_NodesInList(FileInfo)==0)
    {
      FreeStrList(FileInfo);
      FileInfo=NULL;
    }
  }
  return(FileInfo);
}

BOOL DoWeWantToDisplayThis( struct List *list, char *SearchString )
{
  struct Node *ptr;
  BOOL Found = FALSE;
  char *isubstr, *istr;

  /* *C* Add Highlight */

  if (isubstr=upcase(SearchString))
  {

    for( ptr = list->lh_Head; ptr->ln_Succ; ptr = ptr->ln_Succ )
    {
      switch (ptr->ln_Name[0])
      {
        case 'F':  // only search the fileid and filename parts.
        case 'T':
        case 'N':
        case 'I':
          if (istr=upcase(ptr->ln_Name))
          {
            if( strstr( istr, isubstr ) ) Found = TRUE;
            FreeStr(istr);
          }
          break;
      }
    }

    FreeStr(isubstr);
  }
  return( Found );
}

void FileListNotAvailable( UBYTE *description )
{
  sprintf(outstr,ANSI_RESET ANSI_BOLD ANSI_FG_GREEN "File List " ANSI_FG_WHITE "\"%s\""ANSI_FG_GREEN", is not available\r\n",description);
  DOOR_WriteText(outstr);
}

BOOL ForwardList(UBYTE *filename,UBYTE *description)
{
  struct List *FileInfo=NULL;
  BOOL Done=FALSE,DisplayOK=FALSE;
  UBYTE datestr[LEN_DATESTR+1];
//  UBYTE copyoffile[BIG_STR];

  if (FileNames=HBBS_CreateList())
  {
    CurrentFileNumber=0;
    if (AssignOK(filename))
    {
//      sprintf(copyoffile,"%sWork/FileList.TEMP",N_ND->NodeLocation);

//      if (HBBS_CopyFile(filename,copyoffile,0))
//      {
//        if (FL=Lock(copyoffile,ACCESS_READ))
        if (FL=Lock(filename,ACCESS_READ))
        {
          if (FH=OpenFromLock(FL))
          {
            LinesOutput=0;
            while ((!Done) && (FileInfo=GetFileInfo()))
            {
              if (HBBS_NodesInList(FileInfo))
              {
                if (!DisplayOK)
                {
                  strftcpy(datestr,FileInfo->lh_Head->ln_Name,24,34);
                  if (HBBS_DateStrToAmigaTime(datestr) >= fromtime)
                  {
                    DisplayOK=TRUE;
                  }
                }
                if ((1 + LinesOutput + HBBS_NodesInList(FileInfo)) > (N_ND->User->CallData->LinesPerScreen-1) )
                {
                  Done=ScreenPausePrompt(FALSE);
                }
                if (!Done && DisplayOK)
                {
                  if (SearchMode)
                  {
                    if (DoWeWantToDisplayThis(FileInfo,searchstr))
                    {
                      PrintFileInfo(FileInfo);
                    }
                  }
                  else
                  {
                    PrintFileInfo(FileInfo);
                  }
                }
              }
              FreeStrList(FileInfo);
            }
            if (LinesOutput && !Done)
            {
              Done=ScreenPausePrompt(TRUE);
            }
            Close(FH);
          }
          else
          {
            UnLock(FL);
          }
        } else FileListNotAvailable(description);
//        DeleteFile(copyoffile);
//      } else DOOR_WriteText("Could not create a copy of the filelist!\r\n");
    } else FileListNotAvailable(description);
    FreeStrList(FileNames);
  }
  return(Done);

}

BOOL ReverseList(UBYTE *filename,UBYTE *description)
{
  struct List *FileInfo=NULL;
  BOOL Done=FALSE,DisplayOK=FALSE;
  UBYTE datestr[LEN_DATESTR+1];

  if (FileNames=HBBS_CreateList())
  {
    CurrentFileNumber=0;
    if (AssignOK(filename))
    {
      if (FL=Lock(filename,ACCESS_READ))
      {
        if (FH=OpenFromLock(FL))
        {
          if (Seek(FH,0,OFFSET_END)!=-1)
          {
            LinesOutput=0;
            while ((!Done) && (FileInfo=GetFileInfoReverse()))
            {
              if (HBBS_NodesInList(FileInfo))
              {
                if (!DisplayOK)
                {
                  strftcpy(datestr,FileInfo->lh_Head->ln_Name,24,34);
                  if (HBBS_DateStrToAmigaTime(datestr)>=fromtime)
                  {
                    DisplayOK=TRUE;
                  }
                }
                if ((1 + LinesOutput + HBBS_NodesInList(FileInfo)) > (N_ND->User->CallData->LinesPerScreen-1) )
                {
                  Done=ScreenPausePrompt(FALSE);
                }
                if (!Done && DisplayOK)
                {
                  if (SearchMode)
                  {
                    if (DoWeWantToDisplayThis(FileInfo,searchstr))
                    {
                      PrintFileInfo(FileInfo);
                    }
                  }
                  else
                  {
                    PrintFileInfo(FileInfo);
                  }
                }
              }
              FreeStrList(FileInfo);
            }
            if (LinesOutput && !Done)
            {
              Done=ScreenPausePrompt(TRUE);
            }
          }
          Close(FH);
        }
        else
        {
          UnLock(FL);
        }
      } else FileListNotAvailable(description);
    } else FileListNotAvailable(description);
    FreeStrList(FileNames);
  }
  return(Done);
}

BOOL DisplayList( ULONG listnum, UBYTE *datestr,UBYTE *filename,UBYTE *description)
{
  BOOL Cancel=TRUE;
  struct Node *node,*descnode;
  if (filename)
  {
    switch(Mode)
    {
      case FLM_NEW:
      case FLM_SEARCH:
      case FLM_LIST:
        Cancel=ForwardList(filename,description);
        break;
      case FLM_REVERSE:
      case FLM_REVERSESEARCH:
        Cancel=ReverseList(filename,description);
        break;
    }
  }
  else
  {
    if ((listnum>0) && (listnum<=N_ND->CurrentConf->FileLists))
    {

      node=GetNode(N_ND->CurrentConf->FileList,listnum-1);
      descnode=GetNode(N_ND->CurrentConf->ListDesc,listnum-1);

      sprintf(outstr,ANSI_RESET ANSI_BOLD ANSI_FG_YELLOW "Searching for files from "ANSI_FG_WHITE"%s"ANSI_FG_YELLOW" in list "ANSI_FG_BLUE"\"%s\"\r\n" ANSI_RESET,datestr,descnode->ln_Name);
      DOOR_WriteText(outstr);

      switch(Mode)
      {
        case FLM_NEW:
        case FLM_LIST:
        case FLM_SEARCH:
          Cancel=ForwardList(node->ln_Name,descnode->ln_Name);
          break;
        case FLM_REVERSE:
        case FLM_REVERSESEARCH:
          Cancel=ReverseList(node->ln_Name,descnode->ln_Name);
          break;
      }
    }
    else
    {
      DOOR_WriteText("Invalid file list number specified\r\n");
    }
  }
  return(Cancel);
}

void DoConfig( void )
{
  DOOR_WriteText("There are currently no configuration options for this door\r\n");
  DOOR_PausePrompt(NULL);
}

void DoorMain( void )
{
  ULONG loop;
  LONG daysago;
  char datestr[LEN_DATESTR+1];
  ULONG listnum,tmpnum,tmpnum2;
  BOOL error=FALSE,ScanAll=FALSE,Cancel=FALSE,ScanHOLD=FALSE,ScanBAD=FALSE,Done,InvalidOption=FALSE,ListNumberSpecified=FALSE;
  ULONG nextparam=2;
  char liststr[BIG_STR];

  if (N_ND->User->Acs.Data[ACS_SCANFILES]=='Y')
  {
    N_ND->Actions[ACTN_FILESCAN]=ACTC_FILESCAN;

    // default to using the filelist with the newer files in
    // and check to see if there are any file lists at the same time!

    if ((listnum=N_ND->CurrentConf->FileLists)>0)
    {
      // get the time/date

      todaytime=HBBS_GetAmigaTime();
      todaytime-=todaytime % 86400; //reset to midnight
      Amiga2Date(todaytime,&todayDT);
      fromtime=todaytime;

//      todayDT.sec=0;
//      todayDT.min=0;
//      todayDT.hour=0;        // as we want the date check to compare
//      todayDT.wday=0;        // between 00:00am from one day to the next..

//      todaytime=Date2Amiga(&todayDT);

      if (stricmp("NEW",N_ND->ActiveDoor->SystemOptions)==0)
      {
        Mode=FLM_NEW;
        if (gargc>=3 && Mode==FLM_NEW)
        {
          nextparam=3;
          switch(toupper(gargv[2][0]))
          {
            case '?':
              DisplayHelp();
              error=TRUE;
              break;
            case 'T':
              // fromtime is set to today
              break;
            case 'S':
              fromtime=N_ND->User->CallData->LastCalledDate;
              break;
            default:

              // "-" is not allowed, "-<n>" and "<n>" are allowed

              if ( ((strlen(gargv[2])==1) && (isdigit(gargv[2][0]))) ||
                   ((strlen(gargv[2])>1 ) && ((gargv[2][0]=='-') || (isdigit(gargv[2][0])) )))
              {
                if (sscanf(gargv[2],"%ld",&daysago))
                {
                  daysago=abs(daysago); // -2 is the same as 2 :-)
                  fromtime-=(daysago*86400); // 60secs * 60mins * 24hours = 86400 = 1day
                }
              }
              else
              {
                nextparam=2;
              }
              break;

          }
        }

//        fromtr=localtime(&fromtime);
      }


      if (stricmp("REVERSE",N_ND->ActiveDoor->SystemOptions)==0)
      {
        Mode=FLM_REVERSE;
        fromtime=0; // 0 seconds past 1/1/1978
      }

      if (stricmp("REVERSESEARCH",N_ND->ActiveDoor->SystemOptions)==0)
      {
        Mode=FLM_REVERSESEARCH;
        fromtime=0; // 0 seconds past 1/1/1978
        SearchMode=TRUE;
      }

      if (stricmp("SEARCH",N_ND->ActiveDoor->SystemOptions)==0)
      {
        Mode=FLM_SEARCH;
        fromtime=0; // 0 seconds past 1/1/1978
        SearchMode=TRUE;
      }

      if (stricmp("LIST",N_ND->ActiveDoor->SystemOptions)==0)
      {
        Mode=FLM_LIST;
        fromtime=0; // 0 seconds past 1/1/1978

      }

      fromtime-=fromtime % 86400; //reset to midnight (86400 seconds in a day!)

      Amiga2Date(fromtime,&fromDT);

      if (Mode)
      {
        Done=FALSE;
        while (gargc>=nextparam+1 && !error && !Done)
        {
          // user specified a file list to read from ?
          // other than the default one ?

          if (tmpnum2=sscanf(gargv[nextparam],"%ld",&tmpnum))
          {
            listnum=tmpnum;
            ListNumberSpecified=TRUE;
            Done=TRUE;
          }
          else
          {
            // not a number of a file list, perhaps it's an option..
            if (gargv[nextparam][1]== 0)
            {
              switch(toupper(gargv[nextparam][0]))
              {
                case '?':
                  DisplayHelp();
                  error=TRUE;
                  Done=TRUE;
                  break;
                case 'A':
                  ScanAll=TRUE;
                  Done=TRUE;
                  break;
                case 'H':
                  if (N_ND->User->CallData->Access>=255) // *C* Configurable access level
                  {
                    ScanHOLD=TRUE;
                  }
                  else
                  {
                    DOOR_WriteText("Access Denied!\r\n");
                    error=TRUE;
                  }
                  Done=TRUE;
                  break;
                case 'B':
                  if (N_ND->User->CallData->Access>=255) // *C* Configurable access level
                  {
                    ScanBAD=TRUE;
                  }
                  else
                  {
                    DOOR_WriteText("Access Denied!\r\n");
                    error=TRUE;
                  }
                  Done=TRUE;
                  break;
                case 'U':
                  // Upload dir. listnum is already set to this..
                  // so we don't need to do anything except break so the
                  // error msg isn't displayed
                  // but if we wanted to then: listnum=N_ND->CurrentConf->FileLists;
                  break;
                default:
                  InvalidOption=TRUE;
              }
            }
            else
            {
              error=TRUE;
              if (stricmp(gargv[nextparam],"CFG")==0)
              {
                DoConfig();
              }
              else
              {
                if (SearchMode)
                {
                  if (GotSearch)
                  {
                    strcat(searchstr," ");
                    strcat(searchstr,gargv[nextparam]);
                    error=FALSE;
                  }
                  else
                  {
                    strcpy(searchstr,gargv[nextparam]);
                    GotSearch=TRUE;
                    error=FALSE;
                  }
                }
                else
                {
                  InvalidOption=TRUE;
                }
              }
            }
          }

          if (InvalidOption)
          {
            DOOR_WriteText("Invalid Option!\r\n");
            error=TRUE;
          }

          nextparam++;
        }

        if (!error && SearchMode && !GotSearch)
        {
          error=TRUE;
          DOOR_WriteText(ANSI_FG_YELLOW "Enter Search String " ANSI_FG_BLUE ": " ANSI_FG_WHITE);
          DOOR_GetLine(GL_EDIT|GL_DISPLAY,'\0',60,0,NULL);
          if (N_ND->OnlineStatus==OS_ONLINE)
          {
            StripSpaces(N_ND->CurrentLine);
            if (N_ND->CurrentLine[0])
            {
              strcpy(searchstr,N_ND->CurrentLine);
              GotSearch=TRUE;
              error=FALSE;
            }
          }
        }

        if (!error)
        {
          // kludge! (*C* do we still need this...) Ill comment it out to see..
          //if (fromDT.mday<0) fromDT.mday=0; // can't be less than 01-JAN-1978

          fromtime=Date2Amiga(&fromDT);

          HBBS_GetDateString(datestr,fromtime);

          if (ScanAll)
          {
            switch (Mode)
            {
              case FLM_REVERSE:
              case FLM_REVERSESEARCH:
                // use the list with the newest files first.
                for (loop=N_ND->CurrentConf->FileLists;!Cancel && (loop>=1);loop--)
                {
                  Cancel = DisplayList(loop,datestr,NULL,NULL);
                }
                break;

              default:
                // use the list with the oldest files first
                for (loop=1;!Cancel && (loop<=N_ND->CurrentConf->FileLists);loop++)
                {
                  Cancel = DisplayList(loop,datestr,NULL,NULL);
                }
                break;
            }
          }
          else
          {
            if (ScanHOLD)
            {
              DisplayList(0,NULL,N_ND->CurrentConf->HoldFileList,"Hold List");
            }
            else
            {
              if (ScanBAD)
              {
                DisplayList(0,NULL,N_ND->CurrentConf->BadFileList,"Bad List");
              }
              else
              {
                Cancel = FALSE;
                
                // LIST mode ?  if so check for filelist number to display..

                if (Mode == FLM_LIST && !ListNumberSpecified)
                {
                  // if there's more than one file list, display a menu and let the user choose..

                  if (N_ND->CurrentConf->FileLists > 1)
                  {
                    DOOR_DisplaySpecialScreen("FileList");
                    
                    
                    for (loop=1;loop<=N_ND->CurrentConf->FileLists;loop++)
                    {
                      sprintf(liststr,ANSI_FG_WHITE"%2d"ANSI_FG_BLUE") "ANSI_FG_CYAN"%s\r\n",loop,HBBS_ListName(N_ND->CurrentConf->ListDesc,loop-1));
                      DOOR_WriteText(liststr);
                    }

                    DOOR_MenuPrompt(ANSI_FG_YELLOW"\r\nSelect a file list to display :",' ');
                    DOOR_GetLine(GL_EDIT|GL_DISPLAY,'\0',3,0,NULL);
                    
                    RemoveSpaces(N_ND->CurrentLine);
                    if (1 == sscanf(N_ND->CurrentLine,"%d",&listnum))
                    {
                      Cancel = (listnum<1 || listnum>N_ND->CurrentConf->FileLists);
                    }
                    else Cancel = TRUE;
                  }
                }
                // check we're still on-line, and display the selected list!

                if (N_ND->OnlineStatus==OS_ONLINE && !Cancel)
                {
                  DisplayList(listnum,datestr,NULL,NULL);
                }
              }
            }
          }

//          if (N_ND->OnlineStatus==OS_ONLINE)
//          {
//            DOOR_WriteText("Done!\r\n");
//          }
        }
      }
    }
    else
    {
      DOOR_WriteText("No files in this conference\r\n");
    }
  }
  else
  {
    DOOR_WriteText("Access Denied :-)\r\n");
  }
  DOOR_WriteText("\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("FileLister");

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