Welcome to Mike95.com
Home
WELCOME
ABOUT MIKE95.COM
CONTACT ME


Features
FUNNY JOKES
HUMAN FACTOR


C++
Library Source Code:
CGIPARSE
JSTRING
JVECTOR
JSTACK
JHASHTABLE


COM / ASP
MIKE95 COM SVR
- ASP STACK
- ASP QUEUE
- ASP VECTOR


Tutorials:
TEMPLATES
ALGORITHMS
DESIGN PATTERNS


Sample Work
Internet Based
TASK/BUG TRACKER


Visual C++ / MFC
FLIGHT PATH (C++)
MP3 PLAY LIST


Java
JAVA TALK
BAR GRAPH
WEB CAM


Personal
CONTACT ME
RESUME
PICTURES
TRIPS
CGIparse

/*******************************************
  Downloaded from: http://www.mike95.com
  Copyright (c)1997 Michael Olivero
  All Rights Reserved
********************************************/
#include <stdlib.h>
#include <string>
#include <iostream>
#include <stdio.h>
#include <iomanip>
#include "CGIparse.h"


bool CGIparse::mime_sent = false;

CGIparse::node::node( const char* aKey, const char* aValue, node* aNode ) : link(aNode)
{
    key = new char[ strlen( aKey ) + 1 ];
    value = new char[ strlen( aValue ) + 1 ];
    strcpy( key, aKey );
    strcpy( value, aValue );
}

CGIparse::node::~node()
{
    delete [] key;
    delete [] value;
}

CGIparse::CGIparse() : m_head( NULL ), m_tail( NULL ), m_method( NULL )
{

    //stop execution if not executed by browser
    if ( HTTP_USER_AGENT == NULL )
        endMessage(NULL, errorString(300) );

    //check and set request method enviornment
    const char* RM = REQUEST_METHOD;
    if ( RM == NULL )
        endMessage(NULL, errorString(103));
    m_method = new char[ strlen( RM ) + 1 ];
    strcpy( m_method, RM );

    char* temp = NULL; //will contain value of QUERY for either POST/GET

    if ( strcmp(m_method, "GET") == 0 )
    {
        //===========================================
        // Get posting info from environment variable
        //===========================================
        const char* QS = QUERY_STRING;
        if ( QS == NULL )
            endMessage("ERROR", errorString(101));
        temp = new char[ strlen(QS)  + 1 ];
        strcpy( temp, QS );
    }
    else if ( strcmp(m_method, "POST") == 0 )
    {
        //===========================================
        // Get posting info from stdin
        //===========================================
        char *temp2;
        const char* CL = CONTENT_LENGTH;
        if ( CL == NULL )
            endMessage( "ERROR", errorString(102));

        UINT size = atoi( CL );
        if ( size > 0 )
        {
            temp2 = new char[ size + 1 ];
            cin.getline( temp2, size + 1 );
            temp = temp2;
        }
    }

    //process the CGI encoded string
    //==============================
    char* front = temp;            //for memory release since temp becomes NULL
    char* key = temp, * value;

    while( key != NULL )
    {
        if ( (temp = strchr(temp, '=')) != NULL )
            *(temp++) = '\0';
        else
            endMessage("ERROR", errorString(201));

        value = temp;

        if ( (temp = strchr( temp, '&' )) != NULL )
            *(temp++) = '\0';

        addKey( parseHex( key ), parseHex( value ) );

        key = temp;
    }

    delete [] front;
}

void
CGIparse::endMessage( const char* title, const char* message )
{
    //non-browser messages
    if ( title == NULL )
    {
        cerr << message << "\n\n";
        exit(0);
    }

    //prints web error message and terminates application
    //===================================================
    printMime(); //send mime-type if not sent yet

    cout
        << "<table border=\"1\" width=\"415\">\n"
        << "    <tr bgcolor=\"000088\">\n"
        << "        <td><font face=\"Arial\" size=\"2\" color=\"ffffff\">"
        << "<b>" << title << "</b></font></td>\n"
        << "    </tr>\n"
        << "    <tr>\n"
        << "        <td>\n"
        << "            <font face=Arial><i>" << message << "</i></font>\n"
        << "            <hr noshade>\n"
        << "            <font face=Arial size=1>CGIparse library by Michael Olivero"
        << " (<a href=\"mailto:mike95@mediaone.net\">mike95@mediaone.net</a>)</font>\n"
        << "        </td>\n"
        << "    </tr>\n"
        << "</table>" << endl;

    exit( 0 );
}

