//                                  MESSAGE ARCHIVER MODULE
//**********************
//*****  Includes  *****
//**********************
#include <proto/all.h>
#include <stdio.h>
#include <time.h>
#include <exec/memory.h>
#include <stdarg.h>
#include <string.h>
#include <tempest/headers.h>
#include <Tempest/defines.h>

int  DoorStart(TEXT *);
int  DOORIO(WORD);
VOID CloseStuff(VOID);
VOID Activity(BYTE,TEXT *);
int  CheckKey(VOID);
VOID GetPaths(TEXT *,int);
VOID GetStr(TEXT *,int);
int  GetValue(int);
int  hotkey(TEXT *);
VOID input(TEXT *,int);
VOID LineInput(TEXT *,TEXT *,int);
VOID pl(TEXT *,...);
VOID ZmodemDownload(TEXT *);
char *Myctime(long *secs);
ULONG FileSize(TEXT *Source);
int  DumpFile(char filename[]);
int  GetMessages();
VOID ListAreas(VOID);
int  Pause(VOID);
VOID CopyFile(TEXT *Source,TEXT *Destination);
void RIPIT(char *path,char *fname);
VOID HELP(VOID);
VOID Edit_By_Number(int temp);
VOID Settings(VOID);
VOID CR(VOID);
VOID AbortCheck(VOID);
int Age(int Month,int Day,int Year);
long Mytime(void);
VOID HydraDownload(TEXT *mstring);
VOID Open_Read(BYTE Type,int Area);
VOID StripAnsi(TEXT *text);

//********************************
//*****  Structures/Defines  *****
//********************************

 struct MyMessage
  {
   struct Message Msg; // for Exec message routines
   ULONG  Command;     // Command to be executed.

   TEXT   *text1,
          *text2,
          *text3;
   int    Value1,
          Value2;
   ULONG  LongValue;
   LONGBITS Flags;
   int    carrier;
   struct User       *User;
   struct SystemData *SystemData;
   struct NodeData   *NodeData;
   struct Today      *Today;
  };

struct MyMessage send;

struct Config
{
 BYTE Arc[40],             // arc this dir, default
      Compression,         // 0:None, 1:Lzh, 2:lzx, 3:zip
      Strip;               // ^M filter
} Config;

struct LettersPointer INDEX[40];
struct NodeData *NodeData;
struct Letters Letters;
struct MsgPort *MyPort = NULL;
struct Msg_Area MSG[40];
struct MyMessage *msg;
struct User *User;
struct SystemData *SystemData;
struct NodeData *NodeData;
struct Today *Today;
//**********************************************************************
#define NO_SECRET       0
#define SECRET          1
//**********************************************************************
struct MsgPort *TempestPort;
char OutPut[200];
char OutPut2[200];
char systemname[40];
FILE *out;
int  archive[40];          /* start reading at this number   */
BYTE GlobalAbort=0;
int  NODE;
int  START;

//**********************************************************************
char FifoIn[255];
char FifoOut[255];
char WrkFile[255];
//**********************************************************************

///******************
///*****  Main  *****
///******************

