bunkum

an old and silly c99 web server with some fun features
Log | Files | Refs | README

commit 2f6ca9c766f9d7e01fae84de7cc997ea39a872a5
parent 060e65d3ae7e844e7ae0745948c5f82f4daea6d4
Author: quantumish <freifeld.david@gmail.com>
Date:   Mon, 10 Apr 2023 23:06:53 -0700

Actually correctly parse Accept header

Diffstat:
Mhttp.c | 43++++++++++---------------------------------
Mhttp/request.c | 50+++++++++++++++++++++++++++++++-------------------
Mhttp/request.h | 8++++++++
Mhttp/response.c | 2+-
Mutils/shitvec.c | 4++++
Mutils/shitvec.h | 1+
6 files changed, 55 insertions(+), 53 deletions(-)

diff --git a/http.c b/http.c @@ -24,31 +24,6 @@ #include "http/response.h" #include "http/request.h" -void scuffed_htmlescape(char* dst, char* src, size_t sz) { - strcpy(dst, "<pre>\n"); - int offset = 6; - int i; - for (i = 0; i < sz; i++) { - switch (src[i]) { - case '<': - strcpy(dst+i+offset, "&lt;"); - offset += 3; - break; - case '>': - strcpy(dst+i+offset, "&gt;"); - offset += 3; - break; - case '&': - strcpy(dst+i+offset, "&amp;"); - offset += 4; - break; - default: - dst[i+offset] = src[i]; - } - } - strcpy(dst+i+offset, "\n</pre>"); -} - shitvec_t paths; response_t serve_file(request_t req) { @@ -71,13 +46,7 @@ response_t serve_file(request_t req) { char* buf = fbuf; // buffer to be written size_t bufsize = st.st_size; - - if (ext == NULL) { - bufsize = st.st_size * 2; - buf = malloc(bufsize); // FIXME dubious assumption - scuffed_htmlescape(buf, fbuf, st.st_size); - free(fbuf); - } + if (ext == NULL || strcmp(ext, ".png") != 0) { resp_add_hdr(&r, "Content-Encoding", "deflate"); size_t clen = compressBound(st.st_size); @@ -88,6 +57,7 @@ response_t serve_file(request_t req) { buf = cbuf; bufsize = clen; } + resp_add_content(&r, buf, bufsize); free(buf); return r; @@ -117,8 +87,15 @@ void* handle_conn(void* ctxt) { for (size_t i = 0; i < req.headers.vec_sz; i++) { header_line_t hdr = *(header_line_t*)shitvec_get(&req.headers, i); log_debug("Header '%s: %s'", hdr.name, hdr.value); + if (strcmp(hdr.name, "Accept") == 0) { + shitvec_t mtypes = hdr_parse_accept(hdr.value); + for (size_t j = 0; j < mtypes.vec_sz; j++) { + struct req_mimetype mtype = *(struct req_mimetype*)shitvec_get(&mtypes, j); + log_info("Allowed type %s with q=%f", mtype.item, mtype.q); + } + } } - + log_info("Got request for %s", req.path); if (shitvec_check(&paths, req.path, (int(*)(void*,void*))strcmp)) { diff --git a/http/request.c b/http/request.c @@ -2,6 +2,7 @@ #include <string.h> #include <stdint.h> +#include "../utils/log.h" #include "../utils/shitvec.h" #include "request.h" @@ -30,25 +31,36 @@ request_t req_new(char* reqbuf, size_t bufsize) { return req; } -struct qual_item { - float q; - char item[8]; +int cmp_r_mimetype(const void* a, const void* b) { + struct req_mimetype* aa = (struct req_mimetype*)a; + struct req_mimetype* bb = (struct req_mimetype*)b; + if (aa->q > bb->q) return -1; + else if (aa->q == bb->q) return 0; + else if (aa->q < bb->q) return 1; } -shitvec_t parse_accept(char* value) { - shitvec_t items = shitvec_new(16); - char* start = strtok(value, ","); - while (start != NULL) { - struct qual_item i; - strtok(NULL, ","); - - /* strncpy(i.item, start, */ - strchr(start, ';'); - - sscanf(strchr(start, ';'), "q=%f", &i.q); - - printf("%s", start); - } +// TODO handle parse errors +shitvec_t hdr_parse_accept(char* val) { + shitvec_t mimetypes = shitvec_new(sizeof(struct req_mimetype)); + char* start = strtok(val, ","); + char* next; + do { + next = strtok(NULL, ","); + float q = 1; + char* qptr = NULL; + if ((qptr = (char*)memchr(start, ';', next-start))) { + sscanf(qptr, ";q=%f", &q); + } + struct req_mimetype mtype; + mtype.q = q; + memset(mtype.item, 0, MAX_MIMETYPE_LEN); + if (qptr != NULL) strncpy(mtype.item, start, qptr-start); + else if (next != NULL) strncpy(mtype.item, start, next-start); + else strcpy(mtype.item, start); + shitvec_push(&mimetypes, &mtype); + } while ((start = next)); + shitvec_sort(&mimetypes, cmp_r_mimetype); + return mimetypes; } int req_parse(request_t* req) { @@ -60,7 +72,7 @@ int req_parse(request_t* req) { req->headers = shitvec_new(sizeof(header_line_t)); char* start = memchr(req->buf, '\n', MAX_HEADER_NAME+MAX_HEADER_VALUE)+1; while (start+MAX_HEADER_NAME+MAX_HEADER_VALUE < req->buf+req->bufsize) { - header_line_t hdr; + header_line_t hdr = header_line_new(); int matched = sscanf(start, "%32[^:]: %s", hdr.name, hdr.value); if (matched == 0) return 0; // No more headers; else if (matched == 1) { @@ -70,10 +82,10 @@ int req_parse(request_t* req) { shitvec_push(&req->headers, &hdr); start = memchr(start, '\n', MAX_HEADER_NAME+MAX_HEADER_VALUE)+1; } - return 0; } void req_free(request_t* req) { shitvec_free(&req->headers); } + diff --git a/http/request.h b/http/request.h @@ -18,12 +18,20 @@ const char* method_name(enum http_method m); #define MAX_PATH_LEN 128 #define MAX_HEADER_NAME 32 #define MAX_HEADER_VALUE 128 +#define MAX_MIMETYPE_LEN 32 + +struct req_mimetype { + float q; + char item[MAX_MIMETYPE_LEN]; +}; typedef struct header_line { char name[MAX_HEADER_NAME]; char value[MAX_HEADER_VALUE]; } header_line_t; +shitvec_t hdr_parse_accept(char* val); + typedef struct request { char* buf; size_t bufsize; diff --git a/http/response.c b/http/response.c @@ -43,7 +43,7 @@ void resp_add_content(response_t* r, char* content, size_t content_len) { void resp_set_ctype(response_t* r, char* ext) { if (ext == NULL) { - resp_add_hdr(r, "Content-Type", "text/html"); + resp_add_hdr(r, "Content-Type", "text/plain"); } else if (strcmp(ext+1, "html") == 0) { resp_add_hdr(r, "Content-Type", "text/html"); } else if (strcmp(ext+1, "png") == 0) { diff --git a/utils/shitvec.c b/utils/shitvec.c @@ -46,6 +46,10 @@ bool shitvec_check(shitvec_t* sv, void* item, int(cmp)(void*, void*)) { return false; } +void shitvec_sort(shitvec_t* sv, int(*cmp)(const void*, const void*)) { + qsort(sv->arr, sv->vec_sz, sv->e_sz, cmp); +} + void shitvec_free(shitvec_t* sv) { free(sv->arr); } diff --git a/utils/shitvec.h b/utils/shitvec.h @@ -18,6 +18,7 @@ void* shitvec_get(shitvec_t* sv, size_t index); void shitvec_push(shitvec_t* sv, void* item); void shitvec_subpush(shitvec_t* sv, void* item, size_t sz); bool shitvec_check(shitvec_t* sv, void* item, int(cmp)(void*, void*)); +void shitvec_sort(shitvec_t* sv, int(*cmp)(const void*, const void*)); void shitvec_free(shitvec_t* sv); #endif