/*****************************************************************************/
/*
                                 GiftCgi.c

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

#define SOFTWAREVN "1.0.1"
#define SOFTWARENM "GIFT(CGI)"
#ifdef __ALPHA
   char SoftwareID [] = SOFTWARENM " AXP-" SOFTWAREVN;
#endif
#ifdef __ia64
   char SoftwareID [] = SOFTWARENM " IA64-" SOFTWAREVN;
#endif
#ifdef __VAX
   char SoftwareID [] = SOFTWARENM " VAX-" SOFTWAREVN;
#endif

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

/* VMS header files */
#include <descrip.h>
#include <ssdef.h>
#include <stsdef.h>

/* application header files */
#include "gift.h"

#define VMSok(x) ((x) & STS$M_SUCCESS)
#define VMSnok(x) !(((x) & STS$M_SUCCESS))

#define boolean int
#define true 1
#define false 0

/* macro provides NULL pointer if CGI variable does not exist */
#define GetCgiVarIfExists(CharPointer,CgiVariableName) \
   CharPointer = getenv(CgiVariableName)

/* macro provides pointer to empty string even if CGI variable does not exist */
#define GetCgiVar(CharPointer,CgiVariableName) \
   if ((CharPointer = getenv(CgiVariableName)) == NULL) \
       CharPointer = ""; \
   if (Debug) fprintf (stdout, "%s |%s|\n", CgiVariableName, CharPointer);

char  Http200Header [] =
"HTTP/1.0 200 Document follows.\r\n\
Content-Type: text/html\r\n\
\r\n";

char  Http404Header [] =
"HTTP/1.0 404 Error report follows.\r\n\
Content-Type: text/html\r\n\
\r\n";

boolean  Debug,
         HttpHasBeenOutput;

char  *CgiFormDoPtr,
      *CgiPathInfoPtr,
      *CgiPathTranslatedPtr,
      *CgiQueryStringPtr,
      *CgiScriptNamePtr;

FILE  *HttpOut;

/* externs from Gift.c */
extern int  GraphicBackground,
            GraphicBitsPerPixel,
            GraphicByteCount,
            GraphicColourBorder,
            GraphicColourBg,
            GraphicColourCount,
            GraphicColourFg,
            GraphicHeight,
            GraphicHttpOutFd,
            GraphicFontPoints,
            GraphicPixelCount,
            GraphicTransparencyColour,
            GraphicWidth,
            GraphicWidthBorder,
            GraphicWidthFg;

extern unsigned char  *GraphicPtr;

extern struct GraphicFontStruct  Font [];

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

main ()

{
   register int  idx, x, y;

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

   if (getenv ("GIFT$DBUG") != NULL)
   {
      Debug = true;
      system ("SHOW SYM WWW_*");
   }

   /* open another output stream so that the "\n" are not filtered */
#ifdef __DECC
   if ((HttpOut = fopen ("SYS$OUTPUT", "w", "ctx=bin")) == NULL)
      exit (vaxc$errno);
#else
   if ((HttpOut = fopen ("SYS$OUTPUT", "w", "rfm=udf")) == NULL)
      exit (vaxc$errno);
#endif

   GetCgiVar (CgiScriptNamePtr, "WWW_SCRIPT_NAME");
   GetCgiVar (CgiPathInfoPtr, "WWW_PATH_INFO");
   GetCgiVar (CgiPathTranslatedPtr, "WWW_PATH_TRANSLATED");
   GetCgiVar (CgiQueryStringPtr, "WWW_QUERY_STRING");
   GetCgiVar (CgiFormDoPtr, "WWW_FORM_DO");

   GiftInitFonts ();

   if (CgiFormDoPtr[0])
      GiftParseParameters (CgiFormDoPtr, 0);
   else
      GiftParseParameters (CgiQueryStringPtr, 0);

   if (strsame (CgiPathInfoPtr, "/button/", 8))
   {
      /* local storage */
      register char  *cptr, *sptr;
      boolean  Transparent;
      int  SlashCount;
      char  Text [256];

      Transparent = false;
      SlashCount = 0;
      for (cptr = CgiPathInfoPtr+8; *cptr; cptr++)
         if (*cptr == '/') SlashCount++;
      cptr = CgiPathInfoPtr + 8;
      while (SlashCount--)
      {
         for (sptr = cptr; *sptr && *sptr != '/'; sptr++);
         if (*sptr) *sptr++ = '\0';
         if (isdigit(*cptr))
         {
            GraphicFontPoints = atol(cptr);
            GiftCheckFont (GraphicFontPoints);
         }
         else
         if (strsame (cptr, "trans", 5))
            Transparent = true;
         else
            GraphicColourFg = GiftColour (cptr);
         cptr = sptr;
      }
      GiftCopyTextFromUrl (cptr, Text, sizeof(Text));
      if (Transparent) GraphicTransparencyColour = GraphicColourFg;
      GiftDrawButton (GraphicColourFg, Text, &Font[GraphicFontPoints]);
      exit (SS$_NORMAL);
   }

   if (strsame (CgiPathInfoPtr, "/test/colours", -1) ||
       strsame (CgiPathInfoPtr, "/test/colors", -1))
   {
      GiftTestColours ();
      exit (SS$_NORMAL);
   }
   if (strsame (CgiPathInfoPtr, "/test/fonts", -1))
   {
      GiftTestFonts ();
      exit (SS$_NORMAL);
   }
   if (strsame (CgiPathInfoPtr, "/test/graphics", -1))
   {
      GiftTestGraphics ();
      exit (SS$_NORMAL);
   }
   if (strsame (CgiPathInfoPtr, "/test/button", -1))
   {
      GiftButton ("", " Test\nButton", DefaultButtonFontPoints);
      exit (SS$_NORMAL);
   }
   if (strsame (CgiPathInfoPtr, "/test/error", -1))
   {
      GiftGraphicErrorReport ("Bogus error message :^)\n(second line ...\nand third)");
      exit (SS$_NORMAL);
   }
   if (strsame (CgiPathInfoPtr, "/test/usage", -1))
   {
      /* local storage */
      unsigned long  BinTime [2];
      unsigned short  NumTime [7];
      char  String [64];

      sys$gettim (&BinTime);
      sys$numtim (&NumTime, &BinTime);
      sprintf (String, "Usage-Bar: %d%% (alert at 85%%)", NumTime[6]);
      GiftUsageBar (NumTime[6], 85, String);
      exit (SS$_NORMAL);
   }

   if (GraphicPtr == NULL)
      exit (GiftGraphicErrorReport ("No graphic generated!"));

   GiftImage ();

   exit (SS$_NORMAL);
}

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