int main(int argc,char *argv[])
{
 int  END,temp,x,y,H_ANSI;
 char s[200];
 if(!DoorStart(argv[1])) { PutStr("TempesT Door\n"); exit(0); }

 if(!(User->NFlags2 & NF2_ArchiveMessages))
  {
   pl("\r\n[31mAccess Denied![0m\r\n");
   CloseStuff();
  }

 SetTaskPri(FindTask(0),SystemData->DoorsPriority);
 Activity(9,"");
 NODE = atoi(argv[1]);
 LoadData();

 START = 0;
 for(x=0;x<40;x++) Config.Arc[x]=0;   // Default for areas to be arced
 Config.Compression = 0;              // No compression
 Config.Strip       = 1;              // No ^M
 for(x=0;x<40;x++)
  {
   archive[x] = INDEX[x].FirstNumber;
   Config.Arc[x]=0;
  }

 MENU:

 END=0;
 y=0;

 pl("\f[44;37mMessage Archiver Module v3.50, Selected Areas[0m:\r\n\r\n");

 pl("[36mArea[34m|[36mName of Message Area      [34m| [36mStart [34m| [36mLast  [34m| [36mLast Read  [34m|[36mStart At[34m|\r\n");
 pl("[34m====|==========================|=======|=======|============|========|\r\n");
 for(x=1;x<40;x++)
  {
   if(MSGACCESS(x))
    {
     if(Config.Arc[x]==1)
      {
       pl("[33m%4d[34m|[36m%-25s [34m| [32m%5d [34m| [32m%5d [34m| [33m%7d    [34m|[33m %5d  [34m|\r\n",
           x,MSG[x].Name,INDEX[x].FirstNumber,INDEX[x].LastNumber,User->Last_Read_Message[x],archive[x]);
       END++;
       y++;
       if(END>User->Length+4) { Pause(); END=0; }
      }
    }
  }
 if(y==0) pl("[31mNo Msg Areas Selected Yet.\r\n");
 pl("[34m======================================================================\r\n");
 pl("[34m[[35mQ[34m][36muit, [34m[[35mL[34m][36mist Areas, [34m[[35mA[34m][36mll, [34m[[35mN[34m][36mone, [34m[[35mS[34m][36mtart, [34m[[35mH[34m][36melp, [34m[[35m0-39[34m][0m: ");
 input(s,5);
 s[0]=toupper(s[0]);
 switch(s[0])
  {
   case 'Q': pl("[0m\r\n\r\n");
             goto ALLDone;
   case 'S': Settings();
             ArchiveMsg();
             goto MENU;
   case 'L': ListAreas();
             Pause();
             goto MENU;
   case 'H': HELP();
             goto MENU;
   case 'A': for(x=1;x<40;x++)
              {
               if(MSGACCESS(x))
                {
                 archive[x] = INDEX[x].FirstNumber;
                 Config.Arc[x]=1;
                }
              }
             goto MENU;
   case 'N': for(x=0;x<40;x++) Config.Arc[x]=0;
             goto MENU;
  }
 temp = atoi(s);
 if(temp==0) goto MENU;
 if((temp<1)||(temp>39)) goto MENU;
 if(!MSGACCESS(temp)) goto MENU;

 Edit_By_Number(temp);

 goto MENU;

 ALLDone:
 CloseStuff();
}

//============================================================================
VOID HELP(VOID)
{
 pl("\r\n[36mSimply select the msg area numbers you wish to archive.\r\n\r\n");

 pl("[34m[[35mStart[34m].......[36mThe First Message # in that Area.\r\n");
 pl("[34m[[35mLast[34m]........[36mThe Last Message # in that Area.\r\n");
 pl("[34m[[35mLast Read[34m]...[36mThe Last Message you have Read.\r\n");
 pl("[34m[[35mStart At[34m]....[36mStart Archiving Messages at #.\r\n");

 pl("\r\n[44;37mList of Commands[0m:\r\n\r\n");

 pl("[34m[[35mL[34m]...[36mThis will list all msg areas you can select from.\r\n");
 pl("[34m[[35mS[34m]...[36mStart archiving after you are done selecting areas.\r\n");
 pl("[34m[[35mA[34m]...[36mSelect all msg areas for archiving.\r\n");
 pl("[34m[[35mN[34m]...[36mUn-Select all msg areas for archiving.\r\n");
 pl("[34m[[35mQ[34m]...[36mQuit Msg Archiver Module and return to the BBS.\r\n");
 pl("[34m[[35mH[34m]...[36mBrings up this help text.\r\n");
 Pause();
}
//************************
//*****  List Areas  *****
//************************

