From 5a6c7cf08eb0d72d79636535cbd16726e8f940d8 Mon Sep 17 00:00:00 2001 From: Emil Mikulic Date: Sat, 8 Mar 2003 11:54:58 +0000 Subject: [PATCH] . Added lastmod (reply, not request) to struct connection . Added xstrdup() . Made expand_tilde use xstrdup() instead of strdup() (whoops) . process_get() now handles "If-Modified-Since:" . lastmod is generated before Date: so that only one asprintf() is needed to construct the header in process_get() --- trunk/darkhttpd.c | 54 ++++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/trunk/darkhttpd.c b/trunk/darkhttpd.c index c7ff6e2..8838ef1 100644 --- a/trunk/darkhttpd.c +++ b/trunk/darkhttpd.c @@ -14,7 +14,7 @@ * . Generate directory listings. * x Log to file. * . Partial content. - * . If-Modified-Since. + * x If-Modified-Since. * . Keep-alive connections. * . Chroot, set{uid|gid}. * . Port to Win32. @@ -77,7 +77,7 @@ struct connection int header_dont_free, header_only, http_code; enum { REPLY_GENERATED, REPLY_FROMFILE } reply_type; - char *reply; + char *reply, *lastmod; /* reply lastmod, not request if-mod-since */ int reply_dont_free; FILE *reply_file; unsigned int reply_sent, reply_length; @@ -168,6 +168,18 @@ static void *xrealloc(void *original, const size_t size) +/* --------------------------------------------------------------------------- + * strdup() that errx()s if it can't allocate. + */ +static char *xstrdup(const char *src) +{ + char *dest = strdup(src); + if (dest == NULL) errx(1, "out of memory in strdup()"); + return dest; +} + + + /* --------------------------------------------------------------------------- * Split string out of src with range [left:right-1] */ @@ -490,7 +502,7 @@ static char *expand_tilde(const char *path) const char *home; char *tmp = NULL; - if (path[0] != '~') return strdup(path); /* do nothing */ + if (path[0] != '~') return xstrdup(path); /* do nothing */ home = getenv("HOME"); if (home == NULL) @@ -604,7 +616,7 @@ static struct connection *new_connection(void) conn->header_sent = conn->header_length = 0; conn->header_dont_free = conn->header_only = 0; conn->http_code = 0; - conn->reply = NULL; + conn->reply = conn->lastmod = NULL; conn->reply_dont_free = 0; conn->reply_file = NULL; conn->reply_sent = conn->reply_length = 0; @@ -661,6 +673,7 @@ static void free_connection(struct connection *conn) if (conn->user_agent != NULL) free(conn->user_agent); if (conn->header != NULL && !conn->header_dont_free) free(conn->header); if (conn->reply != NULL && !conn->reply_dont_free) free(conn->reply); + if (conn->lastmod != NULL) free(conn->lastmod); if (conn->reply_file != NULL) fclose(conn->reply_file); } @@ -851,7 +864,7 @@ static void parse_request(struct connection *conn) */ static void process_get(struct connection *conn) { - char *decoded_url, *safe_url, *target, *tmp; + char *decoded_url, *safe_url, *target, *if_mod_since; const char *mimetype = NULL; struct stat filestat; @@ -882,8 +895,9 @@ static void process_get(struct connection *conn) free(safe_url); safe_url = NULL; + debugf("uri=%s, target=%s, content-type=%s\n", + conn->uri, target, mimetype); conn->reply_file = fopen(target, "rb"); - debugf("target = %s\n", target); free(target); target = NULL; @@ -912,30 +926,32 @@ static void process_get(struct connection *conn) conn->reply_type = REPLY_FROMFILE; conn->reply_length = filestat.st_size; + conn->lastmod = xstrdup(rfc1123_date(filestat.st_mtime)); - asprintf(&tmp, + /* the browser might already have it */ + if_mod_since = parse_field(conn, "If-Modified-Since: "); + if (if_mod_since != NULL && + strcmp(if_mod_since, conn->lastmod) == 0) + { + debugf("not modified since %s\n", if_mod_since); + default_reply(conn, 304, "Not Modified", ""); + conn->header_only = 1; + return; + } + + conn->header_length = asprintf(&(conn->header), "HTTP/1.1 200 OK\r\n" "Date: %s\r\n" "Server: %s\r\n" "Connection: close\r\n" "Content-Length: %d\r\n" "Content-Type: %s\r\n" - , - rfc1123_date(time(NULL)), pkgname, conn->reply_length, - mimetype - ); - if (tmp == NULL) errx(1, "out of memory in asprintf()"); - - debugf("uri=%s, content-type=%s\n", conn->uri, mimetype); - - conn->header_length = asprintf(&(conn->header), - "%s" "Last-Modified: %s\r\n" "\r\n" , - tmp, rfc1123_date(filestat.st_mtime) + rfc1123_date(time(NULL)), pkgname, conn->reply_length, + mimetype, conn->lastmod ); - free(tmp); if (conn->header == NULL) errx(1, "out of memory in asprintf()"); conn->http_code = 200; }