diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2018-12-17 16:41:46 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2018-12-17 16:41:46 +0000 |
commit | 1826a0817ce18bfdb468789fc79275271e8a92d2 (patch) | |
tree | b32deb38d9bad0a9f0da612e83548c7882af062b /src/libutil | |
parent | 8719b0d659d83b31a1b4bf1779ac656f9463476e (diff) | |
download | rspamd-1826a0817ce18bfdb468789fc79275271e8a92d2.tar.gz rspamd-1826a0817ce18bfdb468789fc79275271e8a92d2.zip |
[Feature] Core: Add QP encoding utility
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/str_util.c | 122 | ||||
-rw-r--r-- | src/libutil/str_util.h | 10 |
2 files changed, 132 insertions, 0 deletions
diff --git a/src/libutil/str_util.c b/src/libutil/str_util.c index 1e43e7726..949bdd337 100644 --- a/src/libutil/str_util.c +++ b/src/libutil/str_util.c @@ -902,6 +902,128 @@ rspamd_encode_base64_fold (const guchar *in, gsize inlen, gint str_len, return rspamd_encode_base64_common (in, inlen, str_len, outlen, TRUE, how); } +gchar * +rspamd_encode_qp_fold (const guchar *in, gsize inlen, gint str_len, + gsize *outlen, enum rspamd_newlines_type how) +{ + gsize olen = 0, span = 0, i = 0; + gchar *out; + gint ch; + const guchar *end = in + inlen, *p = in; + static const gchar hexdigests[16] = "0123456789ABCDEF"; + + while (p < end) { + ch = *p; + + if (ch < 128 && ch != '\r' && ch != '\n') { + olen ++; + span ++; + } + else { + if (str_len > 0 && span + 5 >= str_len) { + if (how == RSPAMD_TASK_NEWLINES_CRLF) { + /* =\r\n */ + olen += 3; + } + else { + olen += 2; + } + span = 0; + } + + olen += 3; + span += 3; + } + + if (str_len > 0 && span >= str_len) { + if (how == RSPAMD_TASK_NEWLINES_CRLF) { + /* =\r\n */ + olen += 3; + } + else { + olen += 2; + } + span = 0; + } + + p ++; + } + + out = g_malloc (olen + 1); + p = in; + i = 0; + span = 0; + + while (p < end) { + ch = *p; + + if (ch < 128 && ch != '\r' && ch != '\n') { + out[i++] = ch; + span ++; + } + else { + if (str_len > 0 && span + 5 >= str_len) { + /* Add new line and then continue */ + switch (how) { + default: + case RSPAMD_TASK_NEWLINES_CRLF: + out[i++] = '='; + out[i++] = '\r'; + out[i++] = '\n'; + break; + case RSPAMD_TASK_NEWLINES_LF: + out[i++] = '='; + out[i++] = '\n'; + break; + case RSPAMD_TASK_NEWLINES_CR: + out[i++] = '='; + out[i++] = '\r'; + break; + } + + span = 0; + } + + out[i++] = '='; + out[i++] = hexdigests[((ch >> 4) & 0xF)]; + out[i++] = hexdigests[(ch & 0xF)]; + span += 3; + } + + if (str_len > 0 && span + 3 >= str_len) { + /* Add new line and then continue */ + switch (how) { + default: + case RSPAMD_TASK_NEWLINES_CRLF: + out[i++] = '='; + out[i++] = '\r'; + out[i++] = '\n'; + break; + case RSPAMD_TASK_NEWLINES_LF: + out[i++] = '='; + out[i++] = '\n'; + break; + case RSPAMD_TASK_NEWLINES_CR: + out[i++] = '='; + out[i++] = '\r'; + break; + } + + span = 0; + } + + g_assert (i <= olen); + p ++; + } + + out[i] = '\0'; + + if (outlen) { + *outlen = i; + } + + return out; +} #define MIN3(a, b, c) ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c))) diff --git a/src/libutil/str_util.h b/src/libutil/str_util.h index 139a85416..935c5116d 100644 --- a/src/libutil/str_util.h +++ b/src/libutil/str_util.h @@ -204,6 +204,16 @@ gchar * rspamd_encode_base64_fold (const guchar *in, gsize inlen, gint str_len, gsize *outlen, enum rspamd_newlines_type how); /** + * Encode and fold string using quoted printable encoding + * @param in input + * @param inlen input length + * @param str_len maximum string length (if <= 0 then no lines are split) + * @return freshly allocated base64 encoded value or NULL if input is invalid + */ +gchar * rspamd_encode_qp_fold (const guchar *in, gsize inlen, gint str_len, + gsize *outlen, enum rspamd_newlines_type how); + +/** * Decode quoted-printable encoded buffer, input and output must not overlap * @param in input * @param inlen length of input |