⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cgi.c

📁 稀疏矩阵、链表、图、队列、二叉树、多叉树、排序、遗传算法等的实现
💻 C
字号:
/*  cgi.c - CGI Utilities 
*
*
*  Copyright (C) 1999   Chad Dixon
*                       Macmillan Computer Publishing
*
*  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., 675 Mass Ave,
*  Cambridge, MA 02139, USA.
*
*  Chad Dixon may be contacted by email at:
*     http://www.loopy.org
*
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cgi.h"

/* DupString()
 *
 * This code may remind you of the strdup() function
 * provided by many compilers; strdup() is not, however,
 * part of the ANSI C standard library. To be totally
 * portable, therefore, we should 'roll our own'.
 * This function returns NULL if the string cannot be
 * duplicated, either because the input pointer is NULL
 * or because there is insufficient memory to make a copy.
 * Otherwise it returns a pointer to the copy.
 * Note: if the function succeeds, we will need to
 * free() the pointer returned by DupString(), once we
 * are finished with that memory.
 */
char *DupString(const char *s)
{
  char *Dup = NULL;
  if(s != NULL)
  {
    Dup = malloc(strlen(s) + 1);
    if(Dup != NULL)
    {
      strcpy(Dup, s);
    }
  }
  return Dup;
}

/* ReadCGIData()
 *
 * This function assumes your data is coming
 * either from GET or POST, and returns a
 * pointer to a safe copy of that data.
 * You are responsible for freeing the
 * memory pointed to by its return value,
 * if the function succeeded.
 *
 * Error return:
 *    NULL
 *    *Error loaded with one value from
 *      CGI_SUCCESS
 *      CGI_NULL_REQ_METHOD
 *      CGI_UNKNOWN_METHOD
 *      CGI_NO_QUERY_STRING
 *      CGI_NO_MEMORY
 *      CGI_BAD_CONTENT_LENGTH
 *      CGI_NO_DATA
 *    all of which are defined in cgi.h
 *
 */

char *ReadCGIData(int *Error)
{
  char *Buffer = NULL;
  char *RequestMethod = NULL;
  char *ContentLength = NULL;
  char *CGIData = NULL;

  size_t Size = 0;

  *Error = CGI_SUCCESS;

  RequestMethod = getenv("REQUEST_METHOD");
  if(NULL == RequestMethod)
  {
    *Error = CGI_NULL_REQ_METHOD;
  }
  
  if(0 == *Error)
  {
    if(strcmp(RequestMethod,"GET") == 0)
    {
      /* GET */
      CGIData = getenv("QUERY_STRING");
      if(NULL == CGIData)
      {
        *Error = CGI_NO_QUERY_STRING;
      }
      else
      {
        Buffer = DupString(CGIData);
        if(NULL == Buffer) 
        {
          *Error = CGI_NO_MEMORY;
        }
      }
    }
    else if(strcmp(RequestMethod,"POST") == 0)
    {
      /* POST */
      ContentLength = getenv("CONTENT_LENGTH");
      if(NULL == ContentLength)
      {
        *Error = CGI_BAD_CONTENT_LENGTH;
      }
      if(0 == *Error)
      {
        Size = (size_t)atoi(ContentLength);
        if(Size <= 0)
        {
          *Error = CGI_BAD_CONTENT_LENGTH;
        }
      }
      if(0 == *Error)
      {
        ++Size;
        Buffer = malloc(Size);
        if(NULL == Buffer)
        {
          *Error = CGI_NO_MEMORY;
        }
        else
        {
          if(NULL == fgets(Buffer, Size, stdin))
          {
            *Error = CGI_NO_DATA;
            free(Buffer);
            Buffer = NULL;
          }
        }
      }
    }
    else
    {
      *Error = CGI_UNKNOWN_METHOD;
    }
  }

  return Buffer;
}

/* CGIHexToAscii()
 *
 * Converts CGI %xx values to their ASCII equivalents.
 *
 */

