CBase64Coding.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #include "stdafx.h"
  2. #include "CBase64Coding.hpp"
  3. #pragma hdrstop
  4. #ifdef MPEXT
  5. #pragma warn -inl
  6. #endif
  7. #define CARRIAGE_RETURN (13)
  8. #define LINE_FEED (10)
  9. /*
  10. ** Author: Samuel R. Blackburn
  11. ** Internet: [email protected]
  12. **
  13. ** You can use it any way you like as long as you don't try to sell it.
  14. **
  15. ** Any attempt to sell WFC in source code form must have the permission
  16. ** of the original author. You can produce commercial executables with
  17. ** WFC but you can't sell WFC.
  18. **
  19. ** Copyright, 2000, Samuel R. Blackburn
  20. **
  21. ** Workfile: CBase64Coding.cpp
  22. ** Revision: 1.3
  23. ** Modtime: 5/12/00 3:39p
  24. ** Reuse Tracing Code: 1
  25. */
  26. //Modified for use with CAsyncProxySocket, removed tracing code
  27. #if defined( _DEBUG ) && ! defined( WFC_STL )
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #define new DEBUG_NEW
  31. #endif // _DEBUG
  32. #define END_OF_BASE64_ENCODED_DATA ('=')
  33. #define BASE64_END_OF_BUFFER (0xFD)
  34. #define BASE64_IGNORABLE_CHARACTER (0xFE)
  35. #define BASE64_UNKNOWN_VALUE (0xFF)
  36. #define BASE64_NUMBER_OF_CHARACTERS_PER_LINE (72)
  37. static inline BYTE __get_character( const BYTE * buffer, const BYTE * decoder_table, int& index, int size_of_buffer )
  38. {
  39. BYTE return_value = 0;
  40. do
  41. {
  42. if ( index >= size_of_buffer )
  43. {
  44. return( BASE64_END_OF_BUFFER );
  45. }
  46. return_value = buffer[ index ];
  47. index++;
  48. }
  49. while( return_value != END_OF_BASE64_ENCODED_DATA &&
  50. decoder_table[ return_value ] == BASE64_IGNORABLE_CHARACTER );
  51. return( return_value );
  52. }
  53. CBase64Coding::CBase64Coding()
  54. {
  55. }
  56. CBase64Coding::~CBase64Coding()
  57. {
  58. }
  59. BOOL CBase64Coding::Encode( const char * source, int len, char * destination_string )
  60. {
  61. const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  62. int loop_index = 0;
  63. int number_of_bytes_to_encode = len;
  64. BYTE byte_to_add = 0;
  65. BYTE byte_1 = 0;
  66. BYTE byte_2 = 0;
  67. BYTE byte_3 = 0;
  68. DWORD number_of_bytes_encoded = (DWORD) ( (double) number_of_bytes_to_encode / (double) 0.75 ) + 1;
  69. // Now add in the CR/LF pairs, each line is truncated at 72 characters
  70. // 2000-05-12
  71. // Thanks go to Ilia Golubev ([email protected]) for finding a bug here.
  72. // I was using number_of_bytes_to_encode rather than number_of_bytes_encoded.
  73. number_of_bytes_encoded += (DWORD)( ( ( number_of_bytes_encoded / BASE64_NUMBER_OF_CHARACTERS_PER_LINE ) + 1 ) * 2 );
  74. char * destination = destination_string;
  75. number_of_bytes_encoded = 0;
  76. while( loop_index < number_of_bytes_to_encode )
  77. {
  78. // Output the first byte
  79. byte_1 = source[ loop_index ];
  80. byte_to_add = alphabet[ ( byte_1 >> 2 ) ];
  81. destination[number_of_bytes_encoded ] = static_cast<char>( byte_to_add );
  82. number_of_bytes_encoded++;
  83. loop_index++;
  84. if ( loop_index >= number_of_bytes_to_encode )
  85. {
  86. // We're at the end of the data to encode
  87. byte_2 = 0;
  88. byte_to_add = alphabet[ ( ( ( byte_1 & 0x03 ) << 4 ) | ( ( byte_2 & 0xF0 ) >> 4 ) ) ];
  89. destination[ number_of_bytes_encoded ] = byte_to_add;
  90. number_of_bytes_encoded++;
  91. destination[ number_of_bytes_encoded ] = END_OF_BASE64_ENCODED_DATA;
  92. number_of_bytes_encoded++;
  93. destination[ number_of_bytes_encoded ] = END_OF_BASE64_ENCODED_DATA;
  94. // 1999-09-01
  95. // Thanks go to Yurong Lin ([email protected]) for finding a bug here.
  96. // We must NULL terminate the string before letting CString have the buffer back.
  97. destination[ number_of_bytes_encoded + 1 ] = 0;
  98. return( TRUE );
  99. }
  100. else
  101. {
  102. byte_2 = source[ loop_index ];
  103. }
  104. byte_to_add = alphabet[ ( ( ( byte_1 & 0x03 ) << 4 ) | ( ( byte_2 & 0xF0 ) >> 4 ) ) ];
  105. destination[ number_of_bytes_encoded ] = byte_to_add;
  106. number_of_bytes_encoded++;
  107. loop_index++;
  108. if ( loop_index >= number_of_bytes_to_encode )
  109. {
  110. // We ran out of bytes, we need to add the last half of byte_2 and pad
  111. byte_3 = 0;
  112. byte_to_add = alphabet[ ( ( ( byte_2 & 0x0F ) << 2 ) | ( ( byte_3 & 0xC0 ) >> 6 ) ) ];
  113. destination[ number_of_bytes_encoded ] = byte_to_add;
  114. number_of_bytes_encoded++;
  115. destination[ number_of_bytes_encoded ] = END_OF_BASE64_ENCODED_DATA;
  116. // 1999-09-01
  117. // Thanks go to Yurong Lin ([email protected]) for finding a bug here.
  118. // We must NULL terminate the string before letting CString have the buffer back.
  119. destination[ number_of_bytes_encoded + 1 ] = 0;
  120. return( TRUE );
  121. }
  122. else
  123. {
  124. byte_3 = source[ loop_index ];
  125. }
  126. loop_index++;
  127. byte_to_add = alphabet[ ( ( ( byte_2 & 0x0F ) << 2 ) | ( ( byte_3 & 0xC0 ) >> 6 ) ) ];
  128. destination[ number_of_bytes_encoded ] = byte_to_add;
  129. number_of_bytes_encoded++;
  130. byte_to_add = alphabet[ ( byte_3 & 0x3F ) ];
  131. destination[ number_of_bytes_encoded ] = byte_to_add;
  132. number_of_bytes_encoded++;
  133. if ( ( number_of_bytes_encoded % BASE64_NUMBER_OF_CHARACTERS_PER_LINE ) == 0 )
  134. {
  135. destination[ number_of_bytes_encoded ] = CARRIAGE_RETURN;
  136. number_of_bytes_encoded++;
  137. destination[ number_of_bytes_encoded ] = LINE_FEED;
  138. number_of_bytes_encoded++;
  139. }
  140. }
  141. // 1999-09-01
  142. // Thanks go to Yurong Lin ([email protected]) for finding a bug here.
  143. // We must NULL terminate the string before letting CString have the buffer back.
  144. destination[ number_of_bytes_encoded ] = 0;
  145. return( TRUE );
  146. }
  147. // End of source
  148. #if 0
  149. <HTML>
  150. <HEAD>
  151. <TITLE>WFC - CBase64Coding</TITLE>
  152. <META name="keywords" content="WFC, MFC extension library, freeware class library, Win32, MIME encoding, base 64, source code">
  153. <META name="description" content="This C++ class let's you MIME encode bytes to text using base64.">
  154. </HEAD>
  155. <BODY>
  156. <H1>CBase64Coding</H1>
  157. Revision: 1.3 <BR><HR>
  158. <H2>Description</H2>
  159. This class gives you the ability to encode/decode data using base64.
  160. <H2>Constructors</H2>
  161. <DL COMPACT>
  162. <DT><PRE><B>CBase64Coding</B>()<DD>
  163. Constructs this object.
  164. </DL>
  165. <H2>Methods</H2>
  166. <DL COMPACT>
  167. <DT><PRE>BOOL <B><A NAME="Decode">Decode</A></B>( const CByteArray&amp; source, CByteArray&amp; destination )
  168. BOOL <B>Decode</B>( const CString&amp; source, CByteArray&amp; destination )</PRE><DD>
  169. This method takes base64 encoded text and produces the bytes. It decodes
  170. the base64 encoding.
  171. <DT><PRE>BOOL <B><A NAME="Encode">Encode</A></B>( const CByteArray&amp; source, CByteArray&amp; destination )
  172. BOOL <B>Encode</B>( const CByteArray&amp; source, CString&amp; destination )</PRE><DD>
  173. This method takes bytes and turns them into base64 text.
  174. </DL>
  175. <H2>Example</H2>
  176. <PRE><CODE>#include &lt;wfc.h&gt;
  177. int _tmain( int number_of_command_line_arguments, LPCTSTR command_line_arguments[] )
  178. {
  179. <A HREF="WfcTrace.htm">WFCTRACEINIT</A>( TEXT( &quot;_tmain()&quot; ) );
  180. CByteArray bytes;
  181. get_file_contents( command_line_arguments[ 0 ], bytes );
  182. <B>CBase64Coding</B> encoder;
  183. CString encoded_data;
  184. if ( encoder.Encode( bytes, encoded_data ) != FALSE )
  185. {
  186. _tprintf( TEXT( &quot;%s\n&quot;, (LPCTSTR) encoded_data );
  187. }
  188. }</CODE></PRE>
  189. <HR><I>Copyright, 2000, <A HREF="mailto:[email protected]">Samuel R. Blackburn</A></I><BR>
  190. $Workfile: CBase64Coding.cpp $<BR>
  191. $Modtime: 5/12/00 3:39p $
  192. </BODY>
  193. </HTML>
  194. #endif