/*****************************************************************************/
/*
                             CgiLib_example.c

Simple example showing the essential elements of using the CGILIB routines.

Demonstrates:  *  initializing the environment
               *  alternate processing according to the environment
               *  getting CGI variables
               *  generating responses
               *  processing POSTed requests

Remember, the behaviours of these scripts are WATCHable.

The $COUNT and $SLEEP logical names were added to allow testing of server
behaviour where a CGIplus script, programmed to exit elegantly after processing
a given number of requests, revealed a timing issue that, depending on the
run-down speed of the script, could result in an HTTP 502 status rather than
transparent reactivation as described in the April 1998 note in the
[SRC.HTTPD]DCL.C module.  This script used from the CGILIB_EXAMPLE.HTML
document was a convenient tool to test the server fix using both GET and POST
requests.


LOGICAL NAMES
-------------
CGILIB_EXAMPLE$COUNT  an integer for exit() after this many CGIplus requests
CGILIB_EXAMPLE$DBUG   turns on all "if (Debug)" statements
CGILIB_EXAMPLE$SLEEP  an integer to sleep this many seconds before exiting


BUILD DETAILS
-------------
$ @BUILD_ONE BUILD CGILIB_EXAMPLE
$ @BUILD_ONE LINK CGILIB_EXAMPLE


COPYRIGHT
---------
Copyright (C) 1999-2005 Mark G.Daniel
This program, comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under the conditions of the GNU GENERAL PUBLIC LICENSE, version 2.


VERSION HISTORY
---------------
15-OCT-2005  MGD  v1.2.1, CGILIB_EXAMPLE$COUNT and CGILIB_EXAMPLE$SLEEP
28-OCT-2000  MGD  v1.2.0, use CGILIB object module
12-APR-2000  MGD  v1.1.1, minor changes for CGILIB 1.4 (Apache)
24-SEP-1999  MGD  v1.0.0, initial development
*/

/*****************************************************************************/

/* standard C header files */
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* application related header file */
#include <cgilib.h>

/* global storage */

int  CgiPlusCount,
     CgiPlusSleep,
     CgiPlusUsage,
     Debug,
     IsCgiPlus;

char  *CgiContentTypePtr,
      *CgiQueryStringPtr,
      *CgiRequestMethodPtr;

/*****************************************************************************/
/*
*/

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

   /*********/
   /* begin */
   /*********/

   if (Debug = (getenv ("CGILIB_EXAMPLE$DBUG") != NULL))
   {
      CgiLibEnvironmentSetDebug (Debug);
      fprintf (stdout, "Content-Type: text/plain\r\n\r\n");
   }

   if (cptr = getenv ("CGILIB_EXAMPLE$COUNT"))
   {
      CgiPlusCount = atoi(cptr);
      if (cptr = getenv ("CGILIB_EXAMPLE$SLEEP"))
         CgiPlusSleep = atoi(cptr);
      else
         CgiPlusSleep = 1;
   }

   CgiLibEnvironmentInit (argc, argv, 0);

   IsCgiPlus = CgiLibEnvironmentIsCgiPlus ();

   if (IsCgiPlus)
   {
      for (;;)
      {
         /* block waiting for the next request */
         CgiLibVar ("");
         ProcessRequest ();
         CgiLibCgiPlusEOF ();
         if (CgiPlusCount)
         {
            CgiPlusCount--;
            if (!CgiPlusCount)
            {
               if (CgiPlusSleep) sleep (CgiPlusSleep);
               exit (1);
            }
         }
      }
   }
   else
      ProcessRequest ();
}

/*****************************************************************************/
/*
*/

ProcessRequest ()
       
