diff options
author | Vsevolod Stakhov <vsevolod@rspamd.com> | 2023-11-25 13:42:03 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rspamd.com> | 2023-11-25 13:42:03 +0000 |
commit | e0befa616f7f0fdfc823b8a442f398e8c649cd95 (patch) | |
tree | 4bc1506a48b9703aa2643107a257ea67ab954553 /src/libmime | |
parent | f8af1c1f2fea4c1c1eda945578eb8c16e7358ef3 (diff) | |
download | rspamd-e0befa616f7f0fdfc823b8a442f398e8c649cd95.tar.gz rspamd-e0befa616f7f0fdfc823b8a442f398e8c649cd95.zip |
[Test] Add unit tests for unfolding
Diffstat (limited to 'src/libmime')
-rw-r--r-- | src/libmime/mime_headers.c | 74 | ||||
-rw-r--r-- | src/libmime/mime_headers.h | 8 |
2 files changed, 81 insertions, 1 deletions
diff --git a/src/libmime/mime_headers.c b/src/libmime/mime_headers.c index 2b6b2acc0..e250e84f1 100644 --- a/src/libmime/mime_headers.c +++ b/src/libmime/mime_headers.c @@ -1025,6 +1025,76 @@ rspamd_message_headers_new(void) return nhdrs; } +gsize rspamd_message_header_unfold_inplace(char *hdr, gsize len) +{ + /* + * t - tortoise (destination) + * h - hare (source) + */ + char *t = hdr, *h = hdr, *end = (hdr + len); + enum { + copy_chars, + folding_cr, + folding_lf, + folding_ws, + } state = copy_chars; + + while (h < end) { + switch (state) { + case copy_chars: + if (*h == '\r') { + state = folding_cr; + h++; + } + else if (*h == '\n') { + state = folding_lf; + h++; + } + else { + *t++ = *h++; + } + break; + case folding_cr: + if (*h == '\n') { + state = folding_lf; + h++; + } + else if (g_ascii_isspace(*h)) { + state = folding_ws; + h++; + } + else { + /* It is weird, not like a folding, so we need to revert back */ + *t++ = '\r'; + state = copy_chars; + } + break; + case folding_lf: + if (g_ascii_isspace(*h)) { + state = folding_ws; + h++; + } + else { + /* It is weird, not like a folding, so we need to revert back */ + *t++ = '\n'; + state = copy_chars; + } + break; + case folding_ws: + if (!g_ascii_isspace(*h)) { + *t++ = ' '; + state = copy_chars; + } + else { + h++; + } + break; + } + } + + return t - hdr; +} + void rspamd_message_set_modified_header(struct rspamd_task *task, struct rspamd_mime_headers_table *hdrs, const gchar *hdr_name, @@ -1201,8 +1271,10 @@ void rspamd_message_set_modified_header(struct rspamd_task *task, nhdr->name = hdr_elt->name; nhdr->value = rspamd_mempool_alloc(task->task_pool, raw_len + 1); + /* Strlcpy will ensure that value will have no embedded \0 */ rspamd_strlcpy(nhdr->value, raw_value, raw_len + 1); - /* TODO: unfold header value, sigh */ + gsize value_len = rspamd_message_header_unfold_inplace(nhdr->value, raw_len); + nhdr->value[value_len] = '\0'; /* Deal with the raw value */ size_t namelen = strlen(hdr_elt->name); diff --git a/src/libmime/mime_headers.h b/src/libmime/mime_headers.h index ffa863e8b..60015a20e 100644 --- a/src/libmime/mime_headers.h +++ b/src/libmime/mime_headers.h @@ -185,6 +185,14 @@ bool rspamd_mime_headers_foreach(const struct rspamd_mime_headers_table *, */ gsize rspamd_strip_smtp_comments_inplace(gchar *input, gsize len); +/** + * Unfold header in place + * @param hdr header value + * @param len length of the header + * @return new unfolded length + */ +gsize rspamd_message_header_unfold_inplace(char *hdr, gsize len); + #ifdef __cplusplus } #endif |