00001
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
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
00059
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
00071
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 }