From 8d4b8f77d49110f04108eec6cbace6a33db78324 Mon Sep 17 00:00:00 2001 From: "me@ow.nekobit.net" Date: Fri, 8 Apr 2022 22:43:48 +0000 Subject: [PATCH] Mime parsing FossilOrigin-Name: e6a37f930fb748cdf6828053bc6df089e4ea426602863ae77aefb62c8ff773f2 --- .gitignore | 3 +- README.md | 2 + src/mime.c | 112 +++++++++++++++++++++++++++++++++++++++++++---------- src/mime.h | 11 +++++- 4 files changed, 105 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 3983865..a125849 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ filec **/*.chtml mastodont-c config.h -treebird \ No newline at end of file +treebird +test/tests \ No newline at end of file diff --git a/README.md b/README.md index c357228..50ba5b6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +# NOTE: This software is not finished. Any bugs are likely noted + # Treebird ![Treebird logo](./meta/treebird.png) diff --git a/src/mime.c b/src/mime.c index 0d9a6b2..fbb2301 100644 --- a/src/mime.c +++ b/src/mime.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "mime.h" char* get_mime_boundary(char* content_type_str, char** bound) @@ -64,49 +65,118 @@ error: return NULL; } -char* strnws(char* str) +static char* strnws(char* str) { for (; isblank(*str); ++str); return str; } -#define STRSCMP(begin, str) strncmp((begin), (str), sizeof(str)) +// Function assumes character is at ';' char +static char* read_key(char** r, char* key) +{ + char* val, *read_val; + size_t key_len = strlen(key); + *r = strnws(*r+1); + if (strncmp(*r, key, key_len) != 0) + return NULL; + *r = strnws(*r + key_len); + if (**r != '=') + return NULL; + *r = strnws(*r + 1); + if (**r == '\"') ++(*r); + val = *r; + // Chop off string + if ((read_val = strchr(*r, '\"')) || + (read_val = strchr(*r, ';')) || + (read_val = strchr(*r, '\r'))) + *read_val = '\0'; + // Jump to end + *r += strlen(val)+1; + + return val; +} + +#define STRSCMP(begin, str) strncmp((begin), (str), sizeof(str)-1) + char* read_form_data(char* boundary, char* begin, struct http_form_info* info) { - char* r, *name; + ptrdiff_t data_size; + // Step 1: Parse name + // Parser variables + char* r, *read_val; size_t bound_len = strlen(boundary); if (strncmp(begin, "--", 2) != 0 || strncmp(begin+2, boundary, bound_len) != 0) return NULL; + // Check if this is the end + if (strncmp(begin + 2 + bound_len, "--", 2) == 0) + return NULL; + r = begin + 2 + bound_len + 2; /* Skip over LRSF */ if (STRSCMP(r, "Content-Disposition") != 0) return NULL; - r = strnws(r + sizeof("Content-Disposition")+1); - if (*r != ':' || - STRSCMP(r, "form-data") != 0) // Fucked up + r = strnws(r + sizeof("Content-Disposition")-1); + if (*r != ':') // Fucked up return NULL; - r = strnws(r + sizeof("form-data")+1); + r = strnws(r + 1); + if (STRSCMP(r, "form-data") != 0) + return NULL; + r = strnws(r + sizeof("form-data")-1); if (*r != ';') return NULL; - r = strnws(r+1); - if (STRSCMP(r, "name") != 0) - return NULL; - r = strnws(r + sizeof("name")+1); - if (*r != '=') - return NULL; - r = strnws(r + 1); - if (*r == '\"') + + info->name = read_key(&r, "name"); + // Step 2: Parse filename (if there) + if (*r == ';') + { + info->filename = read_key(&r, "filename"); + } + else + info->filename = NULL; + + if (*r == '\r') r += 2; - if (*r == '\"') ++r; - name = r; - if ((r = strchr(r, '\"'))) - *r = '\0'; - printf("nameparsed: %s\r\n", name); + // Step 3: Parse Content-type (if there) + if (STRSCMP(r, "Content-Type") == 0) + { + r = strnws(r + sizeof("Content-type")-1); + if (*r != ':') + return NULL; - return name; + r = strnws(r + 1); + info->content_type = r; + if ((r = strchr(r, '\r'))) + *r = '\0'; + else + return NULL; + r += 4; + } + else if (*r == '\r') { + info->content_type = NULL; + r += 2; + } + + // Last step: Find data + info->value = r; + + // Look for end + if ((r = strstr(r, boundary)) && + r && strstr(r-4, "\r\n--")) + { + r[-4] = '\0'; + data_size = (r-4) - info->value; + info->value_size = data_size; + } + else + return NULL; + + // Go back for next read + r -= 2; + + return r; } diff --git a/src/mime.h b/src/mime.h index 631d79c..164f5bc 100644 --- a/src/mime.h +++ b/src/mime.h @@ -19,7 +19,16 @@ #ifndef MIME_H #define MIME_H +struct http_form_info +{ + char* name; + char* filename; + char* content_type; + char* value; + size_t value_size; +}; + char* get_mime_boundary(char* content_type, char** res); -char* read_mime_data(char* boundary, char* begin, struct http_form_info* info); +char* read_form_data(char* boundary, char* begin, struct http_form_info* info); #endif /* MIME_H */