/*
 * This program reads a form submission and uses it to populate a 
 * database.  The program performs a set_symbol call to set symbol
 * ICSMA_REFERENCE to the name of the file created.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <descrip.h>
#include <JPIDEF.H>

#include "scriptlib.h"
#include "cgilib.h"

static $DESCRIPTOR(ref_symbol_dx, "ICSMA_REFERENCE");
static char ref_string[256];
static $DESCRIPTOR(ref_string_dx, ref_string );
int LIB$SET_SYMBOL(), LIB$GETJPI();
/****************************************************************************/
/* Save key list into specially formatted data base:
 *	+key1=value2
 *	+key2=line1
 *	-line2
 *	-line3
 *	+key3=value3
 *
 * each line begins with either a '+' to start a new key/value pair or
 * a - to continue a previous.
 *
 * Return value is 1 for success, 0 for failure.
 */
static int dump_key_list ( char *fname, int count, char **key, char **value )
{
    FILE *out;
    int status, i, j, pos, is_ok, length;
    char c, line[1024];
    /*
     * Open output file.
     */
    out = fopen ( fname, "w" );
    if ( !out ) return 0;
    /*
     * Write entry for each value.
     */
    for ( i = 0, is_ok=1; is_ok && (i < count); i++ ) {
	/*
	 * Build output lines.  Start with '+keyword=', upcasing the
         * keyword and truncating it at 63 characters.
	 */
	pos = 1;
	line[0] = '+';
	for (j=0; (c=key[i][j]) && (j < 64); j++) line[pos++] = toupper(c);
	line[pos++] = '=';
	/*
	 * Append the value the output line, reseting to multiple lines
	 * if carriage control seen.
	 */
	for ( j = 0; (c = value[i][j]); j++ ) {
	    if ( c == '\r' ) {
		/* Skip over CR preceding LF */
		if ( value[i][j+1] == '\n' ) { j++; c = '\n'; }
	    }
	    line[pos++] = c;
	    if ( (1+pos) >= sizeof(line) ) {
		status = fwrite ( line, sizeof(char), pos, out );
		if ( status < pos ) {
		    is_ok = 0;
		    break;
		}
		fwrite ( "\n", sizeof(char), 1, out );
		pos = 1;
		line[0] = '=';
	    } else if ( c == '\n' ) {
		/* write line */
		status = fwrite ( line, sizeof(char), pos, out );
		if ( status < pos ) {
		    is_ok = 0;
		    break;
		}
		pos = 1;
		line[0] = '-';
	    }
	}
	/*
	 * Flush final line.
	 */
	if ( pos > 1 ) {
	    line[pos++] = '\n'; 
	    status = fwrite ( line, 1, pos, out );
	    if ( status < pos ) is_ok = 0;
	}
    }
    status = fclose ( out );
    return 1;
}
/****************************************************************************/
/* Read form content and parse.  Return value is number of keywords parsed,
 * -1 for error.  Key_limit is size of key and value arrays.
 */
