]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
mlmmj: add a parser to extract content-type's mime and boundary
authorBaptiste Daroussin <bapt@FreeBSD.org>
Tue, 27 Aug 2024 09:18:48 +0000 (11:18 +0200)
committerBaptiste Daroussin <bapt@FreeBSD.org>
Tue, 27 Aug 2024 09:18:48 +0000 (11:18 +0200)
include/mlmmj.h
src/mlmmj.c
tests/mlmmj.c

index a45b76aed21e4df2872a8b3e02e5e3360b00cb91..ca352c92e6bd0867519bb66cfd5c7d7d16ae9df2 100644 (file)
@@ -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; \
index 6c2ce8666d8a79c48b1316bbae0c078c4b723891..aa2cc275bef9c894e6d12853fd3e1d214a258e72 100644 (file)
@@ -30,6 +30,7 @@
 #include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
+#include <strings.h>
 #include <time.h>
 #include <unistd.h>
 #include <err.h>
@@ -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,
index 655b76e94ebb599f99f69db20a73e6c03540f452..c7c43889cc03f0e1aa63cb36e1f728718adbc354 100644 (file)
@@ -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());
 }