const char*
CGIparse::parseHex( char* hexstr ) const
{
    //======================
    //Return an empty string
    //======================
    if ( hexstr == NULL || strlen( hexstr ) == 0 )
        return "";

    register UINT x,y;
    for ( x = 0, y = 0; hexstr[y]; x++, y++ )
    {
        if( (hexstr[x] = hexstr[y]) == '+' )
        {
            hexstr[x] = ' ';
            continue;
        }
        else if ( hexstr[x] == '%' )
        {
            hexstr[x] = convertHex(&hexstr[y+1]);
            y+=2;
        }
    }
    hexstr[x] = '\0';
    return hexstr;
}

const UINT
CGIparse::convertHex( const char* what ) const
{
    //0x4f == 01001111 mask

    register char digit;
    digit = (what[0] >= 'A' ? ((what[0] & 0x4F) - 'A')+10 : (what[0] - '0'));
    digit *= 16;
    digit += (what[1] >='A' ? ((what[1] & 0x4F) - 'A')+10 : (what[1] - '0'));

    return digit;
}

CGIparse::~CGIparse()
{
    node* itr = NULL;
    while( m_head )
    {
        itr = m_head;
        m_head = m_head->link;

        delete itr;
    }

    delete [] m_method;
}

void
CGIparse::addKey( const char* aKey, const char* aValue )
{
    if ( m_tail != NULL )
        m_tail = m_tail->link = new node( aKey, aValue );
    else
        m_head = m_tail = new node( aKey, aValue );

    m_size++;
}

void
CGIparse::replaceKey( const char* aKey, const char* aValue )
{
    node* itr = m_head;
    while( itr != NULL )
    {
        if ( strcmp( itr->key, aKey ) == 0 )
        {
            const UINT length = strlen( aValue );
            if ( length > strlen(itr->value) )
            {
                delete [] itr->value;
                itr->value = new char[ length + 1 ];
            }

            strcpy( itr->value, aValue );
            break;
        }

        itr = itr->link;
    }
}

void
CGIparse::removeKey( const char* aKey )
{
    node* itr = m_head;

    //check for null pointer
    if ( itr == NULL )
        return;

    //first check the head
    if ( strcmp( itr->key, aKey ) == 0 )
    {
        m_head = itr->link;

        if ( m_head == NULL )
            m_tail = NULL;

        delete itr;

        m_size--;
        return;
    }

    //loop through all the other values
    //=================================
    while( itr->link != NULL )
    {
        if ( strcmp( itr->link->key, aKey ) == 0 )
        {
            node* toDelete = itr->link;        //for deletion
            itr->link = itr->link->link;

            if ( itr->link == NULL )
                m_tail = itr;

            delete toDelete;
            
            m_size--;
            break;
        }
        
        itr = itr->link;
    }
}

//properly formats a neat HTML table of key/value pairs stored in the object
//==========================================================================
void
CGIparse::formDump()
{
    printMime();

    const node* itr = m_head;

    if ( itr != NULL )
    {
        cout << "<table border=1 width=100%>\n"
             << "    <tr valign=top>\n"
             << "        <th bgcolor=000000 colspan=2><font color=ffffff>Method: <i>"
             << m_method << "</i> " << "Browser: <i>" << HTTP_USER_AGENT << "</i></font></th>"
             << "    </tr>\n"
             << "    <tr valign=top>\n"
             << "        <th bgcolor=ff0000><b>Keys</b></th><th bgcolor=ff0000><b>Values</b></th>\n"
             << "    </tr>\n";

       while( itr != NULL )
        {
            cout << "    <tr valign=top>\n"
                << "        <td bgcolor=00aaff>" << itr->key << "</td>\n"
                << "        <td>" << itr->value << "</td>\n"
                << "    </tr>" << endl;

            itr = itr->link;
        }

        cout << "</table>" << endl;
    }
}


const char*
CGIparse::valueOf( const char* aKey )
{
    node* itr = m_head;

    while( itr != NULL )
    {
        if ( strcmp( itr->key, aKey ) == 0 )
        {
            m_marker = itr;
            return itr->value;
        }

        itr = itr->link;
    }

    m_marker = NULL;
    return NULL;
}

const char*
CGIparse::getNextValue( )
{
    //getNextValue() must be called after a valueOf() function call.
    //This provides support for mutilple values for a single key as
    //in multiple selection boxes
    //=============================================================
    if ( m_marker != NULL )
    {
        const char* curKey = m_marker->key;
        const node* nextLink = m_marker->getLink();

        if ( nextLink != NULL )
        {
            if ( strcmp(nextLink->key, curKey) == 0 )
            {
                m_marker = m_marker->getLink();
                return m_marker->value;
            }
            else
                m_marker = NULL;
        }
        else
            m_marker = NULL;
    }

    return NULL;
}

//check if a particualar key exists
//=================================
bool
CGIparse::defined( const char* aKey ) const
{
    const node* itr = m_head;

    while( itr != NULL )
    {
        if ( strcmp( itr->key, aKey ) == 0 )
            return true;
        itr = itr->link;
    }

    return false;
}

