Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include <comphelper/string.hxx>
21 : : #include <sal/types.h>
22 : : #include <rtl/memory.h>
23 : : #include <rtl/strbuf.hxx>
24 : : #include <tools/cachestr.hxx>
25 : : #include <tools/inetmsg.hxx>
26 : : #include <tools/inetstrm.hxx>
27 : :
28 : : #include <ctype.h> // toupper
29 : :
30 : 0 : inline sal_Bool SAL_CALL ascii_isWhitespace( sal_Unicode ch )
31 : : {
32 [ # # ][ # # ]: 0 : return ((ch <= 0x20) && ch);
33 : : }
34 : :
35 : : #define CONSTASCII_STRINGPARAM(a) (a), RTL_TEXTENCODING_ASCII_US
36 : :
37 : : /** Quoted-Printable Encoding */
38 : : class INetMessageEncodeQPStream_Impl : public INetMessageIStream
39 : : {
40 : : SvStream *pMsgStrm;
41 : :
42 : : sal_uIntPtr nMsgBufSiz;
43 : : sal_Char *pMsgBuffer;
44 : : sal_Char *pMsgRead;
45 : : sal_Char *pMsgWrite;
46 : :
47 : : sal_uIntPtr nTokBufSiz;
48 : : sal_Char *pTokBuffer;
49 : : sal_Char *pTokRead;
50 : : sal_Char *pTokWrite;
51 : :
52 : : INetMessageStreamState eState;
53 : : sal_Bool bDone;
54 : :
55 : : virtual int GetMsgLine (sal_Char *pData, sal_uIntPtr nSize);
56 : :
57 : : public:
58 : : INetMessageEncodeQPStream_Impl (sal_uIntPtr nMsgBufferSize = 1024);
59 : : virtual ~INetMessageEncodeQPStream_Impl (void);
60 : : };
61 : :
62 : : /** Quoted-Printable Decoding */
63 : : class INetMessageDecodeQPStream_Impl : public INetMessageOStream
64 : : {
65 : : INetMessageStreamState eState;
66 : : SvMemoryStream *pMsgBuffer;
67 : :
68 : : sal_uIntPtr nTokBufLen;
69 : : sal_Char pTokBuffer[4];
70 : :
71 : : virtual int PutMsgLine (const sal_Char *pData, sal_uIntPtr nSize);
72 : :
73 : : public:
74 : : INetMessageDecodeQPStream_Impl (void);
75 : : virtual ~INetMessageDecodeQPStream_Impl (void);
76 : : };
77 : :
78 : : /** Base64 Encoding */
79 : : class INetMessageEncode64Stream_Impl : public INetMessageIStream
80 : : {
81 : : SvStream *pMsgStrm;
82 : :
83 : : sal_uIntPtr nMsgBufSiz;
84 : : sal_uInt8 *pMsgBuffer;
85 : : sal_uInt8 *pMsgRead;
86 : : sal_uInt8 *pMsgWrite;
87 : :
88 : : sal_uIntPtr nTokBufSiz;
89 : : sal_Char *pTokBuffer;
90 : : sal_Char *pTokRead;
91 : : sal_Char *pTokWrite;
92 : :
93 : : sal_Bool bDone;
94 : :
95 : : virtual int GetMsgLine (sal_Char *pData, sal_uIntPtr nSize);
96 : :
97 : : public:
98 : : INetMessageEncode64Stream_Impl (sal_uIntPtr nMsgBufferSize = 2048);
99 : : virtual ~INetMessageEncode64Stream_Impl (void);
100 : : };
101 : :
102 : : /** Base64 Decoding */
103 : : class INetMessageDecode64Stream_Impl : public INetMessageOStream
104 : : {
105 : : INetMessageStreamState eState;
106 : :
107 : : sal_uIntPtr nMsgBufSiz;
108 : : sal_Char *pMsgBuffer;
109 : : sal_Char *pMsgRead;
110 : : sal_Char *pMsgWrite;
111 : :
112 : : virtual int PutMsgLine (const sal_Char *pData, sal_uIntPtr nSize);
113 : :
114 : : public:
115 : : INetMessageDecode64Stream_Impl (sal_uIntPtr nMsgBufferSize = 128);
116 : : virtual ~INetMessageDecode64Stream_Impl (void);
117 : : };
118 : :
119 : : // INetIStream
120 : :
121 : 0 : INetIStream::INetIStream ()
122 : : {
123 : 0 : }
124 : :
125 : 0 : INetIStream::~INetIStream (void)
126 : : {
127 [ # # ]: 0 : }
128 : :
129 : 0 : int INetIStream::Read (sal_Char *pData, sal_uIntPtr nSize)
130 : : {
131 : 0 : return GetData (pData, nSize);
132 : : }
133 : :
134 : : // INetOStream
135 : :
136 : 0 : INetOStream::INetOStream ()
137 : : {
138 : 0 : }
139 : :
140 : 0 : INetOStream::~INetOStream (void)
141 : : {
142 [ # # ]: 0 : }
143 : :
144 : 0 : int INetOStream::Write (const sal_Char *pData, sal_uIntPtr nSize)
145 : : {
146 : 0 : return PutData (pData, nSize);
147 : : }
148 : :
149 : : // INetMessageIStream
150 : :
151 : 0 : INetMessageIStream::INetMessageIStream (sal_uIntPtr nBufferSize)
152 : : : pSourceMsg (NULL),
153 : : bHeaderGenerated (sal_False),
154 : : nBufSiz (nBufferSize),
155 : : pMsgStrm (NULL),
156 [ # # ][ # # ]: 0 : pMsgBuffer (new SvMemoryStream)
157 : : {
158 : 0 : pMsgBuffer->SetStreamCharSet (RTL_TEXTENCODING_ASCII_US);
159 [ # # ]: 0 : pBuffer = new sal_Char[nBufSiz];
160 : 0 : pRead = pWrite = pBuffer;
161 : 0 : }
162 : :
163 : 0 : INetMessageIStream::~INetMessageIStream (void)
164 : : {
165 [ # # ]: 0 : delete [] pBuffer;
166 [ # # ][ # # ]: 0 : delete pMsgBuffer;
167 [ # # ][ # # ]: 0 : delete pMsgStrm;
168 [ # # ]: 0 : }
169 : :
170 : 0 : int INetMessageIStream::GetData (sal_Char *pData, sal_uIntPtr nSize)
171 : : {
172 [ # # ]: 0 : if (pSourceMsg == NULL) return INETSTREAM_STATUS_ERROR;
173 : :
174 : 0 : sal_Char *pWBuf = pData;
175 : 0 : sal_Char *pWEnd = pData + nSize;
176 : :
177 [ # # ]: 0 : while (pWBuf < pWEnd)
178 : : {
179 : : // Caller's buffer not yet filled.
180 : 0 : sal_uIntPtr n = pRead - pWrite;
181 [ # # ]: 0 : if (n > 0)
182 : : {
183 : : // Bytes still in buffer.
184 : 0 : sal_uIntPtr m = pWEnd - pWBuf;
185 [ # # ]: 0 : if (m < n) n = m;
186 [ # # ]: 0 : for (sal_uIntPtr i = 0; i < n; i++) *pWBuf++ = *pWrite++;
187 : : }
188 : : else
189 : : {
190 : : // Buffer empty. Reset to <Begin-of-Buffer>.
191 : 0 : pRead = pWrite = pBuffer;
192 : :
193 : : // Read next message line.
194 : 0 : int nRead = GetMsgLine (pBuffer, nBufSiz);
195 [ # # ]: 0 : if (nRead > 0)
196 : : {
197 : : // Set read pointer.
198 : 0 : pRead = pBuffer + nRead;
199 : : }
200 : : else
201 : : {
202 [ # # ]: 0 : if (!bHeaderGenerated)
203 : : {
204 : : // Header generated. Insert empty line.
205 : 0 : bHeaderGenerated = sal_True;
206 : 0 : *pRead++ = '\r';
207 : 0 : *pRead++ = '\n';
208 : : }
209 : : else
210 : : {
211 : : // Body generated.
212 : 0 : return (pWBuf - pData);
213 : : }
214 : : }
215 : : }
216 : : }
217 : 0 : return (pWBuf - pData);
218 : : }
219 : :
220 : 0 : int INetMessageIStream::GetMsgLine (sal_Char *pData, sal_uIntPtr nSize)
221 : : {
222 [ # # ]: 0 : if (pSourceMsg == NULL) return INETSTREAM_STATUS_ERROR;
223 : :
224 : 0 : sal_Char *pWBuf = pData;
225 : 0 : sal_Char *pWEnd = pData + nSize;
226 : :
227 [ # # ]: 0 : if (!bHeaderGenerated)
228 : : {
229 : : sal_uIntPtr i, n;
230 : :
231 [ # # ]: 0 : if (pMsgBuffer->Tell() == 0)
232 : : {
233 : : // Insert formatted header into buffer.
234 : 0 : n = pSourceMsg->GetHeaderCount();
235 [ # # ]: 0 : for (i = 0; i < n; i++)
236 : : {
237 [ # # ]: 0 : INetMessageHeader aHeader (pSourceMsg->GetHeaderField(i));
238 [ # # ]: 0 : if (aHeader.GetValue().getLength())
239 : : {
240 : : // NYI: Folding long lines.
241 [ # # ]: 0 : *pMsgBuffer << aHeader.GetName().getStr();
242 [ # # ]: 0 : *pMsgBuffer << ": ";
243 [ # # ]: 0 : *pMsgBuffer << aHeader.GetValue().getStr();
244 [ # # ]: 0 : *pMsgBuffer << "\r\n";
245 : : }
246 : 0 : }
247 : :
248 : 0 : pMsgWrite = (sal_Char *)(pMsgBuffer->GetData());
249 : 0 : pMsgRead = pMsgWrite + pMsgBuffer->Tell();
250 : : }
251 : :
252 : 0 : n = pMsgRead - pMsgWrite;
253 [ # # ]: 0 : if (n > 0)
254 : : {
255 : : // Move to caller.
256 [ # # ]: 0 : if (nSize < n) n = nSize;
257 [ # # ]: 0 : for (i = 0; i < n; i++) *pWBuf++ = *pMsgWrite++;
258 : : }
259 : : else
260 : : {
261 : : // Reset buffer.
262 : 0 : pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
263 : : }
264 : : }
265 : : else
266 : : {
267 [ # # ]: 0 : if (pSourceMsg->GetDocumentLB())
268 : : {
269 [ # # ]: 0 : if (pMsgStrm == NULL)
270 [ # # ]: 0 : pMsgStrm = new SvStream (pSourceMsg->GetDocumentLB());
271 : :
272 : 0 : sal_uIntPtr nRead = pMsgStrm->Read (pWBuf, (pWEnd - pWBuf));
273 : 0 : pWBuf += nRead;
274 : : }
275 : : }
276 : 0 : return (pWBuf - pData);
277 : : }
278 : :
279 : : // INetMessageOStream
280 : :
281 : 0 : INetMessageOStream::INetMessageOStream (void)
282 : : : pTargetMsg (NULL),
283 : : bHeaderParsed (sal_False),
284 : : eOState (INETMSG_EOL_BEGIN),
285 [ # # ][ # # ]: 0 : pMsgBuffer (new SvMemoryStream)
286 : : {
287 : 0 : }
288 : :
289 : 0 : INetMessageOStream::~INetMessageOStream (void)
290 : : {
291 [ # # ]: 0 : if (pMsgBuffer->Tell() > 0)
292 [ # # ][ # # ]: 0 : PutMsgLine ((const sal_Char *) pMsgBuffer->GetData(), pMsgBuffer->Tell());
293 [ # # ][ # # ]: 0 : delete pMsgBuffer;
294 : :
295 [ # # ]: 0 : if (pTargetMsg)
296 : : {
297 : : SvOpenLockBytes *pLB =
298 [ # # ][ # # ]: 0 : PTR_CAST (SvOpenLockBytes, pTargetMsg->GetDocumentLB());
[ # # ][ # # ]
299 [ # # ]: 0 : if (pLB)
300 : : {
301 [ # # ]: 0 : pLB->Flush();
302 [ # # ]: 0 : pLB->Terminate();
303 : : }
304 : : }
305 [ # # ]: 0 : }
306 : :
307 : : /// Simple Field Parsing (RFC822, Appendix B)
308 : 0 : int INetMessageOStream::PutData (const sal_Char *pData, sal_uIntPtr nSize)
309 : : {
310 [ # # ]: 0 : if (pTargetMsg == NULL) return INETSTREAM_STATUS_ERROR;
311 : :
312 : 0 : const sal_Char *pStop = (pData + nSize);
313 : :
314 [ # # ][ # # ]: 0 : while (!bHeaderParsed && (pData < pStop))
[ # # ]
315 : : {
316 [ # # ]: 0 : if (eOState == INETMSG_EOL_BEGIN)
317 : : {
318 [ # # ][ # # ]: 0 : if ((*pData == '\r') || (*pData == '\n'))
319 : : {
320 : : /*
321 : : * Empty Line. Separates header fields from message body.
322 : : * Skip this and any 2nd line break character (if any).
323 : : */
324 : 0 : pData++;
325 [ # # ][ # # ]: 0 : if ((pData < pStop) && ((*pData == '\r') || (*pData == '\n')))
[ # # ]
326 : 0 : pData++;
327 : :
328 : : // Emit any buffered last header field.
329 [ # # ]: 0 : if (pMsgBuffer->Tell() > 0)
330 : : {
331 : 0 : *pMsgBuffer << '\0';
332 : : int status = PutMsgLine (
333 : 0 : (const sal_Char *) pMsgBuffer->GetData(),
334 : 0 : pMsgBuffer->Tell());
335 [ # # ]: 0 : if (status != INETSTREAM_STATUS_OK) return status;
336 : : }
337 : :
338 : : // Reset to begin.
339 : 0 : eOState = INETMSG_EOL_BEGIN;
340 : 0 : pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
341 : :
342 : : // Mark header parsed.
343 : 0 : bHeaderParsed = sal_True;
344 : : }
345 [ # # ][ # # ]: 0 : else if ((*pData == ' ') || (*pData == '\t'))
346 : : {
347 : : // Continuation line. Unfold multi-line field-body.
348 : 0 : *pMsgBuffer << ' ';
349 : 0 : pData++;
350 : : }
351 : : else
352 : : {
353 : : // Begin of new header field.
354 [ # # ]: 0 : if (pMsgBuffer->Tell() > 0)
355 : : {
356 : : // Emit buffered header field now.
357 : 0 : *pMsgBuffer << '\0';
358 : : int status = PutMsgLine (
359 : 0 : (const sal_Char *) pMsgBuffer->GetData(),
360 : 0 : pMsgBuffer->Tell());
361 [ # # ]: 0 : if (status != INETSTREAM_STATUS_OK) return status;
362 : : }
363 : :
364 : : // Reset to begin of buffer.
365 : 0 : pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
366 : :
367 : : // Insert current character into buffer.
368 : 0 : *pMsgBuffer << *pData++;
369 : : }
370 : :
371 : : // Search for next line break character.
372 [ # # ]: 0 : if (!bHeaderParsed) eOState = INETMSG_EOL_SCR;
373 : : }
374 [ # # ]: 0 : else if (eOState == INETMSG_EOL_FCR)
375 : : {
376 : : // Skip line break character.
377 : 0 : pData++;
378 : :
379 : : // Mark begin of line.
380 : 0 : eOState = INETMSG_EOL_BEGIN;
381 : : }
382 [ # # ][ # # ]: 0 : else if ((*pData == '\r') || (*pData == '\n'))
383 : : {
384 [ # # ]: 0 : if (*pData == '\r') pData++;
385 : 0 : eOState = INETMSG_EOL_FCR;
386 : : }
387 [ # # ]: 0 : else if (ascii_isWhitespace (*pData & 0x7f))
388 : : {
389 : : // Any <LWS> is folded into a single <SP> character.
390 : 0 : sal_Char c = *((const sal_Char *) pMsgBuffer->GetData() + pMsgBuffer->Tell() - 1);
391 [ # # ]: 0 : if (!ascii_isWhitespace (c & 0x7f)) *pMsgBuffer << ' ';
392 : :
393 : : // Skip over this <LWS> character.
394 : 0 : pData++;
395 : : }
396 : : else
397 : : {
398 : : // Any other character is inserted into line buffer.
399 : 0 : *pMsgBuffer << *pData++;
400 : : }
401 : : }
402 : :
403 [ # # ][ # # ]: 0 : if (bHeaderParsed && (pData < pStop))
404 : : {
405 : : // Put message body down-stream.
406 : 0 : return PutMsgLine (pData, (pStop - pData));
407 : : }
408 : :
409 : 0 : return INETSTREAM_STATUS_OK;
410 : : }
411 : :
412 : 0 : int INetMessageOStream::PutMsgLine (const sal_Char *pData, sal_uIntPtr nSize)
413 : : {
414 : : // Check for message container.
415 [ # # ]: 0 : if (pTargetMsg == NULL) return INETSTREAM_STATUS_ERROR;
416 : :
417 : : // Check for header or body.
418 [ # # ]: 0 : if (!IsHeaderParsed())
419 : : {
420 : 0 : rtl::OString aField(pData);
421 : 0 : sal_Int32 nPos = aField.indexOf(':');
422 [ # # ]: 0 : if (nPos != -1)
423 : : {
424 : : rtl::OString aName(
425 : 0 : aField.copy(0, nPos));
426 : : rtl::OString aValue(
427 : 0 : aField.copy(nPos + 1, aField.getLength() - nPos + 1));
428 [ # # ]: 0 : aValue = comphelper::string::stripStart(aValue, ' ');
429 : :
430 : : pTargetMsg->SetHeaderField (
431 [ # # ]: 0 : INetMessageHeader (aName, aValue));
432 : 0 : }
433 : : }
434 : : else
435 : : {
436 : : SvOpenLockBytes *pLB =
437 [ # # ][ # # ]: 0 : PTR_CAST(SvOpenLockBytes, pTargetMsg->GetDocumentLB());
[ # # ][ # # ]
438 [ # # ]: 0 : if (pLB == NULL)
439 : 0 : return INETSTREAM_STATUS_WOULDBLOCK;
440 : :
441 : 0 : sal_Size nDocSiz = pTargetMsg->GetDocumentSize();
442 : 0 : sal_Size nWrite = 0;
443 : :
444 [ # # ]: 0 : pLB->FillAppend ((sal_Char *)pData, nSize, &nWrite);
445 : 0 : pTargetMsg->SetDocumentSize (nDocSiz + nWrite);
446 : :
447 [ # # ]: 0 : if (nWrite < nSize) return INETSTREAM_STATUS_ERROR;
448 : : }
449 : 0 : return INETSTREAM_STATUS_OK;
450 : : }
451 : :
452 : : // INetMessageIOStream
453 : :
454 : 0 : INetMessageIOStream::INetMessageIOStream (sal_uIntPtr nBufferSize)
455 : : : INetMessageIStream (nBufferSize),
456 [ # # ]: 0 : INetMessageOStream ()
457 : : {
458 : 0 : }
459 : :
460 [ # # ]: 0 : INetMessageIOStream::~INetMessageIOStream (void)
461 : : {
462 [ # # ]: 0 : }
463 : :
464 : : // INetMessageEncodeQPStream_Impl
465 : :
466 : : static const sal_Char hex2pr[16] = {
467 : : '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
468 : : 'A', 'B', 'C', 'D', 'E', 'F'
469 : : };
470 : :
471 : : static const sal_Char ebcdic[] = {
472 : : '!', '"', '#', '$', '@', '[', '\\', ']', '^', '`', '{', '|', '}', '~'
473 : : };
474 : :
475 : 0 : INetMessageEncodeQPStream_Impl::INetMessageEncodeQPStream_Impl( sal_uIntPtr nMsgBufferSize)
476 : : : INetMessageIStream (),
477 : : pMsgStrm (NULL),
478 : : nMsgBufSiz (nMsgBufferSize),
479 : : nTokBufSiz (80),
480 : : eState (INETMSG_EOL_SCR),
481 : 0 : bDone (sal_False)
482 : : {
483 : 0 : GenerateHeader (sal_False);
484 : :
485 [ # # ]: 0 : pMsgBuffer = new sal_Char[nMsgBufSiz];
486 : 0 : pMsgRead = pMsgWrite = pMsgBuffer;
487 : :
488 [ # # ]: 0 : pTokBuffer = new sal_Char[nTokBufSiz];
489 : 0 : pTokRead = pTokWrite = pTokBuffer;
490 : 0 : }
491 : :
492 : 0 : INetMessageEncodeQPStream_Impl::~INetMessageEncodeQPStream_Impl (void)
493 : : {
494 [ # # ][ # # ]: 0 : delete pMsgStrm;
495 [ # # ]: 0 : delete [] pMsgBuffer;
496 [ # # ]: 0 : delete [] pTokBuffer;
497 [ # # ]: 0 : }
498 : :
499 : 0 : int INetMessageEncodeQPStream_Impl::GetMsgLine (sal_Char *pData, sal_uIntPtr nSize)
500 : : {
501 : 0 : INetMessage *pMsg = GetSourceMessage ();
502 [ # # ]: 0 : if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
503 : :
504 [ # # ]: 0 : if (pMsg->GetDocumentLB() == NULL) return 0;
505 [ # # ][ # # ]: 0 : if (pMsgStrm == NULL) pMsgStrm = new SvStream (pMsg->GetDocumentLB());
506 : :
507 : 0 : sal_Char *pWBuf = pData;
508 [ # # ]: 0 : while (pWBuf < (pData + nSize))
509 : : {
510 : : // Caller's buffer not yet filled.
511 [ # # ]: 0 : if ((pMsgRead - pMsgWrite) > 0)
512 : : {
513 : : // Bytes still in message buffer.
514 [ # # ][ # # ]: 0 : if ((eState != INETMSG_EOL_BEGIN) &&
515 : : ((pTokRead - pTokBuffer) < 72))
516 : : {
517 : : // Token buffer not yet filled.
518 [ # # ]: 0 : if (eState == INETMSG_EOL_FCR)
519 : : {
520 : 0 : eState = INETMSG_EOL_BEGIN;
521 [ # # ]: 0 : if (*pMsgWrite != '\n')
522 : : {
523 : : // Convert orphant <CR> into <CR><LF> sequence.
524 : 0 : *pTokRead++ = '\n';
525 : : }
526 : 0 : *pTokRead++ = *pMsgWrite++;
527 : : }
528 [ # # ][ # # ]: 0 : else if ((*pMsgWrite == ' ') || (*pMsgWrite == '\t'))
529 : : {
530 : 0 : eState = INETMSG_EOL_FSP;
531 : 0 : *pTokRead++ = *pMsgWrite++;
532 : : }
533 [ # # ]: 0 : else if (*pMsgWrite == '\r')
534 : : {
535 : : // Found <CR>.
536 [ # # ]: 0 : if (eState == INETMSG_EOL_FSP)
537 : : {
538 : : // Encode last (trailing space) character.
539 : 0 : sal_uInt8 c = (sal_uInt8)(*(--pTokRead));
540 : 0 : *pTokRead++ = '=';
541 : 0 : *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
542 : 0 : *pTokRead++ = hex2pr[((c & 0x0f) )];
543 : : }
544 : 0 : eState = INETMSG_EOL_FCR;
545 : 0 : *pTokRead++ = *pMsgWrite++;
546 : : }
547 [ # # ]: 0 : else if (*pMsgWrite == '\n')
548 : : {
549 : : // Found <LF> only.
550 [ # # ]: 0 : if (eState == INETMSG_EOL_FSP)
551 : : {
552 : : // Encode last (trailing space) character.
553 : 0 : sal_uInt8 c = (sal_uInt8)(*(--pTokRead));
554 : 0 : *pTokRead++ = '=';
555 : 0 : *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
556 : 0 : *pTokRead++ = hex2pr[((c & 0x0f) )];
557 : : }
558 : 0 : eState = INETMSG_EOL_BEGIN;
559 : :
560 : : // Convert orphant <LF> into <CR><LF> sequence.
561 : 0 : *pTokRead++ = '\r';
562 : 0 : *pTokRead++ = *pMsgWrite++;
563 : : }
564 [ # # ]: 0 : else if (*pMsgWrite == '=')
565 : : {
566 : : // Escape character itself MUST be encoded, of course.
567 : 0 : sal_uInt8 c = (sal_uInt8)(*pMsgWrite++);
568 : 0 : *pTokRead++ = '=';
569 : 0 : *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
570 : 0 : *pTokRead++ = hex2pr[((c & 0x0f) )];
571 : :
572 : 0 : eState = INETMSG_EOL_SCR;
573 : : }
574 [ # # ][ # # ]: 0 : else if (((sal_uInt8)(*pMsgWrite) > 0x20) &&
575 : : ((sal_uInt8)(*pMsgWrite) < 0x7f) )
576 : : {
577 : : /*
578 : : * Some printable ASCII character.
579 : : * (Encode EBCDIC special characters (NYI)).
580 : : */
581 : 0 : *pTokRead++ = *pMsgWrite++;
582 : 0 : eState = INETMSG_EOL_SCR;
583 : : }
584 : : else
585 : : {
586 : : // Encode any other character.
587 : 0 : sal_uInt8 c = (sal_uInt8)(*pMsgWrite++);
588 : 0 : *pTokRead++ = '=';
589 : 0 : *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
590 : 0 : *pTokRead++ = hex2pr[((c & 0x0f) )];
591 : :
592 : 0 : eState = INETMSG_EOL_SCR;
593 : 0 : }
594 : : }
595 : : else
596 : : {
597 : : // Check for maximum line length.
598 [ # # ]: 0 : if (eState != INETMSG_EOL_BEGIN)
599 : : {
600 : : // Insert soft line break.
601 : 0 : *pTokRead++ = '=';
602 : 0 : *pTokRead++ = '\r';
603 : 0 : *pTokRead++ = '\n';
604 : :
605 : 0 : eState = INETMSG_EOL_BEGIN;
606 : : }
607 : :
608 : : // Copy to caller's buffer.
609 [ # # ]: 0 : if ((pTokRead - pTokWrite) > 0)
610 : : {
611 : : // Bytes still in token buffer.
612 : 0 : *pWBuf++ = *pTokWrite++;
613 : : }
614 : : else
615 : : {
616 : : // Token buffer empty. Reset to <Begin-of-Buffer>.
617 : 0 : pTokRead = pTokWrite = pTokBuffer;
618 : 0 : eState = INETMSG_EOL_SCR;
619 : : }
620 : : }
621 : : }
622 : : else
623 : : {
624 : : // Message buffer empty. Reset to <Begin-of-Buffer>.
625 : 0 : pMsgRead = pMsgWrite = pMsgBuffer;
626 : :
627 : : // Read next message block.
628 : 0 : sal_uIntPtr nRead = pMsgStrm->Read (pMsgBuffer, nMsgBufSiz);
629 [ # # ]: 0 : if (nRead > 0)
630 : : {
631 : : // Set read pointer.
632 : 0 : pMsgRead = (pMsgBuffer + nRead);
633 : : }
634 : : else
635 : : {
636 : : // Nothing more ro read.
637 [ # # ]: 0 : if (!bDone)
638 : : {
639 : : // Append final <CR><LF> and mark we're done.
640 : 0 : *pTokRead++ = '\r';
641 : 0 : *pTokRead++ = '\n';
642 : :
643 : 0 : bDone = sal_True;
644 : : }
645 : : else
646 : : {
647 : : // Already done all encoding.
648 [ # # ]: 0 : if ((pTokRead - pTokWrite) > 0)
649 : : {
650 : : // Bytes still in token buffer.
651 : 0 : *pWBuf++ = *pTokWrite++;
652 : : }
653 : : else
654 : : {
655 : : // Token buffer empty. Reset to <Begin-of-Buffer>.
656 : 0 : pTokRead = pTokWrite = pTokBuffer;
657 : :
658 : : // Return.
659 : 0 : return (pWBuf - pData);
660 : : }
661 : : }
662 : : }
663 : : }
664 : : }
665 : 0 : return (pWBuf - pData);
666 : : }
667 : :
668 : : // INetMessageDecodeQPStream_Impl
669 : :
670 : : static const sal_uInt8 pr2hex[128] = {
671 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
672 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
673 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
674 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
675 : :
676 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
677 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
678 : : 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
679 : : 0x08, 0x09, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
680 : :
681 : : 0x10, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
682 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
683 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
684 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
685 : :
686 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
687 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
688 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
689 : : 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
690 : : };
691 : :
692 : 0 : INetMessageDecodeQPStream_Impl::INetMessageDecodeQPStream_Impl (void)
693 : : : INetMessageOStream (),
694 : : eState (INETMSG_EOL_BEGIN),
695 [ # # ]: 0 : pMsgBuffer (new SvMemoryStream),
696 [ # # ]: 0 : nTokBufLen (0)
697 : : {
698 : 0 : ParseHeader (sal_False);
699 : 0 : }
700 : :
701 : 0 : INetMessageDecodeQPStream_Impl::~INetMessageDecodeQPStream_Impl (void)
702 : : {
703 [ # # ][ # # ]: 0 : delete pMsgBuffer;
704 [ # # ]: 0 : }
705 : :
706 : 0 : int INetMessageDecodeQPStream_Impl::PutMsgLine (
707 : : const sal_Char *pData, sal_uIntPtr nSize)
708 : : {
709 : 0 : INetMessage *pMsg = GetTargetMessage();
710 [ # # ]: 0 : if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
711 : :
712 [ # # ][ # # ]: 0 : SvOpenLockBytes * pLB = PTR_CAST(SvOpenLockBytes, pMsg->GetDocumentLB());
713 [ # # ]: 0 : if (pLB == NULL) return INETSTREAM_STATUS_WOULDBLOCK;
714 : :
715 : 0 : const sal_Char *pStop = pData + nSize;
716 [ # # ]: 0 : while (pData < pStop)
717 : : {
718 [ # # ]: 0 : if (eState == INETMSG_EOL_FESC)
719 : : {
720 : 0 : *(pTokBuffer + nTokBufLen++) = static_cast< char >(toupper(*pData));
721 : 0 : pData++;
722 [ # # ]: 0 : if (nTokBufLen == 2)
723 : : {
724 [ # # ][ # # ]: 0 : if ((*pTokBuffer == '\r') || (*pTokBuffer == '\n'))
725 : : {
726 : : // Soft line break (=<CR><LF>). Emit buffer now.
727 : 0 : eState = INETMSG_EOL_BEGIN;
728 : : }
729 : : else
730 : : {
731 : : // Decode token.
732 : : *pMsgBuffer << sal_uInt8 (
733 : 0 : (pr2hex[(int)(pTokBuffer[0] & 0x7f)] << 4) |
734 : 0 : (pr2hex[(int)(pTokBuffer[1] & 0x7f)] & 15) );
735 : :
736 : : // Search for next <CR>.
737 : 0 : eState = INETMSG_EOL_SCR;
738 : : }
739 : :
740 : : // Reset token buffer.
741 : 0 : nTokBufLen = 0;
742 : : }
743 : : }
744 [ # # ]: 0 : else if (*pData == '=')
745 : : {
746 : : // Found escape character.
747 : 0 : pData++;
748 : 0 : eState = INETMSG_EOL_FESC;
749 : : }
750 [ # # ]: 0 : else if (eState == INETMSG_EOL_FCR)
751 : : {
752 : 0 : *pMsgBuffer << *pData++;
753 : 0 : eState = INETMSG_EOL_BEGIN;
754 : : }
755 [ # # ]: 0 : else if (*pData == '\r')
756 : : {
757 : 0 : *pMsgBuffer << *pData++;
758 : 0 : eState = INETMSG_EOL_FCR;
759 : : }
760 : : else
761 : : {
762 : 0 : *pMsgBuffer << *pData++;
763 : : }
764 : :
765 [ # # ]: 0 : if (eState == INETMSG_EOL_BEGIN)
766 : : {
767 : 0 : sal_Size nRead = pMsgBuffer->Tell();
768 [ # # ]: 0 : if (nRead > 0)
769 : : {
770 : : // Emit buffer.
771 : 0 : sal_Size nDocSiz = pMsg->GetDocumentSize();
772 : 0 : sal_Size nWrite = 0;
773 : :
774 : : pLB->FillAppend (
775 [ # # ][ # # ]: 0 : (sal_Char *)(pMsgBuffer->GetData()), nRead, &nWrite);
776 : 0 : pMsg->SetDocumentSize (nDocSiz + nWrite);
777 : :
778 [ # # ]: 0 : if (nWrite < nRead) return INETSTREAM_STATUS_ERROR;
779 : :
780 [ # # ]: 0 : pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
781 : : }
782 : 0 : eState = INETMSG_EOL_SCR;
783 : : }
784 : : }
785 : 0 : return INETSTREAM_STATUS_OK;
786 : : }
787 : :
788 : : // INetMessageEncode64Stream_Impl
789 : :
790 : : static const sal_Char six2pr[64] = {
791 : : 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
792 : : 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
793 : : 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
794 : : 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
795 : : '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
796 : : };
797 : :
798 : 0 : INetMessageEncode64Stream_Impl::INetMessageEncode64Stream_Impl (
799 : : sal_uIntPtr nMsgBufferSize)
800 : : : INetMessageIStream (),
801 : : pMsgStrm (NULL),
802 : : nMsgBufSiz (nMsgBufferSize),
803 : : nTokBufSiz (80),
804 : 0 : bDone (sal_False)
805 : : {
806 : 0 : GenerateHeader (sal_False);
807 : :
808 [ # # ]: 0 : pMsgBuffer = new sal_uInt8[nMsgBufSiz];
809 : 0 : pMsgRead = pMsgWrite = pMsgBuffer;
810 : :
811 [ # # ]: 0 : pTokBuffer = new sal_Char[nTokBufSiz];
812 : 0 : pTokRead = pTokWrite = pTokBuffer;
813 : 0 : }
814 : :
815 : 0 : INetMessageEncode64Stream_Impl::~INetMessageEncode64Stream_Impl (void)
816 : : {
817 [ # # ][ # # ]: 0 : delete pMsgStrm;
818 [ # # ]: 0 : delete [] pMsgBuffer;
819 [ # # ]: 0 : delete [] pTokBuffer;
820 [ # # ]: 0 : }
821 : :
822 : 0 : int INetMessageEncode64Stream_Impl::GetMsgLine (sal_Char *pData, sal_uIntPtr nSize)
823 : : {
824 : 0 : INetMessage *pMsg = GetSourceMessage ();
825 [ # # ]: 0 : if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
826 : :
827 [ # # ]: 0 : if (pMsg->GetDocumentLB() == NULL) return 0;
828 [ # # ][ # # ]: 0 : if (pMsgStrm == NULL) pMsgStrm = new SvStream (pMsg->GetDocumentLB());
829 : :
830 : 0 : sal_Char *pWBuf = pData;
831 [ # # ]: 0 : while (pWBuf < (pData + nSize))
832 : : {
833 : : // Caller's buffer not yet filled.
834 [ # # ]: 0 : if ((pMsgRead - pMsgWrite) > 0)
835 : : {
836 : : // Bytes still in message buffer.
837 [ # # ]: 0 : if ((pTokRead - pTokBuffer) < 72)
838 : : {
839 : : // Token buffer not yet filled.
840 [ # # # # ]: 0 : switch ((pTokRead - pTokBuffer) % 4)
841 : : {
842 : : case 0:
843 : 0 : *pTokRead++ = six2pr[(int)(*pMsgWrite >> 2)];
844 : 0 : break;
845 : :
846 : : case 1:
847 : : *pTokRead++ = six2pr[
848 : : (int)(((*pMsgWrite << 4) & 060) |
849 : 0 : (((*(pMsgWrite + 1)) >> 4) & 017))];
850 : 0 : pMsgWrite++;
851 : 0 : break;
852 : :
853 : : case 2:
854 : : *pTokRead++ = six2pr[
855 : : (int)(((*pMsgWrite << 2) & 074) |
856 : 0 : (((*(pMsgWrite + 1)) >> 6) & 003))];
857 : 0 : pMsgWrite++;
858 : 0 : break;
859 : :
860 : : default: // == case 3
861 : 0 : *pTokRead++ = six2pr[(int)(*pMsgWrite & 077)];
862 : 0 : pMsgWrite++;
863 : 0 : break;
864 : : }
865 : : }
866 [ # # ]: 0 : else if ((pTokRead - pTokBuffer) == 72)
867 : : {
868 : : // Maximum line length. Append <CR><LF>.
869 : 0 : *pTokRead++ = '\r';
870 : 0 : *pTokRead++ = '\n';
871 : : }
872 : : else
873 : : {
874 [ # # ]: 0 : if ((pTokRead - pTokWrite) > 0)
875 : : {
876 : : // Bytes still in token buffer.
877 : 0 : *pWBuf++ = *pTokWrite++;
878 : : }
879 : : else
880 : : {
881 : : // Token buffer empty. Reset to <Begin-of-Buffer>.
882 : 0 : pTokRead = pTokWrite = pTokBuffer;
883 : : }
884 : : }
885 : : }
886 : : else
887 : : {
888 : : // Message buffer empty. Reset to <Begin-of-Buffer>.
889 : 0 : pMsgRead = pMsgWrite = pMsgBuffer;
890 : :
891 : : // Read next message block.
892 : 0 : sal_uIntPtr nRead = pMsgStrm->Read (pMsgBuffer, nMsgBufSiz);
893 [ # # ]: 0 : if (nRead > 0)
894 : : {
895 : : // Set read pointer.
896 : 0 : pMsgRead = (pMsgBuffer + nRead);
897 : : }
898 : : else
899 : : {
900 : : // Nothing more to read.
901 [ # # ]: 0 : if (!bDone)
902 : : {
903 : : // Append pad character(s) and final <CR><LF>.
904 [ # # # ]: 0 : switch ((pTokRead - pTokBuffer) % 4)
905 : : {
906 : : case 2:
907 : 0 : *pTokRead++ = '=';
908 : : // Fall through for 2nd pad character.
909 : :
910 : : case 3:
911 : 0 : *pTokRead++ = '=';
912 : 0 : break;
913 : :
914 : : default:
915 : 0 : break;
916 : : }
917 : 0 : *pTokRead++ = '\r';
918 : 0 : *pTokRead++ = '\n';
919 : :
920 : : // Mark we're done.
921 : 0 : bDone = sal_True;
922 : : }
923 : : else
924 : : {
925 : : // Already done all encoding.
926 [ # # ]: 0 : if ((pTokRead - pTokWrite) > 0)
927 : : {
928 : : // Bytes still in token buffer.
929 : 0 : *pWBuf++ = *pTokWrite++;
930 : : }
931 : : else
932 : : {
933 : : // Token buffer empty. Reset to <Begin-of-Buffer>.
934 : 0 : pTokRead = pTokWrite = pTokBuffer;
935 : :
936 : : // Reset done flag, if everything has been done.
937 : : // if (pWBuf == pData) bDone = sal_False;
938 : :
939 : : // Return.
940 : 0 : return (pWBuf - pData);
941 : : }
942 : : }
943 : : }
944 : : }
945 : : } // while (pWBuf < (pData + nSize))
946 : 0 : return (pWBuf - pData);
947 : : }
948 : :
949 : : // INetMessageDecode64Stream_Impl
950 : :
951 : : static const sal_uInt8 pr2six[256] = {
952 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
953 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
954 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
955 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
956 : :
957 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
958 : : 0x40, 0x40, 0x40, 0x3E, 0x40, 0x40, 0x40, 0x3F,
959 : : 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
960 : : 0x3C, 0x3D, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
961 : :
962 : : 0x40, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
963 : : 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
964 : : 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
965 : : 0x17, 0x18, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40,
966 : :
967 : : 0x40, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
968 : : 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
969 : : 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
970 : : 0x31, 0x32, 0x33, 0x40, 0x40, 0x40, 0x40, 0x40,
971 : :
972 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
973 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
974 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
975 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
976 : :
977 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
978 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
979 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
980 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
981 : :
982 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
983 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
984 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
985 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
986 : :
987 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
988 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
989 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
990 : : 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
991 : : };
992 : :
993 : 0 : INetMessageDecode64Stream_Impl::INetMessageDecode64Stream_Impl (
994 : : sal_uIntPtr nMsgBufferSize)
995 : : : INetMessageOStream (),
996 : : eState (INETMSG_EOL_SCR),
997 : 0 : nMsgBufSiz (nMsgBufferSize)
998 : : {
999 : 0 : ParseHeader (sal_False);
1000 : :
1001 [ # # ]: 0 : pMsgBuffer = new sal_Char[nMsgBufSiz];
1002 : 0 : pMsgRead = pMsgWrite = pMsgBuffer;
1003 : 0 : }
1004 : :
1005 : 0 : INetMessageDecode64Stream_Impl::~INetMessageDecode64Stream_Impl (void)
1006 : : {
1007 [ # # ]: 0 : delete [] pMsgBuffer;
1008 [ # # ]: 0 : }
1009 : :
1010 : 0 : int INetMessageDecode64Stream_Impl::PutMsgLine (
1011 : : const sal_Char *pData, sal_uIntPtr nSize)
1012 : : {
1013 : 0 : INetMessage *pMsg = GetTargetMessage ();
1014 [ # # ]: 0 : if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
1015 : :
1016 [ # # ][ # # ]: 0 : SvOpenLockBytes * pLB = PTR_CAST(SvOpenLockBytes, pMsg->GetDocumentLB());
1017 [ # # ]: 0 : if (pLB == NULL) return INETSTREAM_STATUS_WOULDBLOCK;
1018 : :
1019 : 0 : const sal_Char *pStop = (pData + nSize);
1020 [ # # ]: 0 : while (pData < pStop)
1021 : : {
1022 [ # # ]: 0 : if (pr2six[(int)(*pData)] > 63)
1023 : : {
1024 : : /*
1025 : : * Character not in base64 alphabet.
1026 : : * Check for <End-of-Stream> or Junk.
1027 : : */
1028 [ # # ]: 0 : if (*pData == '=')
1029 : : {
1030 : : // Final pad character -> Done.
1031 : 0 : sal_Size nDocSiz = pMsg->GetDocumentSize();
1032 : 0 : sal_Size nRead = pMsgWrite - pMsgBuffer;
1033 : 0 : sal_Size nWrite = 0;
1034 : :
1035 [ # # ]: 0 : pLB->FillAppend (pMsgBuffer, nRead, &nWrite);
1036 : 0 : pMsg->SetDocumentSize (nDocSiz + nWrite);
1037 : :
1038 [ # # ]: 0 : if (nWrite < nRead)
1039 : 0 : return INETSTREAM_STATUS_ERROR;
1040 : : else
1041 : 0 : return INETSTREAM_STATUS_LOADED;
1042 : : }
1043 [ # # ]: 0 : else if (eState == INETMSG_EOL_FCR)
1044 : : {
1045 : : // Skip any line break character.
1046 [ # # ][ # # ]: 0 : if ((*pData == '\r') || (*pData == '\n')) pData++;
1047 : :
1048 : : // Store decoded message buffer contents.
1049 : 0 : sal_Size nDocSiz = pMsg->GetDocumentSize();
1050 : 0 : sal_Size nRead = pMsgWrite - pMsgBuffer;
1051 : 0 : sal_Size nWrite = 0;
1052 : :
1053 [ # # ]: 0 : pLB->FillAppend (pMsgBuffer, nRead, &nWrite);
1054 : 0 : pMsg->SetDocumentSize (nDocSiz + nWrite);
1055 : :
1056 [ # # ]: 0 : if (nWrite < nRead) return INETSTREAM_STATUS_ERROR;
1057 : :
1058 : : // Reset to <Begin-of-Buffer>.
1059 : 0 : pMsgWrite = pMsgBuffer;
1060 : 0 : eState = INETMSG_EOL_SCR;
1061 : : }
1062 [ # # ][ # # ]: 0 : else if ((*pData == '\r') || (*pData == '\n'))
1063 : : {
1064 : : // Skip any line break character.
1065 : 0 : pData++;
1066 : 0 : eState = INETMSG_EOL_FCR;
1067 : : }
1068 : : else
1069 : : {
1070 : : // Skip any junk character (may be transmission error).
1071 : 0 : pData++;
1072 : : }
1073 : : }
1074 : : else
1075 : : {
1076 : : // Decode any other character into message buffer.
1077 [ # # # # ]: 0 : switch ((pMsgRead - pMsgBuffer) % 4)
1078 : : {
1079 : : case 0:
1080 : 0 : *pMsgWrite = (pr2six[(int)(*pData++)] << 2);
1081 : 0 : pMsgRead++;
1082 : 0 : break;
1083 : :
1084 : : case 1:
1085 : 0 : *pMsgWrite++ |= (pr2six[(int)(*pData )] >> 4);
1086 : 0 : *pMsgWrite = (pr2six[(int)(*pData++)] << 4);
1087 : 0 : pMsgRead++;
1088 : 0 : break;
1089 : :
1090 : : case 2:
1091 : 0 : *pMsgWrite++ |= (pr2six[(int)(*pData )] >> 2);
1092 : 0 : *pMsgWrite = (pr2six[(int)(*pData++)] << 6);
1093 : 0 : pMsgRead++;
1094 : 0 : break;
1095 : :
1096 : : default: // == case 3
1097 : 0 : *pMsgWrite++ |= (pr2six[(int)(*pData++)]);
1098 : 0 : pMsgRead = pMsgBuffer;
1099 : 0 : break;
1100 : : } // switch ((pMsgRead - pMsgBuffer) % 4)
1101 : : }
1102 : : } // while (pData < pStop)
1103 : 0 : return INETSTREAM_STATUS_OK;
1104 : : }
1105 : :
1106 : : // INetMIMEMessageStream
1107 : :
1108 : 0 : INetMIMEMessageStream::INetMIMEMessageStream (sal_uIntPtr nBufferSize)
1109 : : : INetMessageIOStream (nBufferSize),
1110 : : eState (INETMSG_EOL_BEGIN),
1111 : : nChildIndex (0),
1112 : : pChildStrm (NULL),
1113 : : eEncoding (INETMSG_ENCODING_BINARY),
1114 : : pEncodeStrm (NULL),
1115 : : pDecodeStrm (NULL),
1116 : 0 : pMsgBuffer (NULL)
1117 : : {
1118 : 0 : }
1119 : :
1120 : 0 : INetMIMEMessageStream::~INetMIMEMessageStream (void)
1121 : : {
1122 [ # # ][ # # ]: 0 : delete pChildStrm;
1123 [ # # ][ # # ]: 0 : delete pEncodeStrm;
1124 [ # # ][ # # ]: 0 : delete pDecodeStrm;
1125 [ # # ][ # # ]: 0 : delete pMsgBuffer;
1126 [ # # ]: 0 : }
1127 : :
1128 : : INetMessageEncoding
1129 : 0 : INetMIMEMessageStream::GetMsgEncoding (const String& rContentType)
1130 : : {
1131 [ # # # # ]: 0 : if ((rContentType.CompareIgnoreCaseToAscii ("message" , 7) == 0) ||
[ # # ]
1132 : 0 : (rContentType.CompareIgnoreCaseToAscii ("multipart", 9) == 0) )
1133 : 0 : return INETMSG_ENCODING_7BIT;
1134 : :
1135 [ # # ]: 0 : if (rContentType.CompareIgnoreCaseToAscii ("text", 4) == 0)
1136 : : {
1137 [ # # ]: 0 : if (rContentType.CompareIgnoreCaseToAscii ("text/plain", 10) == 0)
1138 : : {
1139 [ # # ][ # # ]: 0 : if (comphelper::string::getTokenCount(rContentType, '=') > 1)
1140 : : {
1141 [ # # ]: 0 : String aCharset (rContentType.GetToken (1, '='));
1142 [ # # ][ # # ]: 0 : aCharset = comphelper::string::stripStart(aCharset, ' ');
[ # # ]
1143 [ # # ][ # # ]: 0 : aCharset = comphelper::string::stripStart(aCharset, '"');
[ # # ]
1144 : :
1145 [ # # ][ # # ]: 0 : if (aCharset.CompareIgnoreCaseToAscii ("us-ascii", 8) == 0)
1146 : 0 : return INETMSG_ENCODING_7BIT;
1147 : : else
1148 [ # # ]: 0 : return INETMSG_ENCODING_QUOTED;
1149 : : }
1150 : : else
1151 : 0 : return INETMSG_ENCODING_7BIT;
1152 : : }
1153 : : else
1154 : 0 : return INETMSG_ENCODING_QUOTED;
1155 : : }
1156 : :
1157 : 0 : return INETMSG_ENCODING_BASE64;
1158 : : }
1159 : :
1160 : : /// Message Generator
1161 : 0 : int INetMIMEMessageStream::GetMsgLine (sal_Char *pData, sal_uIntPtr nSize)
1162 : : {
1163 : : // Check for message container.
1164 : 0 : INetMIMEMessage *pMsg = GetSourceMessage();
1165 [ # # ]: 0 : if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
1166 : :
1167 : : // Check for header or body.
1168 [ # # ]: 0 : if (!IsHeaderGenerated())
1169 : : {
1170 [ # # ]: 0 : if (eState == INETMSG_EOL_BEGIN)
1171 : : {
1172 : : // Prepare special header fields.
1173 [ # # ]: 0 : if (pMsg->GetParent())
1174 : : {
1175 [ # # ]: 0 : String aPCT (pMsg->GetParent()->GetContentType());
1176 [ # # ][ # # ]: 0 : if (aPCT.CompareIgnoreCaseToAscii ("message/rfc822", 14) == 0)
1177 : : pMsg->SetMIMEVersion (
1178 [ # # ][ # # ]: 0 : String(CONSTASCII_STRINGPARAM("1.0")));
[ # # ]
1179 : : else
1180 [ # # ][ # # ]: 0 : pMsg->SetMIMEVersion (String());
[ # # ][ # # ]
1181 : : }
1182 : : else
1183 : : {
1184 [ # # ][ # # ]: 0 : pMsg->SetMIMEVersion (String(CONSTASCII_STRINGPARAM("1.0")));
[ # # ]
1185 : : }
1186 : :
1187 : : // Check ContentType.
1188 [ # # ]: 0 : String aContentType (pMsg->GetContentType());
1189 [ # # ]: 0 : if (aContentType.Len())
1190 : : {
1191 : : // Determine default Content-Type.
1192 [ # # ][ # # ]: 0 : UniString aDefaultType = pMsg->GetDefaultContentType();
1193 : :
1194 [ # # ]: 0 : if (aDefaultType.CompareIgnoreCaseToAscii (
1195 [ # # ]: 0 : aContentType, aContentType.Len()) == 0)
1196 : : {
1197 : : // No need to specify default.
1198 [ # # ][ # # ]: 0 : pMsg->SetContentType (String());
[ # # ]
1199 [ # # ]: 0 : }
1200 : : }
1201 : :
1202 : : // Check Encoding.
1203 [ # # ][ # # ]: 0 : String aEncoding (pMsg->GetContentTransferEncoding());
1204 [ # # ]: 0 : if (aEncoding.Len())
1205 : : {
1206 : : // Use given Encoding.
1207 [ # # ]: 0 : if (aEncoding.CompareIgnoreCaseToAscii (
1208 [ # # ]: 0 : "base64", 6) == 0)
1209 : 0 : eEncoding = INETMSG_ENCODING_BASE64;
1210 [ # # ]: 0 : else if (aEncoding.CompareIgnoreCaseToAscii (
1211 [ # # ]: 0 : "quoted-printable", 16) == 0)
1212 : 0 : eEncoding = INETMSG_ENCODING_QUOTED;
1213 : : else
1214 : 0 : eEncoding = INETMSG_ENCODING_7BIT;
1215 : : }
1216 : : else
1217 : : {
1218 : : // Use default Encoding for (given|default) Content-Type.
1219 [ # # ]: 0 : if (aContentType.Len() == 0)
1220 : : {
1221 : : // Determine default Content-Type.
1222 [ # # ][ # # ]: 0 : aContentType = pMsg->GetDefaultContentType();
1223 : : }
1224 [ # # ]: 0 : eEncoding = GetMsgEncoding (aContentType);
1225 : : }
1226 : :
1227 : : // Set Content-Transfer-Encoding header.
1228 [ # # ]: 0 : if (eEncoding == INETMSG_ENCODING_BASE64)
1229 : : {
1230 : : // Base64.
1231 : : pMsg->SetContentTransferEncoding (
1232 [ # # ][ # # ]: 0 : String(CONSTASCII_STRINGPARAM("base64")));
[ # # ][ # # ]
1233 : : }
1234 [ # # ]: 0 : else if (eEncoding == INETMSG_ENCODING_QUOTED)
1235 : : {
1236 : : // Quoted-Printable.
1237 : : pMsg->SetContentTransferEncoding (
1238 [ # # ][ # # ]: 0 : String(CONSTASCII_STRINGPARAM("quoted-printable")));
[ # # ][ # # ]
1239 : : }
1240 : : else
1241 : : {
1242 : : // No need to specify default.
1243 [ # # ][ # # ]: 0 : pMsg->SetContentTransferEncoding (String());
[ # # ][ # # ]
1244 : : }
1245 : :
1246 : : // Mark we're done.
1247 [ # # ][ # # ]: 0 : eState = INETMSG_EOL_DONE;
1248 : : }
1249 : :
1250 : : // Generate the message header.
1251 : 0 : int nRead = INetMessageIOStream::GetMsgLine (pData, nSize);
1252 [ # # ]: 0 : if (nRead <= 0)
1253 : : {
1254 : : // Reset state.
1255 : 0 : eState = INETMSG_EOL_BEGIN;
1256 : : }
1257 : 0 : return nRead;
1258 : : }
1259 : : else
1260 : : {
1261 : : // Generate the message body.
1262 [ # # ]: 0 : if (pMsg->IsContainer())
1263 : : {
1264 : : // Encapsulated message body.
1265 [ # # ]: 0 : while (eState == INETMSG_EOL_BEGIN)
1266 : : {
1267 [ # # ]: 0 : if (pChildStrm == NULL)
1268 : : {
1269 : 0 : INetMIMEMessage *pChild = pMsg->GetChild (nChildIndex);
1270 [ # # ]: 0 : if (pChild)
1271 : : {
1272 : : // Increment child index.
1273 : 0 : nChildIndex++;
1274 : :
1275 : : // Create child stream.
1276 [ # # ]: 0 : pChildStrm = new INetMIMEMessageStream;
1277 : 0 : pChildStrm->SetSourceMessage (pChild);
1278 : :
1279 [ # # ]: 0 : if (pMsg->IsMultipart())
1280 : : {
1281 : : // Insert multipart delimiter.
1282 : : rtl::OStringBuffer aDelim(
1283 [ # # ]: 0 : RTL_CONSTASCII_STRINGPARAM("--"));
1284 [ # # ]: 0 : aDelim.append(pMsg->GetMultipartBoundary());
1285 [ # # ]: 0 : aDelim.append(RTL_CONSTASCII_STRINGPARAM("\r\n"));
1286 : :
1287 : 0 : rtl_copyMemory(pData, aDelim.getStr(),
1288 [ # # ]: 0 : aDelim.getLength());
1289 : 0 : return aDelim.getLength();
1290 : : }
1291 : : }
1292 : : else
1293 : : {
1294 : : // No more parts. Mark we're done.
1295 : 0 : eState = INETMSG_EOL_DONE;
1296 : 0 : nChildIndex = 0;
1297 : :
1298 [ # # ]: 0 : if (pMsg->IsMultipart())
1299 : : {
1300 : : // Insert close delimiter.
1301 : : rtl::OStringBuffer aDelim(
1302 [ # # ]: 0 : RTL_CONSTASCII_STRINGPARAM("--"));
1303 [ # # ]: 0 : aDelim.append(pMsg->GetMultipartBoundary());
1304 [ # # ]: 0 : aDelim.append(RTL_CONSTASCII_STRINGPARAM("--\r\n"));
1305 : :
1306 : 0 : rtl_copyMemory (pData, aDelim.getStr(),
1307 [ # # ]: 0 : aDelim.getLength());
1308 : 0 : return aDelim.getLength();
1309 : : }
1310 : : }
1311 : : }
1312 : : else
1313 : : {
1314 : : // Read current child stream.
1315 : 0 : int nRead = pChildStrm->Read (pData, nSize);
1316 [ # # ]: 0 : if (nRead > 0)
1317 : : {
1318 : 0 : return nRead;
1319 : : }
1320 : : else
1321 : : {
1322 : : // Cleanup exhausted child stream.
1323 [ # # ]: 0 : delete pChildStrm;
1324 : 0 : pChildStrm = NULL;
1325 : : }
1326 : : }
1327 : : }
1328 : 0 : return 0;
1329 : : }
1330 : : else
1331 : : {
1332 : : // Single part message body.
1333 [ # # ]: 0 : if (pMsg->GetDocumentLB() == NULL)
1334 : : {
1335 : : // Empty message body.
1336 : 0 : return 0;
1337 : : }
1338 : : else
1339 : : {
1340 : : // Check whether message body needs to be encoded.
1341 [ # # ]: 0 : if (eEncoding == INETMSG_ENCODING_7BIT)
1342 : : {
1343 : : // No Encoding.
1344 : 0 : return INetMessageIOStream::GetMsgLine (pData, nSize);
1345 : : }
1346 : : else
1347 : : {
1348 : : // Apply appropriate Encoding.
1349 [ # # ]: 0 : while (eState == INETMSG_EOL_BEGIN)
1350 : : {
1351 [ # # ]: 0 : if (pEncodeStrm == NULL)
1352 : : {
1353 : : // Create encoder stream.
1354 [ # # ]: 0 : if (eEncoding == INETMSG_ENCODING_QUOTED)
1355 : : {
1356 : : // Quoted-Printable Encoding.
1357 : : pEncodeStrm
1358 [ # # ]: 0 : = new INetMessageEncodeQPStream_Impl;
1359 : : }
1360 : : else
1361 : : {
1362 : : // Base64 Encoding.
1363 : : pEncodeStrm
1364 [ # # ]: 0 : = new INetMessageEncode64Stream_Impl;
1365 : : }
1366 : 0 : pEncodeStrm->SetSourceMessage (pMsg);
1367 : : }
1368 : :
1369 : : // Read encoded message.
1370 : 0 : int nRead = pEncodeStrm->Read (pData, nSize);
1371 [ # # ]: 0 : if (nRead > 0)
1372 : : {
1373 : 0 : return nRead;
1374 : : }
1375 : : else
1376 : : {
1377 : : // Cleanup exhausted encoder stream.
1378 [ # # ]: 0 : delete pEncodeStrm;
1379 : 0 : pEncodeStrm = NULL;
1380 : :
1381 : : // Mark we're done.
1382 : 0 : eState = INETMSG_EOL_DONE;
1383 : : }
1384 : : }
1385 : 0 : return 0;
1386 : : }
1387 : : }
1388 : : }
1389 : : }
1390 : : }
1391 : :
1392 : : /// Message Parser
1393 : 0 : int INetMIMEMessageStream::PutMsgLine (const sal_Char *pData, sal_uIntPtr nSize)
1394 : : {
1395 : : // Check for message container.
1396 : 0 : INetMIMEMessage *pMsg = GetTargetMessage();
1397 [ # # ]: 0 : if (pMsg == NULL) return INETSTREAM_STATUS_ERROR;
1398 : :
1399 : : // Check for header or body.
1400 [ # # ]: 0 : if (!IsHeaderParsed())
1401 : : {
1402 : : // Parse the message header.
1403 : 0 : int nRet = INetMessageIOStream::PutMsgLine (pData, nSize);
1404 : 0 : return nRet;
1405 : : }
1406 : : else
1407 : : {
1408 : 0 : pMsg->SetHeaderParsed();
1409 : : // Parse the message body.
1410 [ # # ]: 0 : if (pMsg->IsContainer())
1411 : : {
1412 : :
1413 : : // Content-Transfer-Encoding MUST be "7bit" (RFC1521).
1414 [ # # ]: 0 : if (pMsg->IsMessage())
1415 : : {
1416 [ # # ]: 0 : if( !pChildStrm )
1417 : : {
1418 : : // Encapsulated message.
1419 [ # # ]: 0 : INetMIMEMessage* pNewMessage = new INetMIMEMessage;
1420 : : pNewMessage->SetDocumentLB (
1421 [ # # ][ # # ]: 0 : new SvAsyncLockBytes(new SvCacheStream, sal_False));
1422 : 0 : pMsg->AttachChild( *pNewMessage, sal_True );
1423 : :
1424 : : // Encapsulated message body. Create message parser stream.
1425 [ # # ]: 0 : pChildStrm = new INetMIMEMessageStream;
1426 : 0 : pChildStrm->SetTargetMessage ( pNewMessage );
1427 : :
1428 : : // Initialize control variables.
1429 : 0 : eState = INETMSG_EOL_BEGIN;
1430 : : }
1431 [ # # ]: 0 : if ( nSize > 0)
1432 : : {
1433 : : // Bytes still in buffer. Put message down-stream.
1434 : 0 : int status = pChildStrm->Write( pData, nSize );
1435 [ # # ]: 0 : if (status != INETSTREAM_STATUS_OK)
1436 : 0 : return status;
1437 : : }
1438 : :
1439 : 0 : return INetMessageIOStream::PutMsgLine (pData, nSize);
1440 : : }
1441 : : else
1442 : : {
1443 : :
1444 : : // Multipart message body. Initialize multipart delimiters.
1445 : : // Multipart message.
1446 [ # # ]: 0 : if (pMsg->GetMultipartBoundary().getLength() == 0)
1447 : : {
1448 : : // Determine boundary.
1449 : : rtl::OString aType(rtl::OUStringToOString(
1450 [ # # ][ # # ]: 0 : pMsg->GetContentType(), RTL_TEXTENCODING_ASCII_US));
[ # # ][ # # ]
1451 : 0 : rtl::OString aLowerType(aType.toAsciiLowerCase());
1452 : :
1453 : : sal_Int32 nPos = aLowerType.indexOfL(
1454 : 0 : RTL_CONSTASCII_STRINGPARAM("boundary="));
1455 : 0 : rtl::OString aBoundary(aType.copy(nPos + 9));
1456 : :
1457 [ # # ]: 0 : aBoundary = comphelper::string::strip(aBoundary, ' ');
1458 [ # # ]: 0 : aBoundary = comphelper::string::strip(aBoundary, '"');
1459 : :
1460 : : // Save boundary.
1461 : 0 : pMsg->SetMultipartBoundary (aBoundary);
1462 : : }
1463 : :
1464 : 0 : rtl::OString aPlainDelim (pMsg->GetMultipartBoundary());
1465 : : rtl::OString aDelim = rtl::OStringBuffer(
1466 : : RTL_CONSTASCII_STRINGPARAM("--")).
1467 [ # # ][ # # ]: 0 : append(aPlainDelim).
1468 : 0 : makeStringAndClear();
1469 : : rtl::OString aPlainClose = rtl::OStringBuffer(
1470 : : aPlainDelim).
1471 [ # # ][ # # ]: 0 : append(RTL_CONSTASCII_STRINGPARAM("--")).
1472 : 0 : makeStringAndClear();
1473 : : rtl::OString aClose = rtl::OStringBuffer(
1474 : : aDelim).
1475 [ # # ][ # # ]: 0 : append(RTL_CONSTASCII_STRINGPARAM("--")).
1476 : 0 : makeStringAndClear();
1477 : :
1478 [ # # ][ # # ]: 0 : if (pMsgBuffer == NULL) pMsgBuffer = new SvMemoryStream;
[ # # ]
1479 [ # # ]: 0 : pMsgBuffer->Write (pData, nSize);
1480 : 0 : sal_uIntPtr nBufSize = pMsgBuffer->Tell();
1481 : :
1482 : : const sal_Char* pChar;
1483 : : const sal_Char* pOldPos;
1484 [ # # ][ # # ]: 0 : for( pOldPos = pChar = (const sal_Char *) pMsgBuffer->GetData(); nBufSize--;
1485 : : pChar++ )
1486 : : {
1487 : : int status;
1488 [ # # ][ # # ]: 0 : if( *pChar == '\r' || *pChar == '\n' )
1489 : : {
1490 [ # # # # : 0 : if( aDelim.compareTo(pOldPos, aDelim.getLength())
# # # # ]
[ # # ][ # # ]
[ # # ]
1491 : : != -1 &&
1492 [ # # ][ # # ]: 0 : aClose.compareTo(pOldPos, aClose.getLength())
1493 : : != -1 &&
1494 [ # # ][ # # ]: 0 : aPlainDelim.compareTo(pOldPos, aPlainDelim.getLength())
1495 : : != -1 &&
1496 [ # # ][ # # ]: 0 : aPlainClose.compareTo(pOldPos, aPlainClose.getLength())
1497 : : != -1 )
1498 : : {
1499 [ # # ][ # # ]: 0 : if( nBufSize &&
[ # # ]
1500 : 0 : ( pChar[1] == '\r' || pChar[1] == '\n' ) )
1501 : 0 : nBufSize--, pChar++;
1502 [ # # ]: 0 : if( pChildStrm )
1503 : : {
1504 : : status = pChildStrm->Write(
1505 [ # # ]: 0 : pOldPos, pChar - pOldPos + 1 );
1506 [ # # ]: 0 : if( status != INETSTREAM_STATUS_OK )
1507 : 0 : return status;
1508 : : }
1509 : : else {
1510 : : SAL_WARN( "tools", "Boundary not found." );
1511 : : }
1512 : : status = INetMessageIOStream::PutMsgLine(
1513 [ # # ]: 0 : pOldPos, pChar - pOldPos + 1 );
1514 [ # # ]: 0 : if( status != INETSTREAM_STATUS_OK )
1515 : 0 : return status;
1516 : 0 : pOldPos = pChar + 1;
1517 : : }
1518 : : else
1519 : : {
1520 [ # # ][ # # ]: 0 : if( nBufSize &&
[ # # ]
1521 : 0 : ( pChar[1] == '\r' || pChar[1] == '\n' ) )
1522 : 0 : nBufSize--, pChar++;
1523 : 0 : pOldPos = pChar + 1;
1524 [ # # ][ # # ]: 0 : DELETEZ( pChildStrm );
1525 : :
1526 [ # # # # ]: 0 : if (aClose.compareTo(pOldPos, aClose.getLength())
[ # # ][ # # ]
[ # # ]
1527 : : != -1 &&
1528 [ # # ][ # # ]: 0 : aPlainClose.compareTo(pOldPos, aClose.getLength())
1529 : : != -1 )
1530 : : {
1531 : : // Encapsulated message.
1532 : : INetMIMEMessage* pNewMessage =
1533 [ # # ][ # # ]: 0 : new INetMIMEMessage;
1534 : : pNewMessage->SetDocumentLB (
1535 : : new SvAsyncLockBytes (
1536 [ # # ][ # # ]: 0 : new SvCacheStream, sal_False));
[ # # ][ # # ]
[ # # ]
1537 : :
1538 [ # # ]: 0 : pMsg->AttachChild( *pNewMessage, sal_True );
1539 : :
1540 : : // Encapsulated message body. Create message parser stream.
1541 [ # # ][ # # ]: 0 : pChildStrm = new INetMIMEMessageStream;
1542 : 0 : pChildStrm->SetTargetMessage ( pNewMessage );
1543 : :
1544 : : // Initialize control variables.
1545 : : }
1546 : 0 : eState = INETMSG_EOL_BEGIN;
1547 : : status = INetMessageIOStream::PutMsgLine(
1548 [ # # ]: 0 : pOldPos, pChar - pOldPos + 1 );
1549 [ # # ]: 0 : if( status != INETSTREAM_STATUS_OK )
1550 : 0 : return status;
1551 : : }
1552 : : }
1553 : : }
1554 [ # # ]: 0 : if( pOldPos < pChar )
1555 : : {
1556 [ # # ][ # # ]: 0 : SvMemoryStream* pNewStream = new SvMemoryStream;
1557 [ # # ]: 0 : pNewStream->Write( pOldPos, pChar - pOldPos );
1558 : 0 : SvMemoryStream* pTmp = pMsgBuffer;
1559 : 0 : pMsgBuffer = pNewStream;
1560 [ # # ][ # # ]: 0 : delete pTmp;
1561 : : }
1562 : : else
1563 : : {
1564 [ # # ]: 0 : pMsgBuffer->Seek( 0L );
1565 [ # # ]: 0 : pMsgBuffer->SetStreamSize( 0 );
1566 : : }
1567 : 0 : return INETSTREAM_STATUS_OK;
1568 : : }
1569 : : }
1570 : : else
1571 : : {
1572 : : /*
1573 : : * Single part message.
1574 : : * Remove any ContentTransferEncoding.
1575 : : */
1576 [ # # ]: 0 : if (pMsg->GetContentType().Len() == 0)
1577 : : {
1578 [ # # ][ # # ]: 0 : pMsg->SetContentType(pMsg->GetDefaultContentType());
[ # # ]
1579 : : }
1580 : :
1581 [ # # ]: 0 : if (eEncoding == INETMSG_ENCODING_BINARY)
1582 : : {
1583 [ # # ][ # # ]: 0 : String aEncoding (pMsg->GetContentTransferEncoding());
1584 [ # # ]: 0 : if (aEncoding.CompareIgnoreCaseToAscii (
1585 [ # # ]: 0 : "base64", 6) == COMPARE_EQUAL)
1586 : 0 : eEncoding = INETMSG_ENCODING_BASE64;
1587 [ # # ]: 0 : else if (aEncoding.CompareIgnoreCaseToAscii (
1588 [ # # ]: 0 : "quoted-printable", 16) == COMPARE_EQUAL)
1589 : 0 : eEncoding = INETMSG_ENCODING_QUOTED;
1590 : : else
1591 [ # # ]: 0 : eEncoding = INETMSG_ENCODING_7BIT;
1592 : : }
1593 : :
1594 [ # # ]: 0 : if (eEncoding == INETMSG_ENCODING_7BIT)
1595 : : {
1596 : : // No decoding necessary.
1597 : 0 : return INetMessageIOStream::PutMsgLine (pData, nSize);
1598 : : }
1599 : : else
1600 : : {
1601 [ # # ]: 0 : if (pDecodeStrm == NULL)
1602 : : {
1603 [ # # ]: 0 : if (eEncoding == INETMSG_ENCODING_QUOTED)
1604 [ # # ]: 0 : pDecodeStrm = new INetMessageDecodeQPStream_Impl;
1605 : : else
1606 [ # # ]: 0 : pDecodeStrm = new INetMessageDecode64Stream_Impl;
1607 : :
1608 : 0 : pDecodeStrm->SetTargetMessage (pMsg);
1609 : : }
1610 : 0 : return pDecodeStrm->Write (pData, nSize);
1611 : : }
1612 : : }
1613 : : }
1614 : : }
1615 : :
1616 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|