VOID ListAreas(VOID)
{
 char string[70];
 int x,END=0;
 pl("\f[36mArea[34m|[36mName of Message Area      [34m| [36mStart [34m|  [36mLast [34m| [36mLast Read  [34m|[36mStart At[34m|[36mArchive\r\n");
 pl("[34m====|==========================|=======|=======|============|========|========\r\n");

 for(x=1;x<40;x++)
  {
   if(MSGACCESS(x))
    {
     if(Config.Arc[x]==1) strcpy(string,"Yes");
     else                 strcpy(string,"No");
     pl("[33m%4d[34m|[36m%-25s [34m| [32m%5d [34m| [32m%5d [34m| [33m%7d    [34m|[33m %5d  [34m| %s\r\n",
         x,MSG[x].Name,INDEX[x].FirstNumber,INDEX[x].LastNumber,User->Last_Read_Message[x],archive[x],string);
     if(END>User->Length+4)
      {
       END=0;
       Pause();
      }
      END++;
    }
  }
 pl("[34m===============================================================================\r\n");
}
//============================================================================
VOID Edit_By_Number(int temp)
{
 char str[20];
 if(Config.Arc[temp]==0) Config.Arc[temp]=1;
 else                    Config.Arc[temp]=0;
 pl("\r\nNew Starting Message: ");
 archive[temp] = NumberInput();
 if(archive[temp] > INDEX[temp].LastNumber) archive[temp]=INDEX[temp].LastNumber;
}
//============================================================================
int MSGACCESS(int slot)
{
 if(strlen(MSG[slot].Name)==0) return (0);
 if(User->MsgBase[slot]=='N') return (0);
 if (MSG[slot].ON==0) return (0);
 if(islower(User->MsgBase[slot])!=0) return (0); // If THEY turned it off!
 return(1);
}
//============================================================================
int LoadData(void)
{
 int fd,x,stat;
 char s[200],s1[255];
 GetPaths(s1,0);
 sprintf(s,"%ssetup/MESSAGES.data",s1);
 fd=Open(s,MODE_OLDFILE);
 if(fd==0) return(-1);
 x=0;
 do
  {
   stat=Read(fd,(char *)&MSG[x],sizeof(struct Msg_Area));
   if(stat<=0)
    {
     Close(fd);
     return(-1);
    }
   x++;
  }
 while(x<40);
 Close(fd);
 x=0;
 do
  {
   sprintf(s,"%sMsgArea_%d.Point",MSG[x].Path,x);
   fd=Open(s,MODE_OLDFILE);
   if(fd==0)
    {
     x++;
     continue;
    }
   stat=Read(fd,(char *)&INDEX[x],sizeof(struct LettersPointer));
   if(stat<=0)
    {
     Close(fd);
     return(-1);
    }
   x++;
  }
 while(x<40);
 Close(fd);
 return(1);
}
//============================================================================
int NumberInput(void)
{
 int answer;
 char str[80];
 str[0]='\0';
 LineInput(str,str,5);
 answer=atoi(str);
 return(answer);
}
//============================================================================
VOID Settings(VOID)
{
 int x;
 pl("\r\n\r\n");

 strip:
 pl("[0m([34m[[32m1[34m] [35m= [36mAmiga Text [35m- [34m[[32m2[34m] [35m= [36mIBM Text[0m) [32mSelect[0m: ");
 x=NumberInput();
 if(x<1 || x>2) goto strip;
 Config.Strip = x;
}
//============================================================================
int ArchiveMsg(void)
{
 int   Area,x,stat;
 long  BytesRAW,BytesARCH;
 char  s[120],s2[120],s3[70];
 GetStr(s,18);
 strcpy(systemname,s);
 systemname[4]=NULL;
 for(x=0;x<strlen(systemname);++x)
  {
   switch(systemname[x])
    {
     case ' ':
     case '/':
     case '\\':
     case ':':
     case '?':
     case '*': s[x]='_'; break;
     default:  s[x]=systemname[x];
    }
  }
 s[x]='\0';
 strcpy(systemname,s);
 sprintf(OutPut,"%sTemporary%d/%s_M%d.cap",SystemData->UploadPath,NODE,systemname,NODE);
 sprintf(OutPut2,"%sTemporary%d/%s_M%d",SystemData->UploadPath,NODE,systemname,NODE);
 DeleteFile(OutPut);
 out=fopen(OutPut,"w");
 if(out==NULL)
  {
   pl("[31mCan't write output file [%s]!!![0m\r\n",OutPut);
   Pause();
   return (0);
  }
 for(Area=0;Area<40;Area++)
  {
   if(Config.Arc[Area]==0) continue;
   sprintf(s,"[33mReading, message area #%d [34m:[0m ",Area);
   AbortCheck();
   if(GlobalAbort>0) break;
   pl(s);
   NextArea(Area);
   Open_Read(0,Area);
  }
 // PMail Question.

 pl("\r\n[36mInclude your Personal Mail in archive (y/n)[0m: ");
 input(s,1);
 if((s[0]=='Y')||(s[0]=='y'))
  {
   NextArea(-1);
   Open_Read(1,0);
  }
 fclose(out);
 if(GlobalAbort>0)
  {
   DeleteFile(OutPut);
   return(0);
  }
 BytesRAW = FileSize(OutPut);
 pl("\r\n[35mUncompressed file will be %ld Bytes. Proceed [Y/n][0m: ",BytesRAW);
 input(s,1);
 if((s[0]=='N')||(s[0]=='n')) return(0);

 comp:
 pl("[32m\r\n[36mCompression Method [0m[[35m0:No Compression, 1:LHA, 2:LZX, 3:ZIP[0m]: ");
 x=NumberInput();
 if(x!=0)
  {
   switch(x)
    {
     case 1:  strcpy(s,"C:LHA"); break;
     case 2:  strcpy(s,"C:LZX"); break;
     case 3:  strcpy(s,"C:ZIP"); break;
     default: goto comp;
    }
   if(access(s,0)!=0)
    {
     pl("[31m\r\nSorry, not currently supported![0m\r\n");
     goto comp;
    }
  }
 Config.Compression = x;
 if(Config.Compression!=0)
  {
   sprintf(FifoIn,"fifo:ARC_Port_%d/wkme",NODE);
   sprintf(FifoOut,"fifo:ARC_Port_%d/r",NODE);
   sprintf(WrkFile,"ram:TestFile-%d",NODE);
   pl("\r\n[35m");
   switch(Config.Compression)
    {
     case 1: pl("LHA");
             sprintf(s,"run >NIL: c:LHA >%s -D a %sTemporary%d/%s_M%d.lha %s",FifoIn,SystemData->UploadPath,NODE,systemname,NODE,OutPut);
             strcat(OutPut2,".lha");
             break;
     case 2: pl("LZX");
             sprintf(s,"run >NIL: c:LZX >%s a -3 %sTemporary%d/%s_M%d.lzx %s",FifoIn,SystemData->UploadPath,NODE,systemname,NODE,OutPut);
             strcat(OutPut2,".lzx");
             break;
     case 3: pl("ZIP");
             sprintf(s,"run >NIL: c:ZIP >%s -9j %sTemporary%d/%s_M%d.zip %s",FifoIn,SystemData->UploadPath,NODE,systemname,NODE,OutPut);
             strcat(OutPut2,".zip");
             break;
    }
   pl("'ing file, please wait...[0m\r\n[36m");
   DeleteFile(OutPut2);
   Execute(s,0L,0L);
   DumpFile(FifoOut);
   pl("[0m");
   BytesARCH = FileSize(OutPut2);
   pl("\r\n[36mCompressed file will be %ld Bytes. Proceed [Y/n]: ",BytesARCH);
   input(s,1);
   if((s[0]=='N')||(s[0]=='n'))
    {
     DeleteFile(OutPut);
     DeleteFile(OutPut2);
     return(0);
    }
  }
 else strcpy(OutPut2,OutPut);

 again:
 if(GetValue(2)==1)
  {
   pl("\r\n[36mEnter Path to copy file to[0m: ");
   input(s,30);
   if((s[strlen(s)-1]!=':')&&(s[strlen(s)-1]!='/'))
       strcat(s,"/");
   strcpy(s2,OutPut2);
   RIPIT(s2,s3);
   sprintf(s2,"%s%s",s,s3);
   CopyFile(OutPut2,s2);
   s[0]='Y';
  }
 else
  {
   pl("\r\n[36mSelect Protocol (1:Zmodem, 2:Hydra)[0m: ");
   input(s,1);
   stat=atoi(s);
   switch(stat)
    {
     case 2:  HydraDownload(OutPut2); break;
     default: ZmodemDownload(OutPut2);
    }

   nope:
   pl("\r\n\r\n[36mDid you get the whole download [0m([35mY/N[0m)[0m: ");
   input(s,1);
   s[0]=toupper(s[0]);
   if(s[0]=='N')
    {
     pl("[36m\r\n(As of now, no changes have been made to your account!)\r\n");
     pl("\r\n [T]ry again, or [A]bort? [T/a]: ");
     input(s,1);
     if(s[0]=='T'||s[0]=='t') goto again;
     else                     s[0]='Y';
    }
  }
 if(s[0]=='Y')
  {
   DeleteFile(OutPut);
   DeleteFile(OutPut2);
  }
 else goto nope;

 update:
 pl("[36m\r\n[36mUpdate Last Read Message Counter (Y/N)[0m: ");
 input(s,1);
 s[0]=toupper(s[0]);
 if(s[0]=='Y') Update();
}
//============================================================================
VOID CR(VOID)
{
 if(Config.Strip==2) fprintf(out,"\r\n");
 else                fprintf(out,"\n");
}

