From 3d334dca671898241732dbc0ef6838b768308da7 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Thu, 21 Sep 2023 02:18:35 +0000 Subject: Implement If-Modified-Since Signed-off-by: Laurent Bercot --- package/deps.mak | 13 ++++--- src/include/tipidee/body.h | 25 ------------- src/include/tipidee/response.h | 6 +++- src/include/tipidee/tipidee.h | 2 +- src/include/tipidee/util.h | 27 ++++++++++++++ src/libtipidee/deps-lib/tipidee | 5 ++- src/libtipidee/tipidee_chunked_read.c | 41 ---------------------- .../tipidee_response_header_common_put.c | 2 +- src/libtipidee/tipidee_response_header_date.c | 19 ++++++++++ src/libtipidee/tipidee_response_header_date_fmt.c | 11 +----- .../tipidee_response_header_lastmodified.c | 24 +++++++++++++ src/libtipidee/tipidee_util_chunked_read.c | 41 ++++++++++++++++++++++ src/libtipidee/tipidee_util_httpdate.c | 22 ++++++++++++ src/tipideed/log.c | 6 ++++ src/tipideed/regular.c | 39 +++++++++++++++----- src/tipideed/tipideed-internal.h | 5 ++- src/tipideed/tipideed.c | 19 +++++++--- 17 files changed, 209 insertions(+), 98 deletions(-) delete mode 100644 src/include/tipidee/body.h create mode 100644 src/include/tipidee/util.h delete mode 100644 src/libtipidee/tipidee_chunked_read.c create mode 100644 src/libtipidee/tipidee_response_header_date.c create mode 100644 src/libtipidee/tipidee_response_header_lastmodified.c create mode 100644 src/libtipidee/tipidee_util_chunked_read.c create mode 100644 src/libtipidee/tipidee_util_httpdate.c diff --git a/package/deps.mak b/package/deps.mak index 0dc6776..854c476 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -5,7 +5,7 @@ src/include/tipidee/conf.h: src/include/tipidee/uri.h src/include/tipidee/response.h: src/include/tipidee/rql.h src/include/tipidee/rql.h: src/include/tipidee/method.h src/include/tipidee/uri.h -src/include/tipidee/tipidee.h: src/include/tipidee/body.h src/include/tipidee/conf.h src/include/tipidee/config.h src/include/tipidee/headers.h src/include/tipidee/method.h src/include/tipidee/response.h src/include/tipidee/rql.h src/include/tipidee/uri.h +src/include/tipidee/tipidee.h: src/include/tipidee/conf.h src/include/tipidee/config.h src/include/tipidee/headers.h src/include/tipidee/method.h src/include/tipidee/response.h src/include/tipidee/rql.h src/include/tipidee/uri.h src/include/tipidee/util.h src/tipideed/tipideed-internal.h: src/include/tipidee/tipidee.h src/config/confnode.o src/config/confnode.lo: src/config/confnode.c src/config/tipidee-config-internal.h src/config/conftree.o src/config/conftree.lo: src/config/conftree.c src/config/tipidee-config-internal.h @@ -13,7 +13,6 @@ src/config/defaults.o src/config/defaults.lo: src/config/defaults.c src/config/t src/config/lexparse.o src/config/lexparse.lo: src/config/lexparse.c src/config/tipidee-config-internal.h src/include/tipidee/config.h src/config/tipidee-config-preprocess.o src/config/tipidee-config-preprocess.lo: src/config/tipidee-config-preprocess.c src/config/tipidee-config.o src/config/tipidee-config.lo: src/config/tipidee-config.c src/config/tipidee-config-internal.h src/include/tipidee/config.h -src/libtipidee/tipidee_chunked_read.o src/libtipidee/tipidee_chunked_read.lo: src/libtipidee/tipidee_chunked_read.c src/include/tipidee/body.h src/libtipidee/tipidee_conf_free.o src/libtipidee/tipidee_conf_free.lo: src/libtipidee/tipidee_conf_free.c src/include/tipidee/conf.h src/libtipidee/tipidee_conf_get.o src/libtipidee/tipidee_conf_get.lo: src/libtipidee/tipidee_conf_get.c src/include/tipidee/conf.h src/libtipidee/tipidee_conf_get_argv.o src/libtipidee/tipidee_conf_get_argv.lo: src/libtipidee/tipidee_conf_get_argv.c src/include/tipidee/conf.h @@ -32,10 +31,14 @@ src/libtipidee/tipidee_method_tostr.o src/libtipidee/tipidee_method_tostr.lo: sr src/libtipidee/tipidee_response_error.o src/libtipidee/tipidee_response_error.lo: src/libtipidee/tipidee_response_error.c src/include/tipidee/method.h src/include/tipidee/response.h src/include/tipidee/rql.h src/libtipidee/tipidee_response_header_builtin.o src/libtipidee/tipidee_response_header_builtin.lo: src/libtipidee/tipidee_response_header_builtin.c src/include/tipidee/config.h src/include/tipidee/response.h src/libtipidee/tipidee_response_header_common_put.o src/libtipidee/tipidee_response_header_common_put.lo: src/libtipidee/tipidee_response_header_common_put.c src/include/tipidee/config.h src/include/tipidee/response.h +src/libtipidee/tipidee_response_header_date.o src/libtipidee/tipidee_response_header_date.lo: src/libtipidee/tipidee_response_header_date.c src/include/tipidee/response.h src/libtipidee/tipidee_response_header_date_fmt.o src/libtipidee/tipidee_response_header_date_fmt.lo: src/libtipidee/tipidee_response_header_date_fmt.c src/include/tipidee/response.h +src/libtipidee/tipidee_response_header_lastmodified.o src/libtipidee/tipidee_response_header_lastmodified.lo: src/libtipidee/tipidee_response_header_lastmodified.c src/include/tipidee/response.h src/libtipidee/tipidee_response_status.o src/libtipidee/tipidee_response_status.lo: src/libtipidee/tipidee_response_status.c src/include/tipidee/response.h src/libtipidee/tipidee_rql_read.o src/libtipidee/tipidee_rql_read.lo: src/libtipidee/tipidee_rql_read.c src/include/tipidee/method.h src/include/tipidee/rql.h src/include/tipidee/uri.h src/libtipidee/tipidee_uri_parse.o src/libtipidee/tipidee_uri_parse.lo: src/libtipidee/tipidee_uri_parse.c src/include/tipidee/uri.h +src/libtipidee/tipidee_util_chunked_read.o src/libtipidee/tipidee_util_chunked_read.lo: src/libtipidee/tipidee_util_chunked_read.c src/include/tipidee/util.h +src/libtipidee/tipidee_util_httpdate.o src/libtipidee/tipidee_util_httpdate.lo: src/libtipidee/tipidee_util_httpdate.c src/include/tipidee/util.h src/tipideed/cgi.o src/tipideed/cgi.lo: src/tipideed/cgi.c src/include/tipidee/headers.h src/include/tipidee/method.h src/include/tipidee/response.h src/include/tipidee/uri.h src/tipideed/tipideed-internal.h src/tipideed/harden.o src/tipideed/harden.lo: src/tipideed/harden.c src/tipideed/tipideed-internal.h src/tipideed/log.o src/tipideed/log.lo: src/tipideed/log.c src/include/tipidee/method.h src/tipideed/tipideed-internal.h @@ -51,12 +54,12 @@ tipidee-config: src/config/tipidee-config.o src/config/confnode.o src/config/con tipidee-config-preprocess: EXTRA_LIBS := -lskarnet tipidee-config-preprocess: src/config/tipidee-config-preprocess.o ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) -libtipidee.a.xyzzy: src/libtipidee/tipidee_chunked_read.o src/libtipidee/tipidee_conf_free.o src/libtipidee/tipidee_conf_get.o src/libtipidee/tipidee_conf_get_argv.o src/libtipidee/tipidee_conf_get_content_type.o src/libtipidee/tipidee_conf_get_redirection.o src/libtipidee/tipidee_conf_get_string.o src/libtipidee/tipidee_conf_get_uint32.o src/libtipidee/tipidee_conf_init.o src/libtipidee/tipidee_headers_get_content_length.o src/libtipidee/tipidee_headers_init.o src/libtipidee/tipidee_headers_parse.o src/libtipidee/tipidee_headers_search.o src/libtipidee/tipidee_method_conv_table.o src/libtipidee/tipidee_method_tonum.o src/libtipidee/tipidee_method_tostr.o src/libtipidee/tipidee_response_error.o src/libtipidee/tipidee_response_header_builtin.o src/libtipidee/tipidee_response_header_common_put.o src/libtipidee/tipidee_response_header_date_fmt.o src/libtipidee/tipidee_response_status.o src/libtipidee/tipidee_rql_read.o src/libtipidee/tipidee_uri_parse.o +libtipidee.a.xyzzy: src/libtipidee/tipidee_conf_free.o src/libtipidee/tipidee_conf_get.o src/libtipidee/tipidee_conf_get_argv.o src/libtipidee/tipidee_conf_get_content_type.o src/libtipidee/tipidee_conf_get_redirection.o src/libtipidee/tipidee_conf_get_string.o src/libtipidee/tipidee_conf_get_uint32.o src/libtipidee/tipidee_conf_init.o src/libtipidee/tipidee_headers_get_content_length.o src/libtipidee/tipidee_headers_init.o src/libtipidee/tipidee_headers_parse.o src/libtipidee/tipidee_headers_search.o src/libtipidee/tipidee_method_conv_table.o src/libtipidee/tipidee_method_tonum.o src/libtipidee/tipidee_method_tostr.o src/libtipidee/tipidee_response_error.o src/libtipidee/tipidee_response_header_builtin.o src/libtipidee/tipidee_response_header_common_put.o src/libtipidee/tipidee_response_header_date.o src/libtipidee/tipidee_response_header_date_fmt.o src/libtipidee/tipidee_response_header_lastmodified.o src/libtipidee/tipidee_response_status.o src/libtipidee/tipidee_rql_read.o src/libtipidee/tipidee_uri_parse.o src/libtipidee/tipidee_util_chunked_read.o src/libtipidee/tipidee_util_httpdate.o else -libtipidee.a.xyzzy: src/libtipidee/tipidee_chunked_read.lo src/libtipidee/tipidee_conf_free.lo src/libtipidee/tipidee_conf_get.lo src/libtipidee/tipidee_conf_get_argv.lo src/libtipidee/tipidee_conf_get_content_type.lo src/libtipidee/tipidee_conf_get_redirection.lo src/libtipidee/tipidee_conf_get_string.lo src/libtipidee/tipidee_conf_get_uint32.lo src/libtipidee/tipidee_conf_init.lo src/libtipidee/tipidee_headers_get_content_length.lo src/libtipidee/tipidee_headers_init.lo src/libtipidee/tipidee_headers_parse.lo src/libtipidee/tipidee_headers_search.lo src/libtipidee/tipidee_method_conv_table.lo src/libtipidee/tipidee_method_tonum.lo src/libtipidee/tipidee_method_tostr.lo src/libtipidee/tipidee_response_error.lo src/libtipidee/tipidee_response_header_builtin.lo src/libtipidee/tipidee_response_header_common_put.lo src/libtipidee/tipidee_response_header_date_fmt.lo src/libtipidee/tipidee_response_status.lo src/libtipidee/tipidee_rql_read.lo src/libtipidee/tipidee_uri_parse.lo +libtipidee.a.xyzzy: src/libtipidee/tipidee_conf_free.lo src/libtipidee/tipidee_conf_get.lo src/libtipidee/tipidee_conf_get_argv.lo src/libtipidee/tipidee_conf_get_content_type.lo src/libtipidee/tipidee_conf_get_redirection.lo src/libtipidee/tipidee_conf_get_string.lo src/libtipidee/tipidee_conf_get_uint32.lo src/libtipidee/tipidee_conf_init.lo src/libtipidee/tipidee_headers_get_content_length.lo src/libtipidee/tipidee_headers_init.lo src/libtipidee/tipidee_headers_parse.lo src/libtipidee/tipidee_headers_search.lo src/libtipidee/tipidee_method_conv_table.lo src/libtipidee/tipidee_method_tonum.lo src/libtipidee/tipidee_method_tostr.lo src/libtipidee/tipidee_response_error.lo src/libtipidee/tipidee_response_header_builtin.lo src/libtipidee/tipidee_response_header_common_put.lo src/libtipidee/tipidee_response_header_date.lo src/libtipidee/tipidee_response_header_date_fmt.lo src/libtipidee/tipidee_response_header_lastmodified.lo src/libtipidee/tipidee_response_status.lo src/libtipidee/tipidee_rql_read.lo src/libtipidee/tipidee_uri_parse.lo src/libtipidee/tipidee_util_chunked_read.lo src/libtipidee/tipidee_util_httpdate.lo endif libtipidee.so.xyzzy: EXTRA_LIBS := -lskarnet -libtipidee.so.xyzzy: src/libtipidee/tipidee_chunked_read.lo src/libtipidee/tipidee_conf_free.lo src/libtipidee/tipidee_conf_get.lo src/libtipidee/tipidee_conf_get_argv.lo src/libtipidee/tipidee_conf_get_content_type.lo src/libtipidee/tipidee_conf_get_redirection.lo src/libtipidee/tipidee_conf_get_string.lo src/libtipidee/tipidee_conf_get_uint32.lo src/libtipidee/tipidee_conf_init.lo src/libtipidee/tipidee_headers_get_content_length.lo src/libtipidee/tipidee_headers_init.lo src/libtipidee/tipidee_headers_parse.lo src/libtipidee/tipidee_headers_search.lo src/libtipidee/tipidee_method_conv_table.lo src/libtipidee/tipidee_method_tonum.lo src/libtipidee/tipidee_method_tostr.lo src/libtipidee/tipidee_response_error.lo src/libtipidee/tipidee_response_header_builtin.lo src/libtipidee/tipidee_response_header_common_put.lo src/libtipidee/tipidee_response_header_date_fmt.lo src/libtipidee/tipidee_response_status.lo src/libtipidee/tipidee_rql_read.lo src/libtipidee/tipidee_uri_parse.lo +libtipidee.so.xyzzy: src/libtipidee/tipidee_conf_free.lo src/libtipidee/tipidee_conf_get.lo src/libtipidee/tipidee_conf_get_argv.lo src/libtipidee/tipidee_conf_get_content_type.lo src/libtipidee/tipidee_conf_get_redirection.lo src/libtipidee/tipidee_conf_get_string.lo src/libtipidee/tipidee_conf_get_uint32.lo src/libtipidee/tipidee_conf_init.lo src/libtipidee/tipidee_headers_get_content_length.lo src/libtipidee/tipidee_headers_init.lo src/libtipidee/tipidee_headers_parse.lo src/libtipidee/tipidee_headers_search.lo src/libtipidee/tipidee_method_conv_table.lo src/libtipidee/tipidee_method_tonum.lo src/libtipidee/tipidee_method_tostr.lo src/libtipidee/tipidee_response_error.lo src/libtipidee/tipidee_response_header_builtin.lo src/libtipidee/tipidee_response_header_common_put.lo src/libtipidee/tipidee_response_header_date.lo src/libtipidee/tipidee_response_header_date_fmt.lo src/libtipidee/tipidee_response_header_lastmodified.lo src/libtipidee/tipidee_response_status.lo src/libtipidee/tipidee_rql_read.lo src/libtipidee/tipidee_uri_parse.lo src/libtipidee/tipidee_util_chunked_read.lo src/libtipidee/tipidee_util_httpdate.lo tipideed: EXTRA_LIBS := -lskarnet tipideed: src/tipideed/tipideed.o src/tipideed/cgi.o src/tipideed/harden.o src/tipideed/log.o src/tipideed/options.o src/tipideed/regular.o src/tipideed/responses.o src/tipideed/send_file.o src/tipideed/tipideed.o src/tipideed/trace.o libtipidee.a.xyzzy INTERNAL_LIBS := diff --git a/src/include/tipidee/body.h b/src/include/tipidee/body.h deleted file mode 100644 index fc8bd9a..0000000 --- a/src/include/tipidee/body.h +++ /dev/null @@ -1,25 +0,0 @@ -/* ISC license. */ - -#ifndef TIPIDEE_BODY_H -#define TIPIDEE_BODY_H - -#include -#include - -#include -#include -#include - -typedef enum tipidee_transfercoding_e tipidee_transfercoding, *tipidee_transfercoding_ref ; -enum tipidee_transfercoding_e -{ - TIPIDEE_TRANSFERCODING_NONE = 0, - TIPIDEE_TRANSFERCODING_FIXED, - TIPIDEE_TRANSFERCODING_CHUNKED, - TIPIDEE_TRANSFERCODING_UNKNOWN -} ; - -extern int tipidee_chunked_read (buffer *, stralloc *, size_t, tain const *, tain *) ; -#define tipidee_chunked_read_g(b, sa, max, deadline) tipidee_chunked_read(b, sa, max, (deadline), &STAMP) - -#endif diff --git a/src/include/tipidee/response.h b/src/include/tipidee/response.h index e0a6177..d549532 100644 --- a/src/include/tipidee/response.h +++ b/src/include/tipidee/response.h @@ -3,6 +3,7 @@ #ifndef TIPIDEE_RESPONSE_H #define TIPIDEE_RESPONSE_H +#include #include #include @@ -24,7 +25,10 @@ extern size_t tipidee_response_status (buffer *, tipidee_rql const *, unsigned i #define tipidee_response_status_line(b, rql, line) tipidee_response_status(b, rql, 0, (line)) extern size_t tipidee_response_header_date_fmt (char *, size_t, tain const *) ; -#define tipidee_response_header_date_fmt_g(buf, max) tipidee_response_header_date_fmt(buf, (max), &STAMP) +extern size_t tipidee_response_header_date (char *, size_t, tain const *) ; +#define tipidee_response_header_date_g(buf, max) tipidee_response_header_date(buf, (max), &STAMP) +extern size_t tipidee_response_header_lastmodified (char *, size_t, struct stat const *) ; + extern size_t tipidee_response_header_common_put (buffer *, uint32_t, tain const *) ; #define tipidee_response_header_common_put_g(b, options) tipidee_response_header_common_put(b, (options), &STAMP) diff --git a/src/include/tipidee/tipidee.h b/src/include/tipidee/tipidee.h index ddd1348..7634366 100644 --- a/src/include/tipidee/tipidee.h +++ b/src/include/tipidee/tipidee.h @@ -3,7 +3,6 @@ #ifndef TIPIDEE_H #define TIPIDEE_H -#include #include #include #include @@ -11,5 +10,6 @@ #include #include #include +#include #endif diff --git a/src/include/tipidee/util.h b/src/include/tipidee/util.h new file mode 100644 index 0000000..5160a69 --- /dev/null +++ b/src/include/tipidee/util.h @@ -0,0 +1,27 @@ +/* ISC license. */ + +#ifndef TIPIDEE_UTIL_H +#define TIPIDEE_UTIL_H + +#include +#include + +#include +#include +#include + +typedef enum tipidee_transfercoding_e tipidee_transfercoding, *tipidee_transfercoding_ref ; +enum tipidee_transfercoding_e +{ + TIPIDEE_TRANSFERCODING_NONE = 0, + TIPIDEE_TRANSFERCODING_FIXED, + TIPIDEE_TRANSFERCODING_CHUNKED, + TIPIDEE_TRANSFERCODING_UNKNOWN +} ; + +extern int tipidee_util_chunked_read (buffer *, stralloc *, size_t, tain const *, tain *) ; +#define tipidee_util_chunked_read_g(b, sa, max, deadline) tipidee_util_chunked_read(b, sa, max, (deadline), &STAMP) + +extern int tipidee_util_httpdate (char const *, tain *) ; + +#endif diff --git a/src/libtipidee/deps-lib/tipidee b/src/libtipidee/deps-lib/tipidee index d218af1..81cc5f7 100644 --- a/src/libtipidee/deps-lib/tipidee +++ b/src/libtipidee/deps-lib/tipidee @@ -1,4 +1,3 @@ -tipidee_chunked_read.o tipidee_conf_free.o tipidee_conf_get.o tipidee_conf_get_argv.o @@ -17,8 +16,12 @@ tipidee_method_tostr.o tipidee_response_error.o tipidee_response_header_builtin.o tipidee_response_header_common_put.o +tipidee_response_header_date.o tipidee_response_header_date_fmt.o +tipidee_response_header_lastmodified.o tipidee_response_status.o tipidee_rql_read.o tipidee_uri_parse.o +tipidee_util_chunked_read.o +tipidee_util_httpdate.o -lskarnet diff --git a/src/libtipidee/tipidee_chunked_read.c b/src/libtipidee/tipidee_chunked_read.c deleted file mode 100644 index 66d5d80..0000000 --- a/src/libtipidee/tipidee_chunked_read.c +++ /dev/null @@ -1,41 +0,0 @@ -/* ISC license. */ - -#include -#include - -#include -#include -#include - -#include - -#include - -int tipidee_chunked_read (buffer *b, stralloc *sa, size_t maxlen, tain const *deadline, tain *stamp) -{ - char line[512] ; - for (;;) - { - size_t chunklen, pos, w = 0 ; - ssize_t r = timed_getlnmax(b, line, 512, &w, '\n', deadline, stamp) ; - if (r < 0) return 0 ; - if (!r) return (errno = EPIPE, 0) ; - pos = size_scan(line, &chunklen) ; - if (!pos) return (errno = EPROTO, 0) ; - if (!memchr("\r\n; \t", line[pos], 5)) return (errno = EPROTO, 0) ; - if (!chunklen) break ; - if (sa->len + chunklen > maxlen) return (errno = EMSGSIZE, 0) ; - if (!stralloc_readyplus(sa, chunklen)) return 0 ; - if (buffer_timed_get(b, sa->s + sa->len, chunklen, deadline, stamp) < chunklen) return 0 ; - sa->len += chunklen ; - } - for (;;) - { - size_t w = 0 ; - ssize_t r = timed_getlnmax(b, line, 512, &w, '\n', deadline, stamp) ; - if (r < 0) return 0 ; - if (!r) return (errno = EPIPE, 0) ; - if (w == 1 || (w == 2 && line[0] == '\r')) break ; - } - return 1 ; -} diff --git a/src/libtipidee/tipidee_response_header_common_put.c b/src/libtipidee/tipidee_response_header_common_put.c index 8352ba9..c67cc94 100644 --- a/src/libtipidee/tipidee_response_header_common_put.c +++ b/src/libtipidee/tipidee_response_header_common_put.c @@ -10,7 +10,7 @@ size_t tipidee_response_header_common_put (buffer *b, uint32_t options, tain const *stamp) { char fmt[128] ; - size_t m = buffer_putnoflush(b, fmt, tipidee_response_header_date_fmt(fmt, 128, stamp)) ; + size_t m = buffer_putnoflush(b, fmt, tipidee_response_header_date(fmt, 128, stamp)) ; for (tipidee_response_header_builtin const *p = tipidee_response_header_builtin_table ; p->key ; p++) { m += buffer_putsnoflush(b, p->key) ; diff --git a/src/libtipidee/tipidee_response_header_date.c b/src/libtipidee/tipidee_response_header_date.c new file mode 100644 index 0000000..d350d2c --- /dev/null +++ b/src/libtipidee/tipidee_response_header_date.c @@ -0,0 +1,19 @@ +/* ISC license. */ + +#include +#include + +#include + +size_t tipidee_response_header_date (char *s, size_t max, tain const *stamp) +{ + size_t l ; + if (max < 8) return (errno = ENOBUFS, 0) ; + memcpy(s, "Date: ", 6) ; + l = tipidee_response_header_date_fmt(s + 6, max - 6, stamp) ; + if (!l) return 0 ; + if (l + 8 > max) return (errno = ENOBUFS, 0) ; + l += 6 ; + s[l++] = '\r' ; s[l++] = '\n' ; + return l ; +} diff --git a/src/libtipidee/tipidee_response_header_date_fmt.c b/src/libtipidee/tipidee_response_header_date_fmt.c index df19673..ca4cdd9 100644 --- a/src/libtipidee/tipidee_response_header_date_fmt.c +++ b/src/libtipidee/tipidee_response_header_date_fmt.c @@ -1,6 +1,5 @@ /* ISC license. */ -#include #include #include @@ -10,15 +9,7 @@ size_t tipidee_response_header_date_fmt (char *s, size_t max, tain const *stamp) { - size_t m = 0, l ; struct tm tm ; - if (m + 6 > max) return 0 ; if (!localtm_from_tai(&tm, tain_secp(stamp), 0)) return 0 ; - memcpy(s, "Date: ", 6) ; m += 6 ; - l = strftime(s + m, max - m, "%a, %d %b %Y %T GMT", &tm) ; - if (!l) return 0 ; - m += l ; - if (m + 2 > max) return 0 ; - s[m++] = '\r' ; s[m++] = '\n' ; - return m ; + return strftime(s, max, "%a, %d %b %Y %T GMT", &tm) ; } diff --git a/src/libtipidee/tipidee_response_header_lastmodified.c b/src/libtipidee/tipidee_response_header_lastmodified.c new file mode 100644 index 0000000..3b3caa6 --- /dev/null +++ b/src/libtipidee/tipidee_response_header_lastmodified.c @@ -0,0 +1,24 @@ +/* ISC license. */ + +#include + +#include +#include +#include + +#include + +size_t tipidee_response_header_lastmodified (char *s, size_t max, struct stat const *st) +{ + tain t ; + size_t l ; + if (max < 17) return (errno = ENOBUFS, 0) ; + if (!tain_from_timespec(&t, &st->st_mtim)) return 0 ; + memcpy(s, "Last-Modified: ", 15) ; + l = tipidee_response_header_date_fmt(s + 15, max - 15, &t) ; + if (!l) return 0 ; + if (l + 17 > max) return (errno = ENOBUFS, 0) ; + l += 15 ; + s[l++] = '\r' ; s[l++] = '\n' ; + return l ; +} diff --git a/src/libtipidee/tipidee_util_chunked_read.c b/src/libtipidee/tipidee_util_chunked_read.c new file mode 100644 index 0000000..850ffae --- /dev/null +++ b/src/libtipidee/tipidee_util_chunked_read.c @@ -0,0 +1,41 @@ +/* ISC license. */ + +#include +#include + +#include +#include +#include + +#include + +#include + +int tipidee_util_chunked_read (buffer *b, stralloc *sa, size_t maxlen, tain const *deadline, tain *stamp) +{ + char line[512] ; + for (;;) + { + size_t chunklen, pos, w = 0 ; + ssize_t r = timed_getlnmax(b, line, 512, &w, '\n', deadline, stamp) ; + if (r < 0) return 0 ; + if (!r) return (errno = EPIPE, 0) ; + pos = size_scan(line, &chunklen) ; + if (!pos) return (errno = EPROTO, 0) ; + if (!memchr("\r\n; \t", line[pos], 5)) return (errno = EPROTO, 0) ; + if (!chunklen) break ; + if (sa->len + chunklen > maxlen) return (errno = EMSGSIZE, 0) ; + if (!stralloc_readyplus(sa, chunklen)) return 0 ; + if (buffer_timed_get(b, sa->s + sa->len, chunklen, deadline, stamp) < chunklen) return 0 ; + sa->len += chunklen ; + } + for (;;) + { + size_t w = 0 ; + ssize_t r = timed_getlnmax(b, line, 512, &w, '\n', deadline, stamp) ; + if (r < 0) return 0 ; + if (!r) return (errno = EPIPE, 0) ; + if (w == 1 || (w == 2 && line[0] == '\r')) break ; + } + return 1 ; +} diff --git a/src/libtipidee/tipidee_util_httpdate.c b/src/libtipidee/tipidee_util_httpdate.c new file mode 100644 index 0000000..cce735d --- /dev/null +++ b/src/libtipidee/tipidee_util_httpdate.c @@ -0,0 +1,22 @@ +/* ISC license. */ + +#include +#include + +#include + +#include + +int tipidee_util_httpdate (char const *s, tain *stamp) +{ + struct tm tm ; + if (strptime(s, "%a, %d %b %Y %T GMT", &tm)) goto got ; + if (strptime(s, "%a, %d-%b-%y %T GMT", &tm)) goto got ; + if (strptime(s, "%a %b %d %T %Y", &tm)) goto got ; + return (errno = EINVAL, 0) ; + + got: + if (!tai_from_localtm(tain_secp(stamp), &tm)) return 0 ; + stamp->nano = 0 ; + return 1 ; +} diff --git a/src/tipideed/log.c b/src/tipideed/log.c index a257ff5..f5f2e81 100644 --- a/src/tipideed/log.c +++ b/src/tipideed/log.c @@ -44,6 +44,12 @@ void log_regular (char const *fn, char const *sizefmt, int ishead, char const *c strerr_warni8x("sending ", ishead ? "headers for " : "", "regular file ", fn, " (", sizefmt, " bytes) with type ", ct) ; } +void log_304 (char const *fn) +{ + if (g.verbosity >= 2) + strerr_warni2x("answering 304 for regular file ", fn) ; +} + void log_nph (char const *const *argv, char const *const *envp) { if (g.verbosity >= 2) diff --git a/src/tipideed/regular.c b/src/tipideed/regular.c index df4b157..5af364d 100644 --- a/src/tipideed/regular.c +++ b/src/tipideed/regular.c @@ -1,8 +1,11 @@ /* ISC license. */ +#include + #include #include +#include #include #include #include @@ -14,21 +17,23 @@ #include #include "tipideed-internal.h" -int respond_regular (tipidee_rql const *rql, char const *fn, uint64_t size, tipidee_resattr const *ra) +int respond_regular (tipidee_rql const *rql, char const *fn, struct stat const *st, tipidee_resattr const *ra) { tain deadline ; + char fmt[128] ; size_t n = tipidee_response_status_line(buffer_1, rql, "200 OK") ; n += tipidee_response_header_common_put_g(buffer_1, !g.cont) ; + { + size_t l = tipidee_response_header_lastmodified(fmt, 128, st) ; + if (l) n += buffer_putnoflush(buffer_1, fmt, l) ; + } n += buffer_putsnoflush(buffer_1, "Content-Type: ") ; n += buffer_putsnoflush(buffer_1, ra->content_type) ; n += buffer_putsnoflush(buffer_1, "\r\nContent-Length: ") ; - { - char fmt[UINT64_FMT] ; - fmt[uint64_fmt(fmt, size)] = 0 ; - n += buffer_putsnoflush(buffer_1, fmt) ; - log_regular(fn, fmt, rql->m == TIPIDEE_METHOD_HEAD, ra->content_type) ; - } + fmt[uint64_fmt(fmt, st->st_size)] = 0 ; + n += buffer_putsnoflush(buffer_1, fmt) ; n += buffer_putnoflush(buffer_1, "\r\n\r\n", 4) ; + log_regular(fn, fmt, rql->m == TIPIDEE_METHOD_HEAD, ra->content_type) ; if (rql->m == TIPIDEE_METHOD_HEAD) { tain_add_g(&deadline, &g.writetto) ; @@ -48,8 +53,26 @@ int respond_regular (tipidee_rql const *rql, char const *fn, uint64_t size, tipi } else die500sys(rql, 111, "open ", fn) ; } - send_file(fd, size, fn) ; + send_file(fd, st->st_size, fn) ; fd_close(fd) ; } return 0 ; } + +int respond_304 (tipidee_rql const *rql, char const *fn, struct stat const *st) +{ + tain deadline ; + char fmt[128] ; + size_t n = tipidee_response_status_line(buffer_1, rql, "304 Not Modified") ; + n += tipidee_response_header_common_put_g(buffer_1, !g.cont) ; + { + size_t l = tipidee_response_header_lastmodified(fmt, 128, st) ; + if (l) n += buffer_putnoflush(buffer_1, fmt, l) ; + } + n += buffer_putnoflush(buffer_1, "\r\n", 2) ; + log_304(fn) ; + tain_add_g(&deadline, &g.writetto) ; + if (!buffer_timed_flush_g(buffer_1, &deadline)) + strerr_diefu1sys(111, "write to stdout") ; + return 0 ; +} diff --git a/src/tipideed/tipideed-internal.h b/src/tipideed/tipideed-internal.h index c4ff928..3eb0644 100644 --- a/src/tipideed/tipideed-internal.h +++ b/src/tipideed/tipideed-internal.h @@ -4,6 +4,7 @@ #define TIPIDEED_INTERNAL_H #include +#include #include #include @@ -127,7 +128,8 @@ extern void send_file (int, uint64_t, char const *) ; /* regular */ -extern int respond_regular (tipidee_rql const *, char const *, uint64_t, tipidee_resattr const *) ; +extern int respond_regular (tipidee_rql const *, char const *, struct stat const *, tipidee_resattr const *) ; +extern int respond_304 (tipidee_rql const *, char const *, struct stat const *) ; /* cgi */ @@ -141,6 +143,7 @@ extern void log_start (void) ; extern void log_and_exit (int) gccattr_noreturn ; extern void log_request (tipidee_rql const *) ; extern void log_regular (char const *, char const *, int, char const *) ; +extern void log_304 (char const *) ; extern void log_nph (char const *const *, char const *const *) ; extern void log_cgi (char const *const *, char const *const *) ; diff --git a/src/tipideed/tipideed.c b/src/tipideed/tipideed.c index 8c1e16e..5b6db10 100644 --- a/src/tipideed/tipideed.c +++ b/src/tipideed/tipideed.c @@ -1,10 +1,11 @@ /* ISC license. */ +#include + #include #include #include #include -#include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -286,8 +288,17 @@ static inline int serve (tipidee_rql *rql, char const *docroot, size_t docrootle return respond_options(rql, ra.iscgi) ; else if (ra.iscgi) return respond_cgi(rql, fn, docrootlen, infopath, uribuf, hdr, &ra, body, bodylen) ; - else - return respond_regular(rql, fn, st.st_size, &ra) ; + + infopath = tipidee_headers_search(hdr, "If-Modified-Since") ; + if (infopath) + { + tain wanted, actual ; + if (tipidee_util_httpdate(infopath, &wanted) + && tain_from_timespec(&actual, &st.st_mtim) + && tain_less(&actual, &wanted)) + return respond_304(rql, fn, &st) ; + } + return respond_regular(rql, fn, &st, &ra) ; } int main (int argc, char const *const *argv, char const *const *envp) @@ -495,7 +506,7 @@ int main (int argc, char const *const *argv, char const *const *envp) } case TIPIDEE_TRANSFERCODING_CHUNKED : { - if (!tipidee_chunked_read_g(buffer_0, &bodysa, g.maxrqbody, &deadline)) + if (!tipidee_util_chunked_read_g(buffer_0, &bodysa, g.maxrqbody, &deadline)) { if (error_temp(errno)) die500sys(&rql, 111, "decode chunked body") ; else if (errno == EMSGSIZE) exit_413(&rql, "Request body too large") ; -- cgit v1.3.1