ErrorGeneral
(
char *Text,
char *SourceFileName,
int SourceLineNumber
)
{
   register char  *cptr;

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

   /* 
      The source file format provided by the "__FILE__" macro will be
      "device:[directory]name.type;ver".  Reduce that to "name.type".
   */
   for (cptr = SourceFileName; *cptr && *cptr != ';'; cptr++);
   if (*cptr)
   {
      while (*cptr != '.') cptr--;
      *cptr-- = '\0';
   }
   while (*cptr != ']') cptr--;
   cptr++;

   if (!HttpHasBeenOutput) fputs (Http404Header, HttpOut);
   fprintf (HttpOut,
"<!-- SoftwareID: %s Module: %s Line: %d -->\n\
<H1>ERROR!</H1>\n\
<P>Reported by server.\n\
<P>%s\n",
   SoftwareID, cptr, SourceLineNumber, Text);

   return (SS$_NORMAL);
}

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

ErrorVmsStatus
(
int StatusValue,
char *Text,
char *HiddenText,
char *SourceFileName,
int SourceLineNumber
)
{
   static char  Message [256];
   static $DESCRIPTOR (MessageDsc, Message);

   register char  *cptr;
   int  status;
   short int  Length;

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

   if (VMSok (status = sys$getmsg (StatusValue, &Length, &MessageDsc, 1, 0))) 
   {
      Message[Length] = '\0';
      Message[0] = toupper(Message[0]);
   }
   else
      exit (status);

   /* 
      The source file format provided by the "__FILE__" macro will be
      "device:[directory]name.type;ver".  Reduce that to "name.type".
   */
   for (cptr = SourceFileName; *cptr && *cptr != ';'; cptr++);
   if (*cptr)
   {
      while (*cptr != '.') cptr--;
      *cptr-- = '\0';
   }
   while (*cptr != ']') cptr--;
   cptr++;

   if (!HttpHasBeenOutput) fputs (Http404Header, HttpOut);
   fprintf (HttpOut,
"<!-- SoftwareID: %s Module: %s Line: %d -->\n\
<H1>ERROR!</H1>\n\
<P>Reported by server.\n\
<P>%s ... <TT>%s</TT>\n\
<!-- %%X%08.08X \"%s\" -->\n",
   SoftwareID, cptr, SourceLineNumber, Message, Text, StatusValue, HiddenText);

   return (SS$_NORMAL);
}

/****************************************************************************/
/*
Does a case-insensitive, character-by-character string compare and returns 
true if two strings are the same, or false if not.  If a maximum number of 
characters are specified only those will be compared, if the entire strings 
should be compared then specify the number of characters as 0.
*/ 

boolean strsame
(
register char *sptr1,
register char *sptr2,
register int  count
)
{
   while (*sptr1 && *sptr2)
   {
      if (toupper (*sptr1++) != toupper (*sptr2++)) return (false);
      if (count)
         if (!--count) return (true);
   }
   if (*sptr1 || *sptr2)
      return (false);
   else
      return (true);
}

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