//============================================================================
Update(void)
{
 int x;
 for(x=0;x<40;x++)
  {
   if(Config.Arc[x]==1) User->Last_Read_Message[x]=INDEX[x].LastNumber;
  }
 return (0);
}

//============================================================================
NextArea(Area)
int Area;
{
 char shit1[130];
 strcpy(shit1,"-----------------------------------------------------------------------");
 CR();
 fprintf(out,".%s.",shit1);  CR();
 if(Area!=-1)
      { fprintf(out,"|          Now Archiving Msg Area :  %-30.30s     |",MSG[Area].Name); CR(); }
 else { fprintf(out,"|          Now Archiving Your Personal Mail                             |"); CR(); }
 fprintf(out,"`%s'",shit1); CR(); CR();
 return(0);
}

//============================================================================
VOID Open_Read(BYTE Type,int Area)
{
 char string[200];
 int in,y;
 if(Type==0) sprintf(string,"%sMsgArea_%d.data",MSG[Area].Path,Area);
 else        sprintf(string,"%sPMail/%d/PM.data",SystemData->AccountInfoPath,User->Slot_Number);
 in=Open(string,MODE_OLDFILE);
 if(in!=0)
  {
   if(Type==0) pl("\f\r\n[35mReading Msg Area [33m%4d[0m:       /[34m [36m%d",Area,INDEX[Area].LastNumber);
   else        pl("\f\r\n[35mReading Your P-Mail  [0m:       /[34m [36m----");
   while(Read(in,(char *)&Letters,sizeof(struct Letters))==sizeof(struct Letters))
    {
     AbortCheck();
     if(GlobalAbort>0) goto QUIT;
     if(Letters.Number!=0)
      {
       if((Type==1)||(Security(Area)))
        {
         if(Letters.Password[0]!=NULL)
          {
           fprintf(out,"Msg #%d, is Password Protected, skipping letter.");
           CR();
          }
         else
          {
           PrintHeader();
           if(Letters.Type!=3) sprintf(string,"%sMsg_%d.%d",MSG[Area].Path,Area,Letters.NumberInArea);
           else                sprintf(string,"%sPMail/%d/PM.%d",SystemData->AccountInfoPath,User->Slot_Number,Letters.Number);
           PrintFile(string,OutPut,1);
          }
         pl("[2;24H%d",Letters.Number);
        }
      }
    }
   QUIT:
   Close(in);
   pl("\r\n[36mThis area is now completed.[0m\r\n\r\n");
  }
}