int CGIHexToAscii(char *s)
{
  /* Set Error to non-zero on error */
  int Error = 0;

  /* It's going to be very convenient to
   * have all the hexadecimal digits in
   * a contiguous, ordered string
   */
  static const char *Hex = "0123456789ABCDEF";

  /* We'll use this to store an offset
   * into the Hex array.
   */
  unsigned int Ascii = 0;

  /* This is basically a spare pointer.
   * We walk it along the list, using
   * it as the current place for storing
   * characters.
   */
  char *p;

  /* non-NULL if a valid hexadecimal digit was found */
  char *Match;

  /* For each character in the string... */
  for(p = s; !Error && *s != '\0'; s++)
  {
    /* Is it a hex-coded character? */
    if(*s == '%')
    {
      /* Yes. Leaving p behind, move s on to
       * the first byte of the encoding.
       */
      s++;

      /* It had better be in the Hex string.
       * If not, that's an error in the data.
       */
      if((Match = strchr(Hex, *s)) != NULL)
      {
        /* We can now calculate the high nybble of the
         * ASCII equivalent of the coded character.
         */
        Ascii = (unsigned int)(Match - Hex);

        /* And now we do the whole thing
         * again for the low nybble.
         */
        s++;
        if((Match = strchr(Hex, *s)) != NULL)
        {
          /* Move the high nybble out of the way */
          Ascii <<= 4;
          Ascii |= (unsigned int)(Match - Hex);

          /* Now we can update the string.
           * Note that p lags behind s by two characters
           * for each hex-encoded character in the data.
           */
          *p++ = (char)Ascii;
        }
        else
        {
          Error = 1;
        }
      }
      else
      {
        Error = 1;
      }
    }
    /* If it's not a hex-encoded character, could it
     * be a +, which needs to become a space?
     */
    else if(*s == '+')
    {
      *p++ = ' ';
    }
    /* No? In which case we just copy the character. */
    else
    {
      *p++ = *s;
    }
  }
  if(!Error)
  {
    /* Let's not forget to zero-terminate the string. */
    *p = '\0';
  }
  return Error;
}

/* CGIDestroyList()
 *
 * Destroys a list built by CGICreateList.
 *
 */
void CGIDestroyList(CGI_LIST *List)
{
  CGI_LIST *Next = NULL;

  while(List != NULL)
  {
    Next = List->Next;
    if(List->Variable != NULL)
    {
      free(List->Variable);
    }
    /* Note: we don't free Value because
     * it is pointing into the Variable
     * area anyway.
     */
    free(List);
    List = Next;
  }
}

/* CGICreateList()
 *
 * Creates a list of CGI variable/value pairs.
 *
 */
CGI_LIST *CGICreateList(char *Data)
{
  /* The list base pointer */
  CGI_LIST *CGIList;
  /* Our current position within the list */
  CGI_LIST *CurrItem = NULL;

  /* If we get any error, however slight, ditch
   * the whole list and walk off the pitch.
   */
  int Error = 0;

  /* One field. Tokenised from Data using '=' */
  char *Field;

  /* Get some memory for the base node */
  CGIList = malloc(sizeof *CGIList);
  if(CGIList != NULL)
  {
    /* Point travelling pointer to base of list */
    CurrItem = CGIList;

    /* Get the first field. Because strtok modifies its
     * input, we can't use the query string directly in
     * case it was stored in the environment variable
     * (GET method) which is why we made a copy earlier.
     */
    Field = strtok(Data, "&\n");
    if(NULL == Field)
    {
      Error = 1; /* No data! */
    }

    /* For each field */
    while(0 == Error && Field != NULL)
    {
      /* Convert encoded characters (eg %21 to '!') */
      if(CGIHexToAscii(Field) != 0)
      {
        Error = 1;
      }
      else
      {
        /* Ensure that default values are in place
         * NB can't use memset because we have no
         * assurance from the ANSI Standard that
         * NULL has a bit pattern of all bits zero.
         */
        CurrItem->Value    = NULL;
        CurrItem->Next     = NULL;

        /* Copy the field data for safe keeping */
        CurrItem->Variable = DupString(Field);
        if(NULL == CurrItem->Variable)
        {
          Error = 2;
        }
        else
        {
          /* Start at Variable */
          CurrItem->Value = CurrItem->Variable;

          /* Keep going unti we hit '=' */
          while(*CurrItem->Value != '\0' &&
                *CurrItem->Value != '=')
          {
            ++CurrItem->Value;
          }
          if('\0' == *CurrItem->Value)
          {
            Error = 3;
          }
          else
          {
            /* Zero-terminate Variable */
            *CurrItem->Value = '\0';
            /* Point to first byte of value */
            ++CurrItem->Value;
          }
        }
      }

      if(0 == Error)
      {
        /* Get next token */
        Field = strtok(NULL, "&\n");
        if(Field != NULL)
        {
          /* allocate memory for next node */
          CurrItem->Next = malloc(sizeof *CurrItem->Next);
          if(NULL == CurrItem->Next)
          {
            Error = 1;
          }
          else
          {
            CurrItem = CurrItem->Next;
          }
        }
      }
    }
    /* If anything went wrong, bin the whole list */
    if(Error != 0)
    {
      CGIDestroyList(CGIList);
      CGIList = NULL;
    }
  }
  return CGIList;
}

/* end of cgi.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -