/*@@ @file Server.c @date Wed Sep 13 20:10:24 2000 @author Tom Goodale @desc Web serving and utility routines. @enddesc @version $Header$ @@*/ #include #include #include "cctk.h" #include "util_Hash.h" #include "httpd.h" static char *rcsid = "$Header$"; CCTK_FILEVERSION(DevThorns_httpd_Server_c) /******************************************************************** ********************* Local Data Types *********************** ********************************************************************/ typedef struct { int (*function)(cGH *, httpRequest *, void *); void *data; } httpPage; /******************************************************************** ********************* Local Routine Prototypes ********************* ********************************************************************/ static httpPage *CreatePageData(int (*function)(cGH *,httpRequest *, void *), void *data); static httpPage *FindPage(char *path, char **residual); /******************************************************************** ********************* Other Routine Prototypes ********************* ********************************************************************/ /******************************************************************** ********************* Local Data ***************************** ********************************************************************/ static uHash *pages = NULL; static const char *notfound_page = "\nError 404: Not Found\ The URI you requested could not be found\n\n"; static const char *notimplemented_page = "\nError 501: Not Implemented\ The requested method is not implemented\n\n"; #define INITIAL_SIZE 16 /******************************************************************** ********************* External Routines ********************** ********************************************************************/ /*@@ @routine HTTP_RequestGet @date Wed Sep 13 20:10:24 2000 @author Tom Goodale @desc Routine to deal with a GET request. @enddesc @calls @calledby @history @endhistory @@*/ int HTTP_RequestGET(cGH *cctkGH, httpRequest *request) { httpPage *pagedata; int retval; char message[1024]; if((pagedata = FindPage(request->uri, &(request->residual)))) { retval = pagedata->function(cctkGH, request, pagedata->data); } else { retval = -1; } if(retval < 0) { strcpy(message,"HTTP/1.0 404 Not Found\r\n"); write(request->filedes, message, strlen(message)); strcpy(message,"Content-Type: text/html\r\n\r\n"); write(request->filedes, message, strlen(message)); write(request->filedes, notfound_page, strlen(notfound_page)); } return retval; } /*@@ @routine HTTP_RequestUnsupported @date Thu Sep 14 12:18:56 2000 @author Tom Goodale @desc @enddesc @calls @calledby @history @endhistory @@*/ int HTTP_RequestUnsupported(cGH *cctkGH, httpRequest *request) { char message[1024]; strcpy(message,"HTTP/1.0 501 Not Implemented\r\n"); write(request->filedes, message, strlen(message)); strcpy(message,"Content-Type: text/html\r\n\r\n"); write(request->filedes, message, strlen(message)); write(request->filedes, notimplemented_page, strlen(notimplemented_page)); return 0; } /*@@ @routine HTTP_RegisterPage @date Wed Sep 13 20:10:24 2000 @author Tom Goodale @desc Routine to register a web page. @enddesc @calls @calledby @history @endhistory @@*/ int HTTP_RegisterPage(const char *path, int (*function)(cGH *, httpRequest *, void *), void *data) { int retval; httpPage *pagedata; /* Create the hash table if it's not already been created */ if(! pages) { pages = Util_HashCreate(INITIAL_SIZE); } if(Util_HashData(pages, strlen(path), path, 0)) { fprintf(stderr, "Page %s already exists\n", path); retval = -1; } else { pagedata = CreatePageData(function, data); if(pagedata) { retval = Util_HashStore(pages, strlen(path), path, 0, (void *)pagedata); } else { retval = -2; } } return 0; } /******************************************************************** ********************* Local Routines ************************* ********************************************************************/ /*@@ @routine CreatePageData @date Wed Sep 13 20:10:24 2000 @author Tom Goodale @desc Creates a httpPage structure. @enddesc @calls @calledby @history @endhistory @@*/ static httpPage *CreatePageData(int (*function)(cGH *, httpRequest *, void *), void *data) { httpPage *pagedata; pagedata = (httpPage *)malloc(sizeof(httpPage)); if(pagedata) { pagedata->function = function; pagedata->data = data; } return pagedata; } /*@@ @routine FindPage @date Wed Sep 13 20:10:24 2000 @author Tom Goodale @desc Finds a page, if it exists. @enddesc @calls @calledby @history @endhistory @@*/ static httpPage *FindPage(char *path, char **residual) { httpPage *pagedata; char *position; char *temp; pagedata = NULL; if(pages) { /* Check for index.html */ if(path[strlen(path)-1] == '/') { #ifdef HTTP_DEBUG printf("Looking for '%sindex.html'\n", path); #endif temp = (char *)malloc(sizeof(path)+11); sprintf(temp,"%sindex.html", path); pagedata = Util_HashData(pages, strlen(temp), temp, 0); *residual = NULL; free(temp); } else { #ifdef HTTP_DEBUG printf("Looking for '%s'\n", path); #endif /* Or exact path */ pagedata = Util_HashData(pages, strlen(path), path, 0); *residual = NULL; } if(!pagedata) { /* Ok, now cycle through. Know it doesn't end with a slash */ for(position = path+strlen(path)-1; position >= path; position--) { if(*position == '/') { #ifdef HTTP_DEBUG printf("Looking for '%s' less '%s' \n", path, position); #endif if((pagedata = Util_HashData(pages, position-path, path, 0))) { *residual = position+1; break; } } } } } else { pagedata = NULL; } return pagedata; }