#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <stddef.h>

#include <exec/exec.h>
#include <exec/types.h>
#include <clib/exec_protos.h>
#include <dos/dos.h>
#include <clib/dos_protos.h>
#include <dos/dosextens.h>
#include <clib/alib_protos.h>

#define MAX_KEYWORDS 9

char SERVER_SOFTWARE[256];
char SERVER_NAME[256];
char GATEWAY_INTERFACE[256];
char SERVER_PROTOCOL[256];
char SERVER_PORT[20];
char REQUEST_METHOD[20];
char HTTP_ACCEPT[1025];
char PATH_INFO[1025];
char PATH_TRANSLATED[1025];
char SCRIPT_NAME[256];
char QUERY_STRING[1025];
char REMOTE_HOST[256];
char REMOTE_ADDR[30];
char REMOTE_USER[256];
char AUTH_TYPE[256];
char CONTENT_TYPE[1025];
char CONTENT_LENGTH[30];
char HTTP_FROM[256];

char name[33];
char email[33];
char subject[61];
char *body = 0L;
char path[256];
char date[256];
char systime[256];

char *Data = 0L;

char *template = 0L;
char *index = 0L;

FILE *in = 0L;
FILE *out = 0L;
FILE *idx = 0L;

struct MsgPort *msg = 0L;

unsigned long fsize(char *fname)
{
    BPTR file;
    __aligned struct FileInfoBlock FileInfo;
    unsigned long filesize;

    if(!fname)
        return 0L;

    file = Lock(fname,ACCESS_READ);
    if(!file)
        return 0L;

    if(!(Examine(file,&FileInfo)))
        return 0L;

    filesize = FileInfo.fib_Size;
    UnLock(file);

    return filesize;
}

void Cleanup(void)
{
    if(body != 0L)
        FreeVec(body);

    if(Data != 0L)
        FreeVec(Data);

    if(index != 0L)
        FreeVec(index);

    if(template != 0L)
        FreeVec(template);

    if(in != 0L)
        fclose(in);

    if(out != 0L)
        fclose(out);

    if(idx != 0L)
        fclose(idx);

    if(msg != 0L)
        DeletePort(msg);

}

char parsehex(char *src)
{
    char c;
    char num[3];
    int high,low;


    num[0] = src[1];
    num[1] = src[2];
    num[2] = '\0';

    switch(num[0])
    {
        case '0'    :   high = 0;
                        break;

        case '1'    :   high = 1;
                        break;

        case '2'    :   high = 2;
                        break;

        case '3'    :   high = 3;
                        break;

        case '4'    :   high = 4;
                        break;

        case '5'    :   high = 5;
                        break;

        case '6'    :   high = 6;
                        break;

        case '7'    :   high = 7;
                        break;

        case '8'    :   high = 8;
                        break;

        case '9'    :   high = 9;
                        break;

        case 'A'    :   high = 10;
                        break;

        case 'B'    :   high = 11;
                        break;

        case 'C'    :   high = 12;
                        break;

        case 'D'    :   high = 13;
                        break;

        case 'E'    :   high = 14;
                        break;

        case 'F'    :   high = 15;
                        break;

        default     :   Cleanup();
                        puts("ERROR processing Hex!\n");
                        exit(10);
    }

    switch(num[1])
    {
        case '0'    :   low = 0;
                        break;

        case '1'    :   low = 1;
                        break;

        case '2'    :   low = 2;
                        break;

        case '3'    :   low = 3;
                        break;

        case '4'    :   low = 4;
                        break;

        case '5'    :   low = 5;
                        break;

        case '6'    :   low = 6;
                        break;

        case '7'    :   low = 7;
                        break;

        case '8'    :   low = 8;
                        break;

        case '9'    :   low = 9;
                        break;

        case 'A'    :   low = 10;
                        break;

        case 'B'    :   low = 11;
                        break;

        case 'C'    :   low = 12;
                        break;

        case 'D'    :   low = 13;
                        break;

        case 'E'    :   low = 14;
                        break;

        case 'F'    :   low = 15;
                        break;

        default     :   Cleanup();
                        puts("ERROR processing Hex!\n");
                        exit(10);
    }

    c = (char)( (16 * high) + low);
    return c;
}

