. Added strntoupper()

. rfc1123_date() now takes a time_t argument
. default_reply() now takes a `reason' string
. Skeleton process_get()
. Implemented process_request() completely (for now) (I hope)
. Changed oversized request error from 400 Bad Request
  to 413 Request Entity Too Large
This commit is contained in:
Emil Mikulic 2003-02-28 11:21:31 +00:00
parent fd0a618d34
commit b959c6bc3a
1 changed files with 60 additions and 15 deletions

View File

@ -12,6 +12,7 @@
#include <sys/queue.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
@ -288,6 +289,18 @@ static void *xrealloc(void *original, const size_t size)
/* ---------------------------------------------------------------------------
* Uppercasify all characters in a string of given length.
*/
static void strntoupper(char *str, const int length)
{
int i;
for (i=0; i<length; i++)
str[i] = toupper(str[i]);
}
/* ---------------------------------------------------------------------------
* If a connection has been idle for more than IDLETIME seconds, it will be
* marked as DONE and killed off in httpd_poll()
@ -305,9 +318,9 @@ static void poll_check_timeout(struct connection *conn)
*/
#define MAX_DATE_LENGTH 29 /* strlen("Fri, 28 Feb 2003 00:02:08 GMT") */
static char _date[MAX_DATE_LENGTH + 1];
static char *rfc1123_date(void)
static char *rfc1123_date(const time_t when)
{
time_t now = time(NULL);
time_t now = when;
strftime(_date, MAX_DATE_LENGTH,
"%a, %d %b %Y %H:%M:%S %Z", gmtime(&now) );
return _date;
@ -319,14 +332,16 @@ static char *rfc1123_date(void)
* A default reply for any occasion.
*/
static void default_reply(struct connection *conn,
const int errcode, const char *errname)
const int errcode, const char *errname, const char *reason)
{
conn->reply_length = asprintf(&(conn->reply),
"<html><head><title>%d %s</title></head><body>\n"
"<h1>%s</h1><hr>\n"
"%s\n"
"<h1>%s</h1>\n" /* errname */
"%s\n" /* reason */
"<hr>\n"
"Generated by %s on %s\n"
"</body></html>\n",
errcode, errname, errname, pkgname);
errcode, errname, errname, reason, pkgname, rfc1123_date(time(NULL)));
if (conn->reply == NULL) errx(1, "out of memory in asprintf()");
@ -338,7 +353,7 @@ static void default_reply(struct connection *conn,
"Content-Length: %d\r\n"
"Content-Type: text/html\r\n"
"\r\n",
errcode, errname, rfc1123_date(), pkgname, conn->reply_length);
errcode, errname, rfc1123_date(time(NULL)), pkgname, conn->reply_length);
if (conn->header == NULL) errx(1, "out of memory in asprintf()");
conn->reply_type = REPLY_GENERATED;
@ -359,13 +374,27 @@ static void parse_request(const char *req, const int length,
*method = (char*)xmalloc(bound1+1);
memcpy(*method, req, bound1);
(*method)[bound1] = '\0';
(*method)[bound1] = 0;
strntoupper(method, bound1);
for (bound2=bound1+1; bound2<length && req[bound2] != ' '; bound2++);
for (bound2=bound1+1; bound2<length && req[bound2] != ' ' &&
req[bound2] != '\r'; bound2++);
*url = (char*)xmalloc(bound2-bound1);
memcpy(*url, req+bound1+1, bound2-bound1-1);
(*url)[bound2-bound1-1] = '\0';
(*url)[bound2-bound1-1] = 0;
}
/* ---------------------------------------------------------------------------
* Process a GET/HEAD request
*/
static void process_get(struct connection *conn,
const char *url, const int header_only)
{
/* FIXME */
default_reply(conn, 200, "OK", "Nothing to see here. Move along.");
}
@ -377,14 +406,29 @@ static void process_request(struct connection *conn)
{
char *method, *url;
parse_request(conn->request, conn->request_length, &method, &url);
debugf("method=``%s'', url=``%s''\n", method, url);
debugf("%s", conn->request);
/* FIXME */
default_reply(conn, 501, "Not Implemented");
if (strcmp(method, "GET") == 0)
process_get(conn, url, 0);
else if (strcmp(method, "HEAD") == 0)
process_get(conn, url, 1);
else if (strcmp(method, "OPTIONS") == 0 ||
strcmp(method, "POST") == 0 ||
strcmp(method, "PUT") == 0 ||
strcmp(method, "DELETE") == 0 ||
strcmp(method, "TRACE") == 0 ||
strcmp(method, "CONNECT") == 0)
default_reply(conn, 501, "Not Implemented",
"That method is not implemented.");
else
default_reply(conn, 400, "Bad Request",
"That method is not a valid HTTP/1.1 method.");
/* advance state */
conn->state = SEND_HEADER;
/* request, method, url not needed anymore */
debugf("%s", conn->request);
free(conn->request);
conn->request = NULL;
debugf("%s-=-\n", conn->header);
@ -430,7 +474,8 @@ static void poll_recv_request(struct connection *conn)
/* die if it's too long */
if (conn->request_length > MAX_REQUEST_LENGTH)
{
default_reply(conn, 400, "Bad Request");
default_reply(conn, 413, "Request Entity Too Large",
"Your request was dropped because it was too long.");
conn->state = SEND_HEADER;
}
}