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

#include <dlg/crypt.h>

#include <proto/all.h>
#include <proto/dos.h>

//#include <pragmas/dlg.h>

int decryptowner(char *, ULONG);

int  main(int argc,char **argv);
int  Copy(char *file1, char *file2);
void Encrypt(char *inbuf, char *outbuf, int size);
int  Decrypt(char *inbuf, char *outbuf);

int   a;
UBYTE CRC;


int main(int argc,char **argv)
{
   int    ifd;
   int    ofd;
   int    counter;

   UBYTE *buf;
   UBYTE  tptbuf[22];

   UBYTE  in    [80];
   UBYTE  out   [80];
   UBYTE  oldbuf[22];

   char   buf1[32];
   char   buf2[32];
   char   buf3[32];
   char   buf4[32];

   BOOL   found;
   BOOL   nfound = FALSE;

   long   numchars;

   UBYTE  SN   [4];
   UBYTE  XORSN[4];
   ULONG  serialnumber;
   ULONG  xorserialnumber;

   if (!(buf=(UBYTE *)malloc(5000)))
   {
      printf(" Update Error ID# 0\n");
      exit(5);
   }

   strcpy(in,  "l:tpt-handler");
   strcpy(out, "update.dat");

   Copy("Update.dat","Update.bak");

   if ((ifd=open(in, O_RDWR))==-1)
   {
      printf("\n Fatal Error\n\n");
      free(buf);
      exit(5);
   }

   if ((ofd=open(out,O_RDWR))==-1)
   {
      printf("\n Update Error ID# 1\n\n");
      close(ifd);
      free(buf);
      exit(5);
   }


   /* Unbreak the update.dat file*/
   read(ofd, buf3, 32);
   read(ofd, buf1, 32);
   read(ofd, buf4, 32);
   read(ofd, buf2, 32);

   lseek(ofd, 0, 0);  

   write(ofd, buf1, 32);
   write(ofd, buf2, 32);
   write(ofd, buf3, 32);
   write(ofd, buf4, 32);


   /* seek from the end of update.dat and find the smiley offset */
   lseek(ofd, -5000L, 2);

   if (read(ofd,buf,5000)!=5000)
   {
      printf("\n Update Error ID# 2\n\n");
      close(ifd);
      close(ofd);
      free(buf);
      exit(5);
   }

   found = FALSE;
   for(counter=4999; counter; counter--)
   {
      if (buf[counter]==')')
      {
         counter--;
         if (buf[counter]=='-')
         {
            counter--;
            if (buf[counter]==':')
            {
               found=TRUE;
               break;
            }
         }
      }
   }

   if (!found)
   {
      printf("\n Update error ID #3\n\n");
      close(ifd);
      close(ofd);
      free(buf);
      exit(5);
   }

   /* we have found the smiley in update.dat */
   lseek(ofd, 134 - (5000 - (long)counter), 2);




   /* read in the last part of tpt-handler */
   lseek(ifd, -5000, 2);

   if (read(ifd, buf, 5000) != 5000)
   {
      printf("\n Update Error ID# 4\n\n");
      close(ifd);
      close(ofd);
      free(buf);
      exit(5);
   }

   found = FALSE;
   for(counter=4999;counter;counter--)
   {
      if (buf[counter]==')')
      {
         counter--;
         if (buf[counter]=='-')
         {
            counter--;
            if (buf[counter]==':')
            {
               found=TRUE;
               break;
            }
         }
      }
   }

   if (!found)
   {
      printf("\n Update error ID# 5\n\n");
      close(ifd);
      close(ofd);
      free(buf);
      exit(5);
   }

   /* We have found the smiley on tpt-handler */
   lseek(ifd, 134 - (5000 - (long)counter), 2);

   read(ifd, buf, 21);
   memcpy(tptbuf,buf,21);
   Decrypt(buf, buf);

   for(a=0; a<21; a++)
   {
      if (buf[a]=='#')
      {
         nfound = TRUE;
         break;
      }
   }

   if(!nfound)
   {
      memcpy(buf,tptbuf,21);
      OldDecrypt(buf,buf);

      for(a=0; a<21; a++)
      {
         if(buf[a]=='#')
         {
            nfound = TRUE;
            break;
         }
      }

      if(!nfound)
      {
         printf("\n Update error ID# 5.5\n\n");
         free(buf);
         exit(5);
      }
   }

   a++;
   buf[a+6] = 0;

   printf("buffer = %s\n",buf);

   if(strncmp(buf+a,"PR",2)  &&
      strncmp(buf+a,"DV",2)  &&
      strncmp(buf+a,"BT",2)  &&
      strncmp(buf+a,"RE",2) )
   {
      printf("Update error ID# 6\n\n");
      exit(5);
   }

   if ((!isdigit(buf[a+2])) ||
   (!isdigit(buf[a+3])) ||
   (!isdigit(buf[a+4])) ||
   (!isdigit(buf[a+5])))
   {
      printf("Update error ID# 7\n\n");
      exit(5);
   }

   // new steve stuff
   serialnumber    = atol(buf+a+2);
   xorserialnumber = serialnumber^0xffffffff;

   SN[0]    = (serialnumber&0xff000000)>>24;
   SN[1]    = (serialnumber&0x00ff0000)>>16;
   SN[2]    = (serialnumber&0x0000ff00)>>8;
   SN[3]    = (serialnumber&0x000000ff)>>0;

   XORSN[0] = (xorserialnumber&0xff000000)>>24;
   XORSN[1] = (xorserialnumber&0x00ff0000)>>16;
   XORSN[2] = (xorserialnumber&0x0000ff00)>>8;
   XORSN[3] = (xorserialnumber&0x000000ff)>>0;

   if (!decryptowner(in, serialnumber))
   {
      printf("Update error ID# 8\n\n");
      exit(5);
   }
   // end new steve stuff


   buf[a]   = 'R';
   buf[a+1] = 'E';
   numchars = strlen(buf);
   Encrypt(buf, oldbuf, numchars);

   write(ofd,   oldbuf, numchars+1);
   write(ofd,  &ofd,    19-numchars);
   write(ofd,  &CRC,    1);

   // new steve stuff
   lseek(ofd, 5, 1);
   write(ofd, SN,    4);  // write the serial number
   write(ofd, XORSN, 4);  // and its exclusive or

   numchars = strlen(in);
   Encrypt(in,  out, numchars);

   write(ofd,   out, numchars+1);
   write(ofd,  &ofd, 78-numchars);
   write(ofd,  &CRC, 1);

   strcpy(in, "Unregistered pirated version -- it's not going to work");
   numchars = strlen(in);
   Encrypt(in, out, numchars);

   write(ofd,  out, numchars+1);
   write(ofd, &ofd, 78-numchars);
   write(ofd, &CRC, 1);
   // end new steve stuff

   close(ifd);
   close(ofd);

   DeleteFile("DLGconfig:misc/DLGSerial");
   if ((ifd=open("DLGconfig:misc/DLGSerial",O_RDWR+O_CREAT))!=EOF)
   {
      write(ifd, buf+a, 6);
      write(ifd,"\n",1);
      close(ifd);
   }

   DeleteFile("l:tpt-handler");
   Copy("update.dat", "l:TPT-Handler");
   Copy("Update.bak", "Update.dat");
   DeleteFile("update.bak");

   free(buf);
   exit(0);
}


