summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2021-07-06 22:58:13 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2021-09-04 08:08:26 -0400
commit91472ab7681b26f36b813f3b245c0e98f91b4c3f (patch)
treec0a71cb0f9d52747ec4c0409f8863b9f64233e83 /src
parenta0a8cf821d2292e6662119e158e73c175452f1c3 (diff)
downloadlighttpd-git-91472ab7681b26f36b813f3b245c0e98f91b4c3f.tar.gz
[tests] t/test_mod_staticfile
move some tests from tests/request.t to src/t/test_mod_staticfile.c
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt27
-rw-r--r--src/Makefile.am5
-rw-r--r--src/meson.build44
-rw-r--r--src/mod_staticfile.c32
-rw-r--r--src/t/test_mod_staticfile.c458
5 files changed, 551 insertions, 15 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5fec0207..c92a85b7 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -927,6 +927,30 @@ add_executable(test_mod_simple_vhost
)
add_test(NAME test_mod_simple_vhost COMMAND test_mod_simple_vhost)
+add_executable(test_mod_staticfile
+ t/test_mod_staticfile.c
+ request.c
+ base64.c
+ buffer.c
+ burl.c
+ array.c
+ chunk.c
+ fdevent.c
+ http-header-glue.c
+ http_cgi.c
+ http_chunk.c
+ http_date.c
+ http_etag.c
+ http_header.c
+ http_kv.c
+ log.c
+ sock_addr.c
+ stat_cache.c
+ algo_splaytree.c
+ ck.c
+)
+add_test(NAME test_mod_staticfile COMMAND test_mod_staticfile)
+
add_executable(test_mod_userdir
t/test_mod_userdir.c
buffer.c
@@ -1084,6 +1108,7 @@ endif()
if(HAVE_LIBFAM)
target_link_libraries(lighttpd fam)
+ target_link_libraries(test_mod_staticfile fam)
endif()
if(HAVE_GDBM_H)
@@ -1204,6 +1229,8 @@ if(WITH_LIBUNWIND)
add_target_properties(test_mod_evhost COMPILE_FLAGS ${LIBUNWIND_CFLAGS})
target_link_libraries(test_mod_simple_vhost ${LIBUNWIND_LDFLAGS})
add_target_properties(test_mod_simple_vhost COMPILE_FLAGS ${LIBUNWIND_CFLAGS})
+ target_link_libraries(test_mod_staticfile ${LIBUNWIND_LDFLAGS})
+ add_target_properties(test_mod_staticfile COMPILE_FLAGS ${LIBUNWIND_CFLAGS})
target_link_libraries(test_mod_userdir ${LIBUNWIND_LDFLAGS})
add_target_properties(test_mod_userdir COMPILE_FLAGS ${LIBUNWIND_CFLAGS})
target_link_libraries(test_request ${LIBUNWIND_LDFLAGS})
diff --git a/src/Makefile.am b/src/Makefile.am
index fe7341e6..1f15aec4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,6 +10,7 @@ noinst_PROGRAMS=\
t/test_mod_access \
t/test_mod_evhost \
t/test_mod_simple_vhost \
+ t/test_mod_staticfile \
t/test_mod_userdir \
t/test_request
@@ -26,6 +27,7 @@ TESTS=\
t/test_mod_access$(EXEEXT) \
t/test_mod_evhost$(EXEEXT) \
t/test_mod_simple_vhost$(EXEEXT) \
+ t/test_mod_staticfile$(EXEEXT) \
t/test_mod_userdir$(EXEEXT) \
t/test_request$(EXEEXT)
@@ -663,6 +665,9 @@ t_test_mod_evhost_LDADD = $(LIBUNWIND_LIBS)
t_test_mod_simple_vhost_SOURCES = t/test_mod_simple_vhost.c buffer.c array.c log.c ck.c
t_test_mod_simple_vhost_LDADD = $(LIBUNWIND_LIBS)
+t_test_mod_staticfile_SOURCES = t/test_mod_staticfile.c request.c base64.c buffer.c burl.c array.c chunk.c fdevent.c http-header-glue.c http_cgi.c http_chunk.c http_date.c http_etag.c http_header.c http_kv.c log.c sock_addr.c stat_cache.c algo_splaytree.c ck.c
+t_test_mod_staticfile_LDADD = $(LIBUNWIND_LIBS) $(FAM_LIBS)
+
t_test_mod_userdir_SOURCES = t/test_mod_userdir.c buffer.c array.c log.c ck.c
t_test_mod_userdir_LDADD = $(LIBUNWIND_LIBS)
diff --git a/src/meson.build b/src/meson.build
index fdf57ca9..a0c6ee9e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -895,7 +895,11 @@ test('test_configfile', executable('test_configfile',
'sock_addr.c',
'ck.c',
],
- dependencies: common_flags + libpcre + libunwind,
+ dependencies: [ common_flags
+ , libpcre
+ , libunwind
+ , libws2_32
+ ],
build_by_default: false,
))
@@ -949,6 +953,38 @@ test('test_mod_simple_vhost', executable('test_mod_simple_vhost',
build_by_default: false,
))
+test('test_mod_staticfile', executable('test_mod_staticfile',
+ sources: [
+ 't/test_mod_staticfile.c',
+ 'request.c',
+ 'base64.c',
+ 'buffer.c',
+ 'burl.c',
+ 'array.c',
+ 'chunk.c',
+ 'fdevent.c',
+ 'http-header-glue.c',
+ 'http_cgi.c',
+ 'http_chunk.c',
+ 'http_date.c',
+ 'http_etag.c',
+ 'http_header.c',
+ 'http_kv.c',
+ 'log.c',
+ 'sock_addr.c',
+ 'stat_cache.c',
+ 'algo_splaytree.c',
+ 'ck.c'
+ ],
+ dependencies: [ common_flags
+ , libfam
+ , libpcre
+ , libunwind
+ , libws2_32
+ ],
+ build_by_default: false,
+))
+
test('test_mod_userdir', executable('test_mod_userdir',
sources: [
't/test_mod_userdir.c',
@@ -974,7 +1010,11 @@ test('test_request', executable('test_request',
'sock_addr.c',
'ck.c',
],
- dependencies: common_flags + libunwind,
+ dependencies: [ common_flags
+ , libpcre
+ , libunwind
+ , libws2_32
+ ],
build_by_default: false,
))
diff --git a/src/mod_staticfile.c b/src/mod_staticfile.c
index 763cc521..d39abe29 100644
--- a/src/mod_staticfile.c
+++ b/src/mod_staticfile.c
@@ -107,25 +107,19 @@ mod_staticfile_not_handled(request_st * const r, const char * const msg)
return HANDLER_GO_ON;
}
-URIHANDLER_FUNC(mod_staticfile_subrequest) {
- if (NULL != r->handler_module) return HANDLER_GO_ON;
- if (!http_method_get_head_post(r->http_method)) return HANDLER_GO_ON;
- /* r->physical.path is non-empty for handle_subrequest_start */
- /*if (buffer_is_blank(&r->physical.path)) return HANDLER_GO_ON;*/
-
- plugin_data * const p = p_d;
- mod_staticfile_patch_config(r, p);
-
- if (p->conf.disable_pathinfo && !buffer_is_blank(&r->pathinfo)) {
+static handler_t
+mod_staticfile_process (request_st * const r, plugin_config * const pconf)
+{
+ if (pconf->disable_pathinfo && !buffer_is_blank(&r->pathinfo)) {
return mod_staticfile_not_handled(r, "pathinfo");
}
- if (p->conf.exclude_ext
- && array_match_value_suffix(p->conf.exclude_ext, &r->physical.path)) {
+ if (pconf->exclude_ext
+ && array_match_value_suffix(pconf->exclude_ext, &r->physical.path)) {
return mod_staticfile_not_handled(r, "extension");
}
- if (!p->conf.etags_used) r->conf.etag_flags = 0;
+ if (!pconf->etags_used) r->conf.etag_flags = 0;
/* r->tmp_sce is set in http_response_physical_path_check() and is valid
* in handle_subrequest_start callback -- handle_subrequest_start callbacks
@@ -138,6 +132,18 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) {
return HANDLER_FINISHED;
}
+URIHANDLER_FUNC(mod_staticfile_subrequest) {
+ if (NULL != r->handler_module) return HANDLER_GO_ON;
+ if (!http_method_get_head_post(r->http_method)) return HANDLER_GO_ON;
+ /* r->physical.path is non-empty for handle_subrequest_start */
+ /*if (buffer_is_blank(&r->physical.path)) return HANDLER_GO_ON;*/
+
+ plugin_data * const p = p_d;
+ mod_staticfile_patch_config(r, p);
+
+ return mod_staticfile_process(r, &p->conf);
+}
+
int mod_staticfile_plugin_init(plugin *p);
int mod_staticfile_plugin_init(plugin *p) {
diff --git a/src/t/test_mod_staticfile.c b/src/t/test_mod_staticfile.c
new file mode 100644
index 00000000..58e4e968
--- /dev/null
+++ b/src/t/test_mod_staticfile.c
@@ -0,0 +1,458 @@
+#include "first.h"
+
+#undef NDEBUG
+#include <sys/types.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "mod_staticfile.c"
+#include "http_date.h"
+#include "http_etag.h"
+#include "http_header.h"
+
+__attribute_noinline__
+static void test_mod_staticfile_reset (request_st * const r)
+{
+ r->http_status = 0;
+ r->resp_htags = 0;
+ array_reset_data_strings(&r->resp_headers);
+ http_response_body_clear(r, 0);
+ buffer_clear(&r->physical.etag);
+ r->conf.etag_flags = ETAG_USE_INODE | ETAG_USE_MTIME | ETAG_USE_SIZE;
+}
+
+__attribute_noinline__
+static void
+run_http_response_send_file (request_st * const r, int line, int status, const char *desc)
+{
+ http_response_send_file(r, &r->physical.path, NULL);
+ if (r->http_status != status) {
+ fprintf(stderr,
+ "%s.%d: %s() failed: expected '%d', got '%d' for test %s\n",
+ __FILE__, line, "http_response_send_file", status,
+ r->http_status, desc);
+ fflush(stderr);
+ abort();
+ }
+}
+
+static void
+test_http_response_send_file (request_st * const r, time_t lmtime)
+{
+ test_mod_staticfile_reset(r);
+ const buffer *vb;
+
+ /*(mismatch test must be first, else stat_cache will have cached mimetype)*/
+ array * const mimetypes_empty = array_init(0);
+ const array * const mimetypes_orig = r->conf.mimetypes;
+ r->conf.mimetypes = mimetypes_empty;
+ run_http_response_send_file(r, __LINE__, 200,
+ "basic static file (w/o mimetype match)");
+ vb = http_header_response_get(r, HTTP_HEADER_CONTENT_TYPE,
+ CONST_STR_LEN("Content-Type"));
+ assert(vb && buffer_eq_slen(vb, CONST_STR_LEN("application/octet-stream")));
+ test_mod_staticfile_reset(r);
+ r->conf.mimetypes = mimetypes_orig;
+ array_free(mimetypes_empty);
+
+ run_http_response_send_file(r, __LINE__, 200,
+ "basic static file (w/ mimetype match)");
+ vb = http_header_response_get(r, HTTP_HEADER_CONTENT_TYPE,
+ CONST_STR_LEN("Content-Type"));
+ assert(vb && buffer_eq_slen(vb, CONST_STR_LEN("text/plain")));
+ vb = http_header_response_get(r, HTTP_HEADER_ETAG,
+ CONST_STR_LEN("ETag"));
+ assert(vb && vb->ptr[0] == '"' && vb->ptr[buffer_clen(vb)-1] == '"');
+ vb = http_header_response_get(r, HTTP_HEADER_LAST_MODIFIED,
+ CONST_STR_LEN("Last-Modified"));
+ assert(vb);
+ test_mod_staticfile_reset(r);
+
+ const uint32_t plen = buffer_clen(&r->physical.path);
+ buffer_append_string_len(&r->physical.path, CONST_STR_LEN("-nonexistent"));
+ run_http_response_send_file(r, __LINE__, 404,
+ "non-existent file");
+ test_mod_staticfile_reset(r);
+ buffer_truncate(&r->physical.path, plen);
+
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ CONST_STR_LEN(""));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-modified-since invalid (empty)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ CONST_STR_LEN("foobar"));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-modified-since invalid (not time string)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ CONST_STR_LEN("this string is too long to be a valid timestamp"));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-modified-since invalid (too long to be valid time string)");
+ test_mod_staticfile_reset(r);
+
+ char lmtime_str[HTTP_DATE_SZ];
+ uint32_t lmtime_len;
+
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),
+ lmtime ? lmtime-1 : lmtime);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-modified-since older than st_mtime");
+ test_mod_staticfile_reset(r);
+
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),lmtime);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-modified-since matches st_mtime");
+ test_mod_staticfile_reset(r);
+
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),lmtime+1);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-modified-since newer than st_mtime");
+ test_mod_staticfile_reset(r);
+
+ buffer_append_string_len(
+ http_header_request_get(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since")),
+ CONST_STR_LEN("; foo"));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-modified-since newer but overload (invalid)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_unset(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"));
+
+ buffer *etag = buffer_init();
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_STR_LEN("foo"));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag mismatch)");
+ vb = http_header_response_get(r, HTTP_HEADER_ETAG,
+ CONST_STR_LEN("ETag"));
+ assert(vb);
+ buffer_copy_buffer(etag, vb);
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_BUF_LEN(etag));
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag match)");
+ test_mod_staticfile_reset(r);
+
+ r->conf.etag_flags = 0;
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_BUF_LEN(etag));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag would match, but etags disabled in config)");
+ test_mod_staticfile_reset(r);
+ r->conf.etag_flags = ETAG_USE_INODE | ETAG_USE_MTIME | ETAG_USE_SIZE;
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_BUF_LEN(etag));
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),
+ lmtime ? lmtime-1 : lmtime);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag match), "
+ "if-modified-since (old) (should be ignored)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_BUF_LEN(etag));
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),lmtime);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag match), "
+ "if-modified-since (now) (should be ignored)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_BUF_LEN(etag));
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ CONST_STR_LEN("Sun, 01 Jan 1970 00:00:01 GMT foo"));
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag match), "
+ "if-modified-since (overlong; invalid) (should be ignored)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_STR_LEN("foo"));
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),
+ lmtime ? lmtime-1 : lmtime);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag mismatch), "
+ "if-modified-since (old) (should be ignored)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_STR_LEN("foo"));
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),lmtime);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag mismatch), "
+ "if-modified-since (now) (should be ignored)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_unset(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"));
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ etag->ptr, buffer_clen(etag)-1);
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag invalid; mismatched quotes)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ etag->ptr+1, buffer_clen(etag)-2);
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag invalid; no quotes)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_STR_LEN("*"));
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag * (unquoted) matches any ETag)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_STR_LEN("\"*\""));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag \"*\" (quoted) is a regular ETag)");
+ test_mod_staticfile_reset(r);
+
+ buffer * const rqst_etag =
+ http_header_request_set_ptr(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"));
+
+ buffer_copy_string_len(rqst_etag, CONST_STR_LEN("W/"));
+ buffer_append_buffer(rqst_etag, etag);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (weak etag) matches like ETag for GET and HEAD)");
+ test_mod_staticfile_reset(r);
+
+ /*(200 expected here instead of 206 since Range is handled later)*/
+ http_header_request_set(r, HTTP_HEADER_RANGE,
+ CONST_STR_LEN("Range"),
+ CONST_STR_LEN("bytes=0-0"));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (weak etag) does not match for Range request)");
+ test_mod_staticfile_reset(r);
+ http_header_request_unset(r, HTTP_HEADER_RANGE, CONST_STR_LEN("Range"));
+
+ buffer_copy_string_len(rqst_etag, CONST_STR_LEN("W/\"12345\""));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (weak etag no match)");
+ test_mod_staticfile_reset(r);
+
+ buffer_append_string_len(rqst_etag, CONST_STR_LEN(", "));
+ buffer_append_buffer(rqst_etag, etag);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag list, second etag matches)");
+ test_mod_staticfile_reset(r);
+
+ buffer_append_string_len(rqst_etag, CONST_STR_LEN(", W/"));
+ buffer_append_buffer(rqst_etag, etag);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag list, second etag matches weakly)");
+ test_mod_staticfile_reset(r);
+
+ buffer_copy_string_len(rqst_etag, CONST_STR_LEN("\"12345\",, ,, , "));
+ buffer_append_buffer(rqst_etag, etag);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag list non-normalized, ending with etag match)");
+ test_mod_staticfile_reset(r);
+
+ buffer_copy_string_len(rqst_etag, CONST_STR_LEN("\"1234\", "));
+ buffer_append_buffer(rqst_etag, etag);
+ buffer_append_string_len(rqst_etag, CONST_STR_LEN(", \"brokentrailing"));
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag list with etag match then invalid trailing data)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_unset(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"));
+
+ buffer_free(etag);
+}
+
+__attribute_noinline__
+static void
+run_mod_staticfile_process (request_st * const r, plugin_config * const pconf, int line, int status, const char *desc)
+{
+ handler_t rc = mod_staticfile_process(r, pconf);
+ if (r->http_status != status
+ || rc != (status ? HANDLER_FINISHED : HANDLER_GO_ON)) {
+ fprintf(stderr,
+ "%s.%d: %s() failed: expected '%d', got '%d' for test %s\n",
+ __FILE__, line, "mod_staticfile_process", status,
+ r->http_status, desc);
+ fflush(stderr);
+ abort();
+ }
+}
+
+static void
+test_mod_staticfile_process (request_st * const r, plugin_config * const pconf)
+{
+ test_mod_staticfile_reset(r);
+
+ pconf->disable_pathinfo = 0;
+ buffer_copy_string_len(&r->pathinfo, CONST_STR_LEN("/pathinfo"));
+ run_mod_staticfile_process(r, pconf, __LINE__, 200,
+ "pathinfo allowed and present");
+ test_mod_staticfile_reset(r);
+ pconf->disable_pathinfo = 1;
+ run_mod_staticfile_process(r, pconf, __LINE__, 0,
+ "pathinfo denied and present");
+ test_mod_staticfile_reset(r);
+ buffer_clear(&r->pathinfo);
+ run_mod_staticfile_process(r, pconf, __LINE__, 200,
+ "pathinfo denied and not present");
+ test_mod_staticfile_reset(r);
+ pconf->disable_pathinfo = 0;
+
+ array * const a = array_init(1);
+ array_insert_value(a, CONST_STR_LEN(".exe"));
+ pconf->exclude_ext = a;
+ run_mod_staticfile_process(r, pconf, __LINE__, 200,
+ "extension disallowed (no match)");
+ test_mod_staticfile_reset(r);
+ buffer_append_string_len(&r->physical.path, CONST_STR_LEN(".exe"));
+ run_mod_staticfile_process(r, pconf, __LINE__, 0,
+ "extension disallowed (match)");
+ test_mod_staticfile_reset(r);
+ pconf->exclude_ext = NULL;
+ array_free(a);
+}
+
+#include <unistd.h> /* unlink() */
+
+int main (void)
+{
+ char fn[] = "/tmp/lighttpd_mod_staticfile.XXXXXX";
+ #ifdef __COVERITY__
+ /* POSIX-2008 requires mkstemp create file with 0600 perms */
+ umask(0600);
+ #endif
+ /* coverity[secure_temp : FALSE] */
+ int fd = mkstemp(fn);
+ if (fd < 0) {
+ perror("mkstemp()");
+ exit(1);
+ }
+ struct stat st;
+ if (0 != fstat(fd, &st)) {
+ perror("fstat()");
+ exit(1);
+ }
+
+ plugin_data * const p = mod_staticfile_init();
+ assert(NULL != p);
+ p->conf.etags_used = 1;
+
+ request_st r;
+
+ memset(&r, 0, sizeof(request_st));
+ r.http_method = HTTP_METHOD_GET;
+ r.http_version = HTTP_VERSION_1_1;
+ r.tmp_buf = buffer_init();
+ r.conf.errh = log_error_st_init();
+ r.conf.errh->errorlog_fd = -1; /* (disable) */
+ r.conf.follow_symlink = 1;
+ buffer_copy_string_len(&r.uri.path, CONST_STR_LEN("/"));
+ array * const mimetypes = array_init(1);
+ r.conf.mimetypes = mimetypes;
+ array_set_key_value(mimetypes, fn+sizeof(fn)-8, 7,
+ CONST_STR_LEN("text/plain"));
+
+ strftime_cache_reset();
+
+ buffer_copy_string_len(&r.physical.path, fn, sizeof(fn)-1);
+ test_http_response_send_file(&r, st.st_mtime);
+
+ r.rqst_htags = 0;
+ array_reset_data_strings(&r.rqst_headers);
+
+ buffer_copy_string_len(&r.physical.path, fn, sizeof(fn)-1);
+ test_mod_staticfile_process(&r, &p->conf);
+
+ array_free(mimetypes);
+ log_error_st_free(r.conf.errh);
+ buffer_free(r.tmp_buf);
+ chunkqueue_reset(&r.write_queue);
+
+ free(r.uri.path.ptr);
+ free(r.physical.etag.ptr);
+ free(r.physical.path.ptr);
+ free(r.physical.rel_path.ptr);
+ free(r.physical.doc_root.ptr);
+
+ free(p);
+ stat_cache_free();
+ unlink(fn);
+ return 0;
+}
+
+
+/*
+ * stub functions
+ */
+
+#include "fdevent_impl.h"
+int fdevent_select_init(struct fdevents *ev) { return NULL == ev; }
+int fdevent_poll_init(struct fdevents *ev) { return NULL == ev; }
+int fdevent_linux_sysepoll_init(struct fdevents *ev) { return NULL == ev; }
+int fdevent_solaris_devpoll_init(struct fdevents *ev) { return NULL == ev; }
+int fdevent_solaris_port_init(struct fdevents *ev) { return NULL == ev; }
+int fdevent_freebsd_kqueue_init(struct fdevents *ev) { return NULL == ev; }
+int fdevent_libev_init(struct fdevents *ev) { return NULL == ev; }
+
+int config_plugin_values_init(server *srv, void *p_d, const config_plugin_keys_t *cpk, const char *mname) {
+ UNUSED(srv);
+ UNUSED(p_d);
+ UNUSED(cpk);
+ UNUSED(mname);
+ return 0;
+}
+
+int config_check_cond(request_st *r, int context_ndx) {
+ UNUSED(r);
+ UNUSED(context_ndx);
+ return 0;
+}