/*****************************************************************************/
/*
                              CGIplusDemo.c

Simple program that can be used in both standard CGI and CGIplus environments.
The standard CGI section merely echoes the remote host name (lacking any
mechanism to list all variables ... apart perhaps from a SHOW SYMBOL WWW_*).
The CGIplus section uses two methods to access the CGI variables. One just
reads CGIPLUSIN checking each line for the required variable (and displaying
them as it goes). The other uses a more sophisticated function that processes
the CGIplus variables and the allows queries on variable names, etc. This
function is presented as a template in CGIplusSkel.c

Defining the logical name CGIPLUSDEMO$STRUCT causes this demo to use 'struct'
mode rather than 'record mode' for for passing the CGIplus variables.


COPYRIGHT
---------
Copyright (C) 1997-2022 Mark G.Daniel

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


VERSION HISTORY (update SOFTWAREVN as well!)
---------------
06-OCT-2004  MGD  v1.4.0, CGILIB object module
23-DEC-2003  MGD  v1.3.2, minor conditional mods to support IA64
30-NOV-2002  MGD  v1.3.1, bugfix; every second CGIplus request incorrectly
                          having the variables read by CgiPlusReader();
05-APR-2001  MGD  v1.3.0, demo/test CGIplus variable 'struct',
                          body via CGIPLUSIN
24-APR-1999  MGD  v1.2.0, use CGILIB.C
21-JUN-1998  MGD  v1.1.0, revision of CgiVar()
08-JUN-1997  MGD  v1.0.0, initial development
*/
/*****************************************************************************/

#define SOFTWAREVN "1.4.0"
#define SOFTWARENM "CGIPLUSDEMO"
#ifdef __ALPHA
#  define SOFTWAREID SOFTWARENM " AXP-" SOFTWAREVN
#endif
#ifdef __ia64
#  define SOFTWAREID SOFTWARENM " IA64-" SOFTWAREVN
#endif
#ifdef __x86_64
#  define SOFTWAREID SOFTWARENM " X86-" SOFTWAREVN
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>

#include "cgilib.h"

char  Utility [] = "CGIPLUSDEMO";

int  Debug,
     IsCgiPlus,
     UsageCounter,
     UseCgiPlusVarStruct;

char  *CgiPlusEofPtr;

char  FirstUsedDateTime [32],
      NowDateTime [32];

unsigned long  UnixTime;
struct tm  *UnixTmPtr;

void CgiPlusDemo ();
void CgiPlusReader ();
void CgiStandardDemo ();

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

main ()

{
   /*********/
   /* begin */
   /*********/

   if (getenv ("CGIPLUSDEMO$DBUG")) Debug = 1;

   CgiLibEnvironmentSetDebug (Debug);

   UseCgiPlusVarStruct = (int)getenv("CGIPLUSDEMO$STRUCT");

   time (&UnixTime);
   UnixTmPtr = localtime (&UnixTime);
   if (!strftime (FirstUsedDateTime, sizeof(FirstUsedDateTime),
                  "%a, %d %b %Y %T", UnixTmPtr))
      strcpy (FirstUsedDateTime, "[error]");

   /* demonstrate the ease with which it may operate in both environments */
   IsCgiPlus = (int)(CgiPlusEofPtr = getenv("CGIPLUSEOF"));

   do {

      time (&UnixTime);
      UnixTmPtr = localtime (&UnixTime);
      if (!strftime (NowDateTime, sizeof(NowDateTime),
                     "%a, %d %b %Y %T", UnixTmPtr))
         strcpy (NowDateTime, "[error]");

      if (IsCgiPlus)
         CgiPlusDemo ();
      else
         CgiStandardDemo ();

   } while (IsCgiPlus);

   exit (1);
}

/*****************************************************************************/
/*
Using standard CGI.  Get CGI variable data using getenv(), not using the
function CgiLibVar() illustrated below.
*/

void CgiStandardDemo ()

{
   char  *cptr;

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

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

   fprintf (stdout,
"Content-Type: text/plain\n\
Expires: Thu, 01 Jan 1970 00:00:01 GMT\n\
\n\
Number of times used: %d (standard CGI)\n\
First used: %s\n\
Now: %s\n\
\n",
      ++UsageCounter, FirstUsedDateTime, NowDateTime);

   if (cptr = getenv("WWW_REMOTE_ADDR"))
      fprintf (stdout, "Remote-Addr: %s\n", cptr);
   else
      fprintf (stdout, "Remote-Addr: NOT FOUND!\n");
}

