From be5ab2e629c2c6900a7923a777068fc434afae47 Mon Sep 17 00:00:00 2001 From: chrisz Date: Thu, 21 Aug 2014 19:23:10 +0000 Subject: [PATCH] Add Last-Modified: HTTP header. OK reyk@ --- usr.sbin/httpd/httpd.h | 6 +++--- usr.sbin/httpd/server_fcgi.c | 8 ++++---- usr.sbin/httpd/server_file.c | 30 +++++++++++++++++------------- usr.sbin/httpd/server_http.c | 30 ++++++++++++++++++------------ 4 files changed, 42 insertions(+), 32 deletions(-) diff --git a/usr.sbin/httpd/httpd.h b/usr.sbin/httpd/httpd.h index 371dd1caac0..6f1b48d95c8 100644 --- a/usr.sbin/httpd/httpd.h +++ b/usr.sbin/httpd/httpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: httpd.h,v 1.53 2014/08/13 16:04:28 reyk Exp $ */ +/* $OpenBSD: httpd.h,v 1.54 2014/08/21 19:23:10 chrisz Exp $ */ /* * Copyright (c) 2006 - 2014 Reyk Floeter @@ -512,7 +512,7 @@ int server_headers(struct client *, int (*)(struct client *, struct kv *, void *), void *); int server_writeresponse_http(struct client *); int server_response_http(struct client *, u_int, struct media_type *, - size_t); + size_t, time_t); void server_reset_http(struct client *); void server_close_http(struct client *); int server_response(struct httpd *, struct client *); @@ -520,7 +520,7 @@ struct server_config * server_getlocation(struct client *, const char *); const char * server_http_host(struct sockaddr_storage *, char *, size_t); -void server_http_date(char *, size_t); +ssize_t server_http_time(time_t, char *, size_t); int server_log_http(struct client *, u_int, size_t); /* server_file.c */ diff --git a/usr.sbin/httpd/server_fcgi.c b/usr.sbin/httpd/server_fcgi.c index 848bae485f7..6eb668ea72f 100644 --- a/usr.sbin/httpd/server_fcgi.c +++ b/usr.sbin/httpd/server_fcgi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server_fcgi.c,v 1.33 2014/08/13 18:00:54 chrisz Exp $ */ +/* $OpenBSD: server_fcgi.c,v 1.34 2014/08/21 19:23:10 chrisz Exp $ */ /* * Copyright (c) 2014 Florian Obser @@ -562,9 +562,9 @@ server_fcgi_header(struct client *clt, u_int code) } else if (kv_add(&desc->http_headers, "Connection", "close") == NULL) return (-1); - /* Date header is mandatory and should be added last */ - server_http_date(tmbuf, sizeof(tmbuf)); - if (kv_add(&desc->http_headers, "Date", tmbuf) == NULL) + /* Date header is mandatory and should be added as late as possible */ + if (server_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0 || + kv_add(&desc->http_headers, "Date", tmbuf) == NULL) return (-1); /* Write initial header (fcgi might append more) */ diff --git a/usr.sbin/httpd/server_file.c b/usr.sbin/httpd/server_file.c index e87bcbdb994..28b17c7273d 100644 --- a/usr.sbin/httpd/server_file.c +++ b/usr.sbin/httpd/server_file.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server_file.c,v 1.33 2014/08/14 07:50:35 chrisz Exp $ */ +/* $OpenBSD: server_file.c,v 1.34 2014/08/21 19:23:10 chrisz Exp $ */ /* * Copyright (c) 2006 - 2014 Reyk Floeter @@ -49,7 +49,7 @@ int server_file_access(struct httpd *, struct client *, char *, size_t); int server_file_request(struct httpd *, struct client *, char *, struct stat *); -int server_file_index(struct httpd *, struct client *); +int server_file_index(struct httpd *, struct client *, struct stat *); int server_file_method(struct client *); int @@ -123,7 +123,7 @@ server_file_access(struct httpd *env, struct client *clt, goto fail; } - return (server_file_index(env, clt)); + return (server_file_index(env, clt, &st)); } return (ret); } else if (!S_ISREG(st.st_mode)) { @@ -220,7 +220,8 @@ server_file_request(struct httpd *env, struct client *clt, char *path, goto abort; media = media_find(env->sc_mediatypes, path); - ret = server_response_http(clt, 200, media, st->st_size); + ret = server_response_http(clt, 200, media, st->st_size, + MIN(time(NULL), st->st_mtim.tv_sec)); switch (ret) { case -1: goto fail; @@ -267,7 +268,7 @@ server_file_request(struct httpd *env, struct client *clt, char *path, } int -server_file_index(struct httpd *env, struct client *clt) +server_file_index(struct httpd *env, struct client *clt, struct stat *st) { char path[MAXPATHLEN]; char tmstr[21]; @@ -279,9 +280,8 @@ server_file_index(struct httpd *env, struct client *clt) struct evbuffer *evb = NULL; struct media_type *media; const char *style; - struct stat st; struct tm tm; - time_t t; + time_t t, dir_mtime; if ((ret = server_file_method(clt)) != 0) { code = ret; @@ -297,6 +297,9 @@ server_file_index(struct httpd *env, struct client *clt) if ((fd = open(path, O_RDONLY)) == -1) goto abort; + /* Save last modification time */ + dir_mtime = MIN(time(NULL), st->st_mtim.tv_sec); + if ((evb = evbuffer_new()) == NULL) goto abort; @@ -328,12 +331,12 @@ server_file_index(struct httpd *env, struct client *clt) dp = namelist[i]; if (skip || - fstatat(fd, dp->d_name, &st, 0) == -1) { + fstatat(fd, dp->d_name, st, 0) == -1) { free(dp); continue; } - t = st.st_mtime; + t = st->st_mtime; localtime_r(&t, &tm); strftime(tmstr, sizeof(tmstr), "%d-%h-%Y %R", &tm); namewidth = 51 - strlen(dp->d_name); @@ -341,18 +344,18 @@ server_file_index(struct httpd *env, struct client *clt) if (dp->d_name[0] == '.' && !(dp->d_name[1] == '.' && dp->d_name[2] == '\0')) { /* ignore hidden files starting with a dot */ - } else if (S_ISDIR(st.st_mode)) { + } else if (S_ISDIR(st->st_mode)) { namewidth -= 1; /* trailing slash */ if (evbuffer_add_printf(evb, "%s/%*s%s%20s\n", dp->d_name, dp->d_name, MAX(namewidth, 0), " ", tmstr, "-") == -1) skip = 1; - } else if (S_ISREG(st.st_mode)) { + } else if (S_ISREG(st->st_mode)) { if (evbuffer_add_printf(evb, "%s%*s%s%20llu\n", dp->d_name, dp->d_name, - MAX(namewidth, 0), " ", tmstr, st.st_size) == -1) + MAX(namewidth, 0), " ", tmstr, st->st_size) == -1) skip = 1; } free(dp); @@ -368,7 +371,8 @@ server_file_index(struct httpd *env, struct client *clt) fd = -1; media = media_find(env->sc_mediatypes, "index.html"); - ret = server_response_http(clt, 200, media, EVBUFFER_LENGTH(evb)); + ret = server_response_http(clt, 200, media, EVBUFFER_LENGTH(evb), + dir_mtime); switch (ret) { case -1: goto fail; diff --git a/usr.sbin/httpd/server_http.c b/usr.sbin/httpd/server_http.c index 9e09428a628..af996a5c4d6 100644 --- a/usr.sbin/httpd/server_http.c +++ b/usr.sbin/httpd/server_http.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server_http.c,v 1.44 2014/08/08 18:29:42 reyk Exp $ */ +/* $OpenBSD: server_http.c,v 1.45 2014/08/21 19:23:10 chrisz Exp $ */ /* * Copyright (c) 2006 - 2014 Reyk Floeter @@ -534,16 +534,16 @@ server_reset_http(struct client *clt) server_log(clt, NULL); } -void -server_http_date(char *tmbuf, size_t len) +ssize_t +server_http_time(time_t t, char *tmbuf, size_t len) { - time_t t; struct tm tm; /* New HTTP/1.1 RFC 7231 prefers IMF-fixdate from RFC 5322 */ - time(&t); - gmtime_r(&t, &tm); - strftime(tmbuf, len, "%a, %d %h %Y %T %Z", &tm); + if (t == -1 || gmtime_r(&t, &tm) == NULL) + return (-1); + else + return (strftime(tmbuf, len, "%a, %d %h %Y %T %Z", &tm)); } const char * @@ -602,7 +602,8 @@ server_abort_http(struct client *clt, u_int code, const char *msg) if (print_host(&srv_conf->ss, hbuf, sizeof(hbuf)) == NULL) goto done; - server_http_date(tmbuf, sizeof(tmbuf)); + if (server_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0) + goto done; /* Do not send details of the Internal Server Error */ switch (code) { @@ -790,7 +791,7 @@ server_getlocation(struct client *clt, const char *path) int server_response_http(struct client *clt, u_int code, - struct media_type *media, size_t size) + struct media_type *media, size_t size, time_t mtime) { struct http_descriptor *desc = clt->clt_desc; const char *error; @@ -835,9 +836,14 @@ server_response_http(struct client *clt, u_int code, kv_set(cl, "%ld", size) == -1) return (-1); - /* Date header is mandatory and should be added last */ - server_http_date(tmbuf, sizeof(tmbuf)); - if (kv_add(&desc->http_headers, "Date", tmbuf) == NULL) + /* Set last modification time */ + if (server_http_time(mtime, tmbuf, sizeof(tmbuf)) <= 0 || + kv_add(&desc->http_headers, "Last-Modified", tmbuf) == NULL) + return (-1); + + /* Date header is mandatory and should be added as late as possible */ + if (server_http_time(time(NULL), tmbuf, sizeof(tmbuf)) <= 0 || + kv_add(&desc->http_headers, "Date", tmbuf) == NULL) return (-1); /* Write completed header */ -- 2.20.1