Hello all,
I am trying to write a simple cgi that will read a postgresql database
(just a list of names for now)and print it. I am not having any luck. I
have attached it, and cgi-lib.c and .h, that have some functions for
parsing the query string, etc. If someone has some time, some help would
be great.
Thanks,
Jeff
_________________________________________
| trep@ctsi.net |
| pgp mail is welcome |
| pgpkey: finger://trep@spock.ctsi.net |
|_______________________________________|
#include <stdio.h>
#include <libpq-fe.h>
#include "cgi-lib.h"
#include <string.h>
/*
* Purpose: To read names from Postgresql database and print them. It is a CGI.
* It requires cgi-lib.h and cgi-lib.c functions.
*/
char mode[5];
FieldArray *fa;
int main()
{
ReadParse(&fa);
mode = (char *)GetValue(&fa, "mode");
if(strcasecmp(&mode, "view") == 0)
{
displaylist();
}
else if(strcasecmp(&mode, "add") == 0)
{
// addentry();
}
}
int displaylist()
{
int totalnames = 1;
PGconn* conn;
PGresult* res;
struct fullnames {
char first[50];
char last[50];
};
/* Connect to database */
conn = PQsetdb("localhost",NULL,NULL,NULL,"names");
if(PQstatus(&conn) == CONNECTION_BAD)
{
printf("%s",PQerrormessage(conn));
exit(1);
}
res = PQexec(conn, "SELECT * from namelist;");
if(PQresultStatus(&res) == PGRES_TUPLES_OK)
{
int i;
int j=0;
totalnames = (int *)PQntuples(res);
struct fullnames fullnameslist[50];
for(i=0; i<totalnames; i++)
{
//char tempstr* = malloc(PQgetlength(&res,i,0));
fullnameslist[i].first = (char *)PQgetvalue(res, i, 0);
fullnameslist[i].last = (char *)PQgetvalue(res, i, 1);
/*
tempfirst = PQgetvalue(res, i, 0);
templast = PQgetvalue(res, i, 1);
//fullnamesarray[j] = tempfirst;
strcat(fullnamesarray[j]," ");
strcat(fullnamesarray[j,templast);
j++;
*/
}
}
PrintHeader();
HtmlTop("names");
for(i=0; i<totalnames; i++)
{
printf("<BR>%s %s<BR>",fullnameslist[1].first, fullnameslist[1].last);
}
HtmlBot();
} /*-------------------------------------------------------------*/
/* File: cgi-lib.h
*
* Header file for CGI query processing routines.
*
* Author: Naba Barkakati
*/
/*---------------------------------------------------------------
* Copyright (c) 1996 Naba Barkakati (LNB Software, Inc.)
*
* Permission to use, copy, modify, and distribute this software
* for any purpose and without any fee is hereby granted,
* provided his notice is included in its entirety in the
* documentation and in the source files.
*
* For more information about this software, consult:
*
* - "UNIX Webmaster Bible" published by IDG Books Worldwide
* (Fall 1996)
*
* - LNB Software, Inc. Web site at http://www.lnbsoft.com/
*
* This software and any related documentation is provided "as is"
* without any warranty of any kind, either express or implied,
* including, without limitation, the implied warranties of
* merchantibility or fitness for a particular purpose. The entire
* risk arising out of use or performance of the software remains
* with you.
*
* In no event shall Naba Barkakati, LNB Software, or their agents
* be liable for any cost, loss, or damage incurred due to the
* use, malfunction, or misuse of the software or the inaccuracy
* of the documentation associated with the software.
*---------------------------------------------------------------
*/
#ifndef __CGI_LIB_H
#define __CGI_LIB_H
typedef struct Field
{
char *name; /* Pointer to the name */
char *value; /* Pointer to value */
}Field;
typedef struct FieldArray
{
int count; /* Number of fields in query */
Field *fields; /* Array of Field structures */
char *query; /* The query string */
} FieldArray;
/* Function prototypes */
int ReadParse(FieldArray *fa);
int ParseQuery(FieldArray *fa);
int MethGet(void);
int MethPost(void);
const char *GetValue(const FieldArray *fa, const char *name);
void PrintVariables(const FieldArray *fa);
void PrintHeader(void);
void HtmlTop(const char *title);
void HtmlBot(void);
void Cleanup(FieldArray *fa);
#endif
/*-------------------------------------------------------------*/
/* File: cgi-lib.c
*
* CGI query processing routines in C (patterned after the
* cgi-lib.pl Perl routines).
*
* Author: Naba Barkakati
*/
/*---------------------------------------------------------------
* Copyright (c) 1996 Naba Barkakati (LNB Software, Inc.)
*
* Permission to use, copy, modify, and distribute this software
* for any purpose and without any fee is hereby granted,
* provided his notice is included in its entirety in the
* documentation and in the source files.
*
* For more information about this software, consult:
*
* - "UNIX Webmaster Bible" published by IDG Books Worldwide
* (Fall 1996)
*
* - LNB Software, Inc. Web site at http://www.lnbsoft.com/
*
* This software and any related documentation is provided "as is"
* without any warranty of any kind, either express or implied,
* including, without limitation, the implied warranties of
* merchantibility or fitness for a particular purpose. The entire
* risk arising out of use or performance of the software remains
* with you.
*
* In no event shall Naba Barkakati, LNB Software, or their agents
* be liable for any cost, loss, or damage incurred due to the
* use, malfunction, or misuse of the software or the inaccuracy
* of the documentation associated with the software.
*---------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "cgi-lib.h"
static char *FieldSep = "&";
static char *ValueSep = "=";
/*-------------------------------------------------------------*/
/* R e a d P a r s e
*
* Read and parse the query string. This is the heart of this
* library of routines. Define a FieldArray structure and pass
* a pointer to that structure as the first argument. For example,
* FieldArray fa;
* ReadParse(&fa);
* On return, the fa->count is the number of fields in the query and
* fa->fields[] is the array of fields.
*
* Returns nonzero if everything goes well; zero in case of error.
*/
int ReadParse(FieldArray *fa)
{
if(fa == NULL) return 0;
/* Initialize the FieldArray structure */
fa->count = 0;
fa->fields = NULL;
fa->query = NULL;
if(MethGet())
{
/* Method is GET; retrieve query from QUERY_STRING environment
* variable
*/
char *p_env = getenv("QUERY_STRING");
if(p_env == NULL) return 0;
/* Copy the environ variable's value into another string */
if((fa->query = strdup(p_env)) != NULL)
return ParseQuery(fa);
else
{
Cleanup(fa);
return 0;
}
}
if(MethPost())
{
/* Method is POST; read query from stdin; read number of bytes
* specified in CONTENT_LENGTH environment variable.
*/
char *p_env = getenv("CONTENT_LENGTH");
int numbytes;
if(p_env == NULL) return 0;
numbytes = atoi(p_env);
/* Allocate memory to hold the query */
fa->query = malloc(numbytes + 1);
if(fa->query != NULL)
{
int n = fread(fa->query, sizeof(char), numbytes, stdin);
fa->query[n] = '\0';
return ParseQuery(fa);
}
else
{
Cleanup(fa);
return 0;
}
}
/* Unknown method */
return 0;
}
/*-------------------------------------------------------------*/
/* P a r s e Q u e r y
*
* Parses a query string "in-place" using strtok and returns
* results in an FieldArray structure (through an array of
* pointers). Returns non-zero if all goes well.
*/
int ParseQuery(FieldArray *fa)
{
int i, nf = 1;
if(fa->query == NULL) return 0;
/* Count the ampersands in the query to find out number of fields */
for(i = 0; fa->query[i] != '\0'; i++)
{
if(fa->query[i] == '&') nf++;
}
fa->count = nf;
/* Allocate that many array of Field structures */
if((fa->fields = (Field*)calloc(nf, sizeof(Field))) == NULL)
{
Cleanup(fa);
return 0;
}
/* Split up the fields by looking for the ampersands */
fa->fields[0].name = strtok(fa->query, FieldSep);
/* Now get the rest of the fields */
for(i = 1; i < nf; i++)
{
fa->fields[i].name = strtok(NULL, FieldSep);
}
/* Now, split each field into name and value at the = sign */
for(i = 0; i < nf; i++)
{
fa->fields[i].name = strtok(fa->fields[i].name, ValueSep);
fa->fields[i].value = strtok(NULL, ValueSep);
}
/* Translate plus signs to spaces and %xx to single characters */
/* First work through the names */
for(i = 0; i < nf; i++)
{
int j;
/* First convert + to space */
for(j = 0; fa->fields[i].name[j] != '\0'; j++)
{
if(fa->fields[i].name[j] == '+')
fa->fields[i].name[j] = ' ';
}
/* Next convert each %xx to a single character */
for(j = 0; fa->fields[i].name[j] != '\0'; j++)
{
if(fa->fields[i].name[j] == '%')
{
int k;
fa->fields[i].name[j] =
16 * HexNum(fa->fields[i].name[j+1]) +
HexNum(fa->fields[i].name[j+2]);
/* Move rest of string two spaces to the left */
for(k = j+3; fa->fields[i].name[k] != '\0'; k++)
fa->fields[i].name[k-2] = fa->fields[i].name[k];
/* Place a null character to mark end of string */
fa->fields[i].name[k-2] = '\0';
}
}
}
/* Now process the values */
for(i = 0; i < nf; i++)
{
int j;
/* Skip fields with missing values (the value is NULL) */
if(fa->fields[i].value == NULL) continue;
/* First convert + to space */
for(j = 0; fa->fields[i].value[j] != '\0'; j++)
{
if(fa->fields[i].value[j] == '+')
fa->fields[i].value[j] = ' ';
}
/* Next convert each %xx to a single character */
for(j = 0; fa->fields[i].value[j] != '\0'; j++)
{
if(fa->fields[i].value[j] == '%')
{
int k;
fa->fields[i].value[j] =
16 * HexNum(fa->fields[i].value[j+1]) +
HexNum(fa->fields[i].value[j+2]);
/* Move rest of string two spaces to the left */
for(k = j+3; fa->fields[i].value[k] != '\0'; k++)
fa->fields[i].value[k-2] = fa->fields[i].value[k];
/* Place a null character to mark end of string */
fa->fields[i].value[k-2] = '\0';
}
}
}
return 1;
}
/*-------------------------------------------------------------*/
/* C l e a n u p
* Cleans up all allocated memory in the FieldArray structure fa->
*/
void Cleanup(FieldArray *fa)
{
if(fa == NULL) return;
if(fa->query != NULL) free(fa->query);
if(fa->fields != NULL) free(fa->fields);
}
/*-------------------------------------------------------------*/
/* M e t h G e t
* Returns nonzero if method is GET.
*/
int MethGet(void)
{
char *p_env = getenv("REQUEST_METHOD");
if(p_env == NULL) return 0;
return(strcasecmp(p_env, "get") == 0);
}
/*-------------------------------------------------------------*/
/* M e t h P o s t
* Returns nonzero if method is POST.
*/
int MethPost(void)
{
char *p_env = getenv("REQUEST_METHOD");
if(p_env == NULL) return 0;
return(strcasecmp(p_env, "post") == 0);
}
/*-------------------------------------------------------------*/
/* G e t V a l u e
*
* Return the value of a field (specified by name), if found.
* Else, return NULL.
*/
const char *GetValue(const FieldArray *fa, const char *name)
{
int i;
for(i = 0; i < fa->count; i++)
{
if(strcmp(name, fa->fields[i].name) == 0)
return fa->fields[i].value;
}
return NULL;
}
/*-------------------------------------------------------------*/
/* P r i n t V a r i a b l e s
*
* Prints the name and value of the fields (like the subroutine
* with the same name in cgi-lib.pl Perl library).
*/
void PrintVariables(const FieldArray *fa)
{
int i;
printf("<dl>\n");
for(i = 0; i < fa->count; i++)
{
printf("<dt>%s</dt>\n", fa->fields[i].name);
printf("<dd>%s</dd>\n", fa->fields[i].value);
}
printf("</dl>\n");
}
/*-------------------------------------------------------------*/
/* P r i n t H e a d e r
*
* Print the MIME header
*/
void PrintHeader(void)
{
printf("Content-type: text/html\n\n");
}
/*-------------------------------------------------------------*/
/* H t m l T o p
*
* Print the top part of the HTML document
*/
void HtmlTop(const char *title)
{
printf("<html>\n<head>\n<title>%s</title></head>\n", title);
printf("<body>\n<h1>%s</h1>\n", title);
}
/*-------------------------------------------------------------*/
/* H t m l B o t
*
* Print the bottom part of the HTML document
*/
void HtmlBot(void)
{
printf("</body>\n</html>\n");
}
/*---------------------------------------------------------------*/
/* H e x N u m
*
* Returns the decimal value corresponding to a hexadecimal
* digit.
*/
int HexNum(int c)
{
if(isdigit(c))
{
return c - '0';
}
else
{
int cl = toupper(c);
return cl - 'A' + 10;
}
}