Solved

Passing parameter to a C CGI.

Posted on 2000-03-31
4
418 Views
Last Modified: 2013-12-25
Experts,

Is it possible to pass parameter to a C CGI from a form, like we used to do on a command line:

    pgm arg1 arg2 ...

Thanks in advance for your help.
0
Comment
Question by:szetoa
  • 2
4 Comments
 
LVL 16

Expert Comment

by:maneshr
Comment Utility
sure you can do that.

here is a sample code in C that will do exactly that....


/************************************************************************\
*                                                                        *
* CookMail                                                               *
* Version 2.13                                                           *
* (c) Copyright Heng Yuan 1996                                           *
* All Rights Reserved.                                                   *
*                                                                        *
* This program can be easily modified to handle forms other than email.  *
* To do so, search the string "WISH" to get to the right place.          *
* Do NOT distribute this program in any modified format.                 *
*                                                                        *
*                                                                        *
* Description:                                                           *
*      A Form Handling CGI script for Unix                               *
*                                                                        *
\************************************************************************/

#ifdef MS
#define DOS
#endif

#ifdef DOS
#include <windows.h>
#endif

#include <stdio.h>
#include "html.h"
#include "string.h"
#include "btree.h"
#include "mime.h"

/*----------------------------------------------------------------------*\
 *                                                                      *
 *   -- YOU MAY CONFIGURE THIS PART --                                  *
 *                                                                      *
\*----------------------------------------------------------------------*/

/* default mailer program */
#ifdef DOS
/* specific handling of BLAT */
static char MAILER[100] = "cookblat.exe";
/* TEMP is the directory where you store all the cookmail temp
   files.  The filenames will be owebm*.html.  Make sure that
   your server is configured with virtual directory /tmp pointed
   to here,
   In LITE version, virtual directory is not needed, but this
   directory is still required.
 */
char TEMP[200] = "TEMP=C:\\TEMP";
#else
static char MAILER[] = "/usr/lib/sendmail";
#endif

/* default forms */
static char FORMform[] = "\
From: ${EMAIL} (${NAME})\n\
Subject: ${SUBJECT}\n\
To: ${TO}\n\
\n\
${MESSAGE}\n\
${ETC}\n";

static char SHOWform[] = "\
<HTML>\n\
<HEAD>\n\
<TITLE>Thank You Note</TITLE>\n\
</HEAD>\n\
<BODY>\n\
<H1>Thank You Note</H1>\n\
Thank you for taking the time to fill out of this form.  Below is what you have submitted.\n\
<HR>\n\
<B>From</B>: ${EMAIL} (${NAME})<BR>\n\
<B>Subject</B>: ${SUBJECT}<BR>\n\
<B>To</B>: ${TO}\n\
<HR>\n\
<PRE>\n\
${MESSAGE}\n\
${ETC}\n\
</PRE>\n\
<HR>\n\
<A HREF=${HTTP_REFERER}><B>Go Back<B></A>\n\
</BODY>\n\
</HTML>\n";

static char CCFORMform[] = "\
From: ${TO} (${REPLYNAME})\n\
Subject: ${SUBJECT}\n\
To: ${EMAIL} (${NAME})\n\
\n\
Thank You For Your Information:\n\
===============================\n\
From: ${EMAIL} (${NAME})\n\
Subject: ${SUBJECT}\n\
To: ${TO}\n\
\n\
${MESSAGE}\n\
${ETC}\n\
===============================\n\
URL: ${HTTP_REFERER}\n";

static char EMPTYform [] = "\
<HTML>\n\
<HEAD>\n\
<TITLE>Data Error</TITLE>\n\
</HEAD>\n\
<BODY>\n\
<H1>Data Error</H1>\n\
Sorry, the following field must not be blank.\n\
<HR>\n\
<CODE>${EMPTYERROR}</CODE>\n\
<HR>\n\
Please go back and fill the form again.\n\
</BODY>\n\
</HTML>\n";

/* This part is for C programmer only */
/* this envhandle only work for those forms without FORM or SHOW field */
void envhandle (btree *env, FILE *f)
{
  char separator[] = "======================================================";
  fprintf (f, "\n%s\n%.*s\n%s\n", env->data, (int)strlen (env->data), separator, getnodedata (env));
/*
  Explaination :
  env->data is the name of the environmental variable which hold the non
    default field name
  \n is carriage return
  strlen (env->data) is the length of the ENV string
  separator is the line which separate the field name and field content
  getnodedata (env) is the content of the ENV field
  Example:
    FOOD=Extra Large Stuffed Pizza
  Where FOOD is the field name and Pizza is the content, the output result
  will be:
    FOOD
    ====
    Extra Large Stuffed Pizza
*/
}

