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