/* ***************************************************************************
*
* Copyright 1992-2003 by Pete Wilson All Rights Reserved
* 50 Staples Street : Lowell Massachusetts 01851 : USA
* http://www.pwilson.net/ pete@pwilson.net +1 978-454-4547
*
* This item is free software: you can redistribute it and/or modify it as
* long as you preserve this copyright notice. Pete Wilson prepared this item
* hoping it might be useful, but it has NO WARRANTY WHATEVER, not even any
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*************************************************************************** */
/* ***************************************************************************
*
* cgi-FORM-INPUT-DEMO.c
*
* CGI to demonstrate certain button/image/submit/reset properties
* Revision History:
*
* DATE VER DESCRIPTION
* ----------- ------ ----------------------------------------------------
* 5-oct-2002 1.0 original
*
*************************************************************************** */
/*
cgi-FORM-INPUT-DEMO.c -- report params passed to CGI from a form
*/
#include "cgi.h"
#define YELLOW "yellow" /* same as yellow hiliter */
#undef YELLOW
#define YELLOW "#ffff99" /* lighter yellow */
#undef LT_GREY
#define LT_GREY "#eeeeee" /* unobtrusive grey */
typedef struct {
char name[128];
char val[128];
} entry;
static int cmd_line; /* non-zero if entered via command line */
static RM this_rm;
RM *
get_request_method(void)
{
static RM * this_rm_p;
int i;
RM legal_rm[] =
{ {"UNKNOWN",UNKNOWN },
{"GET", GET },
{"POST", POST },
{"CONNECT",CONNECT },
{"DELETE", DELETE },
{"HEAD", HEAD },
{"OPTIONS",OPTIONS },
{"PUT", PUT },
{"TRACE", TRACE } };
#define N_RM sizeof(legal_rm)/sizeof(legal_rm[0])
if (this_rm_p == NULL)
{
this_rm_p = &this_rm;
this_rm.name = getenv("REQUEST_METHOD"); /* is there a REQUEST_METHOD? */
if (this_rm.name == NULL) /* no, we were called from command line */
{
this_rm.name = "";
this_rm.val = UNKNOWN;
cmd_line = 1;
}
else
{
for (i = 1; i < N_RM; ++i)
{
if (0 == strcasecmp(legal_rm[i].name, this_rm.name))
{
this_rm.val = legal_rm[i].val;
break;
}
}
}
}
return this_rm_p;
}
void getword(char *word, char *line, char stop);
char x2c(char *what);
void unescape_url(char *url);
void plustospace(char *str);
char *
map3(char ch)
{
static char p[2] = " ";
p[0] = (char) ch;
if (ch == '>') return ">";
if (ch == '<') return "<";
if (ch == '&') return "&";
return p;
}
int
ch_to_nybble(char c)
{
if (c >= '0' && c <= '9') return c - '0';
return (c & 7) + 9;
}
int
remap(char c1, char c2)
{
int i, j, k;
j = ch_to_nybble(c1);
k = ch_to_nybble(c2);
i = (j << 4) | k;
return i;
}
void
start_col_with_bg_color(char * bg_color)
{
}
void
print_name_and_val(entry * entries, int m)
{
int x, i;
printf("%c",10);
/* name[x] column */
printf("%c",10);
/* "name[x]: */
printf("%c",10);
printf("%c",10);
for(x=0; x <= m; x++)
{
printf("name[%d]: %c",x, 10);
}
printf(" | %c",10);
/* the name itself[x] */
printf("%c",10);
printf("%c",10);
for(x=0; x <= m; x++)
{
printf("%s %c",entries[x].name, 10);
}
printf(" | %c",10);
/* the string "val[x]" */
printf("%c",10);
printf("");
for(x=0; x <= m; x++)
{
printf("val[%d]: %c",x, 10);
}
printf("");
printf(" | %c",10);
/* the value val[x] */
printf("%c",10);
printf("");
for(x=0; x <= m; x++)
{
for(i = 0; entries[x].val[i] != '\0'; ++i)
{
printf("%s",map3(entries[x].val[i]));
}
printf(" %c", 10);
}
printf("");
printf(" | %c",10);
printf("
%c",10);
printf("
%c",10);
}
int
main(int argc, char * argv[])
{
int i, ch, rm;
char * rm_str; /* REQUEST_METHOD */
char * qu_str; /* QUERY_STRING */
char * qu_str_temp;
int qu_str_len;
char qu_str_literal[2000]="";
char * temp_p;
int content_length;
char *cl;
int x, m=0;
entry entries[10000];
char stdin_literal[2000] = "";
char stdin_line[1000] = "";
int stdin_len;
RM * rm_ptr;
printf("Content-type: text/html%c%c%c",10,10,10);
/* first of all, find REQUEST_METHOD, QUERY_STRING, and stdin
rm_str = getenv("REQUEST_METHOD"); */
rm_ptr = get_request_method();
rm_str = rm_ptr->name;
rm = rm_ptr->val;
rm_str = get_request_method()->name;
rm = get_request_method()->val;
qu_str = getenv("QUERY_STRING");
if (qu_str == NULL)
{
qu_str = "";
}
qu_str_len = strlen(qu_str);
cl = qu_str;
/* retrieve stdin */
i = 0;
while ((ch = getchar()) != EOF)
{
if (i < sizeof(stdin_line)-1)
{
stdin_line[i] = (char)ch;
stdin_line[i+1] = '\0';
}
++i;
}
stdin_len = i;
temp_p = getenv("CONTENT_LENGTH");
content_length = (temp_p != NULL) ? atoi(temp_p) : 0;
printf("");
printf("");
printf("| Parameters passed through CGI to %s in this invocation",argv[0]);
printf(" |
");
printf("");
printf("| Parameter Name | ");
printf("Parameter Value; raw, undecoded QUERY_STRING and STDIN have enclosing [square brackets] | ");
printf("Notes | ");
printf("
%c",10);
/* show HTTP_USER_AGENT */
printf("");
printf("| HTTP_USER_AGENT | %c",10);
printf("%s%c | ",
(getenv("HTTP_USER_AGENT")==NULL)?"":getenv("HTTP_USER_AGENT"), 10);
printf("
");
/* show all argv[0 ... argc-1] */
printf("");
printf("argc ");
for (i = 0; i < argc; ++i)
{
printf("argv[%d] %c",i, 10);
}
printf(" | ");
printf("%d %c",argc, 10);
for (i = 0; i < argc; ++i)
{
printf("%s%c ", argv[i],10);
}
printf(" | |
%c",10);
/* and show REQUEST_METHOD */
printf("");
printf("| REQUEST_METHOD | %c", 10);
printf("%s%c | ",
YELLOW, rm_str, 10);
switch (rm)
{
case GET:
printf("The one and only GET param -- ever! -- is QUERY_STRING | %c",10);
break;
case POST:
printf("At least three POST params: stdin; tot chars on stdin; and CONTENT_LENGTH%c",10);
break;
default:
printf(" | Unknown: %s%c",rm_str,10);
break;
}
printf(" |
");
/* show QUERY_STRING and strlen QUERY_STRING */
printf("");
printf("");
printf("QUERY_STRING ptr %c",10);
printf("strlen (0x%lx)%c",(unsigned long) qu_str, 10);
printf(" | %c",10);
switch (rm)
{
case GET:
printf("0x%lx %d%c",
YELLOW, (unsigned long) qu_str, qu_str_len, 10);
break;
case POST:
if (qu_str_len <= 0)
{
printf("0x%lx %d%c",
LT_GREY, (unsigned long) qu_str, qu_str_len, 10);
}
else
{
printf("0x%lx %d%c",
YELLOW, (unsigned long) qu_str, qu_str_len, 10);
printf(" | This is a POST with non-empty QUERY_STRING | %c",10);
}
break;
default:
break;
}
printf(" | |
%c",10);
/* show QUERY_STRING */
printf("");
printf("| QUERY_STRING | %c",10);
switch (rm)
{
case GET:
printf("[%s] | %c",
YELLOW, qu_str,10);
printf(" | %c",10);
break;
case POST:
if (0 >= strlen(qu_str))
{
printf("[%s]%c", LT_GREY, qu_str, 10);
printf("| POST with empty QUERY_STRING%c",10);
}
else
{
printf(" | [%s] | %c",
YELLOW, qu_str,10);
}
break;
default:
printf("[%s] | %c",qu_str,10);
printf(" | %c",10);
break;
}
printf(" |
");
/* show plain legible query string */
printf("");
printf("| QS plain | %c",10);
switch (rm)
{
case GET:
printf("%c", YELLOW, 10);
break;
case POST:
if (strlen(qu_str) <= 0)
{
printf("%c", LT_GREY, 10);
}
else
{
printf("%c", YELLOW, 10);
}
break;
default:
printf("| %c", 10);
break;
}
strcpy(qu_str_literal,"");
for (i = 0; i < qu_str_len; ++i)
{
if (qu_str[i] == '+')
{
printf(" ");
strcat(qu_str_literal," ");
}
else if (qu_str[i] != '%')
{
printf("%c",qu_str[i]);
strncat(qu_str_literal, &qu_str[i], 1);
}
else
{
ch = remap(qu_str[i+1], qu_str[i+2]);
if (ch == 0x3c)
{
qu_str_temp = "<";
strcat(qu_str_literal,"<");
}
else if (ch == 0x20)
{
qu_str_temp = " ";
strcat(qu_str_literal,"=");
}
else if (ch == 0x3d)
{
qu_str_temp = "=";
strcat(qu_str_literal,"=");
}
else if (ch == 0x22)
{
qu_str_temp = """;
strcat(qu_str_literal,"\"");
}
else if (ch == 0x2f)
{
qu_str_temp = "/";
strcat(qu_str_literal,"/");
}
else if (ch == 0x3e)
{
qu_str_temp = ">";
strcat(qu_str_literal,">");
}
else if (ch == 0x21)
{
qu_str_temp = "!";
strcat(qu_str_literal,"!");
}
else if (ch == 0x3a)
{
qu_str_temp = ":";
strcat(stdin_literal, ":");
}
else
{
qu_str_temp = "*";
strcat(qu_str_literal,"*");
}
if (qu_str_temp == "*")
{
printf("[0x%x]",ch);
}
else printf("%s", qu_str_temp);
i += 2;
}
}
printf(" | ");
printf(" | | |
");
/* show tokenized query string */
/* set up entries table */
for(x=0;cl[0] != '\0';x++) {
m=x;
getword(entries[x].val,cl,'&');
plustospace(entries[x].val);
unescape_url(entries[x].val);
getword(entries[x].name,entries[x].val,'=');
}
/* "tokenized" show QUERY_STRING as html-printable ascii tokens */
printf("");
printf("| QS tokens | %c", 10);
switch (rm) { /* REQUEST_METHOD mapped to int */
case GET:
printf("", YELLOW);
print_name_and_val(entries, m);
break;
case POST:
if (qu_str_len > 0)
{
printf("", YELLOW);
print_name_and_val(entries, m);
}
else
{
printf("", LT_GREY);
}
break;
default:
printf("| ", LT_GREY);
break;
}
printf(" | ");
printf(" | ");
printf(" | | |
");
/* QUERY_STRING "as rendered" -- show QUERY_STRING honoring markup */
printf("");
printf("| QS rendered | %c",10);
printf("");
if (qu_str_len > 0)
{
printf("%s%c",qu_str_literal, 10);
}
printf(" | ");
printf(" | "); /* "notes" column */
printf("
");
/* show num_chars on stdin and CONTENT_LENGTH */
printf("");
printf("tot stdin chars CONTENT_LENGTH%c | ",10);
i = strlen(stdin_line);
switch (rm)
{
case GET:
printf("%d %d | %c",
LT_GREY, i, content_length,10);
if (i > 0)
{
printf("Should not have been non-zero! | ");
}
printf(" | %c",10);
break;
case POST:
printf("%d %d | %c",
YELLOW, i, content_length, 10);
printf("For POST, these guys better be equal%c | ",10);
break;
default:
printf(" | | %c",10);
break;
}
printf("
");
/* show all on stdin: do the same thing as we did for QUERY_STRING */
printf("");
printf("| STDIN | ");
switch (rm)
{
case GET:
printf("[", LT_GREY);
i = 0;
stdin_line[0] = '\0';
while ((ch = getchar()) != EOF)
{
if (i < sizeof(stdin_line)-1)
{
stdin_line[i] = (char) ch;
stdin_line[i+1] = '\0';
}
printf("%c", (char)ch);
++i;
}
printf("] | ");
printf("This is a GET request, so stdin should be empty | ");
break;
case POST:
printf("", YELLOW);
printf("[%s]%c",stdin_line, 10);
printf(" | ");
printf(" | %c",10);
break;
default:
printf(" | | %c",10);
break;
}
printf("
");
/* stdin plain legible */
printf("");
printf("| stdin plain | %c",10);
switch (rm)
{
case GET:
printf("%c", LT_GREY, 10);
break;
case POST:
if (stdin_len <= 0)
{
printf("%c", LT_GREY,10);
}
else
{
printf("%c", YELLOW, 10);
}
break;
default:
printf("| %c", 10);
break;
}
strcpy(stdin_literal, "");
for (i = 0; i < stdin_len; ++i)
{
if (stdin_line[i] == '+')
{
printf(" ");
strcat(stdin_literal, " ");
}
else if (stdin_line[i] != '%')
{
printf("%c",stdin_line[i]);
strncat(stdin_literal, &stdin_line[i], 1);
}
else
{
ch = remap(stdin_line[i+1], stdin_line[i+2]);
if (ch == 0x3c)
{
qu_str_temp = "<";
strcat(stdin_literal, "<");
}
else if (ch == 0x3d)
{
qu_str_temp = "=";
strcat(stdin_literal, "=");
}
else if (ch == 0x22)
{
qu_str_temp = """;
strcat(stdin_literal, "\"");
}
else if (ch == 0x2f)
{
qu_str_temp = "/";
strcat(stdin_literal, "/");
}
else if (ch == 0x3e)
{
qu_str_temp = ">";
strcat(stdin_literal, ">");
}
else if (ch == 0x21)
{
qu_str_temp = "!";
strcat(stdin_literal, "!");
}
else if (ch == 0x3a)
{
qu_str_temp = ":";
strcat(stdin_literal, ":");
}
else
{
qu_str_temp = "*";
strcat(stdin_literal, "*");
}
if (qu_str_temp == "*")
{
printf("[0x%x]",ch);
}
else printf("%s", qu_str_temp);
i += 2;
}
}
printf(" | ");
printf(" | | |
");
/* stdin "tokenized" -- show stdin tokens */
printf("");
printf("| stdin tokens | %c", 10);
m = 0;
if (strlen(stdin_line) > 0)
{
cl = stdin_line;
for(x=0;cl[0] != '\0';x++) {
m=x;
getword(entries[x].val,cl,'&');
plustospace(entries[x].val);
unescape_url(entries[x].val);
getword(entries[x].name,entries[x].val,'=');
}
printf("", YELLOW);
print_name_and_val(entries, m);
printf(" | ");
printf("All name[] and val[] are C strings. | ");
}
else
{
printf(" | ", LT_GREY);
}
printf("
%c", 10);
/* stdin rendered -- show stdin_line with images */
printf("");
printf("| stdin rendered | %c",10);
printf("");
if (stdin_len > 0)
{
printf("%s%c",stdin_literal, 10);
}
printf(" | ");
printf(" | "); /* "notes" column */
printf("
");
printf("");
printf("");
printf("%c%c",10,10);
return 1;
}
/*
*/