//-----------------------------------------------------------------------------
// Copyright © 2003 - Philip Howard - All rights reserved
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//-----------------------------------------------------------------------------
// package	libh/cgi
// purpose	Demonstrate the cgi_form_parse() function call in a test CGI
//		which can also be a useful web debugging tool.
// homepage	http://libh.slashusr.org/
//-----------------------------------------------------------------------------
// author	Philip Howard
// email	libh at ipal dot org
// homepage	http://phil.ipal.org/
//-----------------------------------------------------------------------------
// This file is best viewed using a fixed spaced font such as Courier
// and in a display at least 120 columns wide.
//-----------------------------------------------------------------------------
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#include <libh/cgi.h>
#include <libh/html.h>

//-----------------------------------------------------------------------------
// program	test.cgi
//
// purpose	A CGI diagnostic tool which displays all CGI form variables
//		sent to the web server from the web browser during a form
//		submission using GET method or POST method, or other web
//		request.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// main
//-----------------------------------------------------------------------------
int main(
    int		argc
    ,
    char * *	argv
    ,
    char * *	envp
    )
{
    char *	request_method	;

    int		n		;


    //-----------------------------------------------
    // Make sure we are running in a CGI environment.
    //-----------------------------------------------
    request_method = getenv( "REQUEST_METHOD" );
    if ( ! request_method ) {
	fprintf( stderr,
		 "Environment variable REQUEST_METHOD is missing.\n"
		 "This program needs to be run as web based CGI.\n"
	);
	return 1;
    }

    //---------------------------------------
    // Check to see if we are running as NPH.
    // Output the HTTP response if so.
    //---------------------------------------
    {
	char * p;
	char * q;
	p = * argv;
	q = p;
	while ( * p ) if ( * p ++ == '/' ) q = p;
	if ( memcmp( "nph-" , q , 4 ) == 0 ) {
	    printf( "HTTP/1.0 200 OK\r\n" );
	}
    }

    //-------------------------------------
    // Output the rest of the HTTP headers.
    //-------------------------------------
    printf( "Content-type: text/html\r\n"
	    "\r\n"
	);
    fflush( stdout );

    //----------------------------------------
    // Make sure this is a GET or POST method.
    //----------------------------------------
    if ( strcmp( request_method , "GET" ) != 0
      && strcmp( request_method , "POST" ) != 0 ) {
	printf( "<html>\n"
		"<head>\n"
		"<title>%s</title>\n"
		"</head>\n"
		"<body bgcolor=\"#ffffff\">\n"
		"<h1>%s</h1>\n",
		"Invalid Request-Method",
		"Invalid Request-Method"
	);
	printf( "<h3>Expected: GET or POST</h3>\n"
		"<h3>Got: "
	);
	html_asis( request_method , ~0 );
	printf( "</h3>\n"
		"</body>\n"
		"</html>\n"
	);
	return 0;
    }

    //-------------------------------
    // Output the title for the page.
    //-------------------------------
    printf( "<html>\n"
	    "<head>\n"
	    "<title>%s</title>\n"
	    "</head>\n"
	    "<body bgcolor=\"#ffffff\">\n"
	    "<h1>%s</h1>\n",
	    "CGI test page",
	    "CGI test page"
    );
    fflush( stdout );

    //---------------------------------------
    // Output the system information section.
    //---------------------------------------
    printf( "<h1>System information</h1>\n"
	    "<table border=0 cellspacing=4 cellpadding=4>\n"
	    "<tr>"
	    "<td bgcolor=\"#e9e9e9\">name</td>\n"
	    "<td bgcolor=\"#e9e9e9\">numeric<br>value</td>\n"
	    "<td bgcolor=\"#e9e9e9\">string<br>length</td>\n"
	    "<td bgcolor=\"#e9e9e9\">string value</td>\n"
	    "</tr>"
    );

    //--------------------------------------------------
    // Show the current working directory from getcwd().
    //--------------------------------------------------
    {
	char * cwd;
	if ( (cwd = getcwd( NULL , 0 )) ) {
	    printf( "<tr>\n"
		    "<td bgcolor=\"#ffe9e9\">"
		    "<code>cwd</code></td>"
		    "<td></td>\n"
		    "<td bgcolor=\"#e9ffe9\" align=right>%lu</td>\n"
		    "<td bgcolor=\"#e9e9ff\"><code>",
		    (unsigned long) strlen( cwd )
	    );
	    html_asis( cwd , ~0 );
	    printf( "</code></td>\n"
		    "</tr>\n" );
	    free( cwd );
	}
    }

    //-------------------------------------------
    // Show the real userid number and name and
    // show the effective userid number and name.
    //-------------------------------------------
    printf( "<tr>\n"
	    "<td bgcolor=\"#ffe9e9\">"
	    "<code>%s</code></td>\n"
	    "<td bgcolor=\"#ffffe9\" align=right>"
	    "<code>%lu</code></td>\n"
	    "<td bgcolor=\"#e9ffe9\" align=right>"
	    "<code>%lu</code></td>\n"
	    "<td bgcolor=\"#e9e9ff\">"
	    "<code>%s</code></td>\n"
	    "</tr>\n",
	    "euid"+1,
	    (unsigned long) getuid(),
	    (unsigned long) strlen(getpwuid(getuid())->pw_name),
	    getpwuid(getuid())->pw_name
    );
    printf( "<tr>\n"
	    "<td bgcolor=\"#ffe9e9\">"
	    "<code>%s</code></td>\n"
	    "<td bgcolor=\"#ffffe9\" align=right>"
	    "<code>%lu</code></td>\n"
	    "<td bgcolor=\"#e9ffe9\" align=right>"
	    "<code>%lu</code></td>\n"
	    "<td bgcolor=\"#e9e9ff\">"
	    "<code>%s</code></td>\n"
	    "</tr>\n",
	    "euid",
	    (unsigned long) geteuid(),
	    (unsigned long) strlen(getpwuid(geteuid())->pw_name),
	    getpwuid(geteuid())->pw_name
    );
    printf( "<tr>\n"
	    "<td bgcolor=\"#ffe9e9\">"
	    "<code>%s</code></td>\n"
	    "<td bgcolor=\"#ffffe9\" align=right>"
	    "<code>%lu</code></td>\n"
	    "<td bgcolor=\"#e9ffe9\" align=right>"
	    "<code>%lu</code></td>\n"
	    "<td bgcolor=\"#e9e9ff\">"
	    "<code>%s</code></td>\n"
	    "</tr>\n",
	    "egid"+1,
	    (unsigned long) getgid(),
	    (unsigned long) strlen(getgrgid(getgid())->gr_name),
	    getgrgid(getgid())->gr_name
    );
    printf( "<tr>\n"
	    "<td bgcolor=\"#ffe9e9\">"
	    "<code>%s</code></td>\n"
	    "<td bgcolor=\"#ffffe9\" align=right>"
	    "<code>%lu</code></td>\n"
	    "<td bgcolor=\"#e9ffe9\" align=right>"
	    "<code>%lu</code></td>\n"
	    "<td bgcolor=\"#e9e9ff\">"
	    "<code>%s</code></td>\n"
	    "</tr>\n",
	    "egid",
	    (unsigned long) getegid(),
	    (unsigned long) strlen(getgrgid(getegid())->gr_name),
	    getgrgid(getegid())->gr_name
    );
    printf( "</table>\n" );

    //-------------------------------------------------------------
    // Output the command argument list that main() is called with.
    //-------------------------------------------------------------
    printf( "<h1>Number of arguments is: %d</h1>\n" , argc );
    if ( argc ) {
	int argn;
	argn = 0;
	printf( "<table border=0 cellspacing=4 cellpadding=4>"
		"<tr>"
		"<td bgcolor=\"#e9e9e9\">len</td>\n"
		"<td bgcolor=\"#e9e9e9\">value of argument</td>\n"
		"</tr>"
	);
	while ( argc -- ) {
	    printf( "<tr>\n"
		    "<td bgcolor=\"#e9ffe9\" align=right>"
		    "<code>%d</code></td>\n"
		    "<td bgcolor=\"#e9e9ff\">",
		    argn
	    );
	    if ( argv[ argn ] ) {
		printf( "<code>" );
		html_asis( argv[ argn ] , ~0 );
		printf( "</code>" );
	    }
	    printf( "</td>\n"
		    "</tr>\n"
	    );
	    ++ argn;
	}
	printf( "</table>\n" );
    }
    fflush( stdout );

    //--------------------------------------
    // Output all the environment variables.
    //--------------------------------------
    {
	char * * p;

	n = 0;
	p = envp;
	while ( * p ) {
	    ++ n;
	    ++ p;
	}
	printf( "<h1>Number of environment variables is: %d</h1>\n"
		"<table border=0 cellspacing=4 cellpadding=4>"
		"<tr>"
		"<td bgcolor=\"#e9e9e9\">name</td>\n"
		"<td bgcolor=\"#e9e9e9\">len</td>\n"
		"<td bgcolor=\"#e9e9e9\">value of environment variable</td>\n"
		"</tr>",
		n
	    );
	p = envp;

	//-- Step through each environment variable and output it.
	while ( * p ) {
	    char * q;
	    q = * p;
	    printf( "<tr>\n"
		    "<td bgcolor=\"#ffe9e9\">"
		    "<code>"
		);
	    while ( * q != '\0' && * q != '=' ) ++ q;
	    html_asis( * p , q - * p );
	    printf( "</code></td>\n"
		    "<td bgcolor=\"#e9ffe9\" align=right><code>"
		);
	    if ( * q ) {
		++ q;
		printf( "%lu</code>"
			"</td>\n"
			"<td bgcolor=\"#e9e9ff\">",
			(unsigned long)strlen(q)
		    );
		printf( "<code>" );
		html_asis( q , ~0 );
		printf( "</code>" );
	    }
	    else {
		printf( "-</code>"
			"<td bgcolor=\"#e9e9ff\">"
		    );
	    }
	    printf( "</td>\n"
		    "</tr>\n"
		);
	    ++ p;
	}
    }

    //-------------------------------------------
    // Close the table for environment variables.
    //-------------------------------------------
    printf( "</table>\n" );
    fflush( stdout );

    //---------------------------------
    // Output QUERY data and POST data.
    //---------------------------------
    n = 0;
    for (;;) {
	char * varstr;
	char * valstr;
	size_t varlen;
	size_t vallen;
	int src;

	//-- Get the next form variable.
	src = cgi_form_parse( & varstr , & varlen , & valstr , & vallen );
	if ( ! src ) break;

	//-- If the data method is different than previous,
	//-- split the table with a header in between.
	if ( src != n ) {
	    if ( n > 0 ) {
		printf( "</table>\n" );
		fflush( stdout );
	    }
	    printf( "<h1>Form data from %s method</h1>\n"
		    "<table border=0 cellspacing=4 cellpadding=4>\n"
		    "<tr>\n"
		    "<td bgcolor=\"#e9e9e9\">len</td>\n"
		    "<td bgcolor=\"#e9e9e9\">name string</td>\n"
		    "<td bgcolor=\"#e9e9e9\">len</td>\n"
		    "<td bgcolor=\"#e9e9e9\">converted value string</td>\n"
		    "</tr>\n",
		    ((src==1)?"QUERY":"POST")
	    );
	    n = src;
	}

	//-- Output the length and string of the name name and its value.
	printf( "<tr>\n"
		"<td bgcolor=\"#e9ffe9\" align=right>%lu</td>\n"
		"<td bgcolor=\"#ffe9e9\">"
		"<code>",
		(unsigned long) varlen
	);
	html_asis( varstr , varlen );
	printf( "</td>\n"
		"<td bgcolor=\"#e9ffe9\" align=right>%lu</td>\n"
		"<td bgcolor=\"#e9e9ff\">"
		"<code>",
		(unsigned long) vallen
	);
	html_asis( valstr , vallen );
	printf( "</td>\n"
		"</tr>\n"
	);
    }

    //-- If there were any variables, then close the table.
    if ( n > 0 ) {
	printf( "</table>\n" );
	fflush( stdout );
    }

    //-- All done.  Finish up and exit.
    printf( "</body></html>\n" );
    fflush( stdout );

    return 0;
}