//============================================================================
int Security(Area)
{
 int stat;
 if(Letters.Flags1 & LET_ACTIVE) return(0);
 if(Letters.Password[0]!=NULL) return(0);
 switch(Letters.Type)
  {
   case 3: return(1); // Email
   case 0: return(1); // Public
   case 1: // Private
           if(stricmp(Letters.Receiver,User->Name)==0) return (1);
           if(stricmp(Letters.Sender,User->Name)==0)   return (1);
           break;
   case 2: // Mass Mail
           if((Letters.StateCode[0]!=NULL)&&(stricmp(User->State,Letters.StateCode)!=0)) return(0);
           if((Letters.CountryCode[0]!=NULL)&&(stricmp(User->Country,Letters.CountryCode)!=0)) return(0);
           if((Letters.MinAccessLev!=0)&&(Letters.MinAccessLev>User->Security)) return(0);
           if((Letters.MaxAccessLev!=0)&&(Letters.MaxAccessLev<User->Security)) return(0);  
           stat=Age(User->BirthDate_Month,User->BirthDate_Day,User->BirthDate_Year);
           if((Letters.MinAge!=0)&&(Letters.MinAge>stat)) return(0);
           if((Letters.MaxAge!=0)&&(Letters.MaxAge<stat)) return(0);
           return(1);
  }
 return(0);
}