/*****************************************************************************/
/*
Alternate between the two methods of obtaining CGI variables in the CGIplus
environment.  First, using the function CgiLibVar(), which allows specific
variable names to be queried.  Second, using a simple read of <stdin>,
checking for the variable names required.
*/

void CgiPlusDemo ()

{
   static int  WasCgiPlusVarStruct = 0;

   char  *cptr;

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

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

   if (UseCgiPlusVarStruct)
   {
      /* wait for the next request */
      CgiLibVar ("");

   fprintf (stdout,
"Content-Type: text/plain\n\
Expires: Thu, 01 Jan 1970 00:00:01 GMT\n\
\n\
Number of times used: %d (CGIplus)\n\
First used: %s\n\
Now: %s\n\
Using: CgiLibVar() in %s mode\n\
\n",
      ++UsageCounter, FirstUsedDateTime, NowDateTime,
      WasCgiPlusVarStruct ? "STRUCT" : "RECORD");

      /* list all CGIplus variables names and values one-by-one */
      while (cptr = CgiLibVar ("*"))
      {
         if (!strncmp (cptr, "WWW_REMOTE_HOST=", 16))
            fprintf (stdout, "Remote-Host: %s\n", cptr+16);
         else
            fprintf (stdout, "|%s|\n", cptr);
      }

      /* query on the supplied variable name */
      fprintf (stdout, "\n");
      if (*(cptr = CgiLibVar ("WWW_REMOTE_ADDR")))
         fprintf (stdout, "Remote-Addr: %s\n", cptr);
      else
         fprintf (stdout, "Remote-Addr: NOT FOUND!\n");

      /* illustrate variable query when not found */
      if (*(cptr = CgiLibVar ("WWW_BOGUS_VARIABLE")))
         fprintf (stdout, "Bogus-Variable: %s\n", cptr);
      else
         fprintf (stdout, "Bogus-Variable: NOT FOUND!\n");

      if (UseCgiPlusVarStruct)
      {
         if (!WasCgiPlusVarStruct) CgiLibCgiPlusSetVarStruct ();
         WasCgiPlusVarStruct = 1;
      }
      else
      if (WasCgiPlusVarStruct)
      {
         CgiLibCgiPlusSetVarRecord ();
         WasCgiPlusVarStruct = 0;
      }
   }
   else
   {
      /* process the variables using a simple read loop */
      CgiPlusReader ();
   }

   /* record-oriented <stdout>, no need to flush, write end-of-output line */
   fprintf (stdout, "%s\n", CgiPlusEofPtr);
}

/*****************************************************************************/
/*
CGIplus variable access method 1 (simple).

Use a simple loop to read lines from standard input.  Detect specific CGI
variables by checking the leading section of these lines for the required
variable name.  The value may then be extracted from the remaining section.
*/

void CgiPlusReader ()

{
#  define CGIPLUS_LINE_SIZE 1024

   int  LineCount = 0;
   char  *cptr;
   char  Line [CGIPLUS_LINE_SIZE];
   FILE  *CgiPlusIn;

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

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

   if (!(CgiPlusIn = fopen (getenv("CGIPLUSIN"), "r")))
      exit (vaxc$errno);

   /* wait for request, discard initial record */
   if (!(fgets (Line, sizeof(Line), CgiPlusIn))) exit (vaxc$errno);

   fprintf (stdout,
"Content-Type: text/plain\n\
\n\
Number of times used: %d (CGIplus)\n\
First used: %s\n\
Now: %s\n\
Using: CgiPlusReader()\n\
\n",
      ++UsageCounter, FirstUsedDateTime, NowDateTime);

   for (;;)
   {
      if ((fgets (Line, sizeof(Line), CgiPlusIn))) exit (vaxc$errno);
      /* first empty line signals the end of CGIplus variables */
      if (Line[0] == '\n') break;
      /* remove the trailing newline */
      for (cptr = Line; *cptr && *cptr != '\n'; cptr++);
      *cptr = '\0';

      /* select only the variable(s) we are interested in */
      if (!strncmp (Line, "WWW_REMOTE_HOST=", 16))
         fprintf (stdout, "Remote-Host: %s\n", Line+16);
      else
         fprintf (stdout, "|%s|\n", Line);
   }

   fclose (CgiPlusIn);
}

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

