| |
| //********************************************************************* |
| //* Base64 - a simple base64 encoder and decoder. |
| //* |
| //* Copyright (c) 1999, Bob Withers - bwit@pobox.com |
| //* |
| //* This code may be freely used for any purpose, either personal |
| //* or commercial, provided the authors copyright notice remains |
| //* intact. |
| //* |
| //* Enhancements by Stanley Yamane: |
| //* o reverse lookup table for the decode function |
| //* o reserve string buffer space in advance |
| //* |
| //********************************************************************* |
| |
| #include "talk/base/base64.h" |
| |
| using std::string; |
| |
| namespace talk_base { |
| |
| static const char fillchar = '='; |
| static const string::size_type np = string::npos; |
| |
| const string Base64::Base64Table( |
| // 0000000000111111111122222222223333333333444444444455555555556666 |
| // 0123456789012345678901234567890123456789012345678901234567890123 |
| "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); |
| |
| // Decode Table gives the index of any valid base64 character in the |
| // Base64 table |
| // 65 == A, 97 == a, 48 == 0, 43 == +, 47 == / |
| |
| const string::size_type Base64::DecodeTable[] = { |
| // 0 1 2 3 4 5 6 7 8 9 |
| np,np,np,np,np,np,np,np,np,np, // 0 - 9 |
| np,np,np,np,np,np,np,np,np,np, //10 -19 |
| np,np,np,np,np,np,np,np,np,np, //20 -29 |
| np,np,np,np,np,np,np,np,np,np, //30 -39 |
| np,np,np,62,np,np,np,63,52,53, //40 -49 |
| 54,55,56,57,58,59,60,61,np,np, //50 -59 |
| np,np,np,np,np, 0, 1, 2, 3, 4, //60 -69 |
| 5, 6, 7, 8, 9,10,11,12,13,14, //70 -79 |
| 15,16,17,18,19,20,21,22,23,24, //80 -89 |
| 25,np,np,np,np,np,np,26,27,28, //90 -99 |
| 29,30,31,32,33,34,35,36,37,38, //100 -109 |
| 39,40,41,42,43,44,45,46,47,48, //110 -119 |
| 49,50,51,np,np,np,np,np,np,np, //120 -129 |
| np,np,np,np,np,np,np,np,np,np, //130 -139 |
| np,np,np,np,np,np,np,np,np,np, //140 -149 |
| np,np,np,np,np,np,np,np,np,np, //150 -159 |
| np,np,np,np,np,np,np,np,np,np, //160 -169 |
| np,np,np,np,np,np,np,np,np,np, //170 -179 |
| np,np,np,np,np,np,np,np,np,np, //180 -189 |
| np,np,np,np,np,np,np,np,np,np, //190 -199 |
| np,np,np,np,np,np,np,np,np,np, //200 -209 |
| np,np,np,np,np,np,np,np,np,np, //210 -219 |
| np,np,np,np,np,np,np,np,np,np, //220 -229 |
| np,np,np,np,np,np,np,np,np,np, //230 -239 |
| np,np,np,np,np,np,np,np,np,np, //240 -249 |
| np,np,np,np,np,np //250 -256 |
| }; |
| |
| string Base64::encodeFromArray(const char * data, size_t len) { |
| size_t i; |
| char c; |
| string ret; |
| |
| ret.reserve(len * 2); |
| |
| for (i = 0; i < len; ++i) { |
| c = (data[i] >> 2) & 0x3f; |
| ret.append(1, Base64Table[c]); |
| c = (data[i] << 4) & 0x3f; |
| if (++i < len) { |
| c |= (data[i] >> 4) & 0x0f; |
| } |
| |
| ret.append(1, Base64Table[c]); |
| if (i < len) { |
| c = (data[i] << 2) & 0x3f; |
| if (++i < len) { |
| c |= (data[i] >> 6) & 0x03; |
| } |
| ret.append(1, Base64Table[c]); |
| } else { |
| ++i; |
| ret.append(1, fillchar); |
| } |
| |
| if (i < len) { |
| c = data[i] & 0x3f; |
| ret.append(1, Base64Table[c]); |
| } else { |
| ret.append(1, fillchar); |
| } |
| } |
| |
| return(ret); |
| } |
| |
| string Base64::encode(const string& data) { |
| string::size_type i; |
| char c; |
| string::size_type len = data.length(); |
| string ret; |
| |
| ret.reserve(len * 2); |
| |
| for (i = 0; i < len; ++i) { |
| c = (data[i] >> 2) & 0x3f; |
| ret.append(1, Base64Table[c]); |
| c = (data[i] << 4) & 0x3f; |
| if (++i < len) { |
| c |= (data[i] >> 4) & 0x0f; |
| } |
| |
| ret.append(1, Base64Table[c]); |
| if (i < len) { |
| c = (data[i] << 2) & 0x3f; |
| if (++i < len) { |
| c |= (data[i] >> 6) & 0x03; |
| } |
| |
| ret.append(1, Base64Table[c]); |
| } else { |
| ++i; |
| ret.append(1, fillchar); |
| } |
| |
| if (i < len) { |
| c = data[i] & 0x3f; |
| ret.append(1, Base64Table[c]); |
| } else { |
| ret.append(1, fillchar); |
| } |
| } |
| |
| return(ret); |
| } |
| |
| string Base64::decode(const string& data) { |
| string::size_type i; |
| char c; |
| char c1; |
| string::size_type len = data.length(); |
| string ret; |
| |
| ret.reserve(len); |
| |
| for (i = 0; i < len; ++i) { |
| do { |
| c = static_cast<char>(DecodeTable[static_cast<unsigned char>(data[i])]); |
| } while (c == np && ++i < len); |
| |
| ++i; |
| |
| do { |
| c1 = static_cast<char>(DecodeTable[static_cast<unsigned char>(data[i])]); |
| } while (c == np && ++i < len); |
| |
| c = (c << 2) | ((c1 >> 4) & 0x3); |
| ret.append(1, c); |
| if (++i < len) { |
| c = data[i]; |
| if (fillchar == c) { |
| break; |
| } |
| |
| do { |
| c = static_cast<char>(DecodeTable[static_cast<unsigned char>(data[i])]); |
| } while (c == np && ++i < len); |
| c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf); |
| ret.append(1, c1); |
| } |
| |
| if (++i < len) { |
| c1 = data[i]; |
| if (fillchar == c1) { |
| break; |
| } |
| |
| do { |
| c1 = static_cast<char>(DecodeTable[static_cast<unsigned char>(data[i])]); |
| } while (c == np && ++i < len); |
| |
| c = ((c << 6) & 0xc0) | c1; |
| ret.append(1, c); |
| } |
| } |
| |
| return(ret); |
| } |
| |
| } // namespace talk_base |