static int parse_form ( int key_limit, char **key, char **value )
{
    int i, j, content_length, length, count, start, finish, flen;
    char *var, *fdata;
    /*
     * Read form content into memory in preparation for parsing.
     */
    count = 0;
    var = cgi_info ( "CONTENT_LENGTH" );
    content_length = var ? atoi(var) : 0;
    
    if ( content_length > 0 ) {
	/*
	 * Allocate buffer and read entire form data into it, forcing final &.
	 */
	fdata = malloc ( content_length+1 );
	if ( !fdata ) return -1;
	
	length = cgi_read ( fdata, content_length );
    } else {
	/* See if form method was GET by mistake. */
	var = cgi_info ( "QUERY_STRING" );
	if ( var ) {
	    length = strlen ( var );
	    fdata = malloc ( length + 1 );
	    if ( !fdata ) return -1;
	    strcpy ( fdata, var );
	} else length = 0;
    }
    if ( length <= 0 ) return length;
/* fdata[length] = '\0'; printf("Raw form data: %s\n", fdata ); */
    /*
     * Parse into keyword/value pairs, ampersands delimit the pairs.
     */
    if ( fdata[length-1] != '&' ) fdata[length++] = '&';
    start = finish = 0;
    for ( i = 0; i < length; i++ ) if ( !fdata[i] || (fdata[i] == '&') ) {
	/*
	 * Value parsed.  Unescape string and look for first equals to
	 * to delimit field name from value.
	 */
	flen = i - start;
	for ( j = start; j < i; j++ ) if ( fdata[j] == '+' ) fdata[j] = ' ';
	net_unescape_string ( &fdata[start], &flen );
	finish = start + flen;
	fdata[finish] = '\0';
	for ( j = start; j < finish; j++ ) if ( fdata[j] == '=' ) {
	    /* Save pointers to pair in callers buffer, terminate strings */
	    key[count] = &fdata[start];
	    fdata[j] = '\0';
	    value[count] = &fdata[j+1];
	    count++;
	    if ( count >= key_limit ) return count;
	    break;
	} else {
	    /* Make characters in field name upper case */
	    /* fdata[j] = _toupper(fdata[j]); */
	}
	start = i + 1;
    }
    return count;
}
/**************************************************************************/
int main ( int argc, char **argv )
{
    int field_count, status, i, code;
    char *db_root;
    char *key[50], *value[50];
    char fname[512];
    time_t now;
    long pid, tmp;
    /*
     * Initialize CGI environment, path_translated is database location.
     */
    status = cgi_init ( argc, argv );
    if ( (status&1) == 0 ) exit ( status );

    db_root = cgi_info ( "PATH_TRANSLATED" );
    if ( !db_root ) {
	cgi_printf ( "content-type: text/plain\n" );
	cgi_printf ( "status: 500 bad info\n\nMissing or invalid path info\n");
        cgi_printf ( "Must supply template file name\n");
	exit ( 1 );
    }
    if ( !*db_root ) {
	cgi_printf ( "content-type: text/plain\n" );
	cgi_printf ( "status: 500 bad info\n\nNull or invalid path info\n");
        cgi_printf ( "Must supply template file name\n");
	exit ( 1 );
    }
    /*
     * Get posted data.
     */
    field_count = parse_form ( 50, key, value );

    cgi_printf ( "content-type: text/html\n" );
  
    /* for ( i = 0; i < field_count; i++ ) {
	cgi_printf ( "%s = '%s'\n", key[i], value[i] );
    } */
    /*
     * Generate reference number from data and 'random' data.
     */
    now = time(&now);
    code = JPI$_PID;
    status = LIB$GETJPI ( &code, 0, 0, &pid, 0, 0 );
    if ( (status&1) == 0 ) pid = 0;
    now = (time_t) (((int) now) ^ 0x0F1238423);
    sprintf(ref_string,"%u-%u", pid, now );
    sprintf(fname,"ICSMA_DATA:%s.ABSTRACT", ref_string );
    ref_string_dx.dsc$w_length = strlen(ref_string);
    code = 1;		/* local table */
    status = LIB$SET_SYMBOL ( &ref_symbol_dx, &ref_string_dx, &code );
    /*
     * Save submitted data.
     */
    if ( (status&1) ) status = dump_key_list ( fname, field_count, key, value );
    if ( status&1 ) {
	cgi_printf("\n<HTML><HEAD><TITLE>Abstract Submission success</TITLE>");
	cgi_printf("</HEAD><BODY>\n");
	cgi_printf("You submission was entered into system for processing,");
	cgi_printf("the reference number is %s.\n", ref_string );
	cgi_printf("</body></html>\n");
    } else {
	cgi_printf("status: 500 Internal failure\n");
	cgi_printf("\n<HTML><HEAD><TITLE>Abstract Submission failure</TITLE>");
	cgi_printf("</HEAD><BODY>\n");

	cgi_printf("An error occurred during the processing of your submission\n");
	cgi_printf("</body></html>\n");
    }
    return 1;
}