//============================================================================
PrintFile(in_f,out_f,mode)
char in_f[],out_f[];
int mode;                    /* mode  0:new   1:append */
{
 FILE *in;
 char string[300];

 in=fopen(in_f,"r");
 if(in!=NULL)
  {
   while(fgets(string,254,in)!=NULL)
    {
     StripAnsi(string);
     string[strlen(string)-1]=NULL;
     fprintf(out,"%s",string); CR();
    }
  }
 else
  {
   fprintf(out,"Message body was not found!"); CR();
  }
 fclose(in);
 return (0);
}
//*****************
//*****  Age  *****
//*****************

int Age(int Month,int Day,int Year)
{
 char string1[60],string2[60],string3[60];
 int tomonth,today,toyear,age;
 long ttime;
 ttime=Mytime();
 strcpy(string1,Myctime(&ttime));

 DateConvert(string1,string2,string3); // Date String
 string2[2]=' ';
 string2[5]=' ';
 sscanf(string2,"%d %d %d",&tomonth,&today,&toyear);
 age=toyear-Year;
 if(tomonth<Month) age--;
 else if((tomonth==Month)&&(today<Day)) age--;
 return(age);
}

//===========================* Beginning of Module *===========================
long Mytime(void) // DateStamp() - time() replacement!
{
 struct DateStamp now;
 long   secs;
 DateStamp(&now);
 secs  = (now.ds_Days * 86400);
 secs += (now.ds_Minute * 60);
 secs += (now.ds_Tick / 50);
 secs += 252460800L;
 return((long)secs);
}
//============================================================================
PrintHeader(void)
{
int  stat;
char Date[140],Temp[135],string1[120],string2[120];
long Global_TimeStorage;

 CR();
 fprintf(out,"[To       ] %-30s   ",Letters.Receiver);
 if(Letters.Rcvd==0L)
  {
   stat = stricmp(Letters.Receiver,"ALL");
   if(stat == 1) fprintf(out,"");
   else          fprintf(out,"[Not Delivered]");
  }
 else
  {
   Global_TimeStorage=Letters.Rcvd;
   sprintf(Date,"%s",Myctime(&Global_TimeStorage));
   fprintf(out,"[Delivered]",Date);
  }
 CR();
 if(Letters.Flags1 & LET_ANONYMOUS) strcpy(Temp,"Anonymous");
 else                               strcpy(Temp,Letters.Sender);

 fprintf(out,"[From     ] %-30s   ",Temp);
 fprintf(out,"[Msg# %d]",Letters.Number);
 CR();

 fprintf(out,"[Subject  ] %-30s   ",Letters.Subject);
 Global_TimeStorage=Letters.Sent;
 strcpy(Date,Myctime(&Global_TimeStorage));

 DateConvert(Date,string1,string2);

 fprintf(out,"[ mailed - %s @ %s]",string1,string2);
 CR();
 switch(Letters.Type)
  {
   case 0: strcpy(Date,"PUBLIC MESSAGE  "); break;
   case 1: strcpy(Date,"PRIVATE MESSAGE "); break;
   case 2: strcpy(Date,"MASSMAIL MESSAGE"); break;
   case 3: strcpy(Date,"E-MAIL MESSAGE");   break;
  }
 if(Letters.Password[0]!=NULL) strcpy(Date,"PASSWORD        ");
 fprintf(out,"[Read     ] %-3d                              ",Letters.Read);
 fprintf(out,"[%s]",Date);
 CR();
 fprintf(out,"[msg Area ] %-30s   ",MSG[Letters.Area].Name);
 if(Letters.ReplyFrom!=0) fprintf(out,"[Response to #%d]",Letters.ReplyFrom);
 CR();
 CR();
 return(0);
}
//============================================================================
DateConvert(InputString,DateString,TimeString)
char *InputString, *DateString, *TimeString;
{
 char *Months[]={ "Jan","Feb","Mar","Apr","May","Jun",
                  "Jul","Aug","Sep","Oct","Nov","Dec" };
 char day[5],month[5],year[5];
 register int x=0;

 strmid(InputString,TimeString,12,8);
 strmid(InputString,year,23,2);
 strmid(InputString,day,9,2);
 strmid(InputString,month,5,3);

 do
  {
   if(strcmp(month,Months[x]) == 0)
      break;
   x++;
  }
 while(x<12);
 x++;

 sprintf(DateString,"%2d/%2s/%2s",x,day,year);
 if(DateString[0]==' ') DateString[0]='0';
 return(0);
}
//============================================================================
VOID AbortCheck(VOID)
{
 int stat;
 char s[100];
 if(CheckKey()!=0)
  {
   pl("\r\n[31mAbort Key Hit, Do you wish to abort [0m[[35mY[0m/[36mn[0m] ");
   input(s,1);
   if((s[0]=='Y')||(s[0]=='y')) GlobalAbort=99;
  }
}
//============================================================================
int DumpFile(char filename[])
{
 char string[255];
 FILE *in;
 in=fopen(filename,"r");
 if(in!=NULL)
  {
   while(fgets(string,200,in)!=NULL)
    {
     string[strlen(string)-1]=NULL;
     pl("[36m%s\r\n",string);
    }
   fclose(in);
  }
 return(0);
}
//===========================* Beginning of Module *===========================
char *Myctime(long *secs)
{
 struct tm *tm;
 tm=gmtime(secs);
 return(asctime(tm));
}
//===========================* Beginning of Module *===========================
void RIPIT(char *path,char *fname)
{
 char string[250];
 strcpy(string,path);
 stcgfp(path,string);
 stcgfn(fname,string);
 if(path[strlen(path)-1]!=':') strcat(path,"/");
}