struct KeyWords {
    char *template;
    char *data;
    int length;
} keywords[MAX_KEYWORDS];


void SortKeywords(struct KeyWords key[], int count)
{
    int i,t;
    struct KeyWords temp;

    for(i=0; i<count; i++)
        for(t=i; t<count; t++)
            if(key[t].template < key[i].template)
            {
                temp.template = keywords[i].template;
                temp.data = keywords[i].data;
                temp.length = keywords[i].length;

                keywords[i].template = keywords[t].template;
                keywords[i].data = keywords[t].data;
                keywords[i].length = keywords[t].length;

                keywords[t].template = temp.template;
                keywords[t].data = temp.data;
                keywords[t].length = temp.length;

            }
}

char *gettime(char *fmt)
{
    struct tm *local;
    time_t t;
    static char timestring[256];

    timestring[0] = '\0';

    t = time(0L);
    local = localtime(&t);
    strftime(timestring,255,fmt,local);

    return timestring;
}


void openport(void)
{
    /* wait until we own the files */

    int safe = FALSE;

    while(!safe)
    {
        Disable();
        if(!(msg = FindPort("simplebb")))
        {
            if(msg = CreatePort("simplebb",0L))
                safe = TRUE;
        }
        Enable();

        Delay(50);
    }
}

main(int argc, char *argv[])
{
    openport();

    puts("content-type: text/plain\n");

    strcpy(SERVER_SOFTWARE,getenv("SERVER_SOFTWARE"));
    strcpy(SERVER_NAME,getenv("SERVER_NAME"));
    strcpy(GATEWAY_INTERFACE,getenv("GATEWAY_INTERFACE"));
    strcpy(SERVER_PROTOCOL,getenv("SERVER_PROTOCOL"));
    strcpy(SERVER_PORT,getenv("SERVER_PORT"));
    strcpy(REQUEST_METHOD,getenv("REQUEST_METHOD"));
    strcpy(HTTP_ACCEPT,getenv("HTTP_ACCEPT"));
    strcpy(PATH_INFO,getenv("PATH_INFO"));
    strcpy(PATH_TRANSLATED,getenv("PATH_TRANSLATED"));
    strcpy(SCRIPT_NAME,getenv("SCRIPT_NAME"));
    strcpy(QUERY_STRING,getenv("QUERY_STRING"));
    strcpy(REMOTE_HOST,getenv("REMOTE_HOST"));
    strcpy(REMOTE_ADDR,getenv("REMOTE_ADDR"));
    strcpy(REMOTE_USER,getenv("REMOTE_USER"));
    strcpy(AUTH_TYPE,getenv("AUTH_TYPE"));
    strcpy(CONTENT_TYPE,getenv("CONTENT_TYPE"));
    strcpy(CONTENT_LENGTH,getenv("CONTENT_LENGTH"));
    strcpy(HTTP_FROM,getenv("HTTP_FROM"));

    int length;
    if(!(strcmp(REQUEST_METHOD,"POST")))
    {
        int count = 0;

        length=atoi(CONTENT_LENGTH);
        Data = AllocVec(length+2,MEMF_CLEAR);
        if(Data != 0L)
        {
            /* Memory alloc successful */
            int ct;
            for(ct=0; ct<length; ct++)
                Data[ct] = fgetc(stdin);

            /*Process Data, get fields */
            char *src,*dst;

            src = Data;
            dst = path;

            src += 5;
            count+= 5;

            while( (*src != '&') && (count < strlen(Data) ))
            {
                *dst = *src;
                if(*dst == '+')
                    *dst = ' ';
                if(*dst == '%')
                {
                    *dst = parsehex(src);
                    src += 2;
                    count += 2;
                }
                dst++;
                src++;
                count++;
            }
            if(count > strlen(Data))
            {
                puts("ERROR in data stream, some fields not defined! (path)\n");
                Cleanup();
                exit(10);
            }
            *dst = '\0';

            dst--;
            if( (*dst != ':') && (*dst != '/') )
            {
                dst++;
                *dst = '/';
            }
            dst++;
            *dst = '\0';

            src += 6;
            count += 6;
            dst = name;
            while( (*src != '&') && (count < strlen(Data) ))
            {
                *dst = *src;
                if(*dst == '+')
                    *dst = ' ';
                if(*dst == '%')
                {
                    *dst = parsehex(src);
                    src += 2;
                    count += 2;
                }
                dst++;
                src++;
                count++;
            }
            if(count > strlen(Data))
            {
                puts("ERROR in data stream, some fields not defined!\n");
                Cleanup();
                exit(10);
            }

            *dst = '\0';

            src += 7;
            count += 7;
            dst = email;
            while( (*src != '&') && (count < strlen(Data) ))
            {
                *dst = *src;
                if(*dst == '+')
                    *dst = ' ';
                if(*dst == '%')
                {
                    *dst = parsehex(src);
                    src += 2;
                    count += 2;
                }
                dst++;
                src++;
                count++;
            }
            if(count > strlen(Data))
            {
                puts("ERROR in data stream, some fields not defined!\n");
                Cleanup();
                exit(10);
            }

            *dst = '\0';

            src += 9;
            count += 9;
            dst = subject;
            while( (*src != '&') && (count < strlen(Data) ))
            {
                *dst = *src;
                if(*dst == '+')
                    *dst = ' ';
                if(*dst == '%')
                {
                    *dst = parsehex(src);
                    src += 2;
                    count += 2;
                }
                dst++;
                src++;
                count++;
            }
            *dst = '\0';

            src += 6;
            count += 6;
            if(count > strlen(Data))
            {
                puts("ERROR in data stream, some fields not defined!\n");
                Cleanup();
                exit(10);
            }

            body = AllocVec(strlen(src)+1,MEMF_CLEAR);
            if(body == 0L)
            {
                puts("ERROR! could not allocate memory for message body!\n");
                Cleanup();
                exit(10);
            }

            dst = body;
            while( (*src != '\0') && (count < strlen(Data) ))
            {
                *dst = *src;
                if(*dst == '+')
                    *dst = ' ';
                if(*dst == '%')
                {
                    *dst = parsehex(src);
                    src += 2;
                    count += 2;
                }
                dst++;
                src++;
                count++;
            }
            *dst = '\0';


            FreeVec(Data);
            Data = 0L;

/* Finished processing data stream, free resources and continue */


            /* Add the new message at the top into <path>index.html */

            char templatename[256];

            /* First, load the message template */

            sprintf(templatename,"%stemplate.html",path);

            unsigned long templatesize = 0L;

            templatesize = fsize(templatename);

            template = AllocVec(templatesize+2,0L);
            if(template == 0L)
            {
                puts("Could not get memory for message template!\n");
                Cleanup();
                exit(10);
            }

            if(!(in = fopen(templatename,"r")))
            {
                puts("Error! Could not open template file!\n");
                Cleanup();
                exit(10);
            }
            dst = template;
            while(!feof(in))
                *dst++=fgetc(in);
            dst--;
            *dst = '\0';
            fclose(in);
            in = 0L;

            unsigned long size;
            char indexname[256];
            char *indexbase;

            sprintf(indexname,"%sindex.html",path);
            size = fsize(indexname);
            if(size == 0L)
            {
                puts("Error finding index.html file!\n");
                Cleanup();
                exit(10);
            }

            index = AllocVec(size+2,0L);
            if(index == 0L)
            {
                puts("Error Allocating index memory.\n");
                Cleanup();
                exit(10);
            }

            idx = fopen(indexname,"r");
            if(idx == 0L)
            {
                Cleanup();
                exit(10);
            }
            indexbase = index;

            while(!(feof(idx)))

                *indexbase++ = fgetc(idx);
            indexbase--;
            *indexbase = '\0';
            fclose(idx);
            idx = 0L;
            indexbase = index;

            char *indexsearch;

            /* Now output the new message <path>x.html */

            char command[256];
            char filename[256];

            sprintf(command,"copy %sindex.html %sindex.old",path,path);
            system(command);

            sprintf(filename,"%sindex.html",path);
            if(!(out = fopen(filename,"w")))
            {
                puts("Error! cannot open output file\n");
                Cleanup();
                exit(10);
            }

            /* Output the header part of the index file until we get to the first message */

            if(!(indexsearch = strstr(index,"<!--begin-->")))
            {
                puts("Error in index file!! No <!--begin--> Block.\n");
                Cleanup();
                exit(10);
            }
            indexsearch += 12;
            while(indexbase < indexsearch)
                fputc(*indexbase++,out);

            fputc('\n',out);

            /* Now, insert our message using the template */


            /* First find all keywords in the template file */
            char *keywd;
            int keywdcount = 0;

            if((keywd = strstr(template,"%%header%%")))
            {
                keywords[keywdcount].template = keywd;
                keywords[keywdcount].data = subject;
                keywords[keywdcount].length = 10;
                keywdcount++;
            }


            if((keywd = strstr(template,"%%email%%")))
            {
                keywords[keywdcount].template = keywd;
                keywords[keywdcount].data = email;
                keywords[keywdcount].length = 9;
                keywdcount++;
            }

            if((keywd = strstr(template,"%%name%%")))
            {
                keywords[keywdcount].template = keywd;
                keywords[keywdcount].data = name;
                keywords[keywdcount].length = 8;
                keywdcount++;
            }

            if((keywd = strstr(template,"%%body%%")))
            {
                keywords[keywdcount].template = keywd;
                keywords[keywdcount].data = body;
                keywords[keywdcount].length = 8;
                keywdcount++;
            }

            if((keywd = strstr(template,"%%date%%")))
            {
                strcpy(date,gettime("%x"));

                keywords[keywdcount].template = keywd;
                keywords[keywdcount].data = date;
                keywords[keywdcount].length = 8;
                keywdcount++;
            }

            if((keywd = strstr(template,"%%time%%")))
            {
                strcpy(systime,gettime("%X"));

                keywords[keywdcount].template = keywd;
                keywords[keywdcount].data = systime;
                keywords[keywdcount].length = 8;
                keywdcount++;
            }

            if(keywdcount <= 0)
            {
                printf("There are no keywords in the template file!!\n");
                Cleanup();
                exit(5);
            }


            /* Sort into proper order */
            SortKeywords(keywords,keywdcount);

            src = template;

            int i;

            /* Output the template file, substituting for keywords */
            for(i=0; i<keywdcount; i++)
            {
                while(src < keywords[i].template)
                    fputc(*src++,out);

                fprintf(out,"%s",keywords[i].data);
                src += keywords[i].length;
            }
            fprintf(out,"%s",src);

            /* Now finish the rest of the index file */
            fprintf(out,"%s",indexbase);

            fclose(out);
            out = 0L;

        }
    }
    else
    {
        puts("REQUEST_METHOD != 'POST'\n");
        Cleanup();
        exit(10);
    }

    char successname[256];
    FILE *success;

    sprintf(successname,"%ssuccess.html",path);
    if(!(success = fopen(successname,"r")))
    {
        puts("Error opening success.html file!!\n");
        Cleanup();
        exit(10);
    }

    char c;
    while(!(feof(success)))
    {
        c = fgetc(success);
        if(!(feof(success)))
            fprintf(stdout,"%c",c);
    }

    fclose(success);
    success = 0L;

    Cleanup();
    exit(0);
}
