#include "zmiglobals.h"
#include "impprotos.h"

#include <link/io.h>

/* global variables */

char prob[20];

/****************************/

typedef int BOOLEAN;

typedef struct FileHandle FileHandle;


unsigned long *the_dup_table=NULL;
char last_dup_table[100];
BOOL last_dup_table_written;

/// read_dup_table
/* Load table from disk.  If unavailable, fill table with zeros. */
void read_dup_table(char *filename,unsigned long *buffer)
{
      BPTR fh;
      int i,length;
   char str[100];

   if( Stricmp(filename,last_dup_table) )
   {
      /* names didn't match, need to swap 'em out */

      if(*last_dup_table)
      {
         write_dup_table(last_dup_table,buffer,TRUE);
      }

      last_dup_table_written=TRUE;
      strcpy(last_dup_table,filename);

      ASPrintf(NULL,str,". Dupe Table: %s: ",filename);

      fh=Open(filename,MODE_OLDFILE);

      if(fh)
      {
         length=Read(fh,(void *)buffer,(TABLELENGTH+1)*sizeof(unsigned long));
         Close(fh);

         if(length == (TABLELENGTH+1)*sizeof(unsigned long))
         {
               Log(str);
               return;
         }
         else
         {
            ASPrintf(NULL,str,". Dupe Table: %s: read %d of %d bytes",filename,length,TABLELENGTH+1);
            Log(str);
         }
      }
      else
      {
         Log("! Dupe Table: Couldn't open!");
      }

      Log(str);

         for(i=0;i<TABLELENGTH+1;i++)
      {
         buffer[i]=0;
      }
   }
   return;
}
//-

/// write_dup_table
/* Save table to disk. If there is a write error, shrug shoulders. */
void write_dup_table(char *filename,unsigned long *buffer,BOOL force)
{
      BPTR fh;
   char *r;
   char buf[100];

   if(force==FALSE)
   {
      last_dup_table_written=FALSE;
      return;
   }

   last_dup_table_written=TRUE;

      fh=Open(filename,MODE_NEWFILE);

   if(!fh)
   {
      // no directory? make one!
      if(!Strnicmp(filename,"PASS:",5))
      {
         strcpy(buf,filename);
         r=strrchr(buf,'/');

         if(r)
         {
            *r=0;
            fh=CreateDir(buf);

            if(fh)
            {
               UnLock(fh);
                  fh=Open(filename,MODE_NEWFILE);
            }
         }
      }
   }
      if(fh)
   {
      Write(fh,(void *)buffer,(TABLELENGTH+1)*sizeof(unsigned long));
      Close(fh);
   }
      return;
}
//-

/// CRC_dup_check
int CRC_dup_check(unsigned long CRC,unsigned long *buffer)
{
      int i,count;

      count=0;
      for(i=1;i<TABLELENGTH+1;i++)
   {
      if(buffer[i]==CRC)
      {
            count++;
      }
   }
      return count;
}
//-

/// add_CRC_to_buffer
void add_CRC_to_buffer(unsigned long CRC,unsigned long *buffer)
{
      if(buffer[0]==TABLELENGTH)
   {
      buffer[0]=0;
   }
      buffer[0]++;

      buffer[buffer[0]]=CRC;
      /* buffer[0] is pointer of current element in buffer. */
}
//-

/// DupCheck
BOOL DupCheck(char *areapathname,char *messagestart, int messagelength, char *echoname, char *whybad,char *datestring,char *tostring,char *fromstring,char *subjectstring)
{
   unsigned long *buffer;  /*unsigned long buffer[TABLELENGTH+10];*/
      char filename[200];
      char *p;
      unsigned long CRC, CRC1;
      int dupcount;
   int i,j;

   buffer=the_dup_table;

   j=messagelength;

      p=stpcpy(filename,areapathname);
      if(*areapathname && p[-1] != ':' && p[-1] != '/')
      stpcpy(p,"/");
      stpcpy(p,"Dupe.DAT");

   i=EndOfMsg(messagestart,messagelength);

   if(MyDEBUG) AFPrintf(NULL,sout,"dupchk: %d->%d",j,i);


   if(i==0)
   {
      strcpy(prob,"NO ORIGIN");
      Reasoning(echoname,whybad,"NO DISCERNABLE ORIGIN LINE");
      if(MyDEBUG) AFPrintf(NULL,sout,"No origin string - toss to bad");
      return (BAD);
   }

   if(i<0)
   {
      strcpy(prob,"NO SEENBY");
      Reasoning(echoname,whybad,"NO DISCERNABLE SEEN-BY LIST");
      if(MyDEBUG) AFPrintf(NULL,sout,"No Seenby's - toss to bad");
      return(BAD);
   }

   messagelength=i;

   if(messagelength<10 && MyDEBUG) AFPrintf(NULL,sout,"message length < 10 ?!?! ->%d\n",messagelength);

   CRC1=CalcCRC((unsigned char *)datestring,strlen(datestring),0);

   CRC1=CalcCRC((unsigned char *)tostring,strlen(tostring),CRC1);

   CRC1=CalcCRC((unsigned char *)fromstring,strlen(fromstring),CRC1);

   CRC1=CalcCRC((unsigned char *)subjectstring,strlen(subjectstring),CRC1);

   CRC=CalcCRC((unsigned char *)messagestart,messagelength,CRC1);

      read_dup_table(filename,buffer);

      dupcount=CRC_dup_check(CRC,buffer);

      if(dupcount<5)
   {
      add_CRC_to_buffer(CRC,buffer);
   }

   write_dup_table(filename,buffer,FALSE);

   if(dupcount)
   {
      strcpy(prob,"DUPLICATE");
      Reasoning(echoname,whybad,"DUPLICATE MESSAGE");
      return(BAD);
   }
   else
         return(GOOD);
}
//-

/// Reasoning
int Reasoning(char *name, char *why , char *reason)
{
   ASPrintf(NULL,why,"\r !!!\r !!! Echo: %s\r !!!  Bad: %s\r !!!\r",name,reason);
   return 1;
}
//-

/// EndOfMsg
int EndOfMsg(char *mes, int k)
{
   /* k = # of bytes in message */

   int oldEOM;

   UBYTE *message;

   char *dummy;

   int lastreturn,l;

   message=(UBYTE *)mes;
   oldEOM=k;

   for(l=(k-1);l>-1;l--)
   {
      if(message[l]=='\r')
      {
         lastreturn=l;
      }
      if(message[l]=='*')
      {
         if(!Strnicmp("* Origin:",message+l,9))
         {
            break;
         }
      }
   }
   /* problem - no origin string */

   if(l<2)
      return(0);  /* 0 will flag no origin */   

   /* we've found the carriage return following
      the origin line in theory */

   /* lastreturn == the carriage return after the origin line */

   if(!stcpm(message+lastreturn,"SEEN-BY",&dummy))
   {
      return(-1*(lastreturn+1)); /* problem - no seenby's, return a negative
                 value of where the last return
                 was */
   }

   return(lastreturn+1); /* this returns the number of bytes to
            check CRC against */
}
//-

