summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/future.html17
-rw-r--r--package/deps.mak18
-rw-r--r--src/config/headers.c2
-rw-r--r--src/include/tipidee/response.h20
-rw-r--r--src/include/tipidee/util.h5
-rw-r--r--src/libtipidee/deps-lib/tipidee7
-rw-r--r--src/libtipidee/tipidee_response_error_nofile.c12
-rw-r--r--src/libtipidee/tipidee_response_error_nofile_G.c4
-rw-r--r--src/libtipidee/tipidee_response_file.c17
-rw-r--r--src/libtipidee/tipidee_response_file_G.c4
-rw-r--r--src/libtipidee/tipidee_response_header_end.c10
-rw-r--r--src/libtipidee/tipidee_response_header_write.c21
-rw-r--r--src/libtipidee/tipidee_response_header_writeall.c11
-rw-r--r--src/libtipidee/tipidee_response_partial.c29
-rw-r--r--src/libtipidee/tipidee_response_partial_G.c12
-rw-r--r--src/libtipidee/tipidee_util_parse_range.c49
-rw-r--r--src/tipideed/cgi.c28
-rw-r--r--src/tipideed/deps-exe/tipideed3
-rw-r--r--src/tipideed/errors.c (renamed from src/tipideed/responses.c)64
-rw-r--r--src/tipideed/redirection.c29
-rw-r--r--src/tipideed/regular.c28
-rw-r--r--src/tipideed/send_file.c74
-rw-r--r--src/tipideed/tipideed-internal.h27
-rw-r--r--src/tipideed/tipideed.c16
24 files changed, 384 insertions, 123 deletions
diff --git a/doc/future.html b/doc/future.html
index 1a8c3e5..512f3b7 100644
--- a/doc/future.html
+++ b/doc/future.html
@@ -25,23 +25,6 @@ of HTTP that would be nice to have, and that may be implemented at some point
down the line.
</p>
-<h2> Ranges </h2>
-
-<p>
- <a href="https://datatracker.ietf.org/doc/html/rfc9110#section-14">Ranges</a>
-are a useful part of HTTP when you are serving big files and connections may
-be interrupted and restarted: supporting the <tt>Range:</tt> header can save
-bandwidth, if the client only asks for the parts of the files that it's still
-missing.
-</p>
-
-<p>
- It hasn't been implemented in tipidee yet because parsing the <tt>Range:</tt>
-header is rather complex, and serving parts of files (as opposed to full files
-sequentially) also requires some extra coding that wasn't deemed worth it for
-an initial release.
-</p>
-
<h2> HTTP Basic Authentication </h2>
<p>
diff --git a/package/deps.mak b/package/deps.mak
index cd49648..b5296c5 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -42,28 +42,34 @@ src/libtipidee/tipidee_log_start.o src/libtipidee/tipidee_log_start.lo: src/libt
src/libtipidee/tipidee_method.o src/libtipidee/tipidee_method.lo: src/libtipidee/tipidee_method.c src/include/tipidee/method.h
src/libtipidee/tipidee_response_error_nofile.o src/libtipidee/tipidee_response_error_nofile.lo: src/libtipidee/tipidee_response_error_nofile.c src/include/tipidee/method.h src/include/tipidee/response.h
src/libtipidee/tipidee_response_error_nofile_G.o src/libtipidee/tipidee_response_error_nofile_G.lo: src/libtipidee/tipidee_response_error_nofile_G.c src/include/tipidee/response.h
-src/libtipidee/tipidee_response_file.o src/libtipidee/tipidee_response_file.lo: src/libtipidee/tipidee_response_file.c src/include/tipidee/conf.h src/include/tipidee/method.h src/include/tipidee/response.h src/include/tipidee/rql.h src/include/tipidee/util.h
+src/libtipidee/tipidee_response_file.o src/libtipidee/tipidee_response_file.lo: src/libtipidee/tipidee_response_file.c src/include/tipidee/response.h
src/libtipidee/tipidee_response_file_G.o src/libtipidee/tipidee_response_file_G.lo: src/libtipidee/tipidee_response_file_G.c 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_G.o src/libtipidee/tipidee_response_header_date_G.lo: src/libtipidee/tipidee_response_header_date_G.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_end.o src/libtipidee/tipidee_response_header_end.lo: src/libtipidee/tipidee_response_header_end.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_header_preparebuiltin.o src/libtipidee/tipidee_response_header_preparebuiltin.lo: src/libtipidee/tipidee_response_header_preparebuiltin.c src/include/tipidee/response.h
+src/libtipidee/tipidee_response_header_write.o src/libtipidee/tipidee_response_header_write.lo: src/libtipidee/tipidee_response_header_write.c src/include/tipidee/response.h
src/libtipidee/tipidee_response_header_writeall.o src/libtipidee/tipidee_response_header_writeall.lo: src/libtipidee/tipidee_response_header_writeall.c src/include/tipidee/response.h
src/libtipidee/tipidee_response_header_writeall_G.o src/libtipidee/tipidee_response_header_writeall_G.lo: src/libtipidee/tipidee_response_header_writeall_G.c src/include/tipidee/response.h
src/libtipidee/tipidee_response_header_writemerge.o src/libtipidee/tipidee_response_header_writemerge.lo: src/libtipidee/tipidee_response_header_writemerge.c src/include/tipidee/headers.h src/include/tipidee/response.h
src/libtipidee/tipidee_response_header_writemerge_G.o src/libtipidee/tipidee_response_header_writemerge_G.lo: src/libtipidee/tipidee_response_header_writemerge_G.c src/include/tipidee/response.h
+src/libtipidee/tipidee_response_partial.o src/libtipidee/tipidee_response_partial.lo: src/libtipidee/tipidee_response_partial.c src/include/tipidee/response.h src/include/tipidee/util.h
+src/libtipidee/tipidee_response_partial_G.o src/libtipidee/tipidee_response_partial_G.lo: src/libtipidee/tipidee_response_partial_G.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_defaulttext.o src/libtipidee/tipidee_util_defaulttext.lo: src/libtipidee/tipidee_util_defaulttext.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/libtipidee/tipidee_util_parse_range.o src/libtipidee/tipidee_util_parse_range.lo: src/libtipidee/tipidee_util_parse_range.c src/include/tipidee/util.h
src/tipideed/cgi.o src/tipideed/cgi.lo: src/tipideed/cgi.c src/include/tipidee/tipidee.h src/tipideed/tipideed-internal.h
+src/tipideed/errors.o src/tipideed/errors.lo: src/tipideed/errors.c src/include/tipidee/log.h src/include/tipidee/response.h src/include/tipidee/util.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/options.o src/tipideed/options.lo: src/tipideed/options.c src/include/tipidee/log.h src/include/tipidee/response.h src/tipideed/tipideed-internal.h
+src/tipideed/redirection.o src/tipideed/redirection.lo: src/tipideed/redirection.c src/include/tipidee/log.h src/include/tipidee/response.h src/include/tipidee/util.h src/tipideed/tipideed-internal.h
src/tipideed/regular.o src/tipideed/regular.lo: src/tipideed/regular.c src/include/tipidee/log.h src/include/tipidee/method.h src/include/tipidee/response.h src/tipideed/tipideed-internal.h
-src/tipideed/responses.o src/tipideed/responses.lo: src/tipideed/responses.c src/include/tipidee/log.h src/include/tipidee/response.h src/include/tipidee/util.h src/tipideed/tipideed-internal.h
src/tipideed/send_file.o src/tipideed/send_file.lo: src/tipideed/send_file.c src/tipideed/tipideed-internal.h
src/tipideed/tipideed.o src/tipideed/tipideed.lo: src/tipideed/tipideed.c src/include/tipidee/tipidee.h src/tipideed/tipideed-internal.h
src/tipideed/trace.o src/tipideed/trace.lo: src/tipideed/trace.c src/include/tipidee/log.h src/include/tipidee/method.h src/include/tipidee/response.h src/tipideed/tipideed-internal.h
@@ -74,12 +80,12 @@ tipidee-config: src/config/tipidee-config.o src/config/util.o src/config/node.o
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_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_errorfile.o src/libtipidee/tipidee_conf_get_redirection.o src/libtipidee/tipidee_conf_get_resattr.o src/libtipidee/tipidee_conf_get_resattr1.o src/libtipidee/tipidee_conf_get_responseheaders.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_log_answer.o src/libtipidee/tipidee_log_exit.o src/libtipidee/tipidee_log_resource.o src/libtipidee/tipidee_log_request.o src/libtipidee/tipidee_log_start.o src/libtipidee/tipidee_method.o src/libtipidee/tipidee_response_error_nofile.o src/libtipidee/tipidee_response_error_nofile_G.o src/libtipidee/tipidee_response_file.o src/libtipidee/tipidee_response_file_G.o src/libtipidee/tipidee_response_header_date.o src/libtipidee/tipidee_response_header_date_G.o src/libtipidee/tipidee_response_header_date_fmt.o src/libtipidee/tipidee_response_header_lastmodified.o src/libtipidee/tipidee_response_header_preparebuiltin.o src/libtipidee/tipidee_response_header_writeall.o src/libtipidee/tipidee_response_header_writeall_G.o src/libtipidee/tipidee_response_header_writemerge.o src/libtipidee/tipidee_response_header_writemerge_G.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_defaulttext.o src/libtipidee/tipidee_util_httpdate.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_errorfile.o src/libtipidee/tipidee_conf_get_redirection.o src/libtipidee/tipidee_conf_get_resattr.o src/libtipidee/tipidee_conf_get_resattr1.o src/libtipidee/tipidee_conf_get_responseheaders.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_log_answer.o src/libtipidee/tipidee_log_exit.o src/libtipidee/tipidee_log_request.o src/libtipidee/tipidee_log_resource.o src/libtipidee/tipidee_log_start.o src/libtipidee/tipidee_method.o src/libtipidee/tipidee_response_error_nofile.o src/libtipidee/tipidee_response_error_nofile_G.o src/libtipidee/tipidee_response_file.o src/libtipidee/tipidee_response_file_G.o src/libtipidee/tipidee_response_header_date.o src/libtipidee/tipidee_response_header_date_G.o src/libtipidee/tipidee_response_header_date_fmt.o src/libtipidee/tipidee_response_header_end.o src/libtipidee/tipidee_response_header_lastmodified.o src/libtipidee/tipidee_response_header_preparebuiltin.o src/libtipidee/tipidee_response_header_write.o src/libtipidee/tipidee_response_header_writeall.o src/libtipidee/tipidee_response_header_writeall_G.o src/libtipidee/tipidee_response_header_writemerge.o src/libtipidee/tipidee_response_header_writemerge_G.o src/libtipidee/tipidee_response_partial.o src/libtipidee/tipidee_response_partial_G.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_defaulttext.o src/libtipidee/tipidee_util_httpdate.o src/libtipidee/tipidee_util_parse_range.o
else
-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_errorfile.lo src/libtipidee/tipidee_conf_get_redirection.lo src/libtipidee/tipidee_conf_get_resattr.lo src/libtipidee/tipidee_conf_get_resattr1.lo src/libtipidee/tipidee_conf_get_responseheaders.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_log_answer.lo src/libtipidee/tipidee_log_exit.lo src/libtipidee/tipidee_log_resource.lo src/libtipidee/tipidee_log_request.lo src/libtipidee/tipidee_log_start.lo src/libtipidee/tipidee_method.lo src/libtipidee/tipidee_response_error_nofile.lo src/libtipidee/tipidee_response_error_nofile_G.lo src/libtipidee/tipidee_response_file.lo src/libtipidee/tipidee_response_file_G.lo src/libtipidee/tipidee_response_header_date.lo src/libtipidee/tipidee_response_header_date_G.lo src/libtipidee/tipidee_response_header_date_fmt.lo src/libtipidee/tipidee_response_header_lastmodified.lo src/libtipidee/tipidee_response_header_preparebuiltin.lo src/libtipidee/tipidee_response_header_writeall.lo src/libtipidee/tipidee_response_header_writeall_G.lo src/libtipidee/tipidee_response_header_writemerge.lo src/libtipidee/tipidee_response_header_writemerge_G.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_defaulttext.lo src/libtipidee/tipidee_util_httpdate.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_errorfile.lo src/libtipidee/tipidee_conf_get_redirection.lo src/libtipidee/tipidee_conf_get_resattr.lo src/libtipidee/tipidee_conf_get_resattr1.lo src/libtipidee/tipidee_conf_get_responseheaders.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_log_answer.lo src/libtipidee/tipidee_log_exit.lo src/libtipidee/tipidee_log_request.lo src/libtipidee/tipidee_log_resource.lo src/libtipidee/tipidee_log_start.lo src/libtipidee/tipidee_method.lo src/libtipidee/tipidee_response_error_nofile.lo src/libtipidee/tipidee_response_error_nofile_G.lo src/libtipidee/tipidee_response_file.lo src/libtipidee/tipidee_response_file_G.lo src/libtipidee/tipidee_response_header_date.lo src/libtipidee/tipidee_response_header_date_G.lo src/libtipidee/tipidee_response_header_date_fmt.lo src/libtipidee/tipidee_response_header_end.lo src/libtipidee/tipidee_response_header_lastmodified.lo src/libtipidee/tipidee_response_header_preparebuiltin.lo src/libtipidee/tipidee_response_header_write.lo src/libtipidee/tipidee_response_header_writeall.lo src/libtipidee/tipidee_response_header_writeall_G.lo src/libtipidee/tipidee_response_header_writemerge.lo src/libtipidee/tipidee_response_header_writemerge_G.lo src/libtipidee/tipidee_response_partial.lo src/libtipidee/tipidee_response_partial_G.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_defaulttext.lo src/libtipidee/tipidee_util_httpdate.lo src/libtipidee/tipidee_util_parse_range.lo
endif
libtipidee.so.xyzzy: EXTRA_LIBS := -lskarnet
-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_errorfile.lo src/libtipidee/tipidee_conf_get_redirection.lo src/libtipidee/tipidee_conf_get_resattr.lo src/libtipidee/tipidee_conf_get_resattr1.lo src/libtipidee/tipidee_conf_get_responseheaders.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_log_answer.lo src/libtipidee/tipidee_log_exit.lo src/libtipidee/tipidee_log_resource.lo src/libtipidee/tipidee_log_request.lo src/libtipidee/tipidee_log_start.lo src/libtipidee/tipidee_method.lo src/libtipidee/tipidee_response_error_nofile.lo src/libtipidee/tipidee_response_error_nofile_G.lo src/libtipidee/tipidee_response_file.lo src/libtipidee/tipidee_response_file_G.lo src/libtipidee/tipidee_response_header_date.lo src/libtipidee/tipidee_response_header_date_G.lo src/libtipidee/tipidee_response_header_date_fmt.lo src/libtipidee/tipidee_response_header_lastmodified.lo src/libtipidee/tipidee_response_header_preparebuiltin.lo src/libtipidee/tipidee_response_header_writeall.lo src/libtipidee/tipidee_response_header_writeall_G.lo src/libtipidee/tipidee_response_header_writemerge.lo src/libtipidee/tipidee_response_header_writemerge_G.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_defaulttext.lo src/libtipidee/tipidee_util_httpdate.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_errorfile.lo src/libtipidee/tipidee_conf_get_redirection.lo src/libtipidee/tipidee_conf_get_resattr.lo src/libtipidee/tipidee_conf_get_resattr1.lo src/libtipidee/tipidee_conf_get_responseheaders.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_log_answer.lo src/libtipidee/tipidee_log_exit.lo src/libtipidee/tipidee_log_request.lo src/libtipidee/tipidee_log_resource.lo src/libtipidee/tipidee_log_start.lo src/libtipidee/tipidee_method.lo src/libtipidee/tipidee_response_error_nofile.lo src/libtipidee/tipidee_response_error_nofile_G.lo src/libtipidee/tipidee_response_file.lo src/libtipidee/tipidee_response_file_G.lo src/libtipidee/tipidee_response_header_date.lo src/libtipidee/tipidee_response_header_date_G.lo src/libtipidee/tipidee_response_header_date_fmt.lo src/libtipidee/tipidee_response_header_end.lo src/libtipidee/tipidee_response_header_lastmodified.lo src/libtipidee/tipidee_response_header_preparebuiltin.lo src/libtipidee/tipidee_response_header_write.lo src/libtipidee/tipidee_response_header_writeall.lo src/libtipidee/tipidee_response_header_writeall_G.lo src/libtipidee/tipidee_response_header_writemerge.lo src/libtipidee/tipidee_response_header_writemerge_G.lo src/libtipidee/tipidee_response_partial.lo src/libtipidee/tipidee_response_partial_G.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_defaulttext.lo src/libtipidee/tipidee_util_httpdate.lo src/libtipidee/tipidee_util_parse_range.lo
tipideed: EXTRA_LIBS := -lskarnet
-tipideed: src/tipideed/tipideed.o src/tipideed/cgi.o src/tipideed/harden.o src/tipideed/options.o src/tipideed/regular.o src/tipideed/responses.o src/tipideed/send_file.o src/tipideed/trace.o src/tipideed/util.o libtipidee.a.xyzzy
+tipideed: src/tipideed/tipideed.o src/tipideed/cgi.o src/tipideed/errors.o src/tipideed/harden.o src/tipideed/options.o src/tipideed/regular.o src/tipideed/redirection.o src/tipideed/send_file.o src/tipideed/trace.o src/tipideed/util.o libtipidee.a.xyzzy
INTERNAL_LIBS :=
diff --git a/src/config/headers.c b/src/config/headers.c
index 0afdfb3..c3aa94c 100644
--- a/src/config/headers.c
+++ b/src/config/headers.c
@@ -21,7 +21,7 @@ struct builtinheaders_s
static struct builtinheaders_s const builtinheaders[] =
{
- { .key = "Accept-Ranges", .value = "none", .overridable = 0 },
+ { .key = "Accept-Ranges", .value = "bytes", .overridable = 0 },
{ .key = "Allow", .value = 0, .overridable = 0 },
{ .key = "Cache-Control", .value = "private", .overridable = 1 },
{ .key = "Connection", .value = 0, .overridable = 0 },
diff --git a/src/include/tipidee/response.h b/src/include/tipidee/response.h
index 31b8df4..f912cd3 100644
--- a/src/include/tipidee/response.h
+++ b/src/include/tipidee/response.h
@@ -10,6 +10,7 @@
#include <skalibs/gccattributes.h>
#include <skalibs/stat.h>
+#include <skalibs/uint64.h>
#include <skalibs/buffer.h>
#include <skalibs/strerr.h>
#include <skalibs/tai.h>
@@ -35,21 +36,24 @@ extern size_t tipidee_response_header_date_G (char *, size_t) ;
extern size_t tipidee_response_header_lastmodified (char *, size_t, struct stat const *) ;
+extern size_t tipidee_response_header_write (buffer *, tipidee_response_header const *, uint32_t) ;
extern size_t tipidee_response_header_writeall (buffer *, tipidee_response_header const *, uint32_t, uint32_t, tain const *) ;
extern size_t tipidee_response_header_writeall_G (buffer *, tipidee_response_header const *, uint32_t, uint32_t) ;
-#define tipidee_response_header_writeall_g(b, rhdr, rhdrn, options) tipidee_response_header_writeall(b, rhdr, rhdrn, (options), &STAMP)
+
+extern size_t tipidee_response_header_end (buffer *) ;
+
extern size_t tipidee_response_header_writemerge (buffer *, tipidee_response_header const *, uint32_t, tipidee_headers const *, uint32_t, tain const *) ;
extern size_t tipidee_response_header_writemerge_G (buffer *, tipidee_response_header const *, uint32_t, tipidee_headers const *, uint32_t) ;
-#define tipidee_response_header_writemerge_g(b, rhdr, rhdrn, hdr, options) tipidee_response_header_writemerge(b, rhdr, rhdrn, hdr, (options), &STAMP)
-size_t tipidee_response_file (buffer *, tipidee_rql const *, unsigned int, char const *, struct stat const *, char const *, tipidee_response_header const *, uint32_t, uint32_t, tain const *) ;
-size_t tipidee_response_file_G (buffer *, tipidee_rql const *, unsigned int, char const *, struct stat const *, char const *, tipidee_response_header const *, uint32_t, uint32_t) ;
-#define tipidee_response_file_g(b, rql, status, reason, st, ct, rhdr, rhdrn, options) tipidee_response_file(b, rql, status, reason, st, ct, rhdr, rhdrn, (options), &STAMP)
+size_t tipidee_response_file (buffer *, tipidee_rql const *, unsigned int, char const *, struct stat const *, uint64_t, char const *, tipidee_response_header const *, uint32_t, uint32_t, tain const *) ;
+size_t tipidee_response_file_G (buffer *, tipidee_rql const *, unsigned int, char const *, struct stat const *, uint64_t, char const *, tipidee_response_header const *, uint32_t, uint32_t) ;
+
+size_t tipidee_response_partial (buffer *, tipidee_rql const *, struct stat const *, uint64_t, uint64_t, char const *, tipidee_response_header const *, uint32_t, uint32_t, tain const *) ;
+size_t tipidee_response_partial_G (buffer *, tipidee_rql const *, struct stat const *, uint64_t, uint64_t, char const *, tipidee_response_header const *, uint32_t, uint32_t) ;
-extern size_t tipidee_response_error_nofile (buffer *, tipidee_rql const *, unsigned int, char const *, char const *, tipidee_response_header const *, uint32_t, uint32_t, tain const *) ;
-extern size_t tipidee_response_error_nofile_G (buffer *, tipidee_rql const *, unsigned int, char const *, char const *, tipidee_response_header const *, uint32_t, uint32_t) ;
-#define tipidee_response_error_nofile_g(b, rql, status, reason, text, rhdr, rhdrn, options) tipidee_response_error_nofile(b, rql, status, reason, text, rhdr, rhdrn, (options), &STAMP)
+extern size_t tipidee_response_error_nofile (buffer *, tipidee_rql const *, unsigned int, char const *, char const *, tipidee_response_header const *, uint32_t, tipidee_response_header const *, uint32_t, uint32_t, tain const *) ;
+extern size_t tipidee_response_error_nofile_G (buffer *, tipidee_rql const *, unsigned int, char const *, char const *, tipidee_response_header const *, uint32_t, tipidee_response_header const *, uint32_t, uint32_t) ;
extern int tipidee_response_header_preparebuiltin (tipidee_response_header *, uint32_t, char const *, size_t) ;
diff --git a/src/include/tipidee/util.h b/src/include/tipidee/util.h
index 7870a23..18eb2ce 100644
--- a/src/include/tipidee/util.h
+++ b/src/include/tipidee/util.h
@@ -3,9 +3,10 @@
#ifndef TIPIDEE_UTIL_H
#define TIPIDEE_UTIL_H
-#include <stddef.h>
+#include <sys/types.h>
#include <stdint.h>
+#include <skalibs/uint64.h>
#include <skalibs/buffer.h>
#include <skalibs/tai.h>
#include <skalibs/stralloc.h>
@@ -31,4 +32,6 @@ extern int tipidee_util_chunked_read (buffer *, stralloc *, size_t, tain const *
extern int tipidee_util_httpdate (char const *, tain *) ;
extern int tipidee_util_defaulttext (unsigned int, tipidee_defaulttext *) ;
+extern int tipidee_util_parse_range (char const *, off_t, uint64_t *, uint64_t *) ;
+
#endif
diff --git a/src/libtipidee/deps-lib/tipidee b/src/libtipidee/deps-lib/tipidee
index 985be7e..33f9f2f 100644
--- a/src/libtipidee/deps-lib/tipidee
+++ b/src/libtipidee/deps-lib/tipidee
@@ -16,8 +16,8 @@ tipidee_headers_parse.o
tipidee_headers_search.o
tipidee_log_answer.o
tipidee_log_exit.o
-tipidee_log_resource.o
tipidee_log_request.o
+tipidee_log_resource.o
tipidee_log_start.o
tipidee_method.o
tipidee_response_error_nofile.o
@@ -27,16 +27,21 @@ tipidee_response_file_G.o
tipidee_response_header_date.o
tipidee_response_header_date_G.o
tipidee_response_header_date_fmt.o
+tipidee_response_header_end.o
tipidee_response_header_lastmodified.o
tipidee_response_header_preparebuiltin.o
+tipidee_response_header_write.o
tipidee_response_header_writeall.o
tipidee_response_header_writeall_G.o
tipidee_response_header_writemerge.o
tipidee_response_header_writemerge_G.o
+tipidee_response_partial.o
+tipidee_response_partial_G.o
tipidee_response_status.o
tipidee_rql_read.o
tipidee_uri_parse.o
tipidee_util_chunked_read.o
tipidee_util_defaulttext.o
tipidee_util_httpdate.o
+tipidee_util_parse_range.o
-lskarnet
diff --git a/src/libtipidee/tipidee_response_error_nofile.c b/src/libtipidee/tipidee_response_error_nofile.c
index 8a7cd53..10da032 100644
--- a/src/libtipidee/tipidee_response_error_nofile.c
+++ b/src/libtipidee/tipidee_response_error_nofile.c
@@ -8,19 +8,21 @@
#include <tipidee/method.h>
#include <tipidee/response.h>
-size_t tipidee_response_error_nofile (buffer *b, tipidee_rql const *rql, unsigned int status, char const *reason, char const *text, tipidee_response_header const *rhdr, uint32_t rhdrn, uint32_t options, tain const *stamp)
+size_t tipidee_response_error_nofile (buffer *b, tipidee_rql const *rql, unsigned int status, char const *reason, char const *text, tipidee_response_header const *rhdr, uint32_t rhdrn, tipidee_response_header const *plus, uint32_t plusn, uint32_t options, tain const *stamp)
{
static char const txt1[] = "<html>\n<head><title>" ;
static char const txt2[] = "</title></head>\n<body>\n<h1> " ;
static char const txt3[] = " </h1>\n<p>\n" ;
static char const txt4[] = "\n</p>\n</body>\n</html>\n" ;
char fmt[SIZE_FMT] ;
+ tipidee_response_header v[2] = { { .key = "Content-Type", .value = "text/html; charset=UTF-8", .options = 0 }, { .key = "Content-Length", .value = fmt, .options = 0 } } ;
size_t n = tipidee_response_status(b, rql, status, reason) ;
n += tipidee_response_header_writeall(b, rhdr, rhdrn, options, stamp) ;
- n += buffer_putsnoflush(b, "Content-Type: text/html; charset=UTF-8\r\n") ;
- n += buffer_putsnoflush(b, "Content-Length: ") ;
- n += buffer_putnoflush(b, fmt, size_fmt(fmt, text ? sizeof(txt1) + sizeof(txt2) + sizeof(txt3) + sizeof(txt4) - 4 + 2 * strlen(reason) + strlen(text) : 0)) ;
- n += buffer_putnoflush(b, "\r\n\r\n", 4) ;
+ if (plusn) n += tipidee_response_header_write(b, plus, plusn) ;
+ fmt[size_fmt(fmt, text ? sizeof(txt1) + sizeof(txt2) + sizeof(txt3) + sizeof(txt4) - 4 + 2 * strlen(reason) + strlen(text) : 0)] = 0 ;
+ n += tipidee_response_header_write(b, v, 2) ;
+
+ n += buffer_putnoflush(b, "\r\n", 2) ;
if (text && rql->m != TIPIDEE_METHOD_HEAD)
{
n += buffer_putsnoflush(b, txt1) ;
diff --git a/src/libtipidee/tipidee_response_error_nofile_G.c b/src/libtipidee/tipidee_response_error_nofile_G.c
index d7239cc..e6bdce5 100644
--- a/src/libtipidee/tipidee_response_error_nofile_G.c
+++ b/src/libtipidee/tipidee_response_error_nofile_G.c
@@ -4,9 +4,9 @@
#include <tipidee/response.h>
-size_t tipidee_response_error_nofile_G (buffer *b, tipidee_rql const *rql, unsigned int status, char const *reason, char const *text, tipidee_response_header const *rhdr, uint32_t rhdrn, uint32_t options)
+size_t tipidee_response_error_nofile_G (buffer *b, tipidee_rql const *rql, unsigned int status, char const *reason, char const *text, tipidee_response_header const *rhdr, uint32_t rhdrn, tipidee_response_header const *plus, uint32_t plusn, uint32_t options)
{
tain wstamp ;
tain_wallclock_read(&wstamp) ;
- return tipidee_response_error_nofile(b, rql, status, reason, text, rhdr, rhdrn, options, &wstamp) ;
+ return tipidee_response_error_nofile(b, rql, status, reason, text, rhdr, rhdrn, plus, plusn, options, &wstamp) ;
}
diff --git a/src/libtipidee/tipidee_response_file.c b/src/libtipidee/tipidee_response_file.c
index f2021ee..b64d086 100644
--- a/src/libtipidee/tipidee_response_file.c
+++ b/src/libtipidee/tipidee_response_file.c
@@ -2,18 +2,15 @@
#include <stddef.h>
-#include <skalibs/types.h>
+#include <skalibs/uint64.h>
#include <skalibs/buffer.h>
-#include <tipidee/conf.h>
-#include <tipidee/method.h>
-#include <tipidee/rql.h>
#include <tipidee/response.h>
-#include <tipidee/util.h>
-size_t tipidee_response_file (buffer *b, tipidee_rql const *rql, unsigned int status, char const *reason, struct stat const *st, char const *ct, tipidee_response_header const *rhdr, uint32_t rhdrn, uint32_t options, tain const *stamp)
+size_t tipidee_response_file (buffer *b, tipidee_rql const *rql, unsigned int status, char const *reason, struct stat const *st, uint64_t cl, char const *ct, tipidee_response_header const *rhdr, uint32_t rhdrn, uint32_t options, tain const *stamp)
{
char fmt[128] ;
+ tipidee_response_header v[2] = { { .key = "Content-Type", .value = ct, .options = 0 }, { .key = "Content-Length", .value = fmt, .options = 0 } } ;
size_t n = tipidee_response_status(b, rql, status, reason) ;
n += tipidee_response_header_writeall(b, rhdr, rhdrn, options & 1, stamp) ;
if (options & 2)
@@ -21,11 +18,7 @@ size_t tipidee_response_file (buffer *b, tipidee_rql const *rql, unsigned int st
size_t l = tipidee_response_header_lastmodified(fmt, 128, st) ;
if (l) n += buffer_putnoflush(b, fmt, l) ;
}
- n += buffer_putsnoflush(b, "Content-Type: ") ;
- n += buffer_putsnoflush(b, ct) ;
- n += buffer_putsnoflush(b, "\r\nContent-Length: ") ;
- fmt[uint64_fmt(fmt, st->st_size)] = 0 ;
- n += buffer_putsnoflush(b, fmt) ;
- n += buffer_putnoflush(b, "\r\n\r\n", 4) ;
+ fmt[uint64_fmt(fmt, cl)] = 0 ;
+ n += tipidee_response_header_write(b, v, 2) ;
return n ;
}
diff --git a/src/libtipidee/tipidee_response_file_G.c b/src/libtipidee/tipidee_response_file_G.c
index 8c08c98..06af667 100644
--- a/src/libtipidee/tipidee_response_file_G.c
+++ b/src/libtipidee/tipidee_response_file_G.c
@@ -4,9 +4,9 @@
#include <tipidee/response.h>
-size_t tipidee_response_file_G (buffer *b, tipidee_rql const *rql, unsigned int status, char const *reason, struct stat const *st, char const *ct, tipidee_response_header const *rhdr, uint32_t rhdrn, uint32_t options)
+size_t tipidee_response_file_G (buffer *b, tipidee_rql const *rql, unsigned int status, char const *reason, struct stat const *st, uint64_t cl, char const *ct, tipidee_response_header const *rhdr, uint32_t rhdrn, uint32_t options)
{
tain wstamp ;
tain_wallclock_read(&wstamp) ;
- return tipidee_response_file(b, rql, status, reason, st, ct, rhdr, rhdrn, options, &wstamp) ;
+ return tipidee_response_file(b, rql, status, reason, st, cl, ct, rhdr, rhdrn, options, &wstamp) ;
}
diff --git a/src/libtipidee/tipidee_response_header_end.c b/src/libtipidee/tipidee_response_header_end.c
new file mode 100644
index 0000000..ddd8575
--- /dev/null
+++ b/src/libtipidee/tipidee_response_header_end.c
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#include <skalibs/buffer.h>
+
+#include <tipidee/response.h>
+
+size_t tipidee_response_header_end (buffer *b)
+{
+ return buffer_put(b, "\r\n", 2) ;
+}
diff --git a/src/libtipidee/tipidee_response_header_write.c b/src/libtipidee/tipidee_response_header_write.c
new file mode 100644
index 0000000..6c8edd9
--- /dev/null
+++ b/src/libtipidee/tipidee_response_header_write.c
@@ -0,0 +1,21 @@
+/* ISC license. */
+
+#include <stddef.h>
+
+#include <skalibs/buffer.h>
+
+#include <tipidee/response.h>
+
+size_t tipidee_response_header_write (buffer *b, tipidee_response_header const *hdr, uint32_t n)
+{
+ size_t m = 0 ;
+ for (uint32_t i = 0 ; i < n ; i++)
+ {
+ if (!hdr[i].value) continue ;
+ m += buffer_putsnoflush(b, hdr[i].key) ;
+ m += buffer_putnoflush(b, ": ", 2) ;
+ m += buffer_putsnoflush(b, hdr[i].value) ;
+ m += buffer_putnoflush(b, "\r\n", 2) ;
+ }
+ return m ;
+}
diff --git a/src/libtipidee/tipidee_response_header_writeall.c b/src/libtipidee/tipidee_response_header_writeall.c
index b94578d..36bc9bf 100644
--- a/src/libtipidee/tipidee_response_header_writeall.c
+++ b/src/libtipidee/tipidee_response_header_writeall.c
@@ -1,5 +1,7 @@
/* ISC license. */
+#include <stddef.h>
+
#include <skalibs/buffer.h>
#include <tipidee/response.h>
@@ -9,13 +11,6 @@ size_t tipidee_response_header_writeall (buffer *b, tipidee_response_header cons
char fmt[128] ;
size_t m = buffer_putnoflush(b, fmt, tipidee_response_header_date(fmt, 128, stamp)) ;
if (options & 1) m += buffer_putsnoflush(b, "Connection: close\r\n") ;
- for (uint32_t i = 0 ; i < rhdrn ; i++)
- {
- if (!rhdr[i].value) continue ;
- m += buffer_putsnoflush(b, rhdr[i].key) ;
- m += buffer_putnoflush(b, ": ", 2) ;
- m += buffer_putsnoflush(b, rhdr[i].value) ;
- m += buffer_putnoflush(b, "\r\n", 2) ;
- }
+ m += tipidee_response_header_write(b, rhdr, rhdrn) ;
return m ;
}
diff --git a/src/libtipidee/tipidee_response_partial.c b/src/libtipidee/tipidee_response_partial.c
new file mode 100644
index 0000000..4411896
--- /dev/null
+++ b/src/libtipidee/tipidee_response_partial.c
@@ -0,0 +1,29 @@
+/* ISC license. */
+
+#include <stddef.h>
+
+#include <skalibs/uint64.h>
+#include <skalibs/buffer.h>
+
+#include <tipidee/util.h>
+#include <tipidee/response.h>
+
+size_t tipidee_response_partial (buffer *b, tipidee_rql const *rql, struct stat const *st, uint64_t start, uint64_t len, char const *ct, tipidee_response_header const *rhdr, uint32_t rhdrn, uint32_t options, tain const *stamp)
+{
+ tipidee_defaulttext dt ;
+ size_t n ;
+ char fmt[UINT64_FMT] ;
+ if (!tipidee_util_defaulttext(206, &dt)) return 0 ;
+ n = tipidee_response_file(b, rql, 206, dt.reason, st, len, ct, rhdr, rhdrn, options, stamp) ;
+ if (len)
+ {
+ n += buffer_putsnoflush(b, "Content-Range: bytes ") ;
+ n += buffer_putnoflush(b, fmt, uint64_fmt(fmt, start)) ;
+ n += buffer_putnoflush(b, "-", 1) ;
+ n += buffer_putnoflush(b, fmt, uint64_fmt(fmt, start + len - 1)) ;
+ n += buffer_putnoflush(b, "/", 1) ;
+ n += buffer_putnoflush(b, fmt, uint64_fmt(fmt, st->st_size)) ;
+ n += buffer_putnoflush(b, "\r\n", 2) ;
+ }
+ return n ;
+}
diff --git a/src/libtipidee/tipidee_response_partial_G.c b/src/libtipidee/tipidee_response_partial_G.c
new file mode 100644
index 0000000..d9c5d78
--- /dev/null
+++ b/src/libtipidee/tipidee_response_partial_G.c
@@ -0,0 +1,12 @@
+/* ISC license. */
+
+#include <skalibs/tai.h>
+
+#include <tipidee/response.h>
+
+size_t tipidee_response_partial_G (buffer *b, tipidee_rql const *rql, struct stat const *st, uint64_t start, uint64_t len, char const *ct, tipidee_response_header const *rhdr, uint32_t rhdrn, uint32_t options)
+{
+ tain wstamp ;
+ tain_wallclock_read(&wstamp) ;
+ return tipidee_response_partial(b, rql, st, start, len, ct, rhdr, rhdrn, options, &wstamp) ;
+}
diff --git a/src/libtipidee/tipidee_util_parse_range.c b/src/libtipidee/tipidee_util_parse_range.c
new file mode 100644
index 0000000..e096fda
--- /dev/null
+++ b/src/libtipidee/tipidee_util_parse_range.c
@@ -0,0 +1,49 @@
+/* ISC license. */
+
+#include <string.h>
+
+#include <skalibs/uint64.h>
+
+#include <tipidee/util.h>
+
+int tipidee_util_parse_range (char const *s, off_t max, uint64_t *start, uint64_t *len)
+{
+ if (strncmp(s, "bytes=", 6)) return -1 ;
+ s += 6 ;
+ if (*s == '-')
+ {
+ uint64_t n ;
+ size_t m = uint64_scan(++s, &n) ;
+ if (!m) return -1 ;
+ s += m ;
+ if (*s && *s != ',') return -1 ;
+ if (n > max) return -1 ;
+ *start = max - n ;
+ *len = n ;
+ return 1 ;
+ }
+ else
+ {
+ uint64_t beg ;
+ uint64_t n ;
+ size_t m = uint64_scan(s, &beg) ;
+ if (!m) return -1 ;
+ s += m ;
+ if (*s++ != '-') return -1 ;
+ if (beg >= max) return -1 ;
+ if (!*s || *s == ',')
+ {
+ *start = beg ;
+ *len = max - beg ;
+ return 1 ;
+ }
+ m = uint64_scan(s, &n) ;
+ if (!m) return -1 ;
+ s += m ;
+ if (*s && *s != ',') return -1 ;
+ if (n >= max || n < beg) return -1 ;
+ *start = beg ;
+ *len = n + 1 - beg ;
+ return 1 ;
+ }
+}
diff --git a/src/tipideed/cgi.c b/src/tipideed/cgi.c
index 343f7af..14da139 100644
--- a/src/tipideed/cgi.c
+++ b/src/tipideed/cgi.c
@@ -25,13 +25,14 @@
#include <tipidee/tipidee.h>
#include "tipideed-internal.h"
+#define dienomem(rql, docroot) die500sys(rql, 111, (docroot), "stralloc_catb")
+
static void addenv_ (tipidee_rql const *rql, char const *docroot, char const *k, char const *v, int slash)
{
if (!stralloc_cats(&g.sa, k)
|| !stralloc_catb(&g.sa, "=/", 1 + !!slash)
|| !stralloc_cats(&g.sa, v)
- || !stralloc_0(&g.sa))
- die500sys(rql, 111, docroot, "stralloc_catb") ;
+ || !stralloc_0(&g.sa)) dienomem(rql, docroot) ;
}
#define addenv(rql, d, k, v) addenv_(rql, d, k, (v), 0)
@@ -40,8 +41,24 @@ static void addenv_ (tipidee_rql const *rql, char const *docroot, char const *k,
static void delenv (tipidee_rql const *rql, char const *docroot, char const *k)
{
if (!stralloc_cats(&g.sa, k)
- || !stralloc_0(&g.sa))
- die500sys(rql, 111, docroot, "stralloc_catb") ;
+ || !stralloc_0(&g.sa)) dienomem(rql, docroot) ;
+}
+
+static void addrequesturi (tipidee_rql const *rql, char const *docroot, char const *script, char const *infopath)
+{
+ if (!stralloc_cats(&g.sa, "REQUEST_URI=")
+ || !stralloc_cats(&g.sa, script)) dienomem(rql, docroot) ;
+ if (infopath)
+ {
+ if (!stralloc_catb(&g.sa, "/", 1)
+ || !stralloc_cats(&g.sa, infopath)) dienomem(rql, docroot) ;
+ }
+ if (rql->uri.query)
+ {
+ if (!stralloc_catb(&g.sa, "?", 1)
+ || !stralloc_cats(&g.sa, rql->uri.query)) dienomem(rql, docroot) ;
+ }
+ if (!stralloc_0(&g.sa)) dienomem(rql, docroot) ;
}
static inline void modify_env (tipidee_rql const *rql, char const *docroot, tipidee_headers const *hdr, size_t cl, char const *script, char const *infopath)
@@ -61,13 +78,14 @@ static inline void modify_env (tipidee_rql const *rql, char const *docroot, tipi
if (rql->uri.query) addenv(rql, docroot, "QUERY_STRING", rql->uri.query) ;
else delenv(rql, docroot, "QUERY_STRING") ;
addenv(rql, docroot, "SCRIPT_NAME", script) ;
+ addrequesturi(rql, docroot, script, infopath) ;
addenv(rql, docroot, "SERVER_NAME", rql->uri.host) ;
{
char proto[9] = "HTTP/1.1" ;
if (!rql->http_minor) proto[7] = '0' ;
addenv(rql, docroot, "SERVER_PROTOCOL", proto) ;
}
-
+
for (size_t i = 0 ; i < hdr->n ; i++)
{
char const *key = hdr->buf + hdr->list[i].left ;
diff --git a/src/tipideed/deps-exe/tipideed b/src/tipideed/deps-exe/tipideed
index 8e5263e..ac5d4a3 100644
--- a/src/tipideed/deps-exe/tipideed
+++ b/src/tipideed/deps-exe/tipideed
@@ -1,8 +1,9 @@
cgi.o
+errors.o
harden.o
options.o
regular.o
-responses.o
+redirection.o
send_file.o
trace.o
util.o
diff --git a/src/tipideed/responses.c b/src/tipideed/errors.c
index 6e32ea9..9b00f3b 100644
--- a/src/tipideed/responses.c
+++ b/src/tipideed/errors.c
@@ -21,22 +21,28 @@
#include "tipideed-internal.h"
-void response_error_early (tipidee_rql const *rql, unsigned int status, char const *reason, char const *text, uint32_t options)
+void response_error_early_plus (tipidee_rql const *rql, unsigned int status, char const *reason, char const *text, tipidee_response_header const *v, uint32_t n, uint32_t options)
{
tain deadline ;
- tipidee_response_error_nofile_G(buffer_1, rql, status, reason, text, g.rhdr, g.rhdrn, options & 1 || !g.cont) ;
+ tipidee_response_error_nofile_G(buffer_1, rql, status, reason, text, g.rhdr, g.rhdrn, v, n, options & 1 || !g.cont) ;
tain_add_g(&deadline, &g.writetto) ;
if (!buffer_timed_flush_g(buffer_1, &deadline))
strerr_diefu1sys(111, "write to stdout") ;
}
-void response_error_early_and_exit (tipidee_rql const *rql, unsigned int status, char const *reason, char const *text)
+void response_error_early_plus_and_exit (tipidee_rql const *rql, unsigned int status, char const *reason, char const *text, tipidee_response_header const *v, uint32_t n)
{
- response_error_early(rql, status, reason, text, 1) ;
+ response_error_early_plus(rql, status, reason, text, v, n, 1) ;
log_and_exit(1) ;
}
-void response_error (tipidee_rql const *rql, char const *docroot, unsigned int status, uint32_t options)
+void eexit_405 (tipidee_rql const *rql)
+{
+ static tipidee_response_header const allowpost = { .key = "Allow", .value = "GET, HEAD, POST", .options = 0 } ;
+ response_error_early_plus_and_exit(rql, 405, "Method Not Allowed", "Invalid method for the resource.", &allowpost, 1) ;
+}
+
+void response_error_plus (tipidee_rql const *rql, char const *docroot, unsigned int status, tipidee_response_header const *plus, uint32_t plusn, uint32_t options)
{
tain deadline ;
tipidee_defaulttext dt ;
@@ -85,7 +91,9 @@ void response_error (tipidee_rql const *rql, char const *docroot, unsigned int s
}
else
{
- tipidee_response_file_G(buffer_1, rql, status, dt.reason, &st, tipidee_conf_get_content_type(&g.conf, g.sa.s + pos), g.rhdr, g.rhdrn, options) ;
+ tipidee_response_file_G(buffer_1, rql, status, dt.reason, &st, st.st_size, tipidee_conf_get_content_type(&g.conf, g.sa.s + pos), g.rhdr, g.rhdrn, options) ;
+ tipidee_response_header_write(buffer_1, plus, plusn) ;
+ tipidee_response_header_end(buffer_1) ;
tipidee_log_answer(g.logv, rql, status, st.st_size) ;
send_file(fd, st.st_size, g.sa.s + pos) ;
fd_close(fd) ;
@@ -95,56 +103,38 @@ void response_error (tipidee_rql const *rql, char const *docroot, unsigned int s
}
}
- tipidee_response_error_nofile_G(buffer_1, rql, status, dt.reason, dt.text, g.rhdr, g.rhdrn, options & 1 || !g.cont) ;
+ tipidee_response_error_nofile_G(buffer_1, rql, status, dt.reason, dt.text, g.rhdr, g.rhdrn, plus, plusn, options & 1 || !g.cont) ;
tipidee_log_answer(g.logv, rql, status, 0) ;
tain_add_g(&deadline, &g.writetto) ;
if (!buffer_timed_flush_g(buffer_1, &deadline))
strerr_diefu1sys(111, "write to stdout") ;
}
-void response_error_and_exit (tipidee_rql const *rql, char const *docroot, unsigned int status)
+void response_error_plus_and_exit (tipidee_rql const *rql, char const *docroot, unsigned int status, tipidee_response_header const *plus, uint32_t plusn)
{
- response_error(rql, docroot, status, 1) ;
+ response_error_plus(rql, docroot, status, plus, plusn, 1) ;
log_and_exit(0) ;
}
-void response_error_and_die (tipidee_rql const *rql, int e, char const *docroot, unsigned int status, char const *const *v, unsigned int n, uint32_t options)
+void response_error_plus_and_die (tipidee_rql const *rql, int e, char const *docroot, unsigned int status, tipidee_response_header const *plus, uint32_t plusn, char const *const *v, unsigned int n, uint32_t options)
{
int serr = errno ;
- response_error(rql, docroot, status, options | 1) ;
+ response_error_plus(rql, docroot, status, plus, plusn, options | 1) ;
errno = serr ;
if (options & 1) strerr_dievsys(e, v, n) ;
else strerr_diev(e, v, n) ;
}
-void exit_405_ (tipidee_rql const *rql, uint32_t options)
+void exit_405 (tipidee_rql const *rql, char const *docroot, uint32_t options)
{
- tain deadline ;
- tipidee_response_status(buffer_1, rql, 405, "Method Not Allowed") ;
- tipidee_response_header_writeall_G(buffer_1, g.rhdr, g.rhdrn, 1) ;
- buffer_putsnoflush(buffer_1, "Allow: GET, HEAD") ;
- if (options & 1) buffer_putsnoflush(buffer_1, ", POST") ;
- buffer_putnoflush(buffer_1, "\r\n\r\n", 4) ;
- if (!(options & 2)) tipidee_log_answer(g.logv, rql, 405, 0) ;
- tain_add_g(&deadline, &g.writetto) ;
- if (!buffer_timed_flush_g(buffer_1, &deadline))
- strerr_diefu1sys(111, "write to stdout") ;
- log_and_exit(0) ;
+ tipidee_response_header hd = { .key = "Allow", .value = options & 1 ? "GET, HEAD, POST" : "GET, HEAD", .options = 0 } ;
+ response_error_plus_and_exit(rql, docroot, 405, &hd, 1) ;
}
-void respond_30x (tipidee_rql const *rql, tipidee_redirection const *rd)
+void respond_416 (tipidee_rql const *rql, char const *docroot, uint64_t size)
{
- static unsigned int const status[4] = { 307, 308, 302, 301 } ;
- static char const *const reason[4] = { "Temporary Redirect", "Permanent Redirect", "Found", "Moved Permanently" } ;
- tain deadline ;
- tipidee_response_status(buffer_1, rql, status[rd->type], reason[rd->type]) ;
- tipidee_response_header_writeall_G(buffer_1, g.rhdr, g.rhdrn, 0) ;
- buffer_putsnoflush(buffer_1, "Content-Length: 0\r\nLocation: ") ;
- buffer_putsnoflush(buffer_1, rd->location) ;
- if (rd->sub) buffer_putsnoflush(buffer_1, rd->sub) ;
- buffer_putnoflush(buffer_1, "\r\n\r\n", 4) ;
- tipidee_log_answer(g.logv, rql, status[rd->type], 0) ;
- tain_add_g(&deadline, &g.writetto) ;
- if (!buffer_timed_flush_g(buffer_1, &deadline))
- strerr_diefu1sys(111, "write to stdout") ;
+ char buf[8 + UINT64_FMT] = "bytes */" ;
+ tipidee_response_header cr = { .key = "Content-Range", .value = buf, .options = 0 } ;
+ buf[8 + uint64_fmt(buf + 8, size)] = 0 ;
+ response_error_plus(rql, docroot, 416, &cr, 1, 0) ;
}
diff --git a/src/tipideed/redirection.c b/src/tipideed/redirection.c
new file mode 100644
index 0000000..e525e66
--- /dev/null
+++ b/src/tipideed/redirection.c
@@ -0,0 +1,29 @@
+/* ISC license. */
+
+#include <skalibs/buffer.h>
+#include <skalibs/strerr.h>
+#include <skalibs/tai.h>
+#include <skalibs/unix-timed.h>
+
+#include <tipidee/log.h>
+#include <tipidee/util.h>
+#include <tipidee/response.h>
+#include "tipideed-internal.h"
+
+void respond_30x (tipidee_rql const *rql, tipidee_redirection const *rd)
+{
+ static unsigned int const status[4] = { 307, 308, 302, 301 } ;
+ tipidee_defaulttext dt ;
+ tain deadline ;
+ tipidee_util_defaulttext(status[rd->type], &dt) ;
+ tipidee_response_status(buffer_1, rql, status[rd->type], dt.reason) ;
+ tipidee_response_header_writeall_G(buffer_1, g.rhdr, g.rhdrn, 0) ;
+ buffer_putsnoflush(buffer_1, "Content-Length: 0\r\nLocation: ") ;
+ buffer_putsnoflush(buffer_1, rd->location) ;
+ if (rd->sub) buffer_putsnoflush(buffer_1, rd->sub) ;
+ buffer_putnoflush(buffer_1, "\r\n\r\n", 4) ;
+ tipidee_log_answer(g.logv, rql, status[rd->type], 0) ;
+ tain_add_g(&deadline, &g.writetto) ;
+ if (!buffer_timed_flush_g(buffer_1, &deadline))
+ strerr_diefu1sys(111, "write to stdout") ;
+}
diff --git a/src/tipideed/regular.c b/src/tipideed/regular.c
index 67fba35..3d82750 100644
--- a/src/tipideed/regular.c
+++ b/src/tipideed/regular.c
@@ -22,7 +22,8 @@ int respond_regular (tipidee_rql const *rql, char const *docroot, char const *fn
if (rql->m == TIPIDEE_METHOD_HEAD)
{
tain deadline ;
- tipidee_response_file_G(buffer_1, rql, 200, "OK", st, ra->content_type, g.rhdr, g.rhdrn, 2 | !g.cont) ;
+ tipidee_response_file_G(buffer_1, rql, 200, "OK", st, st->st_size, ra->content_type, g.rhdr, g.rhdrn, 2 | !g.cont) ;
+ tipidee_response_header_end(buffer_1) ;
tipidee_log_answer(g.logv, rql, 200, st->st_size) ;
tain_add_g(&deadline, &g.writetto) ;
if (!buffer_timed_flush_g(buffer_1, &deadline))
@@ -40,7 +41,8 @@ int respond_regular (tipidee_rql const *rql, char const *docroot, char const *fn
}
else die500sys(rql, 111, docroot, "open ", fn) ;
}
- tipidee_response_file_G(buffer_1, rql, 200, "OK", st, ra->content_type, g.rhdr, g.rhdrn, 2 | !g.cont) ;
+ tipidee_response_file_G(buffer_1, rql, 200, "OK", st, st->st_size, ra->content_type, g.rhdr, g.rhdrn, 2 | !g.cont) ;
+ tipidee_response_header_end(buffer_1) ;
tipidee_log_answer(g.logv, rql, 200, st->st_size) ;
send_file(fd, st->st_size, fn) ;
fd_close(fd) ;
@@ -58,10 +60,30 @@ int respond_304 (tipidee_rql const *rql, char const *fn, struct stat const *st)
size_t l = tipidee_response_header_lastmodified(fmt, 128, st) ;
if (l) buffer_putnoflush(buffer_1, fmt, l) ;
}
- buffer_putnoflush(buffer_1, "\r\n", 2) ;
+ tipidee_response_header_end(buffer_1) ;
tipidee_log_answer(g.logv, rql, 304, 0) ;
tain_add_g(&deadline, &g.writetto) ;
if (!buffer_timed_flush_g(buffer_1, &deadline))
strerr_diefu1sys(111, "write to stdout") ;
return 0 ;
}
+
+int respond_partial (tipidee_rql const *rql, char const *docroot, char const *fn, struct stat const *st, uint64_t start, uint64_t len, tipidee_resattr const *ra)
+{
+ int fd = open_read(fn) ;
+ if (fd == -1)
+ {
+ if (errno == EACCES)
+ {
+ respond_403(rql, docroot) ;
+ return 0 ;
+ }
+ else die500sys(rql, 111, docroot, "open ", fn) ;
+ }
+ tipidee_response_partial_G(buffer_1, rql, st, start, len, ra->content_type, g.rhdr, g.rhdrn, 2 | !g.cont) ;
+ tipidee_response_header_end(buffer_1) ;
+ tipidee_log_answer(g.logv, rql, 206, len) ;
+ send_file_range(fd, start, len, fn) ;
+ fd_close(fd) ;
+ return 0 ;
+}
diff --git a/src/tipideed/send_file.c b/src/tipideed/send_file.c
index 6d97167..bcbd1c7 100644
--- a/src/tipideed/send_file.c
+++ b/src/tipideed/send_file.c
@@ -2,6 +2,66 @@
#include <skalibs/sysdeps.h>
+#ifdef SKALIBS_HASSENDFILE
+
+#include <sys/types.h>
+#include <sys/sendfile.h>
+#include <limits.h>
+
+#include <skalibs/uint64.h>
+#include <skalibs/strerr.h>
+#include <skalibs/tai.h>
+#include <skalibs/unix-timed.h>
+
+#include "tipideed-internal.h"
+
+void init_splice_pipe (void)
+{
+}
+
+struct sendfile_s
+{
+ int fd ;
+ off_t pos ;
+ uint64_t n ;
+} ;
+
+static int s_getfd (void *p)
+{
+ (void)p ;
+ return 1 ;
+}
+
+static int s_isnonempty (void *p)
+{
+ struct sendfile_s *sf = p ;
+ return !!sf->n ;
+}
+
+static int s_flush (void *p)
+{
+ struct sendfile_s *sf = p ;
+ while (sf->n)
+ {
+ ssize_t r = sendfile(1, sf->fd, &sf->pos, sf->n > SSIZE_MAX ? SSIZE_MAX : sf->n) ;
+ if (r == -1) return 0 ;
+ sf->n -= r ;
+ }
+ return 1 ;
+}
+
+void send_file_range (int fd, uint64_t offset, uint64_t n, char const *fn)
+{
+ struct sendfile_s sf = { .pos = offset, .n = n, .fd = fd } ;
+ tain deadline ;
+ tain_add_g(&deadline, &g.writetto) ;
+ if (!buffer_timed_flush_g(buffer_1, &deadline))
+ strerr_diefu2sys(111, "write", " to stdout") ;
+ if (!timed_flush_g(&sf, &s_getfd, &s_isnonempty, &s_flush, &deadline))
+ strerr_diefu3sys(111, "sendfile ", fn, " to stdout") ;
+}
+
+#else
#ifdef SKALIBS_HASSPLICE
#include <skalibs/nonposix.h>
@@ -10,7 +70,9 @@
#include <stdint.h>
#include <unistd.h>
+#include <skalibs/uint64.h>
#include <skalibs/strerr.h>
+#include <skalibs/tai.h>
#include <skalibs/djbunix.h>
#include <skalibs/unix-timed.h>
@@ -53,7 +115,7 @@ static int flush (void *b)
return 1 ;
}
-void send_file (int fd, uint64_t n, char const *fn)
+void send_file_range (int fd, uint64_t offset, uint64_t n, char const *fn)
{
tain deadline ;
struct spliceinfo_s si = { .last = 0 } ;
@@ -62,7 +124,7 @@ void send_file (int fd, uint64_t n, char const *fn)
strerr_diefu2sys(111, "write", " to stdout") ;
while (n)
{
- si.n = splice(fd, 0, g.p[1], 0, n, 0) ;
+ si.n = splice(fd, &offset, g.p[1], 0, n, 0) ;
if (si.n == -1) strerr_diefu2sys(111, "read from ", fn) ;
else if (!si.n) strerr_diefu3x(111, "serve ", fn, ": file was truncated") ;
else if (si.n > n)
@@ -81,7 +143,10 @@ void send_file (int fd, uint64_t n, char const *fn)
#else
#include <sys/uio.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <skalibs/uint64.h>
#include <skalibs/allreadwrite.h>
#include <skalibs/buffer.h>
#include <skalibs/strerr.h>
@@ -94,12 +159,14 @@ void init_splice_pipe (void)
{
}
-void send_file (int fd, uint64_t n, char const *fn)
+void send_file_range (int fd, uint64_t offset, uint64_t n, char const *fn)
{
tain deadline ;
struct iovec v[2] ;
ssize_t r ;
if (!n) goto flushit ; /* I know, I know, but do-while SUCKS */
+ if (offset && lseek(fd, offset, SEEK_SET) == -1)
+ strerr_diefu2sys(111, "lseek on ", fn) ;
fillit:
buffer_wpeek(buffer_1, v) ;
r = allreadv(fd, v, 2) ;
@@ -120,3 +187,4 @@ void send_file (int fd, uint64_t n, char const *fn)
}
#endif
+#endif
diff --git a/src/tipideed/tipideed-internal.h b/src/tipideed/tipideed-internal.h
index 8631861..4b35efa 100644
--- a/src/tipideed/tipideed-internal.h
+++ b/src/tipideed/tipideed-internal.h
@@ -79,28 +79,33 @@ extern void tipideed_harden (unsigned int) ;
/* Responses */
-extern void response_error_early (tipidee_rql const *, unsigned int, char const *, char const *, uint32_t) ; /* set bit 0 for Connection: close */
-extern void response_error_early_and_exit (tipidee_rql const *, unsigned int, char const *, char const *) gccattr_noreturn ;
-extern void exit_405_ (tipidee_rql const *, uint32_t) gccattr_noreturn ; /* set bit 0 for Allow: POST, bit 1 for preexit */
+#define response_error_early(rql, status, reason, text, options) response_error_early_plus(rql, status, reason, text, 0, 0, options)
+extern void response_error_early_plus (tipidee_rql const *, unsigned int, char const *, char const *, tipidee_response_header const *, uint32_t, uint32_t) ;
+#define response_error_early_and_exit(rql, status, reason, text) response_error_early_plus_and_exit(rql, status, reason, (text), 0, 0)
+extern void response_error_early_plus_and_exit (tipidee_rql const *, unsigned int, char const *, char const *, tipidee_response_header const *, uint32_t) gccattr_noreturn ;
+extern void eexit_405 (tipidee_rql const *) gccattr_noreturn ;
#define eexit_400(r, s) response_error_early_and_exit(r, 400, "Bad Request", s)
-#define eexit_405(r) exit_405_((r), 3)
#define eexit_408(r) response_error_early_and_exit((r), 408, "Request Timeout", 0)
#define eexit_413(r, s) response_error_early_and_exit(r, 413, "Request Entity Too Large", s)
#define eexit_501(r, s) response_error_early_and_exit(r, 501, "Not Implemented", s)
+#define response_error(rql, docroot, status, options) response_error_plus(rql, docroot, status, 0, 0, options)
+extern void response_error_plus (tipidee_rql const *, char const *, unsigned int, tipidee_response_header const *, uint32_t, uint32_t) ; /* set bit 0 for Connection: close */
+#define response_error_and_exit(rql, docroot, status) response_error_plus_and_exit(rql, docroot, (status), 0, 0)
+extern void response_error_plus_and_exit (tipidee_rql const *, char const *, unsigned int, tipidee_response_header const *, uint32_t) gccattr_noreturn ;
+#define response_error_and_die(rql, e, docroot, status, v, n, options) response_error_plus_and_die(rql, e, docroot, status, 0, 0, v, n, options)
+extern void response_error_plus_and_die (tipidee_rql const *, int, char const *, unsigned int, tipidee_response_header const *, uint32_t, char const *const *, unsigned int, uint32_t) gccattr_noreturn ; /* set bit 0 for diesys */
-extern void response_error (tipidee_rql const *, char const *, unsigned int, uint32_t) ; /* set bit 0 for Connection: close */
-extern void response_error_and_exit (tipidee_rql const *, char const *, unsigned int) gccattr_noreturn ;
-extern void response_error_and_die (tipidee_rql const *, int, char const *, unsigned int, char const *const *, unsigned int, uint32_t) gccattr_noreturn ; /* set bit 0 for diesys */
-
+extern void exit_405 (tipidee_rql const *, char const *, uint32_t) gccattr_noreturn ;
#define exit_400(r, d) response_error_and_exit(r, (d), 400)
-#define exit_405(r) exit_405_((r), 0)
#define exit_408(r, d) response_error_and_exit(r, (d), 408)
#define exit_413(r, d) response_error_and_exit(r, (d), 413)
#define exit_501(r, d) response_error_and_exit(r, (d), 501)
extern void respond_30x (tipidee_rql const *, tipidee_redirection const *) ;
+extern void respond_416 (tipidee_rql const *, char const *, uint64_t) ;
+
#define respond_403(r, d) response_error(r, (d), 403, 0)
#define respond_404(r, d) response_error(r, (d), 404, 0)
#define respond_414(r, d) response_error(r, (d), 414, 0)
@@ -126,12 +131,14 @@ extern int respond_options (tipidee_rql const *, uint32_t) ;
/* send_file */
extern void init_splice_pipe (void) ;
-extern void send_file (int, uint64_t, char const *) ;
+extern void send_file_range (int, uint64_t, uint64_t, char const *) ;
+#define send_file(fd, n, fn) send_file_range(fd, 0, n, fn)
/* regular */
extern int respond_regular (tipidee_rql const *, char const *, char const *, struct stat const *, tipidee_resattr const *) ;
+extern int respond_partial (tipidee_rql const *, char const *, char const *, struct stat const *, uint64_t, uint64_t, tipidee_resattr const *) ;
extern int respond_304 (tipidee_rql const *, char const *, struct stat const *) ;
diff --git a/src/tipideed/tipideed.c b/src/tipideed/tipideed.c
index 8323db1..69280f6 100644
--- a/src/tipideed/tipideed.c
+++ b/src/tipideed/tipideed.c
@@ -11,6 +11,7 @@
#include <skalibs/posixplz.h>
#include <skalibs/env.h>
#include <skalibs/uint16.h>
+#include <skalibs/uint64.h>
#include <skalibs/types.h>
#include <skalibs/bytestr.h>
#include <skalibs/sgetopt.h>
@@ -286,7 +287,7 @@ static inline int serve (tipidee_rql *rql, char const *docroot, char *uribuf, ti
if (!ra.flags & TIPIDEE_RA_FLAG_CGI)
{
if (infopath) { respond_404(rql, docroot) ; return 0 ; }
- if (rql->m == TIPIDEE_METHOD_POST) exit_405(rql) ;
+ if (rql->m == TIPIDEE_METHOD_POST) exit_405(rql, docroot, 0) ;
}
if (rql->m == TIPIDEE_METHOD_OPTIONS)
@@ -306,6 +307,19 @@ static inline int serve (tipidee_rql *rql, char const *docroot, char *uribuf, ti
&& tain_less(&actual, &wanted))
return respond_304(rql, fn, &st) ;
}
+
+ if (rql->m == TIPIDEE_METHOD_GET)
+ {
+ infopath = tipidee_headers_search(hdr, "Range") ;
+ if (infopath)
+ {
+ uint64_t start, len ;
+ int r = tipidee_util_parse_range(infopath, st.st_size, &start, &len) ;
+ if (r > 0) return respond_partial(rql, docroot, fn, &st, start, len, &ra) ;
+ if (r < 0) { respond_416(rql, docroot, st.st_size) ; return 0 ; }
+ }
+ }
+
return respond_regular(rql, docroot, fn, &st, &ra) ;
}