/*------------------------------------------------------------------------*\
 *                                                                        *
 *     -- END OF CONFIGURATION ** DO NOT MODIFY ANYTHING BELOW --         *
 *                                                                        *
\*------------------------------------------------------------------------*/

/* predefined field names for email */
static char FORM[] = "FORM";         /* email form file */
static char SHOW[] = "SHOW";         /* show form file */
static char EMPTY[] = "EMPTY";       /* empty form file */
static char NAME[] = "NAME";         /* name of sender */
static char EMAIL[] = "EMAIL";       /* email addr of sendor */
static char TO[] = "TO";             /* email address of recipient */
static char SUBJECT[] = "SUBJECT";   /* email subject */
static char MESSAGE[] = "MESSAGE";   /* email message */
static char MIME[] = "MIME";         /* mime encoding for email message */
static char CC[] = "CC";             /* carbon copy email to sender */
static char CCFORM[] = "CCFORM";     /* Cc email form */
static char REPLYNAME[] = "REPLYNAME"; /* for CCFORM, name for TO */

/* defined in html.c */
extern char EMPTYHANDLE[];
extern char EMPTYERROR[];
extern char MULTIPLE[];
extern char MULTIPLEMARK[];

/* predefined field name for returning info */
static char REDIRECT[] = "REDIRECT"; /* default prewritten html */

/* tmpfile name contain the translated form */
static char TMPFILE[256];

/* translate forms and return the file name contain the result */
int translate (const char *);

/* read a file into a buffer */
char *fileread (FILE *fin);

/* display the current cookmail version */
void showversion ()
{
#ifndef LITE
  puts ("CookMail Version 2.13.");
#else
  puts ("CookMail Lite Version 2.13.");
#endif
#ifdef MS
  puts ("This version display HTTP/1.0 200 OK before CGI headers.");
#endif
  puts ("\n\
(c) Copyright 1996, 1997, 1998 Heng Yuan\n\
\n\
Please visit the CookMail homepage at\n\
\thttp://ag.arizona.edu/~heng/cookmail/cookmail.html\n\
for the latest version and other information.");
}

/* read TMPFILE and display it on the web using HTML */
void showtmpfile ()
{
  #ifndef LITE
    #ifdef DOS
      sprintf (TMPFILE, "/tmp/%s", &TMPFILE[strlen (getenv ("TEMP")) + 1]);
      showhtml (TMPFILE);
    #else
      showhtml (TMPFILE);
    #endif
  #else
    FILE *fin = fopen (TMPFILE, "rb");
    char *buffer = fileread (fin);
    showoutput (HTML);
    if (buffer)
      {
      fputs (buffer, stdout);
      free (buffer);
      }
    else
      puts ("Error: out of memory");
    fclose (fin);
    remove (TMPFILE);
  #endif
}