// the following function needs help... it came from the input lib
int Copy(char *file1,char *file2)

{
   int   ofp;
   int   ifp;
   long  sizeofread;
   char *buffer;

   if ((ifp=open(file1,O_RDONLY))==EOF)  return(1);
   if ((ofp=open(file2,O_RDWR | O_CREAT))==EOF)
   {
      close(ifp);
      return(2);
   }

   buffer = malloc(4096);
   if (buffer)
   {
      while((sizeofread=read(ifp,buffer,4096))==4096)
      {
         if (write(ofp,buffer,4096)!=4096)
         {
            close(ifp);
            close(ofp);
            free(buffer);
            return(2);
         }
      }

      if (write(ofp,buffer,sizeofread)!=sizeofread)
      {
         close(ifp);
         close(ofp);
         free(buffer);
         return(2);
      }

      close(ifp);
      close(ofp);
      free(buffer);
   }

   return(0);
}


//identical to routine in license.c
void Encrypt(char *inbuf,char *outbuf,int size)

{
   int   counter;
   UBYTE shift;

   Forbid();
   outbuf[size] = 0;
   outbuf[0]    = size;
   shift        = size;

   for(counter=0;counter<size;counter++)
   {
      outbuf[counter+1] = inbuf[counter]+shift;
      shift             = outbuf[counter+1]-CRYPTOFFSET;
   }

   CRC = shift+MAGICNUMBER;
   Permit();
}


// this routine has been modified to update 1.0 handlers only
int Decrypt(char *inbuf,char *outbuf)
{
   UBYTE numchars, shift, i;

   Forbid();
   numchars = inbuf[0];
   shift    = numchars;
   for(i=0;i<numchars;i++)
   {
      outbuf[i] = inbuf[i+1] - shift;
      shift     = inbuf[i+1] - CRYPTOFFSET;
   }

   Permit();
   return((int)numchars);
}

/// OldDecrypt
// This routine retains backwards compatability
OldDecrypt(char *inbuf, char *outbuf)
{
  UBYTE numchars, shift, i;

  numchars=inbuf[0];
  shift=numchars;

  for(i=0;i<numchars;i++)
  {
    outbuf[i] = inbuf[i+1]-shift;
    shift = inbuf[i+1]-shift;
  }

  return(numchars);
}
//-

