/** * base64.h: Base64 encoding / decoding algorithm. * * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team * Rights to this code are as documented in doc/pod/gplicense.pod. * * $Id: base64.h,v 1.7 2007/09/22 14:27:26 pippijn dead $ */ #ifndef BASE64_H #define BASE64_H #include #include namespace base64 { class encoder { enum step { step_a, step_b, step_c }; struct state { enum step step; char retval; int cnt; }; static size_t enc_block (char const * const txt, size_t ilen, char *code, state *s); static size_t enc_blockend (char *code, state *s); static size_t const CHARS_PER_LINE = 72; static char enc_value (char val) { static char const * const enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; if (val > 63) return '='; return enc[(size_t) val]; } state m_state; size_t m_bufsize; size_t enc_end (char *otxt) { return enc_blockend (otxt, &m_state); } public: encoder (size_t bufsize = 4096) : m_bufsize (bufsize) { } size_t encode (char val) { return enc_value (val); } size_t encode (char const * const code, size_t const ilen, char *otxt) { return enc_block (code, ilen, otxt, &m_state); } bool encode (char const * const code, size_t const ilen, char **otxt) { size_t olen = 1 + (((ilen + 2) / 3) * 4); if (ilen > olen) { *otxt = NULL; return 0; } *otxt = new char[olen]; if (*otxt) encode (code, ilen, *otxt); return olen - 1; } }; class decoder { enum step { step_a, step_b, step_c, step_d }; struct state { enum step step; char c; }; static size_t dec_block (char const * const code, size_t const ilen, char *otxt, state *s); static size_t dec_value (char val) { static char const dec[] = { 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; static char const decsize = sizeof (dec); val -= 43; if (val < 0 || val > decsize) return ULONG_MAX; return dec[(size_t) val]; } state m_state; size_t m_bufsize; public: decoder (size_t bufsize = 4096) : m_bufsize (bufsize) { } size_t decode (char val) { return dec_value (val); } size_t decode (char const * const code, size_t const ilen, char *otxt) { return dec_block (code, ilen, otxt, &m_state); } bool decode (char const * const code, size_t const ilen, char **otxt, size_t *olen) { size_t reqlen = 3 * (ilen / 4) + 3; *otxt = new char[reqlen]; if (!*otxt) return false; if (!decode (code, ilen, *otxt)) { delete[] *otxt; *otxt = NULL; return false; } (*otxt)[reqlen] = '\0'; if (olen) *olen = reqlen; return true; } }; } // namespace base64 #endif // BASE64_H