void
CGIparse::envDump( )
{
    const char* user_agent = HTTP_USER_AGENT;
    if ( user_agent != NULL )
    {
        printMime();

        cout
            << "<table border=\"1\" width=\"100%\">\n"
            << "    <tr valign=\"top\">\n"
            << "        <th bgcolor=\"000000\" colspan=\"2\">"
            << "<font color=\"ffffff\">CGI Enviroment Variable Dump</font></th>\n"
            << "    </tr>\n"
            << "    <tr valign=\"top\">\n"
            << "        <th bgcolor=\"ff0000\"><b>Variable<b></th>"
            << "<th bgcolor=\"ff0000\"><b>Value</b></th>\n"
            << "    </tr>\n" << endl;
    }
    else
    {
        cout << setw(25) << ios::left << "Environment Variable"
            << setw(55) << "Value\n"
            << setw(25) << "===================="
            << setw(55) << "====================" << endl;
    }

#ifdef _WIN32
    //Environment traversal for Windows95/NT
    //======================================
    char** search = _environ;
    char* temp = NULL;
    UINT cur_length, max_length = 0;
    while( *search )
    {
        cur_length = strlen( *search );
        if ( cur_length > max_length )
        {
            max_length = cur_length;
            delete [] temp;
            temp = new char[ cur_length + 1 ];
        }
        strcpy( temp, *search );
        *strrchr( temp, '=' ) = '\0';

        if ( user_agent != NULL )
            cout << "    <tr><td bgcolor=\"00aaff\"><b>" << temp
                << "</b></td><td>" << (temp + strlen(temp) + 1) << "</td></tr>\n";
        else
            printf("%-40s%-40s\n", temp, temp + strlen(temp) + 1);
        
        search++;
    }
    delete [] temp;
#else
    //Standard ENV vars returned for others
    //=====================================
    char* temp[] = { "AUTH_TYPE", "GATEWAY_INTERFACE", "LOGON_USER",
                    "REQUEST_METHOD", "QUERY_STRING", "CONTENT_LENGTH",
                    "CONTENT_TYPE", "DOCUMENT", "DOCUMENT_URI",
                    "DOCUMENT_ROOT", "HTTP_ACCEPT", "HTTP_ACCEPT_LANGUAGE",
                    "HTTP_CONNECTION", "HTTP_HOST", "HTTP_REFERER",
                    "HTTP_USER_AGENT", "HTTP_COOKIE", "REMOTE_ADDR",
                    "REMOTE_HOST", "REMOTE_USER", "REMOTE_IDENT",
                    "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_ADMIN",
                    "SERVER_PORT", "SERVER_PROTOCOL", "SERVER_SOFTWARE",
                    "SERVER_NAME", "PATH", "PATH_INFO",
                    "PATH_TRANSLATED" };
    
    const UINT size = sizeof(temp) / sizeof(char*);
    for( UINT i = 0; i < size; i++ )
    {
        const char* value = getenv(temp[i]);
        if ( value != NULL )
        {
            if ( user_agent != NULL )
                cout << "    <tr><td bgcolor=\"00aaff\"><b>" << temp[i]
                    << "</b></td><td>" << value << "</td></tr>" << endl;
            else
                printf("%-40s%-40s\n", temp[i], value);
        }
    }
#endif

    if ( user_agent != NULL )
        cout << "</table>" << endl;
}

//sends mime type to client, default mime type is "text/html"
//to terminate the mime heading for the client, either one of
//of the following forms of printMime must be called:
//    printMime();
//    printMime( "text/html" ); //same as previous
//    printMime( "other mime", true );    //true signals mime is complete
//=====================================================================
void CGIparse::printMime( const char* mime, bool isLast )
{
    if ( !mime_sent )
    {
        cout << "Content-type: " << mime << endl;

        if ( isLast || strcmp(mime, "text/html") == 0 )
        {
            cout << endl;        //terminate mime header
            mime_sent = true;
        }
    }
}

//custom error messages for CGIparse class
//========================================
const char*
CGIparse::errorString( const UINT number ) const
{
    switch( number )
    {
    case 100:
        return "QUERY_STRING is formated incorrectly";
    case 101:
        return "QUERY_STRING enviornment is 'NULL'";
    case 102:
        return "CONTENT_LENGTH enviornment is 'NULL'";
    case 103:
        return "REQUEST_METHOD enviornment is 'NULL'";
    case 201:
        return "Value string is missing in a [key=value] pair";
    case 300:
        return "Must be executed by a browser with a QUERY or FORM";

    default:
        return "No Message Specified";
    }
}


(c)2024 Mike95.com / Site Disclaimer
Site Meter