commit 1826a08: [Feature] Core: Add QP encoding utility

Vsevolod Stakhov vsevolod at highsecure.ru
Thu Dec 27 18:28:10 UTC 2018


Author: Vsevolod Stakhov
Date: 2018-12-17 16:41:46 +0000
URL: https://github.com/rspamd/rspamd/commit/1826a0817ce18bfdb468789fc79275271e8a92d2

[Feature] Core: Add QP encoding utility

---
 src/libutil/str_util.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/libutil/str_util.h |  10 ++++
 2 files changed, 132 insertions(+)

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
@@ -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


More information about the Commits mailing list