int main ()
{
  int i;
  /* obviously we are not running under appropriet conditions */
  if (REQUEST_METHOD == NULL)
    {
      showversion ();
      return 0;
    }

  /* hmm, we are called not as form handler,
     we must be used as to display HTTP_REFERER */
  if (strcasecmp (REQUEST_METHOD, "GET") == 0 &&
      (QUERY_STRING == NULL ||
       strlen (QUERY_STRING) == 0))
    {
      char *h;
      showoutput (HTML);
      h = HTTP_REFERER;
      if (h != NULL)
      putsf ("<INPUT TYPE=HIDDEN NAME=HTTP_REFERER VALUE=%s>", h);
      return 0;
    }

  #ifdef DOS
    putenv (TEMP);
  #endif

  i = getmethod ();      /* read all fields */
  switch (i)
    {                    /* handle returned message */
      case 0:
        break;
      case 1:            /* Forced EMPTYERROR */
      if (translate (EMPTY) == 0)
        showtmpfile ();
      return 0;
      default:         /* death value */
      showoutput (PLAIN);
      putsf ("Error: internal unknown error id %d, possibily out of memory", i);
      return -1;
    }

  i = strlen (getformdata ("TO"));
  if (i == 0)          /* no address */
    {
      showoutput (PLAIN);
      puts ("Error: no recipient address");
      return -1;
    }

  if (strspn (getformdata ("TO"), "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@.0123456789,-_ \t") < i)    /* invalid address */
    {
      showoutput (PLAIN);
      puts ("Error: invalid characters in email address");
      return -1;
    }

  i = strlen (getformdata ("EMAIL"));
  if (i)
    {
      if (strspn (getformdata ("EMAIL"), "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@.0123456789,-_ \t") < i)    /* invalid address */
      {
        showoutput (PLAIN);
        puts ("Error: invalid characters in email address");
        return -1;
      }
    }

  /* translate email form */
  /* "WISH"
     change here if you wish to use commands other than sendmail to
     store form data.
     please do not distribute the modified form of this program.
   */
  if (translate (FORM) == 0)
    {
/*    char *COMMAND = (char *)malloc (sizeof (MAILER) + strlen (getformdata (TO)) + strlen (TMPFILE) + 2); */
      char *COMMAND = (char *)malloc (sizeof (MAILER) + strlen (getformdata (TO)) + strlen (TMPFILE) + 10);
      if (COMMAND)
      {
#ifdef DOS
        sprintf (COMMAND, "%s %s -t %s -q",
               MAILER,
               TMPFILE,
               getformdata (TO));
#else
        sprintf (COMMAND, "%s %s<%s",
               MAILER,
               getformdata (TO),
               TMPFILE);
#endif
        system (COMMAND);
        remove (TMPFILE);
        free (COMMAND);
      }
      else
      {
        showoutput (PLAIN);
        puts ("Error: unable to send email");
        return -1;
      }
    }
  else                              /* error */
    return -1;

  /* do the carbon copy form */
  if (strcasecmp (getformdata (CC), "on") == 0 &&
      !isemptyenv (getformdata (EMAIL)))
    {
      if (translate (CCFORM) == 0)
      {
/*        char *COMMAND = (char *)malloc (sizeof (MAILER) + strlen (getformdata (TO)) + strlen (TMPFILE) + 2); */
        char *COMMAND = (char *)malloc (sizeof (MAILER) + strlen (getformdata (TO)) + strlen (TMPFILE) + 10);
        if (COMMAND)
          {
#ifdef DOS
            sprintf (COMMAND, "%s %s -t %s -q",
                   MAILER,
                   TMPFILE,
                   getformdata (EMAIL));
#else
            sprintf (COMMAND, "%s %s<%s",
                   MAILER,
                   getformdata (EMAIL),
                   TMPFILE);
#endif
            system (COMMAND);
            remove (TMPFILE);
            free (COMMAND);
          }
      }
    }

  /* translate show form */
  if (strlen (getformdata (REDIRECT)) > 0)
    showhtml (getformdata (REDIRECT));
  else
    {
      if (translate (SHOW) == 0)
      showtmpfile ();

      /* assume tmp files are cleaned periodically.  You can do this
       by using cron/at jobs.  If you are hate to use cron/at jobs,
       use REDIRECT instead.
        "WARNING"
       someone can really fill up the tmp space very quickly if he
       wishs to do so.
       because the source of this program is available to public,
       hackers can always find some bugs :(  There is no good
       solution to this problem.  If you experenced such problem,
       remove this program immediately from your server */
      else
      showoutput (HTML);   /* display nothing */
    }
  return 0;
}

