GME
13
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (the "License"); you may not use this file except in compliance with 00007 * the License. You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 // --------------------------------------------------------------------------- 00019 // Includes 00020 // --------------------------------------------------------------------------- 00021 #include <xercesc/util/Base64.hpp> 00022 #include <xercesc/util/XMLString.hpp> 00023 #include <xercesc/util/Janitor.hpp> 00024 #include <xercesc/internal/XMLReader.hpp> 00025 #include <xercesc/framework/MemoryManager.hpp> 00026 00027 XERCES_CPP_NAMESPACE_BEGIN 00028 00029 // --------------------------------------------------------------------------- 00030 // constants 00031 // --------------------------------------------------------------------------- 00032 static const int BASELENGTH = 255; 00033 static const int FOURBYTE = 4; 00034 00035 // --------------------------------------------------------------------------- 00036 // class data member 00037 // --------------------------------------------------------------------------- 00038 00039 // the base64 alphabet according to definition in RFC 2045 00040 const XMLByte Base64::base64Alphabet[] = { 00041 chLatin_A, chLatin_B, chLatin_C, chLatin_D, chLatin_E, 00042 chLatin_F, chLatin_G, chLatin_H, chLatin_I, chLatin_J, 00043 chLatin_K, chLatin_L, chLatin_M, chLatin_N, chLatin_O, 00044 chLatin_P, chLatin_Q, chLatin_R, chLatin_S, chLatin_T, 00045 chLatin_U, chLatin_V, chLatin_W, chLatin_X, chLatin_Y, chLatin_Z, 00046 chLatin_a, chLatin_b, chLatin_c, chLatin_d, chLatin_e, 00047 chLatin_f, chLatin_g, chLatin_h, chLatin_i, chLatin_j, 00048 chLatin_k, chLatin_l, chLatin_m, chLatin_n, chLatin_o, 00049 chLatin_p, chLatin_q, chLatin_r, chLatin_s, chLatin_t, 00050 chLatin_u, chLatin_v, chLatin_w, chLatin_x, chLatin_y, chLatin_z, 00051 chDigit_0, chDigit_1, chDigit_2, chDigit_3, chDigit_4, 00052 chDigit_5, chDigit_6, chDigit_7, chDigit_8, chDigit_9, 00053 chPlus, chForwardSlash, chNull 00054 }; 00055 00056 // This is an inverse table for base64 decoding. So, if 00057 // base64Alphabet[17] = 'R', then base64Inverse['R'] = 17. 00058 // 00059 // For characters not in base64Alphabet then 00060 // base64Inverse[ch] = 0xFF. 00061 const XMLByte Base64::base64Inverse[BASELENGTH] = 00062 { 00063 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00064 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00065 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, 00066 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00067 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 00068 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00069 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 00070 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00071 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00072 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00073 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00074 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00075 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00076 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00077 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 00078 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 00079 }; 00080 00081 const XMLByte Base64::base64Padding = chEqual; 00082 00083 /*** 00084 * 00085 * Memory Management Issue: 00086 * 00087 * . For memory allocated for result returned to caller (external memory), 00088 * the plugged memory manager is used if it is provided, otherwise global 00089 * new used to retain the pre-memory-manager behaviour. 00090 * 00091 * . For memory allocated for temperary buffer (internal memory), 00092 * XMLPlatformUtils::fgMemoryManager is used. 00093 * 00094 */ 00095 00096 static void* getExternalMemory( MemoryManager* const allocator 00097 , XMLSize_t const sizeToAllocate) 00098 { 00099 return allocator ? allocator->allocate(sizeToAllocate) 00100 : ::operator new(sizeToAllocate); 00101 } 00102 00103 /*** 00104 * internal memory is deallocated by janitorArray 00105 */ 00106 static void returnExternalMemory( MemoryManager* const allocator 00107 , void* buffer) 00108 { 00109 allocator ? allocator->deallocate(buffer) 00110 : ::operator delete(buffer); 00111 } 00112 00138 // number of quadruplets per one line ( must be >1 and <19 ) 00139 const unsigned int Base64::quadsPerLine = 15; 00140 00141 XMLByte* Base64::encode(const XMLByte* const inputData 00142 , const XMLSize_t inputLength 00143 , XMLSize_t* outputLength 00144 , MemoryManager* const memMgr) 00145 { 00146 if (!inputData || !outputLength) 00147 return 0; 00148 00149 int quadrupletCount = ( (int)inputLength + 2 ) / 3; 00150 if (quadrupletCount == 0) 00151 return 0; 00152 00153 // number of rows in encoded stream ( including the last one ) 00154 int lineCount = ( quadrupletCount + quadsPerLine-1 ) / quadsPerLine; 00155 00156 // 00157 // convert the triplet(s) to quadruplet(s) 00158 // 00159 XMLByte b1, b2, b3, b4; // base64 binary codes ( 0..63 ) 00160 00161 XMLSize_t inputIndex = 0; 00162 XMLSize_t outputIndex = 0; 00163 XMLByte *encodedData = (XMLByte*) getExternalMemory(memMgr, (quadrupletCount*FOURBYTE+lineCount+1) * sizeof(XMLByte)); 00164 00165 // 00166 // Process all quadruplet(s) except the last 00167 // 00168 int quad = 1; 00169 for (; quad <= quadrupletCount-1; quad++ ) 00170 { 00171 // read triplet from the input stream 00172 split1stOctet( inputData[ inputIndex++ ], b1, b2 ); 00173 split2ndOctet( inputData[ inputIndex++ ], b2, b3 ); 00174 split3rdOctet( inputData[ inputIndex++ ], b3, b4 ); 00175 00176 // write quadruplet to the output stream 00177 encodedData[ outputIndex++ ] = base64Alphabet[ b1 ]; 00178 encodedData[ outputIndex++ ] = base64Alphabet[ b2 ]; 00179 encodedData[ outputIndex++ ] = base64Alphabet[ b3 ]; 00180 encodedData[ outputIndex++ ] = base64Alphabet[ b4 ]; 00181 00182 if (( quad % quadsPerLine ) == 0 ) 00183 encodedData[ outputIndex++ ] = chLF; 00184 } 00185 00186 // 00187 // process the last Quadruplet 00188 // 00189 // first octet is present always, process it 00190 split1stOctet( inputData[ inputIndex++ ], b1, b2 ); 00191 encodedData[ outputIndex++ ] = base64Alphabet[ b1 ]; 00192 00193 if( inputIndex < inputLength ) 00194 { 00195 // second octet is present, process it 00196 split2ndOctet( inputData[ inputIndex++ ], b2, b3 ); 00197 encodedData[ outputIndex++ ] = base64Alphabet[ b2 ]; 00198 00199 if( inputIndex < inputLength ) 00200 { 00201 // third octet present, process it 00202 // no PAD e.g. 3cQl 00203 split3rdOctet( inputData[ inputIndex++ ], b3, b4 ); 00204 encodedData[ outputIndex++ ] = base64Alphabet[ b3 ]; 00205 encodedData[ outputIndex++ ] = base64Alphabet[ b4 ]; 00206 } 00207 else 00208 { 00209 // third octet not present 00210 // one PAD e.g. 3cQ= 00211 encodedData[ outputIndex++ ] = base64Alphabet[ b3 ]; 00212 encodedData[ outputIndex++ ] = base64Padding; 00213 } 00214 } 00215 else 00216 { 00217 // second octet not present 00218 // two PADs e.g. 3c== 00219 encodedData[ outputIndex++ ] = base64Alphabet[ b2 ]; 00220 encodedData[ outputIndex++ ] = base64Padding; 00221 encodedData[ outputIndex++ ] = base64Padding; 00222 } 00223 00224 // write out end of the last line 00225 encodedData[ outputIndex++ ] = chLF; 00226 // write out end of string 00227 encodedData[ outputIndex ] = 0; 00228 00229 *outputLength = outputIndex; 00230 00231 return encodedData; 00232 } 00233 00234 // 00235 // delete the buffer allocated by decode() if 00236 // decoding is successfully done. 00237 // 00238 // In previous version, we use XMLString::strLen(decodedData) 00239 // to get the length, this will fail for test case containing 00240 // consequtive "A", such "AAFF", or "ab56AA56". Instead of 00241 // returning 3/6, we have 0 and 3, indicating that "AA", after 00242 // decoded, is interpreted as <null> by the strLen(). 00243 // 00244 // Since decode() has track of length of the decoded data, we 00245 // will get this length from decode(), instead of strLen(). 00246 // 00247 int Base64::getDataLength(const XMLCh* const inputData 00248 , MemoryManager* const manager 00249 , Conformance conform ) 00250 00251 { 00252 XMLSize_t retLen = 0; 00253 XMLByte* decodedData = decodeToXMLByte(inputData, &retLen, manager, conform); 00254 00255 if ( !decodedData ) 00256 return -1; 00257 else 00258 { 00259 returnExternalMemory(manager, decodedData); 00260 return (int)retLen; 00261 } 00262 } 00263 00264 XMLByte* Base64::decode(const XMLByte* const inputData 00265 , XMLSize_t* decodedLength 00266 , MemoryManager* const memMgr 00267 , Conformance conform ) 00268 { 00269 XMLByte* canRepInByte = 0; 00270 XMLByte* retStr = decode( 00271 inputData 00272 , decodedLength 00273 , canRepInByte 00274 , memMgr 00275 , conform); 00276 00277 /*** 00278 * Release the canRepData 00279 */ 00280 if (retStr) 00281 returnExternalMemory(memMgr, canRepInByte); 00282 00283 return retStr; 00284 } 00285 00286 00287 XMLByte* Base64::decodeToXMLByte(const XMLCh* const inputData 00288 , XMLSize_t* decodedLen 00289 , MemoryManager* const memMgr 00290 , Conformance conform ) 00291 { 00292 if (!inputData || !*inputData) 00293 return 0; 00294 00295 /*** 00296 * Move input data to a XMLByte buffer 00297 */ 00298 XMLSize_t srcLen = XMLString::stringLen(inputData); 00299 XMLByte *dataInByte = (XMLByte*) getExternalMemory(memMgr, (srcLen+1) * sizeof(XMLByte)); 00300 ArrayJanitor<XMLByte> janFill(dataInByte, memMgr ? memMgr : XMLPlatformUtils::fgMemoryManager); 00301 00302 for (XMLSize_t i = 0; i < srcLen; i++) 00303 dataInByte[i] = (XMLByte)inputData[i]; 00304 00305 dataInByte[srcLen] = 0; 00306 00307 /*** 00308 * Forward to the actual decoding method to do the decoding 00309 */ 00310 *decodedLen = 0; 00311 return decode(dataInByte, decodedLen, memMgr, conform); 00312 } 00313 00314 /*** 00315 * E2-54 00316 * 00317 * Canonical-base64Binary ::= (B64 B64 B64 B64)*((B64 B64 B16 '=')|(B64 B04 '=='))? 00318 * B04 ::= [AQgw] 00319 * B16 ::= [AEIMQUYcgkosw048] 00320 * B64 ::= [A-Za-z0-9+/] 00321 * 00322 ***/ 00323 XMLCh* Base64::getCanonicalRepresentation(const XMLCh* const inputData 00324 , MemoryManager* const memMgr 00325 , Conformance conform) 00326 00327 { 00328 if (!inputData || !*inputData) 00329 return 0; 00330 00331 /*** 00332 * Move input data to a XMLByte buffer 00333 */ 00334 XMLSize_t srcLen = XMLString::stringLen(inputData); 00335 XMLByte *dataInByte = (XMLByte*) getExternalMemory(memMgr, (srcLen+1) * sizeof(XMLByte)); 00336 ArrayJanitor<XMLByte> janFill(dataInByte, memMgr ? memMgr : XMLPlatformUtils::fgMemoryManager); 00337 00338 for (XMLSize_t i = 0; i < srcLen; i++) 00339 dataInByte[i] = (XMLByte)inputData[i]; 00340 00341 dataInByte[srcLen] = 0; 00342 00343 /*** 00344 * Forward to the actual decoding method to do the decoding 00345 */ 00346 XMLSize_t decodedLength = 0; 00347 XMLByte* canRepInByte = 0; 00348 XMLByte* retStr = decode( 00349 dataInByte 00350 , &decodedLength 00351 , canRepInByte 00352 , memMgr 00353 , conform); 00354 00355 if (!retStr) 00356 return 0; 00357 00358 /*** 00359 * Move canonical representation to a XMLCh buffer to return 00360 */ 00361 XMLSize_t canRepLen = XMLString::stringLen((char*)canRepInByte); 00362 XMLCh *canRepData = (XMLCh*) getExternalMemory(memMgr, (canRepLen + 1) * sizeof(XMLCh)); 00363 00364 for (XMLSize_t j = 0; j < canRepLen; j++) 00365 canRepData[j] = (XMLCh)canRepInByte[j]; 00366 00367 canRepData[canRepLen] = 0; 00368 00369 /*** 00370 * Release the memory allocated in the actual decoding method 00371 */ 00372 returnExternalMemory(memMgr, retStr); 00373 returnExternalMemory(memMgr, canRepInByte); 00374 00375 return canRepData; 00376 } 00377 // ----------------------------------------------------------------------- 00378 // Helper methods 00379 // ----------------------------------------------------------------------- 00380 00381 // 00382 // return 0(null) if invalid data found. 00383 // return the buffer containning decoded data otherwise 00384 // the caller is responsible for the de-allocation of the 00385 // buffer returned. 00386 // 00387 // temporary data, rawInputData, is ALWAYS released by this function. 00388 // 00389 00390 /*** 00391 * E2-9 00392 * 00393 * Base64Binary ::= S? B64quartet* B64final? 00394 * 00395 * B64quartet ::= B64 S? B64 S? B64 S? B64 S? 00396 * 00397 * B64final ::= B64 S? B04 S? '=' S? '=' S? 00398 * | B64 S? B64 S? B16 S? '=' S? 00399 * 00400 * B04 ::= [AQgw] 00401 * B16 ::= [AEIMQUYcgkosw048] 00402 * B64 ::= [A-Za-z0-9+/] 00403 * 00404 * 00405 * E2-54 00406 * 00407 * Base64Binary ::= ((B64S B64S B64S B64S)* 00408 * ((B64S B64S B64S B64) | 00409 * (B64S B64S B16S '=') | 00410 * (B64S B04S '=' #x20? '=')))? 00411 * 00412 * B64S ::= B64 #x20? 00413 * B16S ::= B16 #x20? 00414 * B04S ::= B04 #x20? 00415 * 00416 * 00417 * Note that this grammar requires the number of non-whitespace characters 00418 * in the lexical form to be a multiple of four, and for equals signs to 00419 * appear only at the end of the lexical form; strings which do not meet these 00420 * constraints are not legal lexical forms of base64Binary because they 00421 * cannot successfully be decoded by base64 decoders. 00422 * 00423 * Note: 00424 * The above definition of the lexical space is more restrictive than that given 00425 * in [RFC 2045] as regards whitespace -- this is not an issue in practice. Any 00426 * string compatible with the RFC can occur in an element or attribute validated 00427 * by this type, because the whiteSpace facet of this type is fixed to collapse, 00428 * which means that all leading and trailing whitespace will be stripped, and all 00429 * internal whitespace collapsed to single space characters, before the above grammar 00430 * is enforced. 00431 * 00432 */ 00433 00434 XMLByte* Base64::decode ( const XMLByte* const inputData 00435 , XMLSize_t* decodedLength 00436 , XMLByte*& canRepData 00437 , MemoryManager* const memMgr 00438 , Conformance conform 00439 ) 00440 { 00441 if ((!inputData) || (!*inputData)) 00442 return 0; 00443 00444 // 00445 // remove all XML whitespaces from the base64Data 00446 // 00447 XMLSize_t inputLength = XMLString::stringLen( (const char*)inputData ); 00448 XMLByte* rawInputData = (XMLByte*) getExternalMemory(memMgr, (inputLength+1) * sizeof(XMLByte)); 00449 ArrayJanitor<XMLByte> jan(rawInputData, memMgr ? memMgr : XMLPlatformUtils::fgMemoryManager); 00450 00451 XMLSize_t inputIndex = 0; 00452 XMLSize_t rawInputLength = 0; 00453 bool inWhiteSpace = false; 00454 00455 switch (conform) 00456 { 00457 case Conf_RFC2045: 00458 while ( inputIndex < inputLength ) 00459 { 00460 if (!XMLChar1_0::isWhitespace(inputData[inputIndex])) 00461 { 00462 rawInputData[ rawInputLength++ ] = inputData[ inputIndex ]; 00463 } 00464 // RFC2045 does not explicitly forbid more than ONE whitespace 00465 // before, in between, or after base64 octects. 00466 // Besides, S? allows more than ONE whitespace as specified in the production 00467 // [3] S ::= (#x20 | #x9 | #xD | #xA)+ 00468 // therefore we do not detect multiple ws 00469 00470 inputIndex++; 00471 } 00472 00473 break; 00474 case Conf_Schema: 00475 // no leading #x20 00476 if (chSpace == inputData[inputIndex]) 00477 return 0; 00478 00479 while ( inputIndex < inputLength ) 00480 { 00481 if (chSpace != inputData[inputIndex]) 00482 { 00483 rawInputData[ rawInputLength++ ] = inputData[ inputIndex ]; 00484 inWhiteSpace = false; 00485 } 00486 else 00487 { 00488 if (inWhiteSpace) 00489 return 0; // more than 1 #x20 encountered 00490 else 00491 inWhiteSpace = true; 00492 } 00493 00494 inputIndex++; 00495 } 00496 00497 // no trailing #x20 00498 if (inWhiteSpace) 00499 return 0; 00500 00501 break; 00502 00503 default: 00504 break; 00505 } 00506 00507 //now rawInputData contains canonical representation 00508 //if the data is valid Base64 00509 rawInputData[ rawInputLength ] = 0; 00510 00511 // the length of raw data should be divisible by four 00512 if (( rawInputLength % FOURBYTE ) != 0 ) 00513 return 0; 00514 00515 int quadrupletCount = (int)rawInputLength / FOURBYTE; 00516 if ( quadrupletCount == 0 ) 00517 return 0; 00518 00519 // 00520 // convert the quadruplet(s) to triplet(s) 00521 // 00522 XMLByte d1, d2, d3, d4; // base64 characters 00523 XMLByte b1, b2, b3, b4; // base64 binary codes ( 0..64 ) 00524 00525 XMLSize_t rawInputIndex = 0; 00526 XMLSize_t outputIndex = 0; 00527 XMLByte *decodedData = (XMLByte*) getExternalMemory(memMgr, (quadrupletCount*3+1) * sizeof(XMLByte)); 00528 00529 // 00530 // Process all quadruplet(s) except the last 00531 // 00532 int quad = 1; 00533 for (; quad <= quadrupletCount-1; quad++ ) 00534 { 00535 // read quadruplet from the input stream 00536 if (!isData( (d1 = rawInputData[ rawInputIndex++ ]) ) || 00537 !isData( (d2 = rawInputData[ rawInputIndex++ ]) ) || 00538 !isData( (d3 = rawInputData[ rawInputIndex++ ]) ) || 00539 !isData( (d4 = rawInputData[ rawInputIndex++ ]) )) 00540 { 00541 // if found "no data" just return NULL 00542 returnExternalMemory(memMgr, decodedData); 00543 return 0; 00544 } 00545 00546 b1 = base64Inverse[ d1 ]; 00547 b2 = base64Inverse[ d2 ]; 00548 b3 = base64Inverse[ d3 ]; 00549 b4 = base64Inverse[ d4 ]; 00550 00551 // write triplet to the output stream 00552 decodedData[ outputIndex++ ] = set1stOctet(b1, b2); 00553 decodedData[ outputIndex++ ] = set2ndOctet(b2, b3); 00554 decodedData[ outputIndex++ ] = set3rdOctet(b3, b4); 00555 } 00556 00557 // 00558 // process the last Quadruplet 00559 // 00560 // first two octets are present always, process them 00561 if (!isData( (d1 = rawInputData[ rawInputIndex++ ]) ) || 00562 !isData( (d2 = rawInputData[ rawInputIndex++ ]) )) 00563 { 00564 // if found "no data" just return NULL 00565 returnExternalMemory(memMgr, decodedData); 00566 return 0; 00567 } 00568 00569 b1 = base64Inverse[ d1 ]; 00570 b2 = base64Inverse[ d2 ]; 00571 00572 // try to process last two octets 00573 d3 = rawInputData[ rawInputIndex++ ]; 00574 d4 = rawInputData[ rawInputIndex++ ]; 00575 00576 if (!isData( d3 ) || !isData( d4 )) 00577 { 00578 // check if last two are PAD characters 00579 if (isPad( d3 ) && isPad( d4 )) 00580 { 00581 // two PAD e.g. 3c== 00582 if ((b2 & 0xf) != 0) // last 4 bits should be zero 00583 { 00584 returnExternalMemory(memMgr, decodedData); 00585 return 0; 00586 } 00587 00588 decodedData[ outputIndex++ ] = set1stOctet(b1, b2); 00589 } 00590 else if (!isPad( d3 ) && isPad( d4 )) 00591 { 00592 // one PAD e.g. 3cQ= 00593 b3 = base64Inverse[ d3 ]; 00594 if (( b3 & 0x3 ) != 0 ) // last 2 bits should be zero 00595 { 00596 returnExternalMemory(memMgr, decodedData); 00597 return 0; 00598 } 00599 00600 decodedData[ outputIndex++ ] = set1stOctet( b1, b2 ); 00601 decodedData[ outputIndex++ ] = set2ndOctet( b2, b3 ); 00602 } 00603 else 00604 { 00605 // an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data 00606 returnExternalMemory(memMgr, decodedData); 00607 return 0; 00608 } 00609 } 00610 else 00611 { 00612 // no PAD e.g 3cQl 00613 b3 = base64Inverse[ d3 ]; 00614 b4 = base64Inverse[ d4 ]; 00615 decodedData[ outputIndex++ ] = set1stOctet( b1, b2 ); 00616 decodedData[ outputIndex++ ] = set2ndOctet( b2, b3 ); 00617 decodedData[ outputIndex++ ] = set3rdOctet( b3, b4 ); 00618 } 00619 00620 // write out the end of string 00621 decodedData[ outputIndex ] = 0; 00622 *decodedLength = outputIndex; 00623 00624 //allow the caller to have access to the canonical representation 00625 jan.release(); 00626 canRepData = rawInputData; 00627 00628 return decodedData; 00629 } 00630 00631 bool Base64::isData(const XMLByte& octet) 00632 { 00633 return (base64Inverse[octet]!=(XMLByte)-1); 00634 } 00635 00636 XERCES_CPP_NAMESPACE_END