// Define class for Common Gateway Interface interaction with OSU scriptserver.
//
// There is only one instance of this class, which has the external name CGI.
// You must initialize the class using the init member function with the
// following arguments:
//     init ( int argc, 	// size of argv array,
//	      char **argv 	// Argument vector passed to main():
//				//    argv[1]  HTTP method (e.g. GET)
//				//    argv[2]  Translated URL path.
//				//    argv[3]	PROTOCOL version (HTTP/1.0)
//	      [, int mode] )	// Optional operating mode:
//				//    0 - default
//				//    1 - Defer output.
//
// The CGI variables are available as an associative array var:
//
//
#include <stdio.h>

struct symdef {
    char *name;			// Symbol name.
    char *value;		// symbols value
    int state;			// 0-unknown, 1-variables initted, 2-cgimode
};

typedef long symbol_table_scan;
const symbol_table_scan SYMBOL_TABLE_SCAN_BEGIN = 0;

class symbol_table {
  public:
    //  Lookup function is expressed as array reference. (e.g. var["PATH"]);
    symbol_table();
    char *operator [](const char *symname);
    int define(const char *symname, char *value);
    int scan ( symbol_table_scan &context, char *&name, char *&value );
    friend class cgienv;

  private:
    int size;			// current allocation of sym array.
    int used;			// Current number of symbols defined.
    struct symdef *sym;		// Table of defined symbols;
    //
    // Entry function returns pointer to table entry, expanding table with
    // new entry if needed and extend_size > 0
    //
    struct symdef &entry(const char *name, const int extend_size=0);
};

class cgienv {
  public:
    cgienv();
    ~cgienv();
    // The init routine takes the command line arguments passed to main().
    int init ( int argc, char **argv, int mode=0 );
    //
    //  Translate and form_parse only valid when init mode non-zero
    //  and cannot be called after output started.
    //
    int translate ( const char *path, char *translation, int bufsize );
    int parse_form();			// Parses POSTed form data into symbol
					// table.
    int read_content(char *buffer, int bufsize);
    FILE *content_file();		// returns file with request content

    cgienv &operator<<(const char *);	// formatted output
    cgienv &operator<<(const int);
    symbol_table var;
    symbol_table form;

  private:
    int state;			// 0-init, 1-vars done, 2-form done, 3-CGImode
    int var_load(int, char **);	// Querys server and builds var table.
    int content_load();		// querys server for request content.
    FILE *content;
    int content_length;		// Value decoded from content-length header.
    int content_pending;	// Bytes of content not yet read.
    int content_cache_length;	// Size of content in cache.
    int content_cache_pos;	// Current read position in cache.
    char content_cache[8192];
};
////////////////////////////////////////////////////////////////////////////

extern cgienv CGI;
