From: Baptiste Daroussin Date: Tue, 27 Aug 2024 09:18:48 +0000 (+0200) Subject: mlmmj: add a parser to extract content-type's mime and boundary X-Git-Tag: RELEASE_1_5_0~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f3f22ca867a1495a437736257ec07c8c565b1047;p=thirdparty%2Fmlmmj.git mlmmj: add a parser to extract content-type's mime and boundary --- diff --git a/include/mlmmj.h b/include/mlmmj.h index a45b76ae..ca352c92 100644 --- a/include/mlmmj.h +++ b/include/mlmmj.h @@ -135,6 +135,8 @@ void ml_init(struct ml *ml); bool ml_open(struct ml *ml, bool checkuser); void ml_close(struct ml *ml); bool send_probe(struct ml *ml, const char *addr); +void parse_content_type(strlist *, char **mime_type, char **boundary); +char *find_in_list(strlist *, const char *pattern); #define MY_ASSERT(expression) if (!(expression)) { \ errno = 0; \ diff --git a/src/mlmmj.c b/src/mlmmj.c index 6c2ce866..aa2cc275 100644 --- a/src/mlmmj.c +++ b/src/mlmmj.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -113,6 +114,68 @@ send_probe(struct ml *ml, const char *addr) return (true); } +char * +find_in_list(strlist *l, const char *pattern) +{ + size_t len; + + if (l == NULL) + return (NULL); + if (pattern == NULL) + return (NULL); + len = strlen(pattern); + + tll_foreach(*l, el) { + char *str = el->item; + if (str == NULL) + continue; + if (strncasecmp(str, pattern, len) == 0) + return (str); + } + return (NULL); +} + +void +parse_content_type(strlist *allhdrs, char **mime_type, char **boundary) +{ + *boundary = NULL; + *mime_type = NULL; + char *pos; + size_t len = 0; + + char *hdr = find_in_list(allhdrs, "Content-Type:"); + if (hdr == NULL) + return; /* No Content-Type */ + pos = hdr + 13; + while (*pos && (*pos == ' ' || *pos == '\t')) + ++pos; + if (*pos == '"') { + ++pos; + while (pos[len] && pos[len] != '"') + ++len; + } else { + while (pos[len] && pos[len] != ' ' && pos[len] != '\t' && pos[len] != ';') + ++len; + } + if (len > 0) + *mime_type = xstrndup(pos, len); + pos += len; + len = 0; + while (*pos && strncasecmp(pos, "boundary=", 9)) + ++pos; + if (*pos == '\0') + return; /* No boundaries */ + pos += 9; + if (*pos == '"') { + ++pos; + while (pos[len] && pos[len] != '"') + ++len; + } else { + while(pos[len] && pos[len] != ' ' && pos[len] != '\t' && pos[len] != ';') + ++len; + } + *boundary = xstrndup(pos, len); +} bool parse_lastdigest(char *line, long *lastindex, time_t *lasttime, diff --git a/tests/mlmmj.c b/tests/mlmmj.c index 655b76e9..c7c43889 100644 --- a/tests/mlmmj.c +++ b/tests/mlmmj.c @@ -158,6 +158,8 @@ ATF_TC_WITHOUT_HEAD(gethdrline); ATF_TC_WITHOUT_HEAD(readlf); ATF_TC_WITHOUT_HEAD(mod_get_addr_type); ATF_TC_WITHOUT_HEAD(send_probe); +ATF_TC_WITHOUT_HEAD(parse_content_type); +ATF_TC_WITHOUT_HEAD(find_in_list); ATF_TC_BODY(random_int, tc) { @@ -2861,6 +2863,66 @@ ATF_TC_BODY(send_probe, tc) } } +ATF_TC_BODY(find_in_list, tc) +{ + strlist bla = tll_init(); + ATF_REQUIRE(find_in_list(NULL, NULL) == NULL); + ATF_REQUIRE(find_in_list(&bla, NULL) == NULL); + ATF_REQUIRE(find_in_list(&bla, "test") == NULL); + tll_push_back(bla, NULL); + ATF_REQUIRE(find_in_list(&bla, "test") == NULL); + tll_push_back(bla, "plop"); + ATF_REQUIRE(find_in_list(&bla, "test") == NULL); + tll_push_back(bla, "test"); + ATF_REQUIRE_STREQ(find_in_list(&bla, "test"), "test"); + tll_pop_back(bla); + tll_push_back(bla, "test longer"); + ATF_REQUIRE_STREQ(find_in_list(&bla, "test"), "test longer"); +} + +ATF_TC_BODY(parse_content_type, tc) +{ + char *m, *b; + strlist hdrs = tll_init(); + parse_content_type(NULL, &m, &b); + ATF_REQUIRE(m == NULL); + ATF_REQUIRE(b == NULL); + tll_push_back(hdrs, "From: plop"); + parse_content_type(&hdrs, &m, &b); + ATF_REQUIRE(m == NULL); + ATF_REQUIRE(b == NULL); + tll_push_back(hdrs, "Content-Type:"); + parse_content_type(&hdrs, &m, &b); + ATF_REQUIRE(m == NULL); + ATF_REQUIRE(b == NULL); + tll_pop_back(hdrs); + tll_push_back(hdrs, "Content-Type: multipart/mixed"); + parse_content_type(&hdrs, &m, &b); + ATF_REQUIRE_STREQ(m, "multipart/mixed"); + free(m); + ATF_REQUIRE(b == NULL); + tll_pop_back(hdrs); + tll_push_back(hdrs, "Content-Type: multipart/mixed;"); + parse_content_type(&hdrs, &m, &b); + ATF_REQUIRE_STREQ(m, "multipart/mixed"); + free(m); + ATF_REQUIRE(b == NULL); + tll_pop_back(hdrs); + tll_push_back(hdrs, "Content-Type: multipart/mixed;\tboundary=bla"); + parse_content_type(&hdrs, &m, &b); + ATF_REQUIRE_STREQ(m, "multipart/mixed"); + free(m); + ATF_REQUIRE_STREQ(b,"bla"); + free(b); + tll_pop_back(hdrs); + tll_push_back(hdrs, "Content-Type: multipart/mixed;\tboundary=bla;"); + parse_content_type(&hdrs, &m, &b); + ATF_REQUIRE_STREQ(m, "multipart/mixed"); + free(m); + ATF_REQUIRE_STREQ(b,"bla"); + free(b); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, random_int); @@ -2948,6 +3010,8 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, readlf); ATF_TP_ADD_TC(tp, mod_get_addr_type); ATF_TP_ADD_TC(tp, send_probe); + ATF_TP_ADD_TC(tp, parse_content_type); + ATF_TP_ADD_TC(tp, find_in_list); return (atf_no_error()); }