///////////////////////////////////////////////////////////////////////////////
// CGISetup Code                                                           //
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Author:  Hexar William Anderson                                           //
// Date:    10/25/2000                                                       //
// Desc:    This class does all of the work for you when it comes to         //
//          separating CGI input into name/value pairs.  Then, you can access//
//          these values by name or by number.                               //
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// COPYRIGHT NOTICE                                                          //
// Copyright (c) 2001 Hexar W. Anderson                                      //
//                                                                           //
// CGISetup may be used and modified free of charge by anyone so long as this//
// copyright notice remains intact.  By using this code you agree to         //
// indemnify Hexar Anderson from any liability that might arise from its use.//
//                                                                           //
// Attempting to sell the source code for this program without prior written //
// consent is expressly forbidden.  Obtain permission before redistributing  //
// this software over the Internet or any other medium.                      //
///////////////////////////////////////////////////////////////////////////////
 
 
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <ctype.h>
 
#include "cgisetup.h"
 
 
// Functions to be called from outside ////////////////////////////////////////
 
 
int setup(struct cgi *real)
{
char *method;
int len;
char *s;
int i, j;
int values;
int num;
char *temp;
 
 
// Set the number of name/value pairs to zero initially
real->num = 0;
 
 
// Check the Request Method
method = (char*)getenv("REQUEST_METHOD");
if (!method)
   return -1;
 
if (strcmp(method, "POST") == 0)
  {
   // Get the content length
   len = atoi(getenv("CONTENT_LENGTH"));
 
  }
else if (strcmp(method, "GET") == 0)
  {
   s = getenv("QUERY_STRING"); // Sets source string
  
   if (s == NULL)
      return -1;
 
   len = strlen(s);
  }
else
   return -1;
   
// Allocate temporary strings s and temp
temp = (char*)malloc(len + 1);
temp[len] = 0;
 
 
if (strcmp(method, "POST") == 0) // Set source string
  {
   s = (char*)malloc(len + 1);
   s[len] = 0;
 
   // Read the POST data from STDIN into s.
   for (i = 0; i < len; i++)
     {
      s[i] = getchar();
     }
   s[i] = 0;
  }
 
  
// Count the number of name/value pairs using countchars() and countstrings()
values = countchars('&', s) + 1 - countstrings("=&", s);
 
// Initialize the pointers-to-pointers for an array of strings
real->num = values;
real->name = (char**)malloc(values * sizeof(char*));
real->value = (char**)malloc(values * sizeof(char*));
 
 
// Loop through every name/value pair
 
i = 0;
for (num = 0; num < values; num++)
  {
   // Look for an '=', copy characters until = into temp.
   for (j = 0; s[i] != '='; i++, j++)
     {
      temp[j] = s[i];
     }
   temp[j] = 0; // denote the end of temp.
   i++;
 
   if (s[i] == '&')
     {
      // This is an empty value.  Forget we even read temp.
      num--;
      i++;
      continue;
     }
 
   // Convert temp into non-encoded form
   fix(temp);
 
   // Allocate memory for this particular name and copy from temp
   real->name[num] = (char*)malloc(strlen(temp)+1);
   strcpy(real->name[num], temp);
 
   // Now read characters on the right side of =
   for (j = 0; s[i] != '&' && i < len; i++, j++)
     {
      temp[j] = s[i];
     }
    temp[j] = 0;
 
    // Decode temp again
    fix(temp);
 
    // Allocate memory for this value and copy from temp
    real->value[num] = (char*)malloc(strlen(temp)+1);
    strcpy(real->value[num], temp);
    i++;
  }
 
 
// Deallocate our temporary strings
free(s);
free(temp);
 
return 0;
}
 
 
char *findval(struct cgi *real, const char *name)
{
int i;
 
for (i = 0; i < real->num; i++)
  {
   if (strcmp(real->name[i], name) == 0)
      return real->value[i];
  }
 
return "";
}
 
void movefile(const char *from, const char *to)
{
FILE *f1, *f2;
char ch;
 
f1 = fopen(from, "r");
f2 = fopen(to, "w");
 
while (!feof(f1))
  {
   ch = getc(f1);
   if (!feof(f1))
     fputc(ch, f2);  
  }
 
fclose(f1);
fclose(f2);
 
unlink(from);
 
return;
}
 
 
void viewfile(const char *fname)
{
FILE *f1;
char ch;
 
f1 = fopen(fname, "r");
 
while (!feof(f1))
  {
   ch = getc(f1);
   if (!feof(f1)) 
      putchar(ch);
  }
 
fclose(f1);
 
return;
}
 
void freecgi(struct cgi *real)
{
int i;
 
for (i = 0; i < real->num; i++)
  {
   free(real->name[i]);
   free(real->value[i]);
  }
 
free(real->name);
free(real->value);
 
}
 
 
// Internal Utility functions /////////////////////////////////////////////////
 
int countchars(char ch, const char *string)
{
int count = 0;
int len;
int i;
 
len = strlen(string);
 
for (i = 0; i < len; i++)
  {
   if (string[i] == ch)
      count++;
  }
 
return count;
}
 
int countstrings(const char *lookfor, const char *lookin)
{
int i;
int len, len2;
int count = 0;
 
len = strlen(lookin);
len2 = strlen(lookfor);
 
for (i = 0; i < len && len2 + i <= len; i++)
  {
   if (strncmp(&lookin[i], lookfor, len2)==0)
      count++;
  }
  
return count;
}
 
void fix(char *s)
{
char *temp;
int i, j;
 
// Convert the spaces
replace(s, '+', ' ');
 
temp = malloc(strlen(s) * sizeof(char) + 1);
 
j = 0;
for (i = 0; i < strlen(s); i++)
  {
   // Decode Hex values
   if (s[i] == '%')
     {
      temp[j++] = convhex(s[i+1]) * 16 + convhex(s[i+2]);
      i += 2;
     }
   // Or just copy everything else
   else
     temp[j++] = s[i];
  }
 
temp[j] = 0;
 
strcpy(s, temp);
 
free(temp);
  
return;
}
 
 
int convhex(char ch)
{
int ans;
 
if (isdigit(ch))
   return ch-'0';
 
ans = toupper(ch);
return 10 + ans - 'A';
 
}
 
void replace(char *s, char from, char to)
{
int i;
int len;
 
len = strlen(s);
for (i = 0; i < len; i++)
   if (s[i] == from)
      s[i] = to;
 
return;
}
 
 
 
void strlwr(char *s)
{
int i;
 
for (i = 0; i < strlen(s); i++)
  s[i] = tolower(s[i]);
 
return;
}

All material Copyright (c) 2001-2010 Hexar
Please direct all inquiries, love letters, and hate mail to .

Home •  Blog •  Photos •  Code •  Features •  Resume •  WinTetris