/*
  ShowPartUploads
  ===============

    See the docs

  Options
  =======

    N_ND->ActiveDoor->SystemOptions
    -------------------------------

    ignored

    Command Line Arguments
    ----------------------
    
    ignored

*/

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

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


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;

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


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

#define INITERR_NOERROR 0
#define INITERR_NOPARAMS 1
#define INITERR_NOHBBSCOMMON 2
#define INITERR_INITCOMMONFAILED 3
#define INITERR_NOHBBSNODE 4
#define INITERR_INITDOORFAILED 5

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

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

  switch(num)
  {
    case INITERR_NOERROR:
      exit(0);

    case INITERR_NOPARAMS:
      puts("Bad or no paramaters specified, check your config files\n"
           "(Don't try starting doors from the CLI!)");
      break;

    case INITERR_NOHBBSCOMMON:
      puts("Could not open HBBSCommon.library, check your assign's");
      break;

    case INITERR_INITCOMMONFAILED:
      puts("Could not initialise HBBSCommon.library functions\n"
           "Is HBBS Running ?");
      break;

    case INITERR_NOHBBSNODE:
      puts("Could not open HBBSNode.library, check your assign's");
      break;

    case INITERR_INITDOORFAILED:
      puts("The node specified is either not running or did not want to\n"
           "start this door now. (Don't run doors from the CLI!)");
      break;
  }
  exit(20);
}

static VOID Init(char *name)
{
  if(!(HBBSCommonBase = OpenLibrary("HBBSCommon.library",HBBSCOMMONVERSION)))
  {
    CleanUp(INITERR_NOHBBSCOMMON);
  }

  if (!(HBBS_InitCommon()))
  {
    CleanUp(INITERR_INITCOMMONFAILED);
  }

  if(!(HBBSNodeBase = OpenLibrary("HBBSNode.library",HBBSNODEVERSION)))
  {
    CleanUp(INITERR_NOHBBSNODE);
  }

  if (!(HBBS_InitDoor(N_NodeNum,name)))
  {
    CleanUp(INITERR_INITDOORFAILED);
  }
  SetProgramName(name);
}

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