//************************
//*****  Door Start  ***** // MUST BE INCLUDED IN ALL DOORS!
//************************
int DoorStart(TEXT *node)
{
 char string[60];
 send.carrier=0;
 sprintf(string,"%s:TEMPEST_DOOR",node);
 TempestPort=FindPort(string);
 if(TempestPort==NULL) return(int)FALSE;
 MyPort=CreateMsgPort();
 if(MyPort==NULL) return(int)FALSE;
 DOORIO(0);
 User=*&send.User;
 SystemData=*&send.SystemData;
 NodeData=*&send.NodeData;
 Today=*&send.Today;
 return(int)TRUE;
}
//********************
//*****  DoorIO  ***** // MUST BE INCLUDED IN ALL DOORS!
//********************
int DOORIO(WORD Command)
{
 if(send.carrier) return(0);
 send.Command=Command;
 send.Msg.mn_Node.ln_Type = NT_MESSAGE;
 send.Msg.mn_Length = sizeof(send);
 send.Msg.mn_ReplyPort = MyPort;
 send.carrier=0;
 PutMsg((struct MsgPort *)TempestPort,(struct Message *)&send);
 Wait(1 << MyPort->mp_SigBit);
 GetMsg(MyPort);
 if((send.carrier)&&(send.Command!=999)) CloseStuff();
 return(1);
}
//*************************
//*****  Close Stuff  ***** // MUST BE INCLUDED IN ALL DOORS!
//*************************
VOID CloseStuff(VOID)
{
 DOORIO(999);
 while(msg=(struct MyMessage *)GetMsg(MyPort)) ReplyMsg((struct Message *)msg);
 if(MyPort) DeleteMsgPort(MyPort);
 exit(0);
}
//***********************
//*****  Check Key  ***** // Command 15
//***********************
int CheckKey(VOID)
{
 send.Value2=0;
 DOORIO(15);
 return(send.Value2);
}
//***********************
//*****  Get Paths  ***** // Command 30
//***********************
VOID GetPaths(TEXT *s,int opt)
{
 send.Value1=opt;
 strcpy(s,"");
 send.text1=s;
 DOORIO(30);
}
//*********************************
//*****  GetStr (Get String)  ***** // Command 33
//*********************************
VOID GetStr(TEXT *s,int opt)
{
 send.Value1=opt;
 strcpy(s,"");
 send.text1=s;
 DOORIO(33);
}
//***********************
//*****  Get Value  ***** // Command 34
//***********************
int GetValue(int opt)
{
 send.Value1=opt;
 DOORIO(34);
 return(send.Value2);
}
//*********************
//*****  Hot Key  ***** // Command 16
//*********************
int hotkey(TEXT *character)
{
 send.text1=character;
 DOORIO(16);
 return((int)character[0]);
}
//*******************
//*****  Input  ***** // Command 20
//*******************
VOID input(TEXT *mstring,int len)
{
 send.Value1=len;
 send.text1 =mstring;
 DOORIO(20);
}
//*******************
//*****  Pause  ***** // Command 71
//*******************
int Pause(VOID)
{
 DOORIO(71);
 return(send.Value1);
}
//************************
//*****  Line Input  ***** // Command 22
//************************
VOID LineInput(TEXT *ostring,TEXT *mstring,int len)
{
 send.Value1=len;
 send.text1=mstring;
 send.text2=ostring;
 DOORIO(22);
}
//*****************************
//*****  Zmodem Download  ***** // Command 52
//*****************************
VOID ZmodemDownload(TEXT *mstring)
{
 send.text1=mstring;
 DOORIO(52);
}
//****************************
//*****  Hydra Download  ***** // Command 54
//****************************
VOID HydraDownload(TEXT *mstring)
{
 send.text1=mstring;
 DOORIO(54);
}
//**********************
//*****  Activity  ***** // Command 44
//**********************
VOID Activity(BYTE act,TEXT *s)
{
 send.Value1=act;
 send.text1=s;
 DOORIO(44);
}
//*****************************
//*****  PL (Print Line)  ***** // Command 1 with a twist
//*****************************
VOID pl(TEXT *fmt,...)
{
 va_list args;
 TEXT s[255];
 va_start(args,fmt);
 vsprintf(s,fmt,args);
 va_end(args);
 send.text1=&s[0];
 DOORIO(1);
}
//===========================* Beginning of Module *===========================
VOID CopyFile(TEXT *Source,TEXT *Destination)
{
 send.text1=Source;
 send.text2=Destination;
 DOORIO(76);
}
//***********************
//*****  File Size  ***** // Command 78
//***********************
ULONG FileSize(TEXT *Source)
{
 send.text1=Source;
 DOORIO(78);
 return(send.LongValue);
}
//***********************
//*****  StripAnsi  ***** // Command 80
//***********************
VOID StripAnsi(TEXT *text)
{
 send.text1=text;
 DOORIO(80);
}
