DCL 4.0
Loading...
Searching...
No Matches
TransferEncoding.cpp
Go to the documentation of this file.
1#include <ctype.h>
2#define __DCL_INCLUDED_CTYPE_H
3
4#include <dcl/Object.h>
5
6#if __DCL_HAVE_ALLOC_DEBUG
7#undef __DCL_ALLOC_LEVEL
8#define __DCL_ALLOC_LEVEL __DCL_ALLOC_INTERNAL
9#endif
10
12
13#if __DCL_DEBUG
14#undef __THIS_FILE__
15static const char_t* __THIS_FILE__ = __T("dcl/TransferEncoding.cpp");
16#endif
17
18__DCL_BEGIN_NAMESPACE
19
20#undef CR
21#undef LF
22#undef TAB
23
24#define CR 13 // Carriage Return
25#define LF 10 // Line Feed
26#define TAB 9 // HT Horizontal TAB
27
28#undef MAX_LINE_LENGTH
29#define MAX_LINE_LENGTH 76
30
31// RFC2045 6.7
32ByteString QuotedPrintableEncoder::encode(const ByteString& _str)
33{
34 __DCL_ASSERT(_str.length() > 0);
35
36 static const char aHex[] = "0123456789ABCDEF";
37 const byte_t* src = (const byte_t*)_str.data();
38 size_t len = _str.length();
39
40 ByteBuffer* buf = ByteBuffer::create(
41 3 * len + (6 * len) / MAX_LINE_LENGTH + 3);
42 byte_t* dest = (byte_t*) buf->data();
43 int lineCount = 0;
44 while(len--)
45 {
46 byte_t c = *src++;
47 if ((c == CR) && (*src == LF) && len)
48 {
49 // hard line break
50 *dest++ = CR;
51 *dest++ = *src++;
52 len--;
53 lineCount = 0; // reset line count
54 }
55 else
56 { // not hard line break
57 if (//iscntrl(c)
58// ((0x00 <= c) && (c <= 0x1f)) // 0x00 ~ 0x1f
59 (c <= 0x1f)
60 || (c == 0x7f)
61 || (c & 0x80) // 0x80 ~
62 || (c == '=')
63 || ((c == ' ') && (*src == CR)))
64 {
65 // quoting required
66 if ((lineCount + 3) > MAX_LINE_LENGTH)
67 {
68 // soft line break
69 *dest++ = '=';
70 *dest++ = CR;
71 *dest++ = LF;
72 lineCount = 0; // reset
73 }
74
75 *dest++ = '=';
76 *dest++ = aHex[c >> 4];
77 *dest++ = aHex[c & 0x0f];
78 lineCount += 3;
79 }
80 else
81 {
82 // ordinary character
83 if ((lineCount + 1) > MAX_LINE_LENGTH)
84 {
85 // soft line break
86 *dest++ = '=';
87 *dest++ = CR;
88 *dest++ = LF;
89 lineCount = 0; // reset
90 }
91
92 *dest++ = c;
93 lineCount++;
94 }
95 }
96 }
97 *dest = __T('\0');
98 __DCL_ASSERT(buf->data() <= (char*) dest);
99 buf->__dataLength = (char*) dest - buf->data();
100 __DCL_ASSERT(buf->__dataLength <= buf->__allocLength);
101
102 ByteString r = buf;
103 buf->release();
104 return r;
105}
106
107inline char hex2int(int c)
108{
109 if (isdigit(c))
110 return c - '0';
111 else if (('A' <= c) && (c <= 'F'))
112 return c - 'A' + 10;
113 else if (('a' <= c) && (c <= 'f'))
114 return c - 'a' + 10;
115 else
116 {
117 __DCL_ASSERT(false);
118 return -1;
119 }
120}
121
122ByteString QuotedPrintableDecoder::decode(const ByteString& _str)
123{
124 __DCL_ASSERT(_str.length() > 0);
125
126 const byte_t* src = (byte_t*)_str.data();
127 ByteBuffer* buf = ByteBuffer::create(_str.length()); // + 1);
128 byte_t* dest = (byte_t*) buf->data();
129
130 size_t i = 0;
131 size_t j = 0;
132 while(src[i])
133 {
134 if ('=' == src[i])
135 {
136 // quotered character
137
138 if (src[i + 1] && src[i + 2]
139 && isxdigit(src[i + 1]) && isxdigit(src[i + 2]))
140 {
141 dest[j++] = (hex2int(src[i + 1]) << 4)
142 + hex2int(src[i + 2]);
143 i += 3;
144 }
145 else
146 {
147 // check for soft line break
148 int k = 1;
149 while(src[i + k] &&
150 ((src[i + k] == ' ') || (src[i + k] == TAB)))
151 {
152 // skip space or tab character
153 k++;
154 }
155
156 if (!src[i + k])
157 i += k; // end of line reached
158 else if ((src[i + k] == CR) && (src[i + k + 1] == LF))
159 i += k + 2; // CRLF
160 else if ((src[i + k] == CR) || (src[i + k] == LF))
161 i += k + 1; // CR or LF
162 else
163 dest[j++] = src[i++];
164 }
165 }
166 else
167 {
168 // literal
169 dest[j++] = src[i++];
170 }
171 }
172
173 dest[j] = __T('\0');
174 __DCL_ASSERT(j <= buf->__allocLength);
175 buf->__dataLength = j;
176
177 ByteString r = buf;
178 buf->release();
179 return r;
180}
181
182#define BASE64_PADDING_CHAR '='
183
184static const char aBase64Table[] =
185{
186 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
187 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
188 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
189 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
190 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
191};
192
193ByteString Base64Encoder::encode(const ByteString& _str)
194{
195 __DCL_ASSERT(_str.length() > 0);
196
197 size_t nAllocLength = ((_str.length() + 2) / 3) * 4;
198 nAllocLength += 2 * ((nAllocLength / MAX_LINE_LENGTH) + 1); // + 1;
199
200 ByteBuffer* buf = ByteBuffer::create(nAllocLength);
201 byte_t* dest = (byte_t*) buf->data();
202
203 const byte_t* src = (byte_t*)_str.data();
204 size_t len = _str.length();
205 for(size_t i = 1; len >= 3; len -= 3, src += 3)
206 {
207 *dest++ = aBase64Table[src[0] >> 2];
208 *dest++ = aBase64Table[((src[0] & 0x03) << 4) + (src[1] >> 4)];
209 *dest++ = aBase64Table[((src[1] & 0x0f) << 2) + (src[2] >> 6)];
210 *dest++ = aBase64Table[src[2] & 0x3f];
211 if ((i++) == 19) // reached MAX_LINE_LENGTH == (i * 4) == 76
212 {
213 *dest++ = CR;
214 *dest++ = LF;
215 i = 1;
216 }
217 }
218
219 if (len)
220 {
221 *dest++ = aBase64Table[src[0] >> 2];
222 if (len > 1)
223 {
224 *dest++ = aBase64Table[((src[0] & 0x03) << 4) + (src[1] >> 4)];
225 *dest++ = aBase64Table[((src[1] & 0x0f) << 2)];
226 *dest++ = BASE64_PADDING_CHAR;
227 }
228 else
229 {
230 *dest++ = aBase64Table[((src[0] & 0x03) << 4)];
231 *dest++ = BASE64_PADDING_CHAR;
232 *dest++ = BASE64_PADDING_CHAR;
233 }
234 }
235
236 *dest++ = CR;
237 *dest++ = LF;
238
239 *dest = __T('\0');
240 __DCL_ASSERT(buf->data() <= (char*) dest);
241 buf->__dataLength = (char*) dest - buf->data();
242 __DCL_ASSERT(buf->__dataLength <= buf->__allocLength);
243
244 ByteString r = buf;
245 buf->release();
246 return r;
247}
248
249static const char aReverseTable[256] =
250{
251 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
252 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
253 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
254 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
255 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
256 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
257 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
258 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
259 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
260 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
261 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
262 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
263 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
264 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
265 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
266 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
267};
268
269ByteString Base64Decoder::decode(const ByteString& _str)
270{
271 __DCL_ASSERT(_str.length() > 0);
272
273 ByteBuffer* buf = ByteBuffer::create(_str.length());
274 byte_t* dest = (byte_t*) buf->data();
275 const byte_t* src = (const byte_t*)_str.data();
276 size_t len = _str.length();
277
278 size_t i = 0;
279 int ch = 0;
280 while(len--)
281 {
282 ch = *src++;
283 if (ch == BASE64_PADDING_CHAR)
284 break;
285
286 ch = aReverseTable[ch];
287 if (ch < 0)
288 continue; // junk
289
290 switch(i % 4)
291 {
292 case 0 :
293 *dest = ch << 2; // byte 1 high 6 bits
294 break;
295 case 1 :
296 *dest++ |= ch >> 4; // byte 1 low 2 bits
297 *dest = ch << 4; // byte 2 high 4 bits
298 break;
299 case 2 :
300 *dest++ |= ch >> 2; // byte 2 low 4 bits
301 *dest = ch << 6; // byte 3 high 2 bits
302 break;
303 case 3 :
304 *dest++ |= ch; // byte 3 low 6bits
305 break;
306 }
307 i++;
308 }
309
310 __DCL_ASSERT(buf->data() <= (char*) dest);
311 size_t nNewLength = (char*) dest - buf->data();
312 if (ch == BASE64_PADDING_CHAR)
313 {
314 switch(i % 4)
315 {
316 case 0 :
317 case 1 :
318 nNewLength = 0;
319 break;
320 case 2 :
321 if (len && (*src == BASE64_PADDING_CHAR))
322 break;
323 else
324 nNewLength = 0;
325 case 3 :
326 ;
327 }
328 }
329
330 buf->__dataLength = nNewLength;
331 __DCL_ASSERT(buf->__dataLength <= buf->__allocLength);
332 *(buf->data() + buf->__dataLength) = __T('\0');
333
334 ByteString r = buf;
335 buf->release();
336 return r;
337}
338
339__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
wchar_t char_t
Definition Config.h:275
unsigned char byte_t
Definition Config.h:274
#define LF
#define CR
#define __DCL_ASSERT(expr)
Definition Object.h:371
#define __T(str)
Definition Object.h:44
ByteString r
size_t len
ByteBuffer * buf
#define BASE64_PADDING_CHAR
char hex2int(int c)
#define TAB
#define MAX_LINE_LENGTH
static ByteString encode(const ByteString &_str)
static ByteString decode(const ByteString &_str)
static ByteString encode(const ByteString &_str)