You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by pe...@apache.org on 2001/10/10 21:14:08 UTC
cvs commit: xml-xerces/c/src/util Base64.hpp Base64.cpp
peiyongz 01/10/10 12:14:08
Modified: c/src/util Base64.hpp Base64.cpp
Log:
Patch from Petr Gotthard : encode() provided and some other changes
Revision Changes Path
1.3 +83 -33 xml-xerces/c/src/util/Base64.hpp
Index: Base64.hpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/util/Base64.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Base64.hpp 2001/05/28 21:11:16 1.2
+++ Base64.hpp 2001/10/10 19:14:08 1.3
@@ -55,7 +55,7 @@
*/
/*
- * $Id: Base64.hpp,v 1.2 2001/05/28 21:11:16 tng Exp $
+ * $Id: Base64.hpp,v 1.3 2001/10/10 19:14:08 peiyongz Exp $
*/
#ifndef BASE64_HPP
@@ -80,22 +80,44 @@
//@{
/**
+ * Encodes octets into Base64 data
+ *
+ * @param inputData Byte array containing binary data.
+ * @param inputLength Length of the input array.
+ * @param outputLength Pointer to variable, where will be
+ * stored length of returned data.
+ * @return Byte array containing encoded Base64 data,
+ * or NULL if input data can not be encoded.
+ */
+ static XMLCh* encode (
+ const XMLCh* const inputData,
+ const int inputLength,
+ int *outputLength = 0 );
+
+ /**
* Get data length
- * returns length of decoded data given an
- * array containing encoded data.
+ * returns length of decoded data given an array
+ * containing encoded data.
*
- * @param base64Data Byte array containing Base64 data
- * @return a -1 would be return if not
+ * @param inputData Byte array containing Base64 data.
+ * @return Length of decoded data, or -1 if input data
+ * can not be decoded.
*/
- static int getDataLength(const XMLCh* const base64Data);
+ static int getDataLength(
+ const XMLCh* const inputData );
/**
- * Decodes Base64 data into octects
+ * Decodes Base64 data into octets
*
- * @param binaryData Byte array containing Base64 data
- * @return Array containind decoded data.
+ * @param inputData Byte array containing Base64 data.
+ * @param outputLength Reference to variable, where will be
+ * stored length of returned data.
+ * @return Byte array containing decoded binary data, or
+ * NULL if input data can not be decoded.
*/
- static XMLCh* decode(const XMLCh* const base64Data, int& base64DataLen);
+ static XMLCh* decode(
+ const XMLCh* const inputData,
+ int& outputLength );
//@}
@@ -106,17 +128,18 @@
// -----------------------------------------------------------------------
static void init();
-
- static bool isData(const XMLCh& octect);
- static bool isPad(const XMLCh& octect);
+ static bool isData(const XMLCh& octet);
+ static bool isPad(const XMLCh& octet);
- static XMLCh set1stOctect(const XMLCh&, const XMLCh&);
+ static XMLCh set1stOctet(const XMLCh&, const XMLCh&);
+ static XMLCh set2ndOctet(const XMLCh&, const XMLCh&);
+ static XMLCh set3rdOctet(const XMLCh&, const XMLCh&);
+
+ static void split1stOctet(const XMLCh&, XMLCh&, XMLCh&);
+ static void split2ndOctet(const XMLCh&, XMLCh&, XMLCh&);
+ static void split3rdOctet(const XMLCh&, XMLCh&, XMLCh&);
- static XMLCh set2ndOctect(const XMLCh&, const XMLCh&);
-
- static XMLCh set3rdOctect(const XMLCh&, const XMLCh&);
-
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
@@ -126,43 +149,70 @@
// -----------------------------------------------------------------------
// Private data members
//
- // isInitialized
+ // base64Alphabet
+ // The Base64 alphabet (see RFC 2045).
//
- // set once hexNumberTable is initalized.
+ // base64Padding
+ // Padding character (see RFC 2045).
//
- // base64Alphabet
+ // base64Inverse
+ // Table used in decoding base64.
//
- // table used in decoding base64
+ // isInitialized
+ // Set once base64Inverse is initalized.
+ //
+ // quadsPerLine
+ // Number of quadruplets per one line. The encoded output
+ // stream must be represented in lines of no more
+ // than 19 quadruplets each.
//
// -----------------------------------------------------------------------
+
+ static const XMLCh base64Alphabet[];
+ static const XMLCh base64Padding;
- static bool isInitialized;
- static XMLCh base64Alphabet[];
+ static XMLCh base64Inverse[];
+ static bool isInitialized;
+ static const unsigned int quadsPerLine;
};
// -----------------------------------------------------------------------
// Helper methods
// -----------------------------------------------------------------------
-inline bool Base64::isPad(const XMLCh& octect)
+inline bool Base64::isPad(const XMLCh& octet)
{
- return(octect == chEqual);
+ return ( octet == base64Padding );
}
-inline XMLCh Base64::set1stOctect(const XMLCh& b1, const XMLCh& b2)
+inline XMLCh Base64::set1stOctet(const XMLCh& b1, const XMLCh& b2)
{
- return (( b1 <<2 ) | ( b2>>4 ));
+ return (( b1 << 2 ) | ( b2 >> 4 ));
}
-inline XMLCh Base64::set2ndOctect(const XMLCh& b2, const XMLCh& b3)
+inline XMLCh Base64::set2ndOctet(const XMLCh& b2, const XMLCh& b3)
{
- return ((( b2 & 0xf )<<4 ) | (( b3>>2 ) & 0xf));
+ return (( b2 << 4 ) | ( b3 >> 2 ));
}
-inline XMLCh Base64::set3rdOctect(const XMLCh& b3, const XMLCh& b4)
+inline XMLCh Base64::set3rdOctet(const XMLCh& b3, const XMLCh& b4)
{
- return (( b3<<6 ) | b4 );
+ return (( b3 << 6 ) | b4 );
}
-#endif
+inline void Base64::split1stOctet(const XMLCh& ch, XMLCh& b1, XMLCh& b2) {
+ b1 = ch >> 2;
+ b2 = ( ch & 0x3 ) << 4;
+}
+inline void Base64::split2ndOctet(const XMLCh& ch, XMLCh& b2, XMLCh& b3) {
+ b2 |= ch >> 4; // combine with previous value
+ b3 = ( ch & 0xf ) << 2;
+}
+
+inline void Base64::split3rdOctet(const XMLCh& ch, XMLCh& b3, XMLCh& b4) {
+ b3 |= ch >> 6; // combine with previous value
+ b4 = ( ch & 0x3f );
+}
+
+#endif
1.5 +221 -98 xml-xerces/c/src/util/Base64.cpp
Index: Base64.cpp
===================================================================
RCS file: /home/cvs/xml-xerces/c/src/util/Base64.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- Base64.cpp 2001/06/07 20:55:20 1.4
+++ Base64.cpp 2001/10/10 19:14:08 1.5
@@ -56,6 +56,9 @@
/*
* $Log: Base64.cpp,v $
+ * Revision 1.5 2001/10/10 19:14:08 peiyongz
+ * Patch from Petr Gotthard : encode() provided and some other changes
+ *
* Revision 1.4 2001/06/07 20:55:20 tng
* Fix no newline at the end warning. By Pei Yong Zhang.
*
@@ -88,9 +91,128 @@
// ---------------------------------------------------------------------------
// class data member
// ---------------------------------------------------------------------------
+
+// the base64 alphabet according to definition in RFC 2045
+const XMLCh Base64::base64Alphabet[64] = {
+ chLatin_A, chLatin_B, chLatin_C, chLatin_D, chLatin_E,
+ chLatin_F, chLatin_G, chLatin_H, chLatin_I, chLatin_J,
+ chLatin_K, chLatin_L, chLatin_M, chLatin_N, chLatin_O,
+ chLatin_P, chLatin_Q, chLatin_R, chLatin_S, chLatin_T,
+ chLatin_U, chLatin_V, chLatin_W, chLatin_X, chLatin_Y,
+ chLatin_Z, chLatin_a, chLatin_b, chLatin_c, chLatin_d,
+ chLatin_e, chLatin_f, chLatin_g, chLatin_h, chLatin_i,
+ chLatin_j, chLatin_k, chLatin_l, chLatin_m, chLatin_n,
+ chLatin_o, chLatin_p, chLatin_q, chLatin_r, chLatin_s,
+ chLatin_t, chLatin_u, chLatin_v, chLatin_w, chLatin_x,
+ chLatin_y, chLatin_z, chDigit_0, chDigit_1, chDigit_2,
+ chDigit_3, chDigit_4, chDigit_5, chDigit_6, chDigit_7,
+ chDigit_8, chDigit_9, chPlus, chForwardSlash
+};
+const XMLCh Base64::base64Padding = chEqual;
+
+XMLCh Base64::base64Inverse[ BASELENGTH ];
bool Base64::isInitialized = false;
-XMLCh Base64::base64Alphabet[BASELENGTH];
+// number of quadruplets per one line ( must be >1 and <19 )
+const unsigned int Base64::quadsPerLine = 15;
+
+XMLCh* Base64::encode(
+ const XMLCh* const inputData,
+ const int inputLength,
+ int *outputLength )
+{
+ if (!isInitialized)
+ init();
+
+ if ( inputData == 0 )
+ return 0;
+
+ int quadrupletCount = ( inputLength + 2 ) / 3;
+ if (quadrupletCount == 0)
+ return 0;
+
+ // number of rows in encoded stream ( including the last one )
+ int lineCount = ( quadrupletCount + quadsPerLine-1 ) / quadsPerLine;
+
+ //
+ // convert the triplet(s) to quadruplet(s)
+ //
+ XMLCh b1, b2, b3, b4; // base64 binary codes ( 0..63 )
+
+ int inputIndex = 0;
+ int outputIndex = 0;
+ XMLCh *encodedData =
+ new XMLCh[ quadrupletCount*FOURBYTE + lineCount + 1 ];
+
+ //
+ // Process all quadruplet(s) except the last
+ //
+ int quad = 1;
+ for (; quad <= quadrupletCount-1; quad++ )
+ {
+ // read triplet from the input stream
+ split1stOctet( inputData[ inputIndex++ ], b1, b2 );
+ split2ndOctet( inputData[ inputIndex++ ], b2, b3 );
+ split3rdOctet( inputData[ inputIndex++ ], b3, b4 );
+
+ // write quadruplet to the output stream
+ encodedData[ outputIndex++ ] = base64Alphabet[ b1 ];
+ encodedData[ outputIndex++ ] = base64Alphabet[ b2 ];
+ encodedData[ outputIndex++ ] = base64Alphabet[ b3 ];
+ encodedData[ outputIndex++ ] = base64Alphabet[ b4 ];
+
+ if (( quad % quadsPerLine ) == 0 )
+ encodedData[ outputIndex++ ] = chLF;
+ }
+
+ //
+ // process the last Quadruplet
+ //
+ // first octet is present always, process it
+ split1stOctet( inputData[ inputIndex++ ], b1, b2 );
+ encodedData[ outputIndex++ ] = base64Alphabet[ b1 ];
+
+ if( inputIndex < inputLength )
+ {
+ // second octet is present, process it
+ split2ndOctet( inputData[ inputIndex++ ], b2, b3 );
+ encodedData[ outputIndex++ ] = base64Alphabet[ b2 ];
+
+ if( inputIndex < inputLength )
+ {
+ // third octet present, process it
+ // no PAD e.g. 3cQl
+ split3rdOctet( inputData[ inputIndex++ ], b3, b4 );
+ encodedData[ outputIndex++ ] = base64Alphabet[ b3 ];
+ encodedData[ outputIndex++ ] = base64Alphabet[ b4 ];
+ }
+ else
+ {
+ // third octet not present
+ // one PAD e.g. 3cQ=
+ encodedData[ outputIndex++ ] = base64Alphabet[ b3 ];
+ encodedData[ outputIndex++ ] = base64Padding;
+ }
+ }
+ else
+ {
+ // second octet not present
+ // two PADs e.g. 3c==
+ encodedData[ outputIndex++ ] = base64Padding;
+ encodedData[ outputIndex++ ] = base64Padding;
+ }
+
+ // write out end of the last line
+ encodedData[ outputIndex++ ] = chLF;
+ // write out end of string
+ encodedData[ outputIndex ] = 0;
+
+ if( outputLength != 0 )
+ (*outputLength) = outputIndex;
+
+ return encodedData;
+}
+
//
// delete the buffer allocated by decode() if
// decoding is successfully done.
@@ -104,10 +226,10 @@
// Since decode() has track of length of the decoded data, we
// will get this length from decode(), instead of strLen().
//
-int Base64::getDataLength(const XMLCh* const base64Data)
+int Base64::getDataLength( const XMLCh* const inputData )
{
int retLen = 0;
- XMLCh* decodedData = decode(base64Data, retLen);
+ XMLCh* decodedData = decode( inputData, retLen );
if ( !decodedData )
return -1;
@@ -124,132 +246,148 @@
// the caller is responsible for the de-allocation of the
// buffer returned.
//
-// temporary data, normalizedBase64Data, is ALWAYS released by this function.
+// temporary data, rawInputData, is ALWAYS released by this function.
//
-XMLCh* Base64::decode(const XMLCh* const base64Data, int& base64DataLen)
+XMLCh* Base64::decode( const XMLCh* const inputData, int& outputLength )
{
if (!isInitialized)
init();
- if (( base64Data == 0 ) || ( *base64Data == 0 ))
+ if (( inputData == 0 ) || ( *inputData == 0 ))
return 0;
//
- // remove whitespaces from the base64Data
+ // remove all whitespaces from the base64Data
//
- XMLCh* normalizedBase64Data = XMLString::replicate(base64Data);
- XMLString::trim(normalizedBase64Data);
- ArrayJanitor<XMLCh> jan(normalizedBase64Data);
+ int inputLength = XMLString::stringLen( inputData );
+ XMLCh* rawInputData = new XMLCh[ inputLength + 1 ];
+ ArrayJanitor<XMLCh> jan(rawInputData);
+
+ int inputIndex = 0;
+ int rawInputLength = 0;
+ while ( inputIndex < inputLength )
+ {
+// if( !isspace( inputData[ inputIndex ] ))
+ if (!XMLPlatformUtils::fgTransService->isSpace(inputData[inputIndex]))
+ rawInputData[ rawInputLength++ ] = inputData[ inputIndex ];
- //
- // check the length: should be divisible by four
- //
- int strLen = XMLString::stringLen(normalizedBase64Data);
- if (strLen%FOURBYTE != 0)
+ inputIndex++;
+ }
+ rawInputData[ rawInputLength ] = 0;
+
+ // the length of raw data should be divisible by four
+ if (( rawInputLength % FOURBYTE ) != 0 )
return 0;
- int numberQuadruple = strLen/FOURBYTE;
- if (numberQuadruple == 0)
+ int quadrupletCount = rawInputLength / FOURBYTE;
+ if ( quadrupletCount == 0 )
return 0;
//
// convert the quadruplet(s) to triplet(s)
//
- XMLCh d1, d2, d3, d4;
- XMLCh b1, b2, b3, b4;
+ XMLCh d1, d2, d3, d4; // base64 characters
+ XMLCh b1, b2, b3, b4; // base64 binary codes ( 0..64 )
- int i = 0;
- int encodedIndex = 0;
- int dataIndex = 0;
- XMLCh *decodedData = new XMLCh[numberQuadruple*3+1];
+ int rawInputIndex = 0;
+ int outputIndex = 0;
+ XMLCh *decodedData = new XMLCh[ quadrupletCount*3 + 1 ];
//
- // Prcess all quadruple(s) except for the last
+ // Process all quadruplet(s) except the last
//
- for (; i < numberQuadruple-1; i++)
+ int quad = 1;
+ for (; quad <= quadrupletCount-1; quad++ )
{
- if (!isData( (d1 = normalizedBase64Data[dataIndex++]) )||
- !isData( (d2 = normalizedBase64Data[dataIndex++]) )||
- !isData( (d3 = normalizedBase64Data[dataIndex++]) )||
- !isData( (d4 = normalizedBase64Data[dataIndex++]) ))
+ // read quadruplet from the input stream
+ if (!isData( (d1 = rawInputData[ rawInputIndex++ ]) ) ||
+ !isData( (d2 = rawInputData[ rawInputIndex++ ]) ) ||
+ !isData( (d3 = rawInputData[ rawInputIndex++ ]) ) ||
+ !isData( (d4 = rawInputData[ rawInputIndex++ ]) ))
{
+ // if found "no data" just return NULL
delete[] decodedData;
- return 0;//if found "no data" just return null
+ return 0;
}
-
- b1 = base64Alphabet[d1];
- b2 = base64Alphabet[d2];
- b3 = base64Alphabet[d3];
- b4 = base64Alphabet[d4];
- decodedData[encodedIndex++] = set1stOctect(b1, b2);
- decodedData[encodedIndex++] = set2ndOctect(b2, b3);
- decodedData[encodedIndex++] = set3rdOctect(b3, b4);
+ b1 = base64Inverse[ d1 ];
+ b2 = base64Inverse[ d2 ];
+ b3 = base64Inverse[ d3 ];
+ b4 = base64Inverse[ d4 ];
+
+ // write triplet to the output stream
+ decodedData[ outputIndex++ ] = set1stOctet(b1, b2);
+ decodedData[ outputIndex++ ] = set2ndOctet(b2, b3);
+ decodedData[ outputIndex++ ] = set3rdOctet(b3, b4);
}
//
- // process the last Quadruple
- // the first two octets
- if (!isData( (d1 = normalizedBase64Data[dataIndex++]) ) ||
- !isData( (d2 = normalizedBase64Data[dataIndex++]) ))
+ // process the last Quadruplet
+ //
+ // first two octets are present always, process them
+ if (!isData( (d1 = rawInputData[ rawInputIndex++ ]) ) ||
+ !isData( (d2 = rawInputData[ rawInputIndex++ ]) ))
{
+ // if found "no data" just return NULL
delete[] decodedData;
- return 0;//if found "no data" just return null
+ return 0;
}
- b1 = base64Alphabet[d1];
- b2 = base64Alphabet[d2];
+ b1 = base64Inverse[ d1 ];
+ b2 = base64Inverse[ d2 ];
- // the last two octets
- d3 = normalizedBase64Data[dataIndex++];
- d4 = normalizedBase64Data[dataIndex++];
+ // try to process last two octets
+ d3 = rawInputData[ rawInputIndex++ ];
+ d4 = rawInputData[ rawInputIndex++ ];
if (!isData( d3 ) || !isData( d4 ))
{
- //Check if they are PAD characters
+ // check if last two are PAD characters
if (isPad( d3 ) && isPad( d4 ))
{
- //Two PAD e.g. 3c[Pad][Pad]
- if ((b2 & 0xf) != 0)//last 4 bits should be zero
+ // two PAD e.g. 3c==
+ if ((b2 & 0xf) != 0) // last 4 bits should be zero
{
delete[] decodedData;
return 0;
}
- decodedData[encodedIndex++] = set1stOctect(b1, b2);
- decodedData[encodedIndex] = 0;
+ decodedData[ outputIndex++ ] = set1stOctet(b1, b2);
}
- else if (!isPad( d3) && isPad(d4))
+ else if (!isPad( d3 ) && isPad( d4 ))
{
- //One PAD e.g. 3cQ[Pad]
- b3 = base64Alphabet[ d3 ];
- if ((b3 & 0x3) != 0)//last 2 bits should be zero
+ // one PAD e.g. 3cQ=
+ b3 = base64Inverse[ d3 ];
+ if (( b3 & 0x3 ) != 0 ) // last 2 bits should be zero
{
delete[] decodedData;
return 0;
}
- decodedData[encodedIndex++] = set1stOctect(b1, b2);
- decodedData[encodedIndex++] = set2ndOctect(b2, b3);
- decodedData[encodedIndex] = 0;
+ decodedData[ outputIndex++ ] = set1stOctet( b1, b2 );
+ decodedData[ outputIndex++ ] = set2ndOctet( b2, b3 );
}
else
{
+ // an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data
delete[] decodedData;
- return 0;//an error like "3c[Pad]r", "3cdX", "3cXd", "3cXX" where X is non data
+ return 0;
}
}
else
- { //No PAD e.g 3cQl
- b3 = base64Alphabet[d3];
- b4 = base64Alphabet[d4];
- decodedData[encodedIndex++] = set1stOctect(b1, b2);
- decodedData[encodedIndex++] = set2ndOctect(b2, b3);
- decodedData[encodedIndex++] = set3rdOctect(b3, b4);
- decodedData[encodedIndex] = 0;
+ {
+ // no PAD e.g 3cQl
+ b3 = base64Inverse[ d3 ];
+ b4 = base64Inverse[ d4 ];
+ decodedData[ outputIndex++ ] = set1stOctet( b1, b2 );
+ decodedData[ outputIndex++ ] = set2ndOctet( b2, b3 );
+ decodedData[ outputIndex++ ] = set3rdOctet( b3, b4 );
}
+
+ // write out the end of string
+ decodedData[ outputIndex ] = 0;
+ outputLength = outputIndex;
- base64DataLen = encodedIndex;
return decodedData;
}
@@ -261,42 +399,27 @@
if (isInitialized)
return;
+ isInitialized = true;
+
+ // create inverse table for base64 decoding
+ // if base64Alphabet[ 17 ] = 'R', then base64Inverse[ 'R' ] = 17
+ // for characters not in base64Alphabet the base64Inverse[] = -1
+
int i;
- // [0] = -1, [255] = -1
+ // set all fields to -1
for ( i = 0; i < BASELENGTH; i++ )
- base64Alphabet[i] = (XMLCh)-1;
+ base64Inverse[i] = (XMLCh)-1;
- // [65] = 0, [90] = 25
- for ( i = chLatin_Z; i >= chLatin_A; i-- )
- base64Alphabet[i] = (XMLCh)( i - chLatin_A );
-
- // [97] = 0 + 26 = 26, [122] = 25 + 26 = 51
- for ( i = chLatin_z; i >= chLatin_a; i-- )
- base64Alphabet[i] = (XMLCh)( i - chLatin_a + 26 );
-
- // [48] = 0 + 52, [57] = 9 + 52
- for ( i = chDigit_9; i >= chDigit_0; i-- )
- base64Alphabet[i] = (XMLCh)( i- chDigit_0 + 52 );
-
- // [43] = 62
- // [47] = 63
- base64Alphabet[chPlus] = (XMLCh) 62;
- base64Alphabet[chForwardSlash] = (XMLCh) 63;
-
- isInitialized=true;
-
- //
- // index: 0 42 43 47 48 57 65 90 97 122 254
- // char: '+' '/' '0' '9' 'A' 'Z' 'a' 'z'
- // value: -1 ... -1 62 -1... 63 52 61 0 25 -1.. 26 51 -1...
- //
+ // compute inverse table
+ for ( i = 0; i < 64; i++ )
+ base64Inverse[ base64Alphabet[i] ] = (XMLCh)i;
}
-bool Base64::isData(const XMLCh& octect)
+bool Base64::isData(const XMLCh& octet)
{
// sanity check to avoid out-of-bound index
- if (( octect >= BASELENGTH ) || ( octect < 0 ))
+ if (( octet >= BASELENGTH ) || ( octet < 0 ))
return false;
- return( base64Alphabet[octect] != (XMLCh) -1);
+ return( base64Inverse[octet] != (XMLCh) -1);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: xerces-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xerces-cvs-help@xml.apache.org