#include "bbs.h"
#include <dos/dostags.h>
#include <workbench/workbench.h>
#include <clib/icon_protos.h>
char Xprlib[100];
char prototitle[100];
char XprOpts[200];
extern UBYTE serin[];
int StartProcess(char *s,ULONG Stack);
/*extern struct Commands *Cmds;
extern struct User User;
extern char MAINMENU_Li[];
*/
int Async;
#define STRNULL ""
int notvaliddoor=0;
int UpperCheck(char str1[],char str2[]);
int CheckInUse(char *str);
void RemoveEnvDoor(char *str);
void DoorLog(char Type,char *str);
int ErrorDoorInUse;
int DOORTYPE;
int DoorAccessHigher;
char DoorPassWord[20];
UBYTE ServerCommand[255];
ULONG DoorStack=4096L;   
void UnLockDoor(BPTR *DoorLock);  
char *LookUp(char str[],char File[],int Private,BPTR *LockDoor);                      
int PassParams=0;
int CustomCommand(char Location[],char CustomCmd[],int Private)
{
   FILE *fi;
   register int i=0;
   int stat;
   char str[200];
   char RunIt[200];
   char TempCmd[200];
BPTR LockDoor=NULL;
   notvaliddoor=0;
   ErrorDoorInUse=0;
   DoorAccessHigher=FALSE;
    strlim(ServerCommand,CustomCmd,195);StripReturn(ServerCommand);
   strcpy(RunIt,Location);
   strlim(TempCmd,CustomCmd,195);
   while(TempCmd[i]!='\0')
   {
      if(TempCmd[i]==' ') { TempCmd[i]='\0'; break; }
      i++;
   }
 
   strcpy(str,LookUp(TempCmd,RunIt,Private,&LockDoor));
   PurgeLine();
   StripReturn(str);
   if(*(str)!='\0' && Cmds->AcLvl[LVL_NODE_NUMBER]<10 && !notvaliddoor && !ErrorDoorInUse)
   {
       if(DOORTYPE!='G' )
       {

        if((fi=fopen(str,"r"))==NULL) 
        {
           
            AEPutStr("Error, can't locate Custom Command\n\r");
            AEPutStr("or Command is in use\n\r");
            UnLockDoor(&LockDoor);
            return(0);
        } fclose(fi);
       }
       else { 
          if(DoorPassWord[0]!='\0')
        {
           AEPutStr("\r\n");
           AEPutStr("Enter Password >: ");
           strcpy(TempCmd,"");
           stat=LineInputConverted("",TempCmd,15,KEYBOARD_TIMEOUT);
           if(stat<0) {   UnLockDoor(&LockDoor); return(2); }
           stat=StringCompare(TempCmd,DoorPassWord);
           if(strcmp(TempCmd,DoorPassWord))
           {
             AEPutStr("\r\nInValid Password!\r\n\r\n"); UnLockDoor(&LockDoor); return(1); 
             
           }
           else AEPutStr("\r\n");
        }
        if(PassParams)
        { sprintf(MAINMENU_Li,"%s%s",str,&ServerCommand[i]); return(PassParams); }
        strcpy(MAINMENU_Li,str); return(2); 
      }
        SetEnvStat(ENV_DOORS);
        switch(DOORTYPE)
        {
          case 'I': sprintf(RunIt,"%s %d",str,Cmds->AcLvl[LVL_NODE_NUMBER]);
                    break;
          case 'P': sprintf(RunIt,"%sUtils/PARADOOR %s %d",Cmds->BBSLoc,str,Cmds->AcLvl[LVL_NODE_NUMBER]);
                    break;
          case 'R': sprintf(RunIt,"%sUtils/REXXDOOR %d %s",Cmds->BBSLoc,Cmds->AcLvl[LVL_NODE_NUMBER],str);
                    break;
          case 'W': sprintf(RunIt,"%sUtils/REXXEXEC %d %d",Cmds->BBSLoc,Cmds->AcLvl[LVL_NODE_NUMBER],str);
                    break;
          case 'L': sprintf(RunIt,"%s %d",str,Cmds->AcLvl[LVL_NODE_NUMBER]);
                    break;
          default:  sprintf(RunIt,"%s %d",str,Cmds->AcLvl[LVL_NODE_NUMBER]);
                    break;
        }
        if(DOORTYPE=='R') DOORTYPE='X';
        
        DoorLog(DOORTYPE,TempCmd);
        if(DoorPassWord[0]!='\0')
        {
           AEPutStr("\r\n");
           AEPutStr("Enter Password >: ");
           strcpy(TempCmd,"");
           stat=LineInputConverted("",TempCmd,15,KEYBOARD_TIMEOUT);
           if(stat<0) {   UnLockDoor(&LockDoor); return(2); }
           stat=StringCompare(TempCmd,DoorPassWord);
           if(strcmp(TempCmd,DoorPassWord))
           {
             AEPutStr("\r\nInValid Password!\r\n\r\n"); UnLockDoor(&LockDoor); return(1); 
             
           }
           else AEPutStr("\r\n");
        } 
        if(!StartProcess(RunIt,DoorStack))
        { AEPutStr("Error Loading Module\r\n\r\n"); UnLockDoor(&LockDoor);return(1); } 
        if(DOORTYPE=='I' || DOORTYPE=='L')
        { 
          DoorLog(DOORTYPE,STRNULL);UnLockDoor(&LockDoor);return(1);
        }
        if(Control(Cmds->AcLvl[LVL_NODE_NUMBER],DOORTYPE,Private))
        { 
          DoorLog(DOORTYPE,STRNULL);
          UnLockDoor(&LockDoor);
          //PurgeLine();
          return(2);
        } 
        else 
        { 
          DoorLog(DOORTYPE,STRNULL);
          UnLockDoor(&LockDoor);
          return(1); 
        }
   }
   if(ErrorDoorInUse) 
   { 
     sprintf(TempCmd,"%sUserInDoor",Cmds->BBSLoc);
     if(!ChecktoDisplay(TempCmd,RunIt,1,0))
	{
       AEPutStr("This Door is in use at this time\r\n");
	}
     return(1);
   }
   if(notvaliddoor)
   {                 
      if(!Private)
      {
        if(DoorAccessHigher)
        AEPutStr("\r\nCommand requires higher access.\r\n\r\n");
        else
        AEPutStr("\r\nNo such command!!  Use '?' for command list.\r\n\r\n");
      }
      UnLockDoor(&LockDoor);
      return(1);
   }
   return(0);
}

