#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <dos.h>
#include <exec/types.h>
#include <dos/dos.h>
#include <dos/dosextens.h>

#include <devices/tpt.h>

#include <dlg/cron.h>
#include <dlg/resman.h>
#include <dlg/user.h>
#include <dlg/msg.h>
#include <dlg/portconfig.h>
#include <dlg/input.h>
#include <dlg/misc.h>
#include <dlg/menu.h>
#include <dlg/log.h>

#include <dlg_private/dlg.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/dlg.h>

#include <pragmas/dlg.h>

static char version[]="$VER: Door 2.2 © 1995-1997 by DLG Development "__AMIGADATE__"";

void   main(int, char **);
void   Check_Birthday(void);
BOOL   CheckANSI(BOOL);
void   Find_Pointers(void);
void   Get_Computer_Type(char, char *);
void  _CXBRK(void);
void  _abort(void);

BPTR               sout    = NULL;
struct Library    *DLGBase = NULL;
char             **SA;

struct USER_DATA       TempUser = {"", 24, 80, 0, 1, 0, "", "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, 0, 0, 0, 0, 0, "", 0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", 0, 0, 0, "", 0, "", 0, 0, 0, "", 0, 0, 0};
struct USER_DATA       UserDat;
struct Ram_File        RStruct;
struct Global_Settings Globals;

struct UserInfo ui = {&UserDat, &RStruct};
struct Query    q  = {NULL, NULL, NULL, NULL, NULL, 0, 0, 0};

char   Cur_User[33];
char   Ext     [4];
char   login = 0;
char   tempstring[256];

USHORT pos   = 0;


