00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00032
00033 #ifndef GROOVX_RUTZ_BASE64_CC_UTC20050626084020_DEFINED
00034 #define GROOVX_RUTZ_BASE64_CC_UTC20050626084020_DEFINED
00035
00036 #include "base64.h"
00037
00038 #include "rutz/bytearray.h"
00039 #include "rutz/error.h"
00040 #include "rutz/mappedfile.h"
00041
00042 #include <cctype>
00043
00044 #include "rutz/trace.h"
00045 #include "rutz/debug.h"
00046 GVX_DBG_REGISTER
00047
00048 namespace
00049 {
00050 const char base64_chars[65] =
00051 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00052 "abcdefghijklmnopqrstuvwxyz"
00053 "0123456789+/";
00054
00055 const int base64_to_num2[256] =
00056 {
00057 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00058 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00059 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
00060 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,
00061 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
00062 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
00063 -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
00064 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,
00065 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00066 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00067 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00068 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00069 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00070 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00071 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00072 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00073 };
00074 }
00075
00076 void rutz::base64_encode(const unsigned char* src,
00077 unsigned int src_len,
00078 rutz::byte_array& dst,
00079 unsigned int line_width)
00080 {
00081 GVX_TRACE("rutz::base64_encode");
00082 dst.vec.resize(0);
00083
00084 if (src_len == 0) return;
00085
00086 unsigned int reserve_size = ((src_len+2)/3) * 4;
00087 if (line_width > 0)
00088 reserve_size += 2*(src_len/line_width + 2);
00089 dst.vec.reserve(reserve_size);
00090 int i = 0;
00091 unsigned int c = 0;
00092 unsigned char dec3[3];
00093 unsigned char enc4[4];
00094
00095 if (line_width > 0)
00096 {
00097 dst.vec.push_back('\n');
00098 dst.vec.push_back('\t');
00099 }
00100
00101 const unsigned char* const stop = src + src_len;
00102
00103 for (const unsigned char* p = src; p < stop; ++p)
00104 {
00105 dec3[i++] = *p;
00106
00107 if (i == 3)
00108 {
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 enc4[0] = (dec3[0] & 0xfc) >> 2;
00119 enc4[1] = ((dec3[0] & 0x03) << 4) + ((dec3[1] & 0xf0) >> 4);
00120 enc4[2] = ((dec3[1] & 0x0f) << 2) + ((dec3[2] & 0xc0) >> 6);
00121 enc4[3] = dec3[2] & 0x3f;
00122
00123 for (i = 0; i < 4; ++i)
00124 dst.vec.push_back(base64_chars[enc4[i]]);
00125
00126 i = 0;
00127
00128 c += 4;
00129
00130 if (line_width > 0 && c > line_width)
00131 {
00132 c = 0;
00133 dst.vec.push_back('\n');
00134 dst.vec.push_back('\t');
00135 }
00136 }
00137 }
00138
00139 GVX_ASSERT(i >= 0 && i <= 2);
00140
00141 if (i == 1)
00142 {
00143 enc4[0] = (dec3[0] & 0xfc) >> 2;
00144 enc4[1] = (dec3[0] & 0x03) << 4;
00145
00146 dst.vec.push_back(base64_chars[enc4[0]]);
00147 dst.vec.push_back(base64_chars[enc4[1]]);
00148 dst.vec.push_back('=');
00149 dst.vec.push_back('=');
00150 }
00151 else if (i == 2)
00152 {
00153 enc4[0] = (dec3[0] & 0xfc) >> 2;
00154 enc4[1] = ((dec3[0] & 0x03) << 4) + ((dec3[1] & 0xf0) >> 4);
00155 enc4[2] = (dec3[1] & 0x0f) << 2;
00156
00157 dst.vec.push_back(base64_chars[enc4[0]]);
00158 dst.vec.push_back(base64_chars[enc4[1]]);
00159 dst.vec.push_back(base64_chars[enc4[2]]);
00160 dst.vec.push_back('=');
00161 }
00162 }
00163
00164 void rutz::base64_encode_string(const char* str,
00165 rutz::byte_array& dst,
00166 unsigned int line_width)
00167 {
00168 rutz::base64_encode(reinterpret_cast<const unsigned char*>(str),
00169 strlen(str),
00170 dst,
00171 line_width);
00172 }
00173
00174 void rutz::base64_encode_file(const char* filename,
00175 rutz::byte_array& dst,
00176 unsigned int line_width)
00177 {
00178 rutz::mapped_infile m(filename);
00179 rutz::base64_encode(static_cast<const unsigned char*>(m.memory()),
00180 m.length(),
00181 dst,
00182 line_width);
00183 }
00184
00185 void rutz::base64_decode(const char* src,
00186 unsigned int in_len,
00187 rutz::byte_array& dst)
00188 {
00189 GVX_TRACE("rutz::base64_decode");
00190 dst.vec.resize(0);
00191 dst.vec.reserve((in_len / 4) * 3);
00192
00193 int i = 0;
00194 unsigned char enc4[4];
00195 unsigned char dec3[3];
00196
00197 const char* const stop = src+in_len;
00198
00199 for (const char* p = src; p < stop; ++p)
00200 {
00201 int n = base64_to_num2[static_cast<unsigned char>(*p)];
00202 if (n >= 0)
00203 {
00204 enc4[i++] = n;
00205
00206 if (i == 4)
00207 {
00208 dec3[0] = (enc4[0] << 2) + ((enc4[1] & 0x30) >> 4);
00209 dec3[1] = ((enc4[1] & 0xf) << 4) + ((enc4[2] & 0x3c) >> 2);
00210 dec3[2] = ((enc4[2] & 0x3) << 6) + enc4[3];
00211
00212 for (i = 0; i < 3; ++i)
00213 dst.vec.push_back(dec3[i]);
00214
00215 i = 0;
00216 }
00217 }
00218
00219 else if (*p == '=')
00220 break;
00221
00222 else if (isspace(*p))
00223 continue;
00224
00225 else
00226 throw rutz::error("invalid character within base64 string",
00227 SRC_POS);
00228 }
00229
00230 GVX_ASSERT(i != 1);
00231
00232
00233 if (i == 2)
00234 {
00235
00236
00237
00238 dec3[0] = (enc4[0] << 2) + ((enc4[1] & 0x30) >> 4);
00239
00240 dst.vec.push_back(dec3[0]);
00241 }
00242
00243 else if (i == 3)
00244 {
00245
00246
00247 dec3[0] = (enc4[0] << 2) + ((enc4[1] & 0x30) >> 4);
00248 dec3[1] = ((enc4[1] & 0xf) << 4) + ((enc4[2] & 0x3c) >> 2);
00249
00250 dst.vec.push_back(dec3[0]);
00251 dst.vec.push_back(dec3[1]);
00252 }
00253 }
00254
00255 void rutz::base64_decode(const rutz::byte_array& src,
00256 rutz::byte_array& dst)
00257 {
00258 base64_decode(reinterpret_cast<const char*>(&src.vec[0]),
00259 src.vec.size(),
00260 dst);
00261 }
00262
00263 static const char __attribute__((used)) vcid_groovx_rutz_base64_cc_utc20050626084020[] = "$Id: base64.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00264 #endif // !GROOVX_RUTZ_BASE64_CC_UTC20050626084020_DEFINED