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