void main(int argc,char **argv)
{
   struct Process *myproc;

   SHORT  timeallowed;
   SHORT  tries = 0;
   long   destevent;

   char   string     [256];
   char   titlestring[82];
   char   titlescreen[40];

   if(NULL == (DLGBase = OpenLibrary(DLGNAME, DLGVERSION))) exit(5);

   myproc               = (struct Process *)FindTask(0);
   myproc->pr_WindowPtr = (void *)-1;
   sout                 =  Output();


   if (GetDevName(Ext) == -1)
   {
      Printf("Can't find device name\n\n");
      _abort();
   }

   if (ReadGlobals(Ext,&Globals) == -1)
   {
      Printf("Failed to read globals\n\n");
      _CXBRK();
   }

   UseCharSet(Globals.CharSet, Ext);
   if (!(SA = getlang(Ext)))  _CXBRK();

   ASPrintf(NULL, titlescreen, "DLGConfig:text/title.%s", Ext);
   if ((Globals.Flags & AUTO_ANSI))
   if (CheckANSI(TRUE))
   {
      TempUser.Ansi_Flag = (Globals.Flags & (ANSI_COLOR + ANSI_CLR + ANSI_POS + ANSI_SCROLL + ANSI_NOFREEZE));
      ASPrintf(NULL, titlescreen, "DLGConfig:text/title.%s.ansi", Ext);
      if (!Exists(titlescreen))  strcpy(titlescreen, "DLGConfig:text/title.ansi");
      if (!Exists(titlescreen))  ASPrintf(NULL, titlescreen, "DLGConfig:text/title.%s", Ext);
   }
   if (!Exists(titlescreen))  strcpy(titlescreen,"DLGConfig:text/title.txt");

   BCPend(Ext);
   TSetFlags(T_SER_TIMEOUT, Ext);
   TTimeDelay(20, Ext);

   ReadRam(&RStruct, Ext);
   RStruct.CLI = (char)myproc->pr_TaskNum;
   strcpy(RStruct.Action, SA[68]);
   WriteRam(&RStruct, Ext);

   if (RStruct.Baud_Rate < Globals.MinBaud)
   {
      DispForm("DLGCONFIG:Text/BaudRateTooLow.txt", &TempUser, &TempUser, &RStruct, Ext);
      _CXBRK();
   }

   ASPrintf(NULL, titlestring, SA[69], Ext); 
   TTitle(titlestring, Ext);

   Clr(255);
   if (argc < 2)
   {
      RawDump(titlescreen);
      
      destevent = TimeUntilShutdown(Ext);
      if (destevent < 3)
      {
         DispForm("DLGCONFIG:Text/NoProceed.txt", &TempUser, &TempUser, &RStruct, Ext);
         _CXBRK();
      }
   }

   if (argc > 1)  strcpy(RStruct.Command_Stack, argv[1]);

   while(TRUE)
   {
      BPTR  gr;
      long  zflag;
      int   pp;

      char  filename[128];
      char  password[13];

      tries++;
      movmem(&TempUser, &UserDat, sizeof(struct USER_DATA));
      ClearLine();

      if (tries == 4)
      {
         AFPrintf(&TempUser, sout, SA[70]);
         _CXBRK();
      }

      Chk_Abort();
      q.prompt     = SA[71];
      q.string     = Cur_User;
      q.length     = 32;
      q.typelength = 32;
      q.flags      = QUERY_CAPITAL|QUERY_NOSTACK;
      DLGQuery(&q, &ui);
      TwoLines();

      StripSpaces(Cur_User);
      if (!Cur_User[0])  continue;

      if (!Globals.AutoAccess)
      {
         zflag = 0;

         if (gr = OpenGroup(Globals.NameList))
         {
            char   priname[30];

            while(NextInGroup(gr, priname))
            {
               if (!Stricmp(priname, Cur_User))
               {
                  zflag++;
                  break;
               }
            }
            CloseGroup(gr);

            if (!zflag)
            {
               AFPrintf(&TempUser, sout, SA[72], Cur_User);
               zflag = BoolQuery(SA[73], 0, &ui);
               TwoLines();
               if (!zflag)  continue;

               DispForm("DLGCONFIG:Text/PortIsPrivate.txt", &TempUser, &TempUser, &RStruct, Ext);
               _CXBRK();
            }
         }
               }

      ASPrintf(NULL, filename, "USER:%s/user.data", Cur_User);
      UnderScore(filename);

      if ((pp = open(filename, O_RDONLY)) == EOF)
      {
         AFPrintf(&TempUser, sout, SA[72], Cur_User);
         zflag = BoolQuery(SA[73], 0, &ui);
         TwoLines();

         if (zflag)
         {
            AFPrintf(&TempUser, sout, SA[74], Cur_User);
            ASPrintf(&TempUser, string, "DLG:NewUser \"%s\" %ANSI", Cur_User); 
            OverlayProgram(string);
            tries = 0;
         }

         continue;
      }

      read(pp, &UserDat, sizeof(UserDat));
      close(pp);

      if (UserDat.Screen_Width < 20)
      UserDat.Screen_Width = 80;

      if (argc < 2)
      {
         q.prompt        = SA[75];
         q.string        = password;
         q.length        = 11;
         q.typelength    = 11;
         q.flags         = (UserDat.UUCP & UUCP_CLIENT)?0:QUERY_HIDDEN|QUERY_NOSTACK;
         DLGQuery(&q, &ui);

         if (Stricmp(UserDat.Password, password))
         {
            Inform(Cur_User, SA[76], Ext, 0);
            TwoLines();
            AFPrintf(&UserDat, sout, SA[77], tries);
            Upper(Cur_User);
            WriteLog(BAD_PASSWORD, SA[78], Ext, Cur_User);
            continue;
         }
      }

      strcpy(RStruct.Name, Cur_User);
      break;
   }

   if (UserDat.charset)  UseCharSet(UserDat.charset, Ext);

   if (UserDat.menuset)
   {
      struct MenuSet Set;

      Set.number = UserDat.menuset;
      if (GetStruct("DLGConfig:Misc/MenuSets.bbs", (char *)&Set, sizeof(Set), 1) != -1)
      if (LoadLang(Ext,Set.language)!=RMNOERR)
      if (LoadLang(Ext,"English")!=RMNOERR)
      _CXBRK();
   }

   if (!(UserDat.UUCP&UUCP_CLIENT))  Clr(UserDat.Ansi_Flag);

   TTimeDelay((long)(Globals.TimeOut * 12), Ext);

   {
      char   date[26];

      MDate(date);
      if (Strnicmp(date, UserDat.Last_Login, 13))
      UserDat.Daily_Used = 0;

      timeallowed = (UserDat.Daily_Limit - UserDat.Daily_Used);
      if (timeallowed > UserDat.Session_Limit)
      timeallowed = UserDat.Session_Limit;
   }

   if (timeallowed >= 2)
   {
      destevent = TimeUntilShutdown(Ext);
      if (timeallowed > destevent && !(UserDat.UUCP & UUCP_CLIENT))
      {
         pos = 0;
         DispForm("DLGCONFIG:Text/Event.txt", &UserDat, &UserDat, &RStruct, Ext);
         AFPrintf(&UserDat, sout, SA[79], timeallowed, destevent);
         timeallowed = destevent;
      }
   }

   if (timeallowed < 2)
   {
      pos = 0;
      DispForm("DLGCONFIG:Text/NotEnoughTime.txt", &UserDat, &UserDat, &RStruct, Ext);
      _CXBRK();
   }


   {
      long  ssize1;
      long  ssize2;
      char  newstack[80];

      ssize1 = ASPrintf(NULL, newstack, "%s%s", Globals.ForcedStack, UserDat.stack);
      ssize2 = strlen(RStruct.Command_Stack);
      if (ssize1 + ssize2 < 254)  movmem(newstack, RStruct.Command_Stack + ssize2, ssize1 + 1);
   }

   if (argc < 3)
   strcpy(RStruct.menu, Globals.DefMenu);
   else
   strcpy(RStruct.menu, argv[2]);

   if (!WriteRam(&RStruct, Ext))
   {
      AFPrintf(&UserDat, sout, SA[81]);
      _CXBRK();
   }

   WriteLog(SUCCESSFUL_LOGIN, RStruct.Name, Ext,"");
   login = 1;
   UserDat.Total_Calls++;
   UserDat.Long_Date = (AmigaTime()/60) * 60;
   WriteUser(RStruct.Name, &UserDat);

   if (argc < 2)
   {
      ASPrintf(&UserDat, string, SA[82], Cur_User, UserDat.City, Ext);
      Inform("ALL", string, Ext, 0);
   }

   {
      char   log     [30];
      char   date    [26];
      char   ctstring[36];

      ASPrintf(NULL, log, "> NIL: DLG:RemoveUser %s", Ext);
      Upper(log);

      while(CronEvent(DELEVENT, 0, log));
      CronEvent(ADDEVENT, (long)(timeallowed - 2), log);

      MDate(date);
      Get_Computer_Type(UserDat.Computer_Type, ctstring);

      ASPrintf(&UserDat, titlestring, SA[80], Ext, Cur_User, RStruct.Baud_Rate, date+14,(long)(timeallowed-1), ctstring);
      TTitle(titlestring,Ext);  
   }

   if (!(UserDat.UUCP & UUCP_CLIENT))
   {
      if (argc < 2)
      {
         DispForm("DLGCONFIG:Text/Login.txt", &UserDat, &UserDat, &RStruct,Ext);

         if (Exists("DLGCONFIG:Batch/Login.batch"))
         {
            ASPrintf(NULL, string, "Execute DLGCONFIG:Batch/Login.batch %s", Ext);
            Execute(string, 0, 0);
            ReadUser(&RStruct, &UserDat, Ext);
         }

         if (Exists("DLGCONFIG:Batch/Login.DLGBatch"))
         {
            DialogBatch("DLGCONFIG:Batch/Login.DLGBatch",&UserDat,&RStruct,Ext);
            ReadUser(&RStruct, &UserDat, Ext);
         }
      }

      if (!Globals.GlobalScreen && UserDat.Pop_Screen)
      {
         struct Port     CPort;
         struct Displays Display;

         ASPrintf(NULL, string, "DlgConfig:Port/%s.port", Ext);
         GetFirstStruct(string, (char *)&CPort, sizeof(CPort));

         ASPrintf(NULL, string, "DlgConfig:Port/%s", CPort.DisplayFile);
         GetFirstStruct(string, (char *)&Display, sizeof(Display));

         if (!Globals.DefaultScreen)
         TWindow(WOPEN,      &Display.Window, Ext);
         else
         TScreen(TPOPSCREEN, &Display.Screen, Ext);
      }

      if (UserDat.User_Level > 254)
      {
         ULONG size;
         
         if (FileSize(NEWUSERS, &size) != -1)
         {
            if (size == sizeof(struct NameStruct))
               AFPrintf(&UserDat, sout, SA[83]);
            else
               AFPrintf(&UserDat, sout, SA[84], (size/sizeof(struct NameStruct)));
            
            if (argc > 1)   Pause();
         }
      }
      
      if (argc < 2)  Pause();
      Clr(UserDat.Ansi_Flag);
   }

   if (UserDat.UUCP & UUCP_CLIENT)
   {
      struct tdev_info info;
      char   ExeString[255];

      TDevQuery(&info, Ext);
      ASPrintf(NULL, ExeString, "Execute DLGCONFIG:batch/UUCP.batch %s %s %d", Ext, info.devname, info.unit);
      TFreeze(Ext);
      CronEvent(ADDEVENT, 0, ExeString);
      BCResume(Ext);
      AFPrintf(&UserDat, sout, SA[85]);
      _abort();
   }

   Check_Birthday();

   ASPrintf(NULL, string, "USER:%s/Event.log", RStruct.Name);
   UnderScore(string);
   if (Exists(string))
   {
      AFPrintf(&UserDat, sout, SA[86]);

      pos = 0;
      DispForm(string, &UserDat, &UserDat, &RStruct, Ext);
      AFPrintf(&UserDat, sout, "\n");
      Pause();

      Clr(UserDat.Ansi_Flag);
   }

   if(Exists("DLGConfig:Rexx/Bulletin.DLX"))
   {
      ASPrintf(NULL,tempstring,"DLG:DLGRX -p %s -s DLGConfig:Rexx/Bulletin.DLX",Ext);
      OverlayProgram(tempstring);
   }

   if(Exists("DLGConfig:Batch/Bulletin.DLGBatch"))
      DialogBatch("DLGconfig:Batch/Bulletin.DLGBatch",&UserDat,&RStruct,Ext);


//   OverlayProgram("DLG:Bulletin");
   ChainProgram("DLG:Menu", Ext);
   _abort();
}


void Check_Birthday(void)

{
   char  date   [36];
   char  mthname[10];
   char  mthref [46];

   long  day;
   long  month;

   strcpy(mthref, SA[87]);

   MDate(date);
   sscanf(date, "%s %d %s", &mthname, &day, &mthname);

   for(month = 0; month < 12; month++)
   if (!(Strnicmp(mthref+(month*3), mthname, 3)))  break;

   month++;
   if ((month == UserDat.Birth_Month) && (day == UserDat.Birth_Day))
   {
      pos = 0;
      DispForm("DLGCONFIG:Text/HappyBirthday.txt", &UserDat, &UserDat, &RStruct, Ext);
      AFPrintf(&UserDat, sout, "\n");
      Pause();
      Clr(UserDat.Ansi_Flag);
      WriteLog(HAPPY_BIRTHDAY, RStruct.Name, Ext, "");
   }
}


#define ANSI_CHECK "[6n"

BOOL CheckANSI(BOOL tell)

{
   unsigned char c;

   ClearLine();

   AFPrintf(NULL,sout,ANSI_CHECK);

   if (!WaitForChar(Input(), 2000000))
   {
      ClearLine();
      return(FALSE);
   }

   c = ReadChar(10000);
   if (c == '')
   {
      c = ReadChar(10000);
      if (c != '[')
      {
         ClearLine();
         return(FALSE);
      }

      c = 0x9b;
   }


   if (c == 0x9b)
   {
      while((c = ReadChar(10000)))
      {
         if (c == 'R')
         {
            if (tell)
               AFPrintf(NULL,sout,SA[88]);

            ClearLine();
            return(TRUE);
         }

         if (c == ';')            continue;
         if (c < '0' || c > '9')  break;
      }
   }

   ClearLine();
   return(FALSE);
}


void Get_Computer_Type(char type, char *retstr)

{
   struct Computer_Type Ct;

   *retstr    =  0;
   Ct.Number = type;

   if (!GetStruct("DlgConfig:Port/ComputerTypes.bbs", (char *)&Ct, sizeof(struct Computer_Type), 1))
   ASPrintf(&UserDat,retstr,"%-23.23s",Ct.Name);

   return;
}


void _abort()

{
   CloseLibrary(DLGBase);
   exit(0);
}


void _CXBRK()

{
   long lock;
   char ramfile[80];

   if (!login)
   {
      RStruct.Name[0] = 0;
      if (TCheckCarrier(Ext))
      WriteLog(NORMAL_LOGOUT, RStruct.Name, Ext, "Door");
      else
      WriteLog(LOST_CARRIER,  RStruct.Name, Ext, "Door");

      ASPrintf(NULL, ramfile, "T:%s.User", Ext);
      while((lock = Lock(ramfile,ACCESS_READ)) != 0)
      {
         UnLock(lock);
         if (DeleteFile(ramfile))  break;
      }
   }
   else
   LogOut(&RStruct,&UserDat,Ext,"Door");

   CloseLibrary(DLGBase);
   exit(0);
}
