]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] Base64 decode
authorKrzysztof Piotr Oledzki <ole@ans.pl>
Fri, 29 Jan 2010 12:36:23 +0000 (13:36 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 31 Jan 2010 18:14:07 +0000 (19:14 +0100)
Implement Base64 decoding with a reverse table.

The function accepts and decodes classic base64 strings, which
can be composed from many streams as long each one is properly
padded, for example: SGVsbG8=IEhBUHJveHk=IQ==

include/common/base64.h
src/base64.c

index bd77c687a23230e4bfa890078876d2c0dccd81b0..e668001f40f770380cff7458042fada572c70fc7 100644 (file)
@@ -17,6 +17,8 @@
 #include <common/config.h>
 
 int a2base64(char *in, int ilen, char *out, int olen);
+int base64dec(const char *in, size_t ilen, char *out, size_t olen);
+
 extern const char base64tab[];
 
 #endif /* _COMMON_BASE64_H */
index e0126225e7c02c399432755272a29a41c1734137..ea244a25f72c1b5cae2e8efb055971b6f449b5de 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * Ascii to Base64 conversion as described in RFC1421.
+ * ASCII <-> Base64 conversion as described in RFC1421.
  *
  * Copyright 2006-2008 Willy Tarreau <w@1wt.eu>
+ * Copyright 2009-2010 Krzysztof Piotr Oledzki <ole@ans.pl>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  *
  */
 
+#include <stdlib.h>
+#include <string.h>
+
 #include <common/base64.h>
 #include <common/config.h>
 
+#define B64BASE        '#'             /* arbitrary chosen base value */
+#define B64CMIN        '+'
+#define B64CMAX        'z'
+#define B64PADV        64              /* Base64 chosen special pad value */
+
 const char base64tab[65]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+const char base64rev[]="b###cXYZ[\\]^_`a###d###$%&'()*+,-./0123456789:;<=######>?@ABCDEFGHIJKLMNOPQRSTUVW";
 
 /* Encodes <ilen> bytes from <in> to <out> for at most <olen> chars (including
  * the trailing zero). Returns the number of bytes written. No check is made
@@ -57,3 +67,71 @@ int a2base64(char *in, int ilen, char *out, int olen)
 
        return convlen;
 }
+
+/* Decodes <ilen> bytes from <in> to <out> for at most <olen> chars.
+ * Returns the number of bytes converted. No check is made for
+ * <in> or <out> to be NULL. Returns -1 if <in> is invalid or ilen
+ * has wrong size, -2 if <olen> is too short.
+ * 1 to 3 output bytes are produced for 4 input bytes.
+ */
+int base64dec(const char *in, size_t ilen, char *out, size_t olen) {
+
+       unsigned char t[4];
+       signed char b;
+       int convlen = 0, i = 0, pad = 0;
+
+       if (ilen % 4)
+               return -1;
+
+       if (olen < ilen / 4 * 3)
+               return -2;
+
+       while (ilen) {
+
+               /* if (*p < B64CMIN || *p > B64CMAX) */
+               b = (signed char)*in - B64CMIN;
+               if ((unsigned char)b > (B64CMAX-B64CMIN))
+                       return -1;
+
+               b = base64rev[b] - B64BASE - 1;
+
+               /* b == -1: invalid character */
+               if (b < 0)
+                       return -1;
+
+               /* padding has to be continous */
+               if (pad && b != B64PADV)
+                       return -1;
+
+               /* valid padding: "XX==" or "XXX=", but never "X===" or "====" */
+               if (pad && i < 2)
+                       return -1;
+
+               if (b == B64PADV)
+                       pad++;
+
+               t[i++] = b;
+
+               if (i == 4) {
+                       /*
+                        * WARNING: we allow to write little more data than we
+                        * should, but the checks from the beginning of the
+                        * functions guarantee that we can safely do that.
+                        */
+
+                       /* xx000000 xx001111 xx111122 xx222222 */
+                       out[convlen]   = ((t[0] << 2) + (t[1] >> 4));
+                       out[convlen+1] = ((t[1] << 4) + (t[2] >> 2));
+                       out[convlen+2] = ((t[2] << 6) + (t[3] >> 0));
+
+                       convlen += 3-pad;
+
+                       pad = i = 0;
+               }
+
+               in++;
+               ilen--;
+       }
+
+       return convlen;
+}