. 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:
parent
fd0a618d34
commit
b959c6bc3a
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue