Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

Base64.cc

Go to the documentation of this file.
00001 // $Id: Base64.cc,v 1.2 2004/09/08 20:15:18 vern Exp $
00002 
00003 #include "config.h"
00004 #include "Base64.h"
00005 
00006 static int base64_table[256];
00007 
00008 static void init_base64_table()
00009         {
00010         static int table_initialized = 0;
00011 
00012         if ( ++table_initialized > 1 )
00013                 return;
00014 
00015         int i;
00016         for ( i = 0; i < 256; ++i )
00017                 base64_table[i] = -1;
00018 
00019         for ( i = 0; i < 26; ++i )
00020                 {
00021                 base64_table['A' + i] = i;
00022                 base64_table['a' + i] = i + 26;
00023                 }
00024 
00025         for ( i = 0; i < 10; ++i )
00026                 base64_table['0' + i] = i + 52;
00027 
00028         // Casts to avoid compiler warnings.
00029         base64_table[int('+')] = 62;
00030         base64_table[int('/')] = 63;
00031         base64_table[int('=')] = 0;
00032         }
00033 
00034 Base64Decoder::Base64Decoder(Connection* arg_conn)
00035         {
00036         init_base64_table();
00037         base64_group_next = 0;
00038         base64_padding = base64_after_padding = 0;
00039         errored = 0;
00040         conn = arg_conn;
00041         }
00042 
00043 int Base64Decoder::Decode(int len, const char* data, int* pblen, char** pbuf)
00044         {
00045         int blen;
00046         char* buf;
00047 
00048         if ( ! pbuf )
00049                 internal_error("nil pointer to decoding result buffer");
00050 
00051         if ( *pbuf )
00052                 {
00053                 buf = *pbuf;
00054                 blen = *pblen;
00055                 }
00056         else
00057                 {
00058                 // Estimate the maximal number of 3-byte groups needed,
00059                 // plus 1 byte for the optional ending NUL.
00060                 blen = int((len + base64_group_next + 3) / 4) * 3 + 1;
00061                 *pbuf = buf = new char[blen];
00062                 }
00063 
00064         int dlen = 0;
00065 
00066         while ( 1 )
00067                 {
00068                 if ( base64_group_next == 4 )
00069                         {
00070                         // For every group of 4 6-bit numbers,
00071                         // write the decoded 3 bytes to the buffer.
00072                         if ( base64_after_padding )
00073                                 {
00074                                 if ( ++errored == 1 )
00075                                         IllegalEncoding("extra base64 groups after '=' padding are ignored");
00076                                 base64_group_next = 0;
00077                                 continue;
00078                                 }
00079 
00080                         int num_octets = 3 - base64_padding;
00081 
00082                         if ( buf + num_octets > *pbuf + blen )
00083                                 break;
00084 
00085                         uint32 bit32 =
00086                                 ((base64_group[0] & 0x3f) << 18) |
00087                                 ((base64_group[1] & 0x3f) << 12) |
00088                                 ((base64_group[2] & 0x3f) << 6)  |
00089                                 ((base64_group[3] & 0x3f));
00090 
00091                         if ( --num_octets >= 0 )
00092                                 *buf++ = char((bit32 >> 16) & 0xff);
00093 
00094                         if ( --num_octets >= 0 )
00095                                 *buf++ = char((bit32 >> 8) & 0xff);
00096 
00097                         if ( --num_octets >= 0 )
00098                                 *buf++ = char((bit32) & 0xff);
00099 
00100                         if ( base64_padding > 0 )
00101                                 base64_after_padding = 1;
00102 
00103                         base64_group_next = 0;
00104                         base64_padding = 0;
00105                         }
00106 
00107                 if ( dlen >= len )
00108                         break;
00109 
00110                 if ( data[dlen] == '=' )
00111                         ++base64_padding;
00112 
00113                 int k = base64_table[(unsigned char) data[dlen]];
00114                 if ( k >= 0 )
00115                         base64_group[base64_group_next++] = k;
00116                 else
00117                         {
00118                         if ( ++errored == 1 )
00119                                 IllegalEncoding(fmt("character %d ignored by Base64 decoding", (int) (data[dlen])));
00120                         }
00121 
00122                 ++dlen;
00123                 }
00124 
00125         *pblen = buf - *pbuf;
00126         return dlen;
00127         }
00128 
00129 int Base64Decoder::Done(int* pblen, char** pbuf)
00130         {
00131         const char* padding = "===";
00132 
00133         if ( base64_group_next != 0 )
00134                 {
00135                 if ( base64_group_next < 4 )
00136                         IllegalEncoding(fmt("incomplete base64 group, padding with %d bits of 0", (4-base64_group_next) * 6));
00137                 Decode(4 - base64_group_next, padding, pblen, pbuf);
00138                 return -1;
00139                 }
00140 
00141         if ( pblen )
00142                 *pblen = 0;
00143 
00144         return 0;
00145         }
00146 
00147 BroString* decode_base64(BroString* s)
00148         {
00149         int rlen;
00150         char* rbuf = 0;
00151         int rlen2;
00152         char* rbuf2 = 0;
00153 
00154         Base64Decoder dec(0);
00155         if ( dec.Decode(s->Len(), (const char*) s->Bytes(), &rlen, &rbuf) == -1 )
00156                 goto err;
00157 
00158         if ( dec.Done(&rlen2, &rbuf2) < 0 )
00159                 goto err;
00160 
00161         rbuf[rlen] = '\0';
00162         return new BroString(1, (u_char*) rbuf, rlen);
00163 
00164 err:
00165         delete [] rbuf;
00166         delete [] rbuf2;
00167         return 0;
00168         }

Generated on Wed Sep 14 02:55:57 2005 for bro_docs by doxygen 1.3.5