]> source.dussan.org Git - rspamd.git/commitdiff
[Feature] Core: Add QP encoding utility
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 17 Dec 2018 16:41:46 +0000 (16:41 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 17 Dec 2018 16:41:46 +0000 (16:41 +0000)
src/libutil/str_util.c
src/libutil/str_util.h

index 1e43e7726cd59d8ab6891d3c0198133738ea22e1..949bdd3371d86a19fefe4e2e6403eaad76ab5d2e 100644 (file)
@@ -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)))
 
index 139a85416395751d42e5083838392426b374a789..935c5116dda9d58685d35470caafec9c4ca7c0a8 100644 (file)
@@ -203,6 +203,16 @@ gchar * rspamd_encode_base64 (const guchar *in, gsize inlen, gint str_len,
 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