void DoorMain( void )
{                                           
  BPTR FL;
  struct FileInfoBlock *FB;
  char *partuploadpath;
  struct Node *node;
  BOOL Found,
       First=TRUE,
       CheckedAll=FALSE,
       LoginCheckMode=FALSE;
  int pos;
  struct List *deletelist;
  LONG More;
  V_BIGNUM fileuserid;
  struct ConfData *CurrentConf;
  char filename[1024];
  
  if (N_ND->OnlineStatus==OS_ONLINE && N_ND->User->Valid)
  {                
    if (deletelist = HBBS_CreateList())
    { 
      
      if ( (gargc >= 3) && 
           (stricmp(gargv[2],"LOGINCHECK") == 0))
      {
        LoginCheckMode = TRUE;
        CurrentConf = (struct ConfData *)BBSGlobal -> ConfList -> lh_Head;
      }
      else
      {
        CheckedAll=TRUE; // only check one conference
        CurrentConf = N_ND -> CurrentConf;
      }
      
      do
      {
        for (node = CurrentConf -> PartUpload -> lh_Head ; 
             node -> ln_Succ ;
             node = node -> ln_Succ )
        {
          partuploadpath = node->ln_Name;
          
          if (FL = Lock(partuploadpath,ACCESS_READ))
          {            
            if (FB=AllocVec(sizeof(struct FileInfoBlock),MEMF_PUBLIC))
            {
              if (Examine(FL,FB))
              {
                do
                {
                  if (More=ExNext(FL,FB))
                  {
                    if (FB->fib_DirEntryType<0) // File ? or DIR
                    { 
                                
                      // find the @ and get the userid after the @ and compare to the current user.
                      // then clear the @<userid> from the filename
                    
                      pos = strlen(FB->fib_FileName);
                      Found = FALSE;
                      filename[0]=0; // set this so we can decide which files to process later.
                      
                      while (pos > 0 && !Found)
                      {
                        if (FB->fib_FileName[--pos] == '@') 
                        {
                          Found = TRUE;
                          if (1 == sscanf(FB->fib_FileName+(pos+1),"%d",&fileuserid))
                          {
                            if (fileuserid == N_ND->User->CallData->UserID) 
                            {
                              strNcpy(filename,FB->fib_FileName,pos);
                            }
                          }
                        }
                      }
                      
                      if (filename[0]) // skip files not for us and ones called "@n" e.g. "@5" (invalid name)
                      {
                        if (First)
                        {
                          DOOR_WriteText(ANSI_RESET ANSI_FG_YELLOW"Found an incomplete upload!\r\n"ANSI_FG_CYAN"You can either delete it now, or resume it when you like\r\n");
                          First=FALSE;
                        }
                        
                        sprintf(outstr,ANSI_FG_CYAN"File: "ANSI_FG_YELLOW"%s "ANSI_FG_CYAN"Size: "ANSI_FG_YELLOW"%ld"ANSI_FG_CYAN" Delete it ? ",filename,FB->fib_Size);
                        if (DOOR_ContinuePrompt(outstr,DCP_ADDYN | DCP_DEFAULT_NO))
                        {
                          DOOR_WriteText(ANSI_FG_YELLOW"Deleted\r\n");
                          
                            /* Don't delete the file now, but add the name of it to a list, for later
                             * so we don't distrub the ExNext() sequence 
                             */
                             
                          strNcpy(outstr,partuploadpath,1024);
                          AddPart(outstr,FB->fib_FileName,1024); 
                          NewStrNode(outstr,deletelist);
                        }
                        else
                        {
                          DOOR_WriteText(ANSI_FG_YELLOW"Keeping, please resume this file soon\r\n");
                        }
                      }
                    }
                  }
                }
                while (More);
              }
              FreeVec(FB);
            }
            UnLock(FL);
          }
        }

        if (LoginCheckMode)
        { 
          CurrentConf = (struct ConfData *)CurrentConf -> node.ln_Succ;

          if (CurrentConf -> node.ln_Succ == NULL)
          {
            CheckedAll=TRUE;
          }
        }

      } while (!CheckedAll);
      
      for (node = deletelist->lh_Head ;                              
           node -> ln_Succ ;
           node = node->ln_Succ )
      { 
        DOOR_SysopText(ANSI_FG_CYAN);
        sprintf(outstr,"Deleting file %s at user's request\r\n",node->ln_Name);
        DOOR_SysopText(outstr);
        HBBS_AddToCallersLog(outstr);
        DeleteFile(node->ln_Name);
      }                           
      
      FreeStrList(deletelist);
    }
      
  }

}

int main(int argc,char **argv)
{

  /* set these so that we can access the paramaters in the rest of the program */

  gargc=argc;
  gargv=argv;

  /* Check to see if we've got any paramaters */

  if (argc <= 1)
  {
    CleanUp(INITERR_NOPARAMS);
  }

  /* Get the node number from the paramaters */

  if (sscanf(argv[1],"%d",&N_NodeNum)==0)
  {
    CleanUp(INITERR_NOPARAMS);
  }

  /* Initialise and set the door/program name */

  Init("PartUpload");

  /* if the init() didn't fail then we need to ask HBBS for the pointer to
     it's data structures */

  if (BBSGlobal=HBBS_GimmeBBS())
  {
    /* Then we need to get the node's data structures for the node this door is going to run on */

    if (N_ND=HBBS_NodeDataPtr(N_NodeNum))
    {

      /* Now that's done, you can put the rest of your code here, or in the DoorMain() function */

      DoorMain();
    }
  }

  /* Cleanup and close libraries */

  CleanUp(INITERR_NOERROR);
}

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