[MINOR] Base64 decode

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==
This commit is contained in:
Krzysztof Piotr Oledzki 2010-01-29 13:36:23 +01:00 committed by Willy Tarreau
parent 4a3323b83d
commit fccbdc8421
2 changed files with 81 additions and 1 deletions

View File

@ -17,6 +17,8 @@
#include <common/config.h> #include <common/config.h>
int a2base64(char *in, int ilen, char *out, int olen); 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[]; extern const char base64tab[];
#endif /* _COMMON_BASE64_H */ #endif /* _COMMON_BASE64_H */

View 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 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 * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -10,10 +11,19 @@
* *
*/ */
#include <stdlib.h>
#include <string.h>
#include <common/base64.h> #include <common/base64.h>
#include <common/config.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 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 /* 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 * 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; 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;
}