summaryrefslogtreecommitdiffstats
path: root/src/libutil/str_util.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2018-12-17 16:41:46 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2018-12-17 16:41:46 +0000
commit1826a0817ce18bfdb468789fc79275271e8a92d2 (patch)
treeb32deb38d9bad0a9f0da612e83548c7882af062b /src/libutil/str_util.c
parent8719b0d659d83b31a1b4bf1779ac656f9463476e (diff)
downloadrspamd-1826a0817ce18bfdb468789fc79275271e8a92d2.tar.gz
rspamd-1826a0817ce18bfdb468789fc79275271e8a92d2.zip
[Feature] Core: Add QP encoding utility
Diffstat (limited to 'src/libutil/str_util.c')
-rw-r--r--src/libutil/str_util.c122
1 files changed, 122 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)))