/* actural translation routin, shell script would have done this easier */
int translate (const char *form)
{
  FILE *fin, *fout;
  char *tmp, *tmp2, *tmp3;
  char *buffer;
  btree *usedtree = NULL;

  /* get form data */
  tmp = getformdata (form);
  if (tmp != NULL && strlen (tmp) > 0)      /* user has specified a form */
    {
      fin = fopen (tmp, "rb");  /* file not found :( */
      if (fin == NULL)
      {
        showoutput (PLAIN);
        putsf ("Error: unable to find %s formating file: %s\n", form, tmp);
        return -1;
      }
      buffer = fileread (fin);
      fclose (fin);
      if (buffer == NULL)
      {
        showoutput (PLAIN);
        putsf ("Error: empty %s formating file: %s\n", form, tmp);
        return -1;
      }
    }
  else
    {
      if (form == FORM)
      buffer = FORMform;
      else if (form == SHOW)
      buffer = SHOWform;
      else if (form == CCFORM)
      buffer = CCFORMform;
      else /* form == EMPTY */
      buffer = EMPTYform;
    }

  /* all the tmpfiles has a name of owebmXXXXXXX.html */
  /* "WARNING"
     you may have to create a link to /tmp directory in your
     httpd document root,
       ln -s /tmp tmp
     To prevent this directory from visible to the outside world,
     create an empty default HTML file in that directory, such as
     .html index.html index.htm default.htm or default.html
     If your system has a periodical program that removes aged
     files, you may have to create another program that touches
     this file regularly.  For instance,
       /bin/touch .html
  */
#ifdef DOS
  tmp = tempnam (getenv ("TEMP"), "owebm");
#else
  tmp = (char *)tempnam ("/tmp", "owebm");
#endif
  sprintf (TMPFILE, "%s.html", tmp);

  free (tmp);
  fout = fopen (TMPFILE, "wb+");
  if (fout == NULL)
    {
      showoutput (PLAIN);
      puts ("Error: unable to create temp file");
      return -1;
    }

  /* now start translating */

  tmp = buffer;        /* this pointer indicate position of last var */
  tmp2 = tmp;          /* this pointer indicate strchr result */
  tmp3 = tmp;          /* this pointer indicate position of last $ */

  if (usedtree == NULL)
    usedtree = addtree (NULL, strdup (http_referer), NULL, NULL);
  addtree (usedtree, strdup (TO), NULL, NULL);
  addtree (usedtree, strdup (NAME), NULL, NULL);
  addtree (usedtree, strdup (EMAIL), NULL, NULL);
  addtree (usedtree, strdup (SUBJECT), NULL, NULL);
  addtree (usedtree, strdup (MESSAGE), NULL, NULL);
  addtree (usedtree, strdup (EMPTYHANDLE), NULL, NULL);
  addtree (usedtree, strdup (MULTIPLE), NULL, NULL);
  addtree (usedtree, strdup (MULTIPLEMARK), NULL, NULL);
  addtree (usedtree, strdup (REDIRECT), NULL, NULL);
  addtree (usedtree, strdup (FORM), NULL, NULL);
  addtree (usedtree, strdup (SHOW), NULL, NULL);
  addtree (usedtree, strdup (EMPTY), NULL, NULL);
  addtree (usedtree, strdup (EMPTYERROR), NULL, NULL);
  addtree (usedtree, strdup (MIME), NULL, NULL);
  addtree (usedtree, strdup (CC), NULL, NULL);
  addtree (usedtree, strdup (CCFORM), NULL, NULL);
  addtree (usedtree, strdup (REPLYNAME), NULL, NULL);

  do
    {
      /* use ${var} pair to identify variable */
      tmp2 = strchr (tmp3, '$');
      if (tmp2 == NULL)
      fputs (tmp, fout); /* nothing found */
      else if (*(char *)(tmp2 + 1) != '{')
      tmp3 = tmp2 + 1;   /* false alarm */
      else
      {
        *tmp2 = '\0';
        fputs (tmp, fout);
        tmp = tmp2;
        tmp3 = tmp2 + 2;
        tmp2 = strchr (tmp3, '}');
        if (tmp2 == NULL) /* another false alarm? */
          {
            *tmp = '{';
            fputs (tmp, fout);
          }
        else
          {
            *tmp2 = '\0';
            if (strcmp (tmp3, "ETC") != 0)
            {
              tmp = getformdata (tmp3);
              /* add env to used list */
              addtree (usedtree, strdup (tmp3), NULL, NULL);
              if (tmp)  /* found the variable */
                fputs (tmp, fout);
            }
            else                               /* found ${ETC} */
            {
              if (linearstart)
                {
                  btree *temp = linearstart;
                  while (temp)
                  {
                    if (intree (usedtree, temp->data) != 0)
                      envhandle (temp, fout);
                    temp = temp->linearnext;
                  }
                }
            }
            tmp = tmp2 + 1;
            tmp3 = tmp;
          }
      }
    }
  while (tmp2 != NULL);

  if (buffer != FORMform && buffer != SHOWform && buffer != EMPTYform &&
      buffer != CCFORMform)
    free (buffer);
  trashtree (usedtree);

  /* end translating */

  /* mime processing */
  if ((form == FORM || form == CCFORM) &&
      strcasecmp (getformdata (MIME), "on") == 0)
    {
      char *ptr;
      buffer = fileread (fout);
      if (buffer)
      {
        ptr = mime_encode (buffer, strlen (buffer));
        if (ptr)
          {
            fseek (fout, 0, SEEK_SET);
            fputs (ptr, fout);
            free (ptr);
          }
        free (buffer);
      }
    }

  fclose (fout);

  return 0;
}

char *fileread (FILE *fin)
{
  char *buffer;
  int length;

  fseek (fin, 0, SEEK_END);
  length = ftell (fin);
  fseek (fin, 0, SEEK_SET);

  buffer = (char *)malloc (length + 1);
  buffer[length] = '\0';

  if (!buffer)
    return NULL;

  fread (buffer, 1, length, fin);
  return buffer;
}

0
 
LVL 23

Accepted Solution

by:
chensu earned 50 total points
Comment Utility
You should use hidden parameters just like other parameters along with the form. For example, this EE form uses the following hidden parameter to pass the qid value.

<input type="hidden" name="qid" value="10320837">
0
 
LVL 1

Author Comment

by:szetoa
Comment Utility
Let me digest them and will get back to you later.  Thanks.
0
 
LVL 1

Author Comment

by:szetoa
Comment Utility
Thanks chensu and maneshr.
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Preface This is the third article about the EE Collaborative Login Project. A Better Website Login System (http://www.experts-exchange.com/A_2902.html) introduces the Login System and shows how to implement a login page. The EE Collaborative Logi…
Browsers only know CSS so your awesome SASS code needs to be translated into normal CSS. Here I'll try to explain what you should aim for in order to take full advantage of SASS.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now