
/* qdir_post.c */
/* Andrew Davison, July 1997 (ad@ratree.psu.ac.th) */

/* Send a POST method to 
   http://catsix.coe.psu.ac.th/cgi-bin/qdir
   to search the database, and print the reply.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <bstring.h>     /* for bzero(), bcopy() */
#include <unistd.h>      /* for read(), write(), close() */

#define SIZE 512          /* max length of a string */
#define MAX_ENTRIES 5     /* max number of input fields */

#define HOST "catsix.coe.psu.ac.th"    /* address of machine with database */
#define APPL "cgi-bin/qdir"            /* CGI location of application */


void get_urlstr(char urlstr[]);
int open_socket(char *host, char *cmd);
void send_POST(int sd, char *appl, char *urlstr);
void show_reply(int sd);


int main()
{
  int sd;
  char urlstr[SIZE];

  get_urlstr(urlstr);
  sd = open_socket(HOST, "sock_post");
  send_POST(sd, APPL, urlstr);
  show_reply(sd);
  close(sd);

  return 0;
}


void get_urlstr(char urlstr[])
/* Read in MAX_ENTRIES value strings (which can be empty)
   and use them to build a name1=value1&name2=valu2&... pairs 
   string in urlstr[]. 
   The name strings are: pat1, pat2,... pat<MAX_ENTRIES-1>
*/
{
  int i;
  char val[SIZE], line[SIZE];

  urlstr[0] = '\0';
  for(i=0; i < MAX_ENTRIES; i++) {
    printf("Enter a value for pat%d: ", i+1);
    fgets(val, SIZE, stdin);
    val[strlen(val)-1] = '\0';     /* overwrite '\n' */
    sprintf(line, "pat%d=%s&", i+1, val);
    strcat(urlstr, line);
  }
  urlstr[strlen(urlstr)-1] = '\0';   /* overwrite last '&' */
}


int open_socket(char *host, char *cmd)
/* Create a socket. Assign host's details to name.
   Create a stream using name and connect the socket to it.

   The lines marked with "CHG" are different from the 
   open_socket() function in "Programming with the HTTP Protocol"
   Web Techniques article.
*/
{
  struct sockaddr_in name;
  struct hostent *hptr;
  int sd;

  if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {    /* CHG */
    perror(cmd);
    exit(1);
  }

  /* initialise the name struct to all zeros */        /* CHG */
  bzero(&name, sizeof(name)); 
/*  memset(&name, 0, sizeof(name)); */

  name.sin_family = AF_INET;
  name.sin_port = htons(80);         /* host is a HTTP server */ /* CHG */

  if ((hptr = gethostbyname(host)) == NULL) {
    perror("gethostbyname");
    exit(1);
  }

  /* copy the IP address of host into name */
  bcopy(hptr->h_addr, &name.sin_addr.s_addr, hptr->h_length); 
/*  memcpy(&name.sin_addr.s_addr, hptr->h_addr, hptr->h_length); */  /* CHG */
/*  name.sin_addr.s_addr = * (unsigned long *) hptr->h_addr; */

  printf("Trying to contact %s...\n", host);
  if (connect(sd, (struct sockaddr *) &name, sizeof(name)) < 0) {    /* CHG */
    close(sd);
    perror(cmd);
    exit(1);
  }

  return sd;
}


void send_POST(int sd, char *appl, char *urlstr)
/* Send the POST message, which consists of a POST line,
   a Content-type line, a Content-length line, a blank line,
   and finally the name1=value1&name2=value2&... pairs string.
*/
{
  char *ct = "Content-type: application/x-www-form-urlencoded\n";
  char line[SIZE];
  int ulen = strlen(urlstr);

  printf("Sending a POST request...\n");

  sprintf(line, "POST /%s HTTP/1.0\n", appl);
  write(sd, line, strlen(line));

  write(sd, ct, strlen(ct));

  sprintf(line, "Content-length: %d\n\n", ulen);
  write(sd, line, strlen(line));

  write(sd, urlstr, ulen);
}


void show_reply(int sd)
/* Print the reply to the POST message */
{
  char buf[SIZE];
  int no;

  printf("Waiting for a response\n");
  while ((no = read(sd, buf, SIZE)) > 0)
    write(1, buf, no);    /* write to stdout */
}