{
   int  Context;
   char  *VariablePtr;

   /*********/
   /* begin */
   /*********/

   if (Debug) fprintf (stdout, "ProcessRequest()\n");

   CgiRequestMethodPtr = CgiLibVar ("WWW_REQUEST_METHOD");

   if (CgiLibEnvironmentIsWasd())
   {
      /* need this to be record-oriented for the DCL output records */
      CgiLibEnvironmentRecordOut ();
   }

   /* generate an HTTP header, plain-text content-type */
   CgiLibResponseHeader (200, "text/plain");

   fprintf (stdout, "Current environment is \"%s\" (%s)\n\n",
      CgiLibEnvironmentName(), CGILIB_SOFTWAREID);

   if (CgiLibEnvironmentIsCgiPlus())
      fprintf (stdout, "Usage count is %d.\n\n", ++CgiPlusUsage);

   if (CgiLibEnvironmentIsWasd() ||
       CgiLibEnvironmentIsApache())
   {
      fprintf (stdout,
"These are the CGI variables contained in the subprocess' DCL symbols:\n\n");

      /* with standard CGI the variables are all in DCL symbols */
      system ("SHOW SYMBOL WWW_*");
   }

   if (!strcmp (CgiRequestMethodPtr, "POST"))
      ProcessPost ();
   else
   if (CgiLibEnvironmentIsCgiPlus() ||
       CgiLibEnvironmentIsOsu())
   {
      fprintf (stdout,
"These are the CGI variables created from the %s:\n\n",
         CgiLibEnvironmentIsCgiPlus() ? "CGIPLUSIN stream" :
                                        "OSU dialog phase");

      while ((VariablePtr = CgiLibVarNull ("*")) != NULL)
         fprintf (stdout, "  %s\n", VariablePtr);
   }

   CgiQueryStringPtr = CgiLibVar ("WWW_QUERY_STRING");
   if (strchr (CgiQueryStringPtr, '=') != NULL)
   {
      fprintf (stdout,
"\nHere are the form elements of QUERY_STRING via CgiLibFormEncodedParse():\n\n");

      Context = 0;
      while ((VariablePtr =
              CgiLibFormEncodedParse (CgiQueryStringPtr, &Context)) != NULL)
         fprintf (stdout, "  %s\n", VariablePtr);
   }
}

/*****************************************************************************/
/*
*/

ProcessPost ()
       
{
   int  Context,
        PostBufferCount;
   char  *VariablePtr,
         *PostBufferPtr;

   /*********/
   /* begin */
   /*********/

   if (Debug) fprintf (stdout, "ProcessPost()\n");

   /* read the POSTed request body */
   CgiLibReadRequestBody (&PostBufferPtr, &PostBufferCount);
   if (PostBufferPtr == NULL ||
       PostBufferCount == 0)
   {
      CgiLibResponseError (__FILE__, __LINE__, 0, "No body in the POST!");
      return;
   }

   CgiContentTypePtr = CgiLibVar ("WWW_CONTENT_TYPE");

   if (!strcmp (CgiContentTypePtr, "application/x-www-form-urlencoded"))
   {
      /* is URL form encoded, turn that into pseudo CGI variables */
      CgiLibFormRequestBody (PostBufferPtr, PostBufferCount);

      fprintf (stdout,
"Request was via a POSTed form.\n\n\
Here are the form elements converted to pseudo CGI variables:\n\n");

      if (CgiLibEnvironmentIsCgiPlus())
         fprintf (stdout,
"(via CGIplus, so you'll also see the CGI environment variables)\n");
      else
      if (CgiLibEnvironmentIsOsu())
         fprintf (stdout,
"(via OSU, so you'll also see the CGI environment variables)\n\n");

      while ((VariablePtr = CgiLibVarNull ("*")) != NULL)
         fprintf (stdout, "  %s\n", VariablePtr);

      fprintf (stdout,
"\nHere are the form elements via CgiLibFormEncodedParse():\n\n");

      Context = 0;
      while ((VariablePtr =
              CgiLibFormEncodedParse (PostBufferPtr, &Context)) != NULL)
         fprintf (stdout, "  %s\n", VariablePtr);

      free (PostBufferPtr);
   }
   else
   {
      /* we'll just assume it's a body of displayable text */
      CgiLibResponseHeader (200, "text/plain");
      fputs (PostBufferPtr, stdout);
      free (PostBufferPtr);
   }
}

/*****************************************************************************/

