Go to the documentation of this file.00001 #include "ace/Codecs.h"
00002 #include "ace/Log_Msg.h"
00003 #include "ace/OS_Memory.h"
00004 #include "ace/OS_NS_ctype.h"
00005
00006 ACE_RCSID (ace,
00007 Codecs,
00008 "$Id: Codecs.cpp 80826 2008-03-04 14:51:23Z wotte $")
00009
00010 namespace
00011 {
00012
00013 #undef alphabet
00014 #undef pad
00015 #undef max_columns
00016
00017
00018 ACE_Byte const alphabet[] =
00019 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00020
00021
00022 ACE_Byte const pad = '=';
00023
00024
00025
00026 int const max_columns = 72;
00027 }
00028
00029 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00030
00031 bool ACE_Base64::init_ = false;
00032
00033 ACE_Byte ACE_Base64::decoder_[256];
00034
00035 ACE_Byte ACE_Base64::member_[256];
00036
00037 ACE_Byte*
00038 ACE_Base64::encode (const ACE_Byte* input,
00039 const size_t input_len,
00040 size_t* output_len,
00041 bool is_chunked)
00042 {
00043 if (!ACE_Base64::init_)
00044 ACE_Base64::init();
00045
00046 if (!input)
00047 return 0;
00048
00049 ACE_Byte* result = 0;
00050
00051 size_t length = ((input_len + 2) / 3) * 4;
00052 size_t num_lines = length / max_columns + 1;
00053 length += num_lines + 1;
00054 ACE_NEW_RETURN (result, ACE_Byte[length], 0);
00055
00056 int char_count = 0;
00057 int bits = 0;
00058 size_t pos = 0;
00059 int cols = 0;
00060
00061 for (size_t i = 0; i < input_len; ++i)
00062 {
00063 bits += input[i];
00064 ++char_count;
00065
00066 if (char_count == 3)
00067 {
00068 result[pos++] = alphabet[bits >> 18];
00069 result[pos++] = alphabet[(bits >> 12) & 0x3f];
00070 result[pos++] = alphabet[(bits >> 6) & 0x3f];
00071 result[pos++] = alphabet[bits & 0x3f];
00072 cols += 4;
00073 if (cols == max_columns) {
00074 if (is_chunked)
00075 result[pos++] = '\n';
00076 cols = 0;
00077 }
00078 bits = 0;
00079 char_count = 0;
00080 }
00081 else
00082 {
00083 bits <<= 8;
00084 }
00085 }
00086
00087 if (char_count != 0)
00088 {
00089 bits <<= (16 - (8 * char_count));
00090 result[pos++] = alphabet[bits >> 18];
00091 result[pos++] = alphabet[(bits >> 12) & 0x3f];
00092 cols += 2;
00093 if (char_count == 1)
00094 {
00095 result[pos++] = pad;
00096 result[pos++] = pad;
00097 cols += 2;
00098 }
00099 else
00100 {
00101 result[pos++] = alphabet[(bits >> 6) & 0x3f];
00102 result[pos++] = pad;
00103 cols += 2;
00104 }
00105 }
00106
00107 if (cols > 0 && is_chunked)
00108 result[pos++] = '\n';
00109
00110 result[pos] = 0;
00111 *output_len = pos;
00112 return result;
00113 }
00114
00115 size_t
00116 ACE_Base64::length (const ACE_Byte* input)
00117 {
00118 if (!ACE_Base64::init_)
00119 ACE_Base64::init();
00120
00121 ACE_Byte* ptr = const_cast<ACE_Byte*> (input);
00122 while (*ptr != 0 &&
00123 (member_[*(ptr)] == 1 || *ptr == pad
00124 || ACE_OS::ace_isspace (*ptr)))
00125 ++ptr;
00126 size_t len = ptr - input;
00127 len = ((len + 3) / 4) * 3 + 1 ;
00128 return len;
00129 }
00130
00131 ACE_Byte*
00132 ACE_Base64::decode (const ACE_Byte* input, size_t* output_len)
00133 {
00134 if (!ACE_Base64::init_)
00135 ACE_Base64::init();
00136
00137 if (!input)
00138 return 0;
00139
00140 size_t result_len = ACE_Base64::length (input);
00141 ACE_Byte* result = 0;
00142 ACE_NEW_RETURN (result, ACE_Byte[result_len], 0);
00143
00144 ACE_Byte* ptr = const_cast<ACE_Byte*> (input);
00145 while (*ptr != 0 &&
00146 (member_[*(ptr)] == 1 || *ptr == pad
00147 || ACE_OS::ace_isspace (*ptr)))
00148 ++ptr;
00149 size_t input_len = ptr - input;
00150
00151 int char_count = 0;
00152 int bits = 0;
00153 size_t pos = 0;
00154
00155 size_t i = 0;
00156 for (; i < input_len; ++i)
00157 {
00158 if (input[i] == pad)
00159 break;
00160 if (!ACE_Base64::member_[input[i]])
00161 continue;
00162 bits += decoder_[input[i]];
00163 ++char_count;
00164
00165 if (char_count == 4)
00166 {
00167 result[pos++] = static_cast<ACE_Byte> (bits >> 16);
00168 result[pos++] = static_cast<ACE_Byte> ((bits >> 8) & 0xff);
00169 result[pos++] = static_cast<ACE_Byte> (bits & 0xff);
00170 bits = 0;
00171 char_count = 0;
00172 }
00173 else
00174 {
00175 bits <<= 6;
00176 }
00177 }
00178
00179 int errors = 0;
00180 if ( i == input_len)
00181 {
00182 if (char_count)
00183 {
00184 ACE_ERROR ((LM_ERROR,
00185 ACE_TEXT ("Decoding incomplete: atleast %d bits truncated\n"),
00186 (4 - char_count) * 6));
00187 ++errors;
00188 }
00189 }
00190 else
00191 {
00192 switch (char_count)
00193 {
00194 case 1:
00195 ACE_ERROR ((LM_ERROR,
00196 ACE_TEXT ("Decoding incomplete: atleast 2 bits missing\n")));
00197 ++errors;
00198 break;
00199 case 2:
00200 result[pos++] = static_cast<ACE_Byte> (bits >> 10);
00201 break;
00202 case 3:
00203 result[pos++] = static_cast<ACE_Byte> (bits >> 16);
00204 result[pos++] = static_cast<ACE_Byte> ((bits >> 8) & 0xff);
00205 break;
00206 }
00207 }
00208
00209 if (errors)
00210 {
00211 delete[] result;
00212 return 0;
00213 }
00214 result[pos] = 0;
00215 *output_len = pos;
00216 return result;
00217 }
00218
00219 void
00220 ACE_Base64::init ()
00221 {
00222 if (!ACE_Base64::init_)
00223 {
00224 for (ACE_Byte i = 0; i < sizeof (alphabet); ++i)
00225 {
00226 ACE_Base64::decoder_[alphabet[i]] = i;
00227 ACE_Base64::member_ [alphabet[i]] = 1;
00228 }
00229 ACE_Base64::init_ = true;
00230 }
00231 return;
00232 }
00233
00234 ACE_END_VERSIONED_NAMESPACE_DECL