1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 2 * 3 * This library is open source and may be redistributed and/or modified under 4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 5 * (at your option) any later version. The full license is in LICENSE file 6 * included with this distribution, and on the openscenegraph.org website. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * OpenSceneGraph Public License for more details. 12 */ 13 14 /* This file is derived from the libb64 project which itself was released to public domain. 15 * For details, see http://sourceforge.net/projects/libb64. Original code by Chris Venter 16 * c++ wrapper for a base64 encoding and decoding algorithm 17 */ 18 19 #include <osgDB/ConvertBase64> 20 21 #include <sstream> 22 #include <string.h> 23 24 namespace osgDB 25 { 26 NullCompressor()27 const int CHARS_PER_LINE = 72; 28 compress(std::ostream & fout,const std::string & src)29 int base64_decode_value(char value_in) 30 { 31 static const char decoding[] = {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}; 32 static const char decoding_size = sizeof(decoding); 33 value_in -= 43; 34 if (value_in < 0 || value_in > decoding_size) return -1; 35 return decoding[(int)value_in]; 36 } decompress(std::istream & fin,std::string & target)37 38 void base64_init_decodestate(base64_decodestate* state_in) 39 { 40 state_in->step = step_a; 41 state_in->plainchar = 0; 42 } 43 44 int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in) 45 { 46 const char* codechar = code_in; 47 char* plainchar = plaintext_out; 48 char fragment; 49 50 *plainchar = state_in->plainchar; 51 52 switch (state_in->step) 53 { 54 while (1) 55 { 56 case step_a: 57 do { 58 if (codechar == code_in+length_in) 59 { 60 state_in->step = step_a; ZLibCompressor()61 state_in->plainchar = *plainchar; 62 return plainchar - plaintext_out; compress(std::ostream & fout,const std::string & src)63 } 64 fragment = (char)base64_decode_value(*codechar++); 65 } while (fragment < 0); 66 *plainchar = (fragment & 0x03f) << 2; 67 case step_b: 68 do { 69 if (codechar == code_in+length_in) 70 { 71 state_in->step = step_b; 72 state_in->plainchar = *plainchar; 73 return plainchar - plaintext_out; 74 } 75 fragment = (char)base64_decode_value(*codechar++); 76 } while (fragment < 0); 77 *plainchar++ |= (fragment & 0x030) >> 4; 78 *plainchar = (fragment & 0x00f) << 4; 79 case step_c: 80 do { 81 if (codechar == code_in+length_in) 82 { 83 state_in->step = step_c; 84 state_in->plainchar = *plainchar; 85 return plainchar - plaintext_out; 86 } 87 fragment = (char)base64_decode_value(*codechar++); 88 } while (fragment < 0); 89 *plainchar++ |= (fragment & 0x03c) >> 2; 90 *plainchar = (fragment & 0x003) << 6; 91 case step_d: 92 do { 93 if (codechar == code_in+length_in) 94 { 95 state_in->step = step_d; 96 state_in->plainchar = *plainchar; 97 return plainchar - plaintext_out; 98 } 99 fragment = (char)base64_decode_value(*codechar++); 100 } while (fragment < 0); 101 *plainchar++ |= (fragment & 0x03f); 102 } 103 } 104 /* control should not reach here */ 105 return plainchar - plaintext_out; 106 } 107 108 void base64_init_encodestate(base64_encodestate* state_in) 109 { 110 state_in->step = step_A; 111 state_in->result = 0; 112 state_in->stepcount = 0; 113 } 114 decompress(std::istream & fin,std::string & target)115 char base64_encode_value(char value_in) 116 { 117 static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 118 if (value_in > 63) return '='; 119 return encoding[(int)value_in]; 120 } 121 122 int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) 123 { 124 const char* plainchar = plaintext_in; 125 const char* const plaintextend = plaintext_in + length_in; 126 char* codechar = code_out; 127 char result; 128 char fragment; 129 130 result = state_in->result; 131 132 switch (state_in->step) 133 { 134 while (1) 135 { 136 case step_A: 137 if (plainchar == plaintextend) 138 { 139 state_in->result = result; 140 state_in->step = step_A; 141 return codechar - code_out; 142 } 143 fragment = *plainchar++; 144 result = (fragment & 0x0fc) >> 2; 145 *codechar++ = base64_encode_value(result); 146 result = (fragment & 0x003) << 4; 147 case step_B: 148 if (plainchar == plaintextend) 149 { 150 state_in->result = result; 151 state_in->step = step_B; 152 return codechar - code_out; 153 } 154 fragment = *plainchar++; 155 result |= (fragment & 0x0f0) >> 4; 156 *codechar++ = base64_encode_value(result); 157 result = (fragment & 0x00f) << 2; 158 case step_C: 159 if (plainchar == plaintextend) 160 { 161 state_in->result = result; 162 state_in->step = step_C; 163 return codechar - code_out; 164 } 165 fragment = *plainchar++; 166 result |= (fragment & 0x0c0) >> 6; 167 *codechar++ = base64_encode_value(result); 168 result = (fragment & 0x03f) >> 0; 169 *codechar++ = base64_encode_value(result); 170 171 ++(state_in->stepcount); 172 if (state_in->stepcount == CHARS_PER_LINE/4) 173 { 174 *codechar++ = '\n'; 175 state_in->stepcount = 0; 176 } 177 } 178 } 179 /* control should not reach here */ 180 return codechar - code_out; 181 } 182 183 int base64_encode_blockend(char* code_out, base64_encodestate* state_in) 184 { 185 char* codechar = code_out; 186 187 switch (state_in->step) 188 { 189 case step_B: 190 *codechar++ = base64_encode_value(state_in->result); 191 *codechar++ = '='; 192 *codechar++ = '='; 193 break; 194 case step_C: 195 *codechar++ = base64_encode_value(state_in->result); 196 *codechar++ = '='; 197 break; 198 case step_A: 199 break; 200 } 201 *codechar++ = '\n'; 202 203 return codechar - code_out; 204 } 205 206 int Base64encoder::encode(char value_in) 207 { 208 return base64_encode_value(value_in); 209 } 210 211 int Base64encoder::encode(const char* code_in, const int length_in, char* plaintext_out) 212 { 213 return base64_encode_block(code_in, length_in, plaintext_out, &_state); 214 } 215 216 int Base64encoder::encode_end(char* plaintext_out) 217 { 218 return base64_encode_blockend(plaintext_out, &_state); 219 } 220 221 void Base64encoder::encode(std::istream& istream_in, std::ostream& ostream_in) 222 { 223 base64_init_encodestate(&_state); 224 225 const int N = _buffersize; 226 char* plaintext = new char[N]; 227 char* code = new char[2*N]; 228 int plainlength; 229 int codelength; 230 231 do 232 { 233 istream_in.read(plaintext, N); 234 plainlength = istream_in.gcount(); 235 236 codelength = encode(plaintext, plainlength, code); 237 ostream_in.write(code, codelength); 238 } 239 while (istream_in.good() && plainlength > 0); 240 241 codelength = encode_end(code); 242 ostream_in.write(code, codelength); 243 244 base64_init_encodestate(&_state); 245 246 delete [] code; 247 delete [] plaintext; 248 } 249 250 void Base64encoder::encode(const char* chars_in, int length_in, std::string& code_out) 251 { 252 std::stringstream stream_out; 253 { 254 std::stringstream stream_in; 255 { 256 stream_in<<std::string(chars_in, length_in); 257 } 258 stream_in.seekg(0, stream_in.beg); 259 encode(stream_in, stream_out); 260 } 261 stream_out.seekg (0, stream_out.beg); 262 code_out = stream_out.str(); 263 } 264 265 int Base64decoder::decode(char value_in) 266 { 267 return base64_decode_value(value_in); 268 } 269 270 int Base64decoder::decode(const char* code_in, const int length_in, char* plaintext_out) 271 { 272 return base64_decode_block(code_in, length_in, plaintext_out, &_state); 273 } 274 275 void Base64decoder::decode(std::istream& istream_in, std::ostream& ostream_in) 276 { 277 base64_init_decodestate(&_state); 278 279 const int N = _buffersize; 280 char* code = new char[N]; 281 char* plaintext = new char[N]; 282 int codelength; 283 int plainlength; 284 285 do 286 { 287 istream_in.read((char*)code, N); 288 codelength = istream_in.gcount(); 289 plainlength = decode(code, codelength, plaintext); 290 ostream_in.write((const char*)plaintext, plainlength); 291 } 292 while (istream_in.good() && codelength > 0); 293 294 base64_init_decodestate(&_state); 295 296 delete [] code; 297 delete [] plaintext; 298 } 299 300 char* Base64decoder::decode(const std::vector<std::string>& str_in, std::vector<unsigned int>& pos_out) 301 { 302 std::stringstream stream_out; 303 { 304 std::stringstream stream_in; 305 306 pos_out.resize(str_in.size()); 307 308 for (unsigned int i = 0; i < str_in.size(); ++i) 309 { 310 stream_in.clear(); 311 stream_in<<str_in.at(i); 312 stream_in.seekg(0, stream_in.beg); 313 314 decode(stream_in, stream_out); 315 pos_out.at(i) = stream_out.tellp(); 316 } 317 } 318 319 // Allocate memory for use with osg::Image 320 const std::string str = stream_out.str(); 321 char* allocated_out = new char[str.size()]; 322 memcpy(allocated_out, str.c_str(), str.size()); 323 324 return allocated_out; 325 } 326 327 } // namespace osgDB 328