]> source.dussan.org Git - rspamd.git/commitdiff
Add base64 encoding routine.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 20 May 2015 10:49:51 +0000 (11:49 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 20 May 2015 10:49:51 +0000 (11:49 +0100)
src/libutil/util.c
src/libutil/util.h

index 15f73bf0942dc1ce27427a98e308fb4aeaf85944..8aac96a90e5f3b95170e8d17e718a52ff7a9ec20 100644 (file)
@@ -2315,6 +2315,172 @@ rspamd_decode_base32 (const gchar *in, gsize inlen, gsize *outlen)
        return res;
 }
 
+gchar *
+rspamd_encode_base64 (const guchar *in, gsize inlen, gint str_len, gsize *outlen)
+{
+       gsize allocated_len = (inlen / 3) * 4 + 4;
+       gchar *out, *o;
+       guint64 n;
+       guint32 t1, t2, t3;
+       gint cols, shift;
+       guint i = 0;
+       static const char b64_enc[] =
+               "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+               "abcdefghijklmnopqrstuvwxyz"
+               "0123456789+/";
+
+       if (str_len > 0) {
+               allocated_len += (allocated_len / str_len + 1) * 2 + 1;
+       }
+
+       out = g_malloc (allocated_len);
+       o = out;
+       cols = 0;
+
+       while (inlen > 6) {
+               n = *(guint64 *)in;
+               n = GUINT64_TO_BE (n);
+
+               if (str_len <= 0 || cols <= str_len - 8) {
+                       *o++ = b64_enc[(n >> 58) & 0x3F];
+                       *o++ = b64_enc[(n >> 52) & 0x3F];
+                       *o++ = b64_enc[(n >> 46) & 0x3F];
+                       *o++ = b64_enc[(n >> 40) & 0x3F];
+                       *o++ = b64_enc[(n >> 34) & 0x3F];
+                       *o++ = b64_enc[(n >> 28) & 0x3F];
+                       *o++ = b64_enc[(n >> 22) & 0x3F];
+                       *o++ = b64_enc[(n >> 16) & 0x3F];
+                       cols += 8;
+               }
+               else {
+                       cols = str_len - cols;
+                       shift = 58;
+                       while (cols) {
+                               *o++ = b64_enc[(n >> shift) & 0x3F];
+                               shift -= 6;
+                               cols --;
+                       }
+
+                       *o++ = '\r';
+                       *o++ = '\n';
+
+                       /* Remaining bytes */
+                       while (shift >= 16) {
+                               *o++ = b64_enc[(n >> shift) & 0x3F];
+                               shift -= 6;
+                               cols ++;
+                       }
+               }
+
+               in += 6;
+               inlen -= 6;
+       }
+
+       if (str_len > 0 && cols >= str_len) {
+               *o++ = '\r';
+               *o++ = '\n';
+               cols = 0;
+       }
+       /* Trailing bytes */
+       if (inlen > 2) {
+               for (i = 0; i < inlen - 2; i += 3) {
+                       t1 = in[i]; t2 = in[i+1]; t3 = in[i+2];
+                       *o++ = b64_enc[t1];
+                       if (str_len > 0 && ++cols >= str_len) {
+                               *o++ = '\r';
+                               *o++ = '\n';
+                               cols = 0;
+                       }
+                       *o++ = b64_enc[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
+                       if (str_len > 0 && ++cols >= str_len) {
+                               *o++ = '\r';
+                               *o++ = '\n';
+                               cols = 0;
+                       }
+                       *o++ = b64_enc[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];
+                       if (str_len > 0 && ++cols >= str_len) {
+                               *o++ = '\r';
+                               *o++ = '\n';
+                               cols = 0;
+                       }
+                       *o++ = b64_enc[t3];
+                       if (str_len > 0 && ++cols >= str_len) {
+                               *o++ = '\r';
+                               *o++ = '\n';
+                               cols = 0;
+                       }
+               }
+       }
+
+       /* Padding + remaining data (0 - 2 bytes) */
+       switch (inlen - i) {
+       case 0:
+               break;
+       case 1:
+               t1 = in[i];
+               *o++ = b64_enc[t1];
+               if (str_len > 0 && ++cols >= str_len) {
+                       *o++ = '\r';
+                       *o++ = '\n';
+                       cols = 0;
+               }
+               *o++ = b64_enc[(t1 & 0x03) << 4];
+               if (str_len > 0 && ++cols >= str_len) {
+                       *o++ = '\r';
+                       *o++ = '\n';
+                       cols = 0;
+               }
+               *o++ = '=';
+               if (str_len > 0 && ++cols >= str_len) {
+                       *o++ = '\r';
+                       *o++ = '\n';
+                       cols = 0;
+               }
+               *o++ = '=';
+               if (str_len > 0 && ++cols >= str_len) {
+                       *o++ = '\r';
+                       *o++ = '\n';
+                       cols = 0;
+               }
+               break;
+       default: /* case 2 */
+               t1 = in[i]; t2 = in[i+1];
+               *o++ = b64_enc[t1];
+               if (str_len > 0 && ++cols >= str_len) {
+                       *o++ = '\r';
+                       *o++ = '\n';
+                       cols = 0;
+               }
+               *o++ = b64_enc[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
+               if (str_len > 0 && ++cols >= str_len) {
+                       *o++ = '\r';
+                       *o++ = '\n';
+                       cols = 0;
+               }
+               *o++ = b64_enc[(t2 & 0x0F) << 2];
+               if (str_len > 0 && ++cols >= str_len) {
+                       *o++ = '\r';
+                       *o++ = '\n';
+                       cols = 0;
+               }
+               *o++ = '=';
+       }
+
+       if (str_len > 0 && ++cols >= str_len) {
+               *o++ = '\r';
+               *o++ = '\n';
+               cols = 0;
+       }
+
+       *o = '\0';
+
+       if (outlen != NULL) {
+               *outlen = o - out;
+       }
+
+       return out;
+}
+
 gdouble
 rspamd_get_ticks (void)
 {
index af2e00065b10983d6a4995a22f8ac6ed0c9129f0..c4170881cad53cf6ecdfb3e28cd41b18de884c73 100644 (file)
@@ -428,6 +428,16 @@ gchar * rspamd_encode_base32 (const guchar *in, gsize inlen);
  */
 guchar* rspamd_decode_base32 (const gchar *in, gsize inlen, gsize *outlen);
 
+/**
+ * Encode string using base64 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_base64 (const guchar *in, gsize inlen, gint str_len,
+               gsize *outlen);
+
 /**
  * Portably return the current clock ticks as seconds
  * @return