char *LookUp(char str[],char File[],int Private,BPTR *LockDoor)
{
   register int i;
   struct DiskObject *dobj;
   char BBSCMD[400];
   char ReturnStr[400];
   char temp[200];
  char another[200];
   char *s;
   char **oldtooltypes;
   char LineType;
   int length;
   int Access=255;
   Async=TRUE;
   sprintf(BBSCMD,"%s%s",File,str);
   i=strlen(str);
   length=strlen(File)-1;
   i+=length;
   strcpy(ReturnStr,"");
   PassParams=FALSE;
   while(i>length)
   {
     if(dobj=GetDiskObject(BBSCMD))
     {
        oldtooltypes=dobj->do_ToolTypes;
        strcpy(ReturnStr,BBSCMD);
        if(s=FindToolType(oldtooltypes,"LOCATION"))
        {
           strcpy(ReturnStr,s); 
        }
        LineType='M';
        if(s=FindToolType(oldtooltypes,"MULTINODE"))
        {
          if(MatchToolValue(s,"YES"))
          {
             LineType='M';
          }
          else LineType='S';
        }
        if(s=FindToolType(oldtooltypes,"ACCESS"))
        {
           strcpy(temp,s); Access=atoi(temp);
        }
        DOORTYPE='I';
        if(s=FindToolType(oldtooltypes,"TYPE"))
        {
           if(MatchToolValue(s,"XIM")) DOORTYPE='X';
           if(MatchToolValue(s,"AIM")) DOORTYPE='R';
           if(MatchToolValue(s,"IIM")) DOORTYPE='I';
           if(MatchToolValue(s,"TIM")) DOORTYPE='P';
           if(MatchToolValue(s,"AEM")) DOORTYPE='W';
           if(MatchToolValue(s,"SIM")) { Async=FALSE;DOORTYPE='L'; } 
             
        }
        strcpy(DoorPassWord,"");
        if(s=FindToolType(oldtooltypes,"PASSWORD"))
        {
           strcpy(DoorPassWord,s); 
        }
        if(s=FindToolType(oldtooltypes,"PASS_PARAMETERS")) 
           PassParams=atoi(s);
         if(s=FindToolType(oldtooltypes,"INTERNAL"))
              {
                strcpy(ReturnStr,s);  DOORTYPE='G';strupr(ReturnStr);
                FreeDiskObject(dobj); notvaliddoor=0; ErrorDoorInUse=0;
                 return(ReturnStr);
              }
        DoorStack=4096L;
        if(s=FindToolType(oldtooltypes,"STACK"))
        {
           strcpy(temp,s); DoorStack=atol(temp);
        }
        
        if(LineType=='S')
        {
          sprintf(another,"%s.lock",ReturnStr);
        if(!(*(LockDoor)=Lock(another,ACCESS_WRITE))) ErrorDoorInUse=1;
        }
        if(User.Sec_Status<Access) DoorAccessHigher=TRUE;
        if((User.Sec_Status>=Access || Private) && Access!=0 && ErrorDoorInUse==0)
        {
          FreeDiskObject(dobj);
          return(ReturnStr);
        }else notvaliddoor=1;
      if(!ErrorDoorInUse && LineType=='S') UnLockDoor(LockDoor);
        FreeDiskObject(dobj); break;
    }
    BBSCMD[i]='\0';
    i--; if(Private) break;
  }
  if(notvaliddoor) strcpy(MAINMENU_Li,"");
  return("");
}
int UpperCheck(char str1[],char str2[])
{
   strupr(str1);
   strupr(str2);
   if(*(str2)=='*')
   {
      if(!strcmp(str1,str2+1)) return(1);
      if(!strnicmp(str1,str2+1,strlen(str2+1))) 
      { strcpy(MAINMENU_Li,""); return(0); }
   }
   
   if(!strcmp(str1,str2))
       return(1);
   return(0);
}

void UnLockDoor(BPTR *DoorLock)
{
  if(*(DoorLock)!=NULL) UnLock(*(DoorLock));
  *(DoorLock)=NULL;
}
int CheckInUse(char *str)
{
   FILE *fi;
   
   char TestIt[200];
   sprintf(TestIt,"T:%s",str);
   StripReturn(TestIt);
   strupr(TestIt);
   fi=fopen(TestIt,"r");
   if(fi==NULL)
   {
     fi=fopen(TestIt,"w");
     fclose(fi);
     ErrorDoorInUse=0; return(0);
   }
   fclose(fi);
   return(1);
}

void RemoveEnvDoor(char *str)
{
   char TestIt[200];
   sprintf(TestIt,"T:%s",str);
   StripReturn(TestIt);
   DeleteFile(TestIt);
}
void DoorLog(char Type,char *str)
{

  FILE *fi;
  long TSys;
  char string[200];
  char str1[200];
  if(!Sopt->Toggles[2]) return;
                  TSys=time(NULL);
  sprintf(str1,"%s",ctime(&TSys));
  str1[strlen(str1)-1]='\0';
  if(str[0]!=NULL)
  sprintf(string,"[%-25.25s] %s - %c - %-10.10s\n",str1,User.Name,Type,str);
  else
  sprintf(string,"[%-25.25s] %s - %c - Exiting\n",str1,User.Name,Type);

  sprintf(str1,"%sNode%d/DoorLog",Cmds->BBSLoc,Cmds->AcLvl[LVL_NODE_NUMBER]);
  fi=fopen(str1,"a");
  fprintf(fi,"%s",string);
  fclose(fi);

}

struct TagItem tags[]={ {SYS_Input,0},{SYS_Output,0},{SYS_Asynch,TRUE},{NP_StackSize,0},{NP_Priority,0},{TAG_DONE,0}};

int StartProcess(char *s,ULONG Stack)
{
    int temp;
    tags[3].ti_Data=Stack;
    if(Async) tags[2].ti_Data=TRUE; else tags[2].ti_Data=FALSE;
    temp=SystemTagList(s,tags);
    if(temp==-1)
    {
      return(0);
    }
    return(1);
}

ULONG protocol;
ULONG xprinit;
ULONG ReceivePath;
ULONG SendPath;
UBYTE sendopt;
UBYTE myxprunit;
ULONG myxprdevice;
UBYTE BatchXfer;
extern void xprsequence(void);
void XPRSend(char *filename)
{ 
  ULONG time1;
  ULONG time2;
  sendopt=1;
  
  protocol=(ULONG)&Xprlib[0];
  xprinit=(ULONG)&XprOpts[0];
  SendPath=(ULONG)filename;
  myxprdevice=(ULONG)Cmds->SerDev;
  myxprunit=Cmds->SerDevUnit;
  time1=time(NULL);
  xprsequence();
  time2=time(NULL);
  TTTM=time2-time1;
 TTEFF=(((TBT/TTTM)*100L)/(Online_Baud/10L));
  //if(Online_NFiles!=0) Online_NFiles /=2;
 Delay(50L);
	    AbortIO(ReadSerReq);
	    WaitIO(ReadSerReq);
   ReadSerReq->IOSer.io_Command = CMD_READ;
	    ReadSerReq->IOSer.io_Data    = (APTR)&serin[0];
	    ReadSerReq->IOSer.io_Length  = 1L;
	    SendIO(ReadSerReq);

}
void XPRReceive(char *filename)
{ 
  char temp[200];
  ULONG time1;
  ULONG time2;
  sprintf(temp," %s",filename);
  protocol=(ULONG)&Xprlib[0];
  xprinit=(ULONG)&XprOpts[0];
  ReceivePath=(ULONG)&temp[0];
  myxprdevice=(ULONG)Cmds->SerDev;
  myxprunit=Cmds->SerDevUnit;
  sendopt=0;
  time1=time(NULL);
  xprsequence();
  time2=time(NULL);
  TTTM=time2-time1;
	  
 Delay(50L);
	    AbortIO(ReadSerReq);
	    WaitIO(ReadSerReq);
   ReadSerReq->IOSer.io_Command = CMD_READ;
	    ReadSerReq->IOSer.io_Data    = (APTR)&serin[0];
	    ReadSerReq->IOSer.io_Length  = 1L;
	    SendIO(ReadSerReq);

  ReceivePlayPen();
 
  TTEFF=(((TBT/TTTM)*100L)/(Online_Baud/10L));
	  
}

void GetProtocol(void)
{
  char string[100];
  register int i;
  strcpy(Xprlib,"INTERNAL"); strcpy(prototitle,"Internal Zmodem");
  if(GET_BIT(ACS_XPR_SEND) || GET_BIT(ACS_XPR_RECEIVE))
  {
    sprintf(GSTR1,"%sProtocols/XprTypes",Cmds->BBSLoc);
    sprintf(GSTR2,"TITLE.%d",User.XferProtocol+1);
    GetFromIconStr(GSTR1,GSTR2,prototitle);
    sprintf(GSTR2,"LIBRARY.%d",User.XferProtocol+1);
    GetFromIconStr(GSTR1,GSTR2,Xprlib);
    strcpy(XprOpts,"TN,AY,OR,KY,SN,RN,DN,F0,B32");
  if(strcmp(Xprlib,"INTERNAL"))
  {
    strcpy(string,Xprlib);
    i=strlen(string)-1;
    while(string[i]!='\0' && string[i]!='.') { string[i]='\0'; i--; }
    if(i>0) string[i]='\0';
    sprintf(GSTR1,"%sProtocols/%s",Cmds->BBSLoc,string);
    GetFromIconStr(GSTR1,"OPTIONS",XprOpts);
    if(IsFromIcon(GSTR1,"AE_BATCH")) BatchXfer=TRUE; else BatchXfer=FALSE;
  }
  }
}

void ClearProtocol(void)
{
   User.XferProtocol=0;
     strcpy(Xprlib,"INTERNAL"); strcpy(prototitle,"Internal Zmodem");
}