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