1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: inetstrm.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
33 #include <sal/types.h>
34 #include <rtl/memory.h>
35 #include <tools/cachestr.hxx>
36 #include <tools/debug.hxx>
37 #include <tools/inetmsg.hxx>
38 #include <tools/inetstrm.hxx>
40 #include <ctype.h> // toupper
42 inline sal_Bool SAL_CALL
ascii_isWhitespace( sal_Unicode ch
)
44 return ((ch
<= 0x20) && ch
);
47 #define CONSTASCII_STRINGPARAM(a) (a), RTL_TEXTENCODING_ASCII_US
49 /*=======================================================================
51 * INetMessageEncodeQPStream Interface.
52 * (Quoted-Printable Encoding)
54 *=====================================================================*/
55 class INetMessageEncodeQPStream_Impl
: public INetMessageIStream
69 INetMessageStreamState eState
;
72 virtual int GetMsgLine (sal_Char
*pData
, ULONG nSize
);
75 INetMessageEncodeQPStream_Impl (ULONG nMsgBufferSize
= 1024);
76 virtual ~INetMessageEncodeQPStream_Impl (void);
79 /*=====================================================================
81 * INetMessageDecodeQPStream Interface.
82 * (Quoted-Printable Decoding)
84 *====================================================================*/
85 class INetMessageDecodeQPStream_Impl
: public INetMessageOStream
87 INetMessageStreamState eState
;
88 SvMemoryStream
*pMsgBuffer
;
91 sal_Char pTokBuffer
[4];
93 virtual int PutMsgLine (const sal_Char
*pData
, ULONG nSize
);
96 INetMessageDecodeQPStream_Impl (void);
97 virtual ~INetMessageDecodeQPStream_Impl (void);
100 /*======================================================================
102 * INetMessageEncode64Stream Interface.
105 *====================================================================*/
106 class INetMessageEncode64Stream_Impl
: public INetMessageIStream
111 sal_uInt8
*pMsgBuffer
;
113 sal_uInt8
*pMsgWrite
;
116 sal_Char
*pTokBuffer
;
122 virtual int GetMsgLine (sal_Char
*pData
, ULONG nSize
);
125 INetMessageEncode64Stream_Impl (ULONG nMsgBufferSize
= 2048);
126 virtual ~INetMessageEncode64Stream_Impl (void);
129 /*======================================================================
131 * INetMessageDecode64Stream Interface.
134 *====================================================================*/
135 class INetMessageDecode64Stream_Impl
: public INetMessageOStream
137 INetMessageStreamState eState
;
140 sal_Char
*pMsgBuffer
;
144 virtual int PutMsgLine (const sal_Char
*pData
, ULONG nSize
);
147 INetMessageDecode64Stream_Impl (ULONG nMsgBufferSize
= 128);
148 virtual ~INetMessageDecode64Stream_Impl (void);
151 /*=========================================================================
153 * INetIStream Implementation.
155 *=======================================================================*/
159 INetIStream::INetIStream ()
166 INetIStream::~INetIStream (void)
173 int INetIStream::Read (sal_Char
*pData
, ULONG nSize
)
175 return GetData (pData
, nSize
);
181 void INetIStream::Decode64 (SvStream
& rIn
, SvStream
& rOut
)
184 aMsg
.SetDocumentLB(new SvAsyncLockBytes(&rOut
, FALSE
));
186 INetMessageDecode64Stream_Impl
aStream (8192);
187 aStream
.SetTargetMessage (&aMsg
);
189 sal_Char
* pBuf
= new sal_Char
[8192];
192 while ((nRead
= rIn
.Read (pBuf
, 8192)) > 0)
193 aStream
.Write( pBuf
, nRead
);
194 aStream
.Write ("\r\n", 2);
202 void INetIStream::Encode64 (SvStream
& rIn
, SvStream
& rOut
)
206 new SvLockBytes (&rIn
, FALSE
));
208 INetMessageEncode64Stream_Impl
aStream (8192);
209 aStream
.SetSourceMessage (&aMsg
);
211 sal_Char
* pBuf
= new sal_Char
[8192];
214 while ((nRead
= aStream
.Read (pBuf
, 8192)) > 0)
215 rOut
.Write( pBuf
, nRead
);
220 /*=========================================================================
222 * INetOStream Implementation.
224 *=======================================================================*/
228 INetOStream::INetOStream ()
235 INetOStream::~INetOStream (void)
242 int INetOStream::Write (const sal_Char
*pData
, ULONG nSize
)
244 return PutData (pData
, nSize
);
247 /*=========================================================================
249 * INetMessageIStream Implementation.
251 *=======================================================================*/
253 * INetMessageIStream.
255 INetMessageIStream::INetMessageIStream (ULONG nBufferSize
)
257 bHeaderGenerated (FALSE
),
258 nBufSiz (nBufferSize
),
260 pMsgBuffer (new SvMemoryStream
)
262 pMsgBuffer
->SetStreamCharSet (RTL_TEXTENCODING_ASCII_US
);
263 pBuffer
= new sal_Char
[nBufSiz
];
264 pRead
= pWrite
= pBuffer
;
268 * ~INetMessageIStream.
270 INetMessageIStream::~INetMessageIStream (void)
280 int INetMessageIStream::GetData (sal_Char
*pData
, ULONG nSize
)
282 if (pSourceMsg
== NULL
) return INETSTREAM_STATUS_ERROR
;
284 sal_Char
*pWBuf
= pData
;
285 sal_Char
*pWEnd
= pData
+ nSize
;
287 while (pWBuf
< pWEnd
)
289 // Caller's buffer not yet filled.
290 ULONG n
= pRead
- pWrite
;
293 // Bytes still in buffer.
294 ULONG m
= pWEnd
- pWBuf
;
296 for (ULONG i
= 0; i
< n
; i
++) *pWBuf
++ = *pWrite
++;
300 // Buffer empty. Reset to <Begin-of-Buffer>.
301 pRead
= pWrite
= pBuffer
;
303 // Read next message line.
304 int nRead
= GetMsgLine (pBuffer
, nBufSiz
);
308 pRead
= pBuffer
+ nRead
;
312 if (!bHeaderGenerated
)
314 // Header generated. Insert empty line.
315 bHeaderGenerated
= TRUE
;
322 return (pWBuf
- pData
);
327 return (pWBuf
- pData
);
333 int INetMessageIStream::GetMsgLine (sal_Char
*pData
, ULONG nSize
)
335 if (pSourceMsg
== NULL
) return INETSTREAM_STATUS_ERROR
;
337 sal_Char
*pWBuf
= pData
;
338 sal_Char
*pWEnd
= pData
+ nSize
;
340 if (!bHeaderGenerated
)
344 if (pMsgBuffer
->Tell() == 0)
346 // Insert formatted header into buffer.
347 n
= pSourceMsg
->GetHeaderCount();
348 for (i
= 0; i
< n
; i
++)
350 INetMessageHeader
aHeader (pSourceMsg
->GetHeaderField(i
));
351 if (aHeader
.GetValue().Len())
353 // NYI: Folding long lines.
354 *pMsgBuffer
<< (sal_Char
*)(aHeader
.GetName().GetBuffer());
356 *pMsgBuffer
<< (sal_Char
*)(aHeader
.GetValue().GetBuffer());
357 *pMsgBuffer
<< "\r\n";
361 pMsgWrite
= (sal_Char
*)(pMsgBuffer
->GetData());
362 pMsgRead
= pMsgWrite
+ pMsgBuffer
->Tell();
365 n
= pMsgRead
- pMsgWrite
;
369 if (nSize
< n
) n
= nSize
;
370 for (i
= 0; i
< n
; i
++) *pWBuf
++ = *pMsgWrite
++;
375 pMsgBuffer
->Seek (STREAM_SEEK_TO_BEGIN
);
380 if (pSourceMsg
->GetDocumentLB())
382 if (pMsgStrm
== NULL
)
383 pMsgStrm
= new SvStream (pSourceMsg
->GetDocumentLB());
385 ULONG nRead
= pMsgStrm
->Read (pWBuf
, (pWEnd
- pWBuf
));
389 return (pWBuf
- pData
);
392 /*=========================================================================
394 * INetMessageOStream Implementation.
396 *=======================================================================*/
398 * INetMessageOStream.
400 INetMessageOStream::INetMessageOStream (void)
402 bHeaderParsed (FALSE
),
403 eOState (INETMSG_EOL_BEGIN
),
404 pMsgBuffer (new SvMemoryStream
)
409 * ~INetMessageOStream.
411 INetMessageOStream::~INetMessageOStream (void)
413 if (pMsgBuffer
->Tell() > 0)
414 PutMsgLine ((const sal_Char
*) pMsgBuffer
->GetData(), pMsgBuffer
->Tell());
419 SvOpenLockBytes
*pLB
=
420 PTR_CAST (SvOpenLockBytes
, pTargetMsg
->GetDocumentLB());
431 * (Simple Field Parsing (RFC822, Appendix B)).
433 int INetMessageOStream::PutData (const sal_Char
*pData
, ULONG nSize
)
435 if (pTargetMsg
== NULL
) return INETSTREAM_STATUS_ERROR
;
437 const sal_Char
*pStop
= (pData
+ nSize
);
439 while (!bHeaderParsed
&& (pData
< pStop
))
441 if (eOState
== INETMSG_EOL_BEGIN
)
443 if ((*pData
== '\r') || (*pData
== '\n'))
446 * Empty Line. Separates header fields from message body.
447 * Skip this and any 2nd line break character (if any).
450 if ((pData
< pStop
) && ((*pData
== '\r') || (*pData
== '\n')))
453 // Emit any buffered last header field.
454 if (pMsgBuffer
->Tell() > 0)
457 int status
= PutMsgLine (
458 (const sal_Char
*) pMsgBuffer
->GetData(),
460 if (status
!= INETSTREAM_STATUS_OK
) return status
;
464 eOState
= INETMSG_EOL_BEGIN
;
465 pMsgBuffer
->Seek (STREAM_SEEK_TO_BEGIN
);
467 // Mark header parsed.
468 bHeaderParsed
= TRUE
;
470 else if ((*pData
== ' ') || (*pData
== '\t'))
472 // Continuation line. Unfold multi-line field-body.
478 // Begin of new header field.
479 if (pMsgBuffer
->Tell() > 0)
481 // Emit buffered header field now.
483 int status
= PutMsgLine (
484 (const sal_Char
*) pMsgBuffer
->GetData(),
486 if (status
!= INETSTREAM_STATUS_OK
) return status
;
489 // Reset to begin of buffer.
490 pMsgBuffer
->Seek (STREAM_SEEK_TO_BEGIN
);
492 // Insert current character into buffer.
493 *pMsgBuffer
<< *pData
++;
496 // Search for next line break character.
497 if (!bHeaderParsed
) eOState
= INETMSG_EOL_SCR
;
499 else if (eOState
== INETMSG_EOL_FCR
)
501 // Skip line break character.
504 // Mark begin of line.
505 eOState
= INETMSG_EOL_BEGIN
;
507 else if ((*pData
== '\r') || (*pData
== '\n'))
509 if (*pData
== '\r') pData
++;
510 eOState
= INETMSG_EOL_FCR
;
512 else if (ascii_isWhitespace (*pData
& 0x7f))
514 // Any <LWS> is folded into a single <SP> character.
515 sal_Char c
= *((const sal_Char
*) pMsgBuffer
->GetData() + pMsgBuffer
->Tell() - 1);
516 if (!ascii_isWhitespace (c
& 0x7f)) *pMsgBuffer
<< ' ';
518 // Skip over this <LWS> character.
523 // Any other character is inserted into line buffer.
524 *pMsgBuffer
<< *pData
++;
528 if (bHeaderParsed
&& (pData
< pStop
))
530 // Put message body down-stream.
531 return PutMsgLine (pData
, (pStop
- pData
));
534 return INETSTREAM_STATUS_OK
;
540 int INetMessageOStream::PutMsgLine (const sal_Char
*pData
, ULONG nSize
)
542 // Check for message container.
543 if (pTargetMsg
== NULL
) return INETSTREAM_STATUS_ERROR
;
545 // Check for header or body.
546 if (!IsHeaderParsed())
548 ByteString
aField (pData
);
549 USHORT nPos
= aField
.Search (':');
550 if (nPos
!= STRING_NOTFOUND
)
553 aField
.Copy (0, nPos
));
555 aField
.Copy (nPos
+ 1, aField
.Len() - nPos
+ 1));
556 aValue
.EraseLeadingChars (' ');
558 pTargetMsg
->SetHeaderField (
559 INetMessageHeader (aName
, aValue
));
564 SvOpenLockBytes
*pLB
=
565 PTR_CAST(SvOpenLockBytes
, pTargetMsg
->GetDocumentLB());
567 return INETSTREAM_STATUS_WOULDBLOCK
;
569 sal_Size nDocSiz
= pTargetMsg
->GetDocumentSize();
572 pLB
->FillAppend ((sal_Char
*)pData
, nSize
, &nWrite
);
573 pTargetMsg
->SetDocumentSize (nDocSiz
+ nWrite
);
575 if (nWrite
< nSize
) return INETSTREAM_STATUS_ERROR
;
577 return INETSTREAM_STATUS_OK
;
580 /*=========================================================================
582 * INetMessageIOStream Implementation.
584 *=======================================================================*/
586 * INetMessageIOStream.
588 INetMessageIOStream::INetMessageIOStream (ULONG nBufferSize
)
589 : INetMessageIStream (nBufferSize
),
590 INetMessageOStream ()
595 * ~INetMessageIOStream.
597 INetMessageIOStream::~INetMessageIOStream (void)
601 /*=======================================================================
603 * INetMessageEncodeQPStream_Impl Implementation.
604 * (Quoted-Printable Encoding)
606 *=====================================================================*/
607 static const sal_Char hex2pr
[16] = {
608 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
609 'A', 'B', 'C', 'D', 'E', 'F'
612 static const sal_Char ebcdic
[] = {
613 '!', '"', '#', '$', '@', '[', '\\', ']', '^', '`', '{', '|', '}', '~'
617 * INetMessageEncodeQPStream_Impl.
619 INetMessageEncodeQPStream_Impl::INetMessageEncodeQPStream_Impl (
620 ULONG nMsgBufferSize
)
621 : INetMessageIStream (),
623 nMsgBufSiz (nMsgBufferSize
),
625 eState (INETMSG_EOL_SCR
),
628 GenerateHeader (FALSE
);
630 pMsgBuffer
= new sal_Char
[nMsgBufSiz
];
631 pMsgRead
= pMsgWrite
= pMsgBuffer
;
633 pTokBuffer
= new sal_Char
[nTokBufSiz
];
634 pTokRead
= pTokWrite
= pTokBuffer
;
638 * ~INetMessageEncodeQPStream_Impl.
640 INetMessageEncodeQPStream_Impl::~INetMessageEncodeQPStream_Impl (void)
643 delete [] pMsgBuffer
;
644 delete [] pTokBuffer
;
650 int INetMessageEncodeQPStream_Impl::GetMsgLine (sal_Char
*pData
, ULONG nSize
)
652 INetMessage
*pMsg
= GetSourceMessage ();
653 if (pMsg
== NULL
) return INETSTREAM_STATUS_ERROR
;
655 if (pMsg
->GetDocumentLB() == NULL
) return 0;
656 if (pMsgStrm
== NULL
) pMsgStrm
= new SvStream (pMsg
->GetDocumentLB());
658 sal_Char
*pWBuf
= pData
;
659 while (pWBuf
< (pData
+ nSize
))
661 // Caller's buffer not yet filled.
662 if ((pMsgRead
- pMsgWrite
) > 0)
664 // Bytes still in message buffer.
665 if ((eState
!= INETMSG_EOL_BEGIN
) &&
666 ((pTokRead
- pTokBuffer
) < 72))
668 // Token buffer not yet filled.
669 if (eState
== INETMSG_EOL_FCR
)
671 eState
= INETMSG_EOL_BEGIN
;
672 if (*pMsgWrite
!= '\n')
674 // Convert orphant <CR> into <CR><LF> sequence.
677 *pTokRead
++ = *pMsgWrite
++;
679 else if ((*pMsgWrite
== ' ') || (*pMsgWrite
== '\t'))
681 eState
= INETMSG_EOL_FSP
;
682 *pTokRead
++ = *pMsgWrite
++;
684 else if (*pMsgWrite
== '\r')
687 if (eState
== INETMSG_EOL_FSP
)
689 // Encode last (trailing space) character.
690 sal_uInt8 c
= (sal_uInt8
)(*(--pTokRead
));
692 *pTokRead
++ = hex2pr
[((c
& 0xf0) >> 4)];
693 *pTokRead
++ = hex2pr
[((c
& 0x0f) )];
695 eState
= INETMSG_EOL_FCR
;
696 *pTokRead
++ = *pMsgWrite
++;
698 else if (*pMsgWrite
== '\n')
701 if (eState
== INETMSG_EOL_FSP
)
703 // Encode last (trailing space) character.
704 sal_uInt8 c
= (sal_uInt8
)(*(--pTokRead
));
706 *pTokRead
++ = hex2pr
[((c
& 0xf0) >> 4)];
707 *pTokRead
++ = hex2pr
[((c
& 0x0f) )];
709 eState
= INETMSG_EOL_BEGIN
;
711 // Convert orphant <LF> into <CR><LF> sequence.
713 *pTokRead
++ = *pMsgWrite
++;
715 else if (*pMsgWrite
== '=')
717 // Escape character itself MUST be encoded, of course.
718 sal_uInt8 c
= (sal_uInt8
)(*pMsgWrite
++);
720 *pTokRead
++ = hex2pr
[((c
& 0xf0) >> 4)];
721 *pTokRead
++ = hex2pr
[((c
& 0x0f) )];
723 eState
= INETMSG_EOL_SCR
;
725 else if (((sal_uInt8
)(*pMsgWrite
) > 0x20) &&
726 ((sal_uInt8
)(*pMsgWrite
) < 0x7f) )
729 * Some printable ASCII character.
730 * (Encode EBCDIC special characters (NYI)).
732 *pTokRead
++ = *pMsgWrite
++;
733 eState
= INETMSG_EOL_SCR
;
737 // Encode any other character.
738 sal_uInt8 c
= (sal_uInt8
)(*pMsgWrite
++);
740 *pTokRead
++ = hex2pr
[((c
& 0xf0) >> 4)];
741 *pTokRead
++ = hex2pr
[((c
& 0x0f) )];
743 eState
= INETMSG_EOL_SCR
;
748 // Check for maximum line length.
749 if (eState
!= INETMSG_EOL_BEGIN
)
751 // Insert soft line break.
756 eState
= INETMSG_EOL_BEGIN
;
759 // Copy to caller's buffer.
760 if ((pTokRead
- pTokWrite
) > 0)
762 // Bytes still in token buffer.
763 *pWBuf
++ = *pTokWrite
++;
767 // Token buffer empty. Reset to <Begin-of-Buffer>.
768 pTokRead
= pTokWrite
= pTokBuffer
;
769 eState
= INETMSG_EOL_SCR
;
775 // Message buffer empty. Reset to <Begin-of-Buffer>.
776 pMsgRead
= pMsgWrite
= pMsgBuffer
;
778 // Read next message block.
779 ULONG nRead
= pMsgStrm
->Read (pMsgBuffer
, nMsgBufSiz
);
783 pMsgRead
= (pMsgBuffer
+ nRead
);
787 // Nothing more ro read.
790 // Append final <CR><LF> and mark we're done.
798 // Already done all encoding.
799 if ((pTokRead
- pTokWrite
) > 0)
801 // Bytes still in token buffer.
802 *pWBuf
++ = *pTokWrite
++;
806 // Token buffer empty. Reset to <Begin-of-Buffer>.
807 pTokRead
= pTokWrite
= pTokBuffer
;
810 return (pWBuf
- pData
);
816 return (pWBuf
- pData
);
819 /*=====================================================================
821 * INetMessageDecodeQPStream_Impl Implementation.
822 * (Quoted-Printable Decoding)
824 *====================================================================*/
825 static const sal_uInt8 pr2hex
[128] = {
826 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
827 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
828 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
829 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 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
834 0x08, 0x09, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
836 0x10, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
837 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
838 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
839 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
841 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
842 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
843 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
844 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10
848 * INetMessageDecodeQPStream_Impl.
850 INetMessageDecodeQPStream_Impl::INetMessageDecodeQPStream_Impl (void)
851 : INetMessageOStream (),
852 eState (INETMSG_EOL_BEGIN
),
853 pMsgBuffer (new SvMemoryStream
),
860 * ~INetMessageDecodeQPStream_Impl.
862 INetMessageDecodeQPStream_Impl::~INetMessageDecodeQPStream_Impl (void)
870 int INetMessageDecodeQPStream_Impl::PutMsgLine (
871 const sal_Char
*pData
, ULONG nSize
)
873 INetMessage
*pMsg
= GetTargetMessage();
874 if (pMsg
== NULL
) return INETSTREAM_STATUS_ERROR
;
876 SvOpenLockBytes
* pLB
= PTR_CAST(SvOpenLockBytes
, pMsg
->GetDocumentLB());
877 if (pLB
== NULL
) return INETSTREAM_STATUS_WOULDBLOCK
;
879 const sal_Char
*pStop
= pData
+ nSize
;
880 while (pData
< pStop
)
882 if (eState
== INETMSG_EOL_FESC
)
884 *(pTokBuffer
+ nTokBufLen
++) = static_cast< char >(toupper(*pData
));
888 if ((*pTokBuffer
== '\r') || (*pTokBuffer
== '\n'))
890 // Soft line break (=<CR><LF>). Emit buffer now.
891 eState
= INETMSG_EOL_BEGIN
;
896 *pMsgBuffer
<< sal_uInt8 (
897 (pr2hex
[(int)(pTokBuffer
[0] & 0x7f)] << 4) |
898 (pr2hex
[(int)(pTokBuffer
[1] & 0x7f)] & 15) );
900 // Search for next <CR>.
901 eState
= INETMSG_EOL_SCR
;
904 // Reset token buffer.
908 else if (*pData
== '=')
910 // Found escape character.
912 eState
= INETMSG_EOL_FESC
;
914 else if (eState
== INETMSG_EOL_FCR
)
916 *pMsgBuffer
<< *pData
++;
917 eState
= INETMSG_EOL_BEGIN
;
919 else if (*pData
== '\r')
921 *pMsgBuffer
<< *pData
++;
922 eState
= INETMSG_EOL_FCR
;
926 *pMsgBuffer
<< *pData
++;
929 if (eState
== INETMSG_EOL_BEGIN
)
931 sal_Size nRead
= pMsgBuffer
->Tell();
935 sal_Size nDocSiz
= pMsg
->GetDocumentSize();
939 (sal_Char
*)(pMsgBuffer
->GetData()), nRead
, &nWrite
);
940 pMsg
->SetDocumentSize (nDocSiz
+ nWrite
);
942 if (nWrite
< nRead
) return INETSTREAM_STATUS_ERROR
;
944 pMsgBuffer
->Seek (STREAM_SEEK_TO_BEGIN
);
946 eState
= INETMSG_EOL_SCR
;
949 return INETSTREAM_STATUS_OK
;
952 /*======================================================================
954 * INetMessageEncode64Stream_Impl Implementation.
957 *====================================================================*/
958 static const sal_Char six2pr
[64] = {
959 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
960 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
961 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
962 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
963 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
967 * INetMessageEncode64Stream_Impl.
969 INetMessageEncode64Stream_Impl::INetMessageEncode64Stream_Impl (
970 ULONG nMsgBufferSize
)
971 : INetMessageIStream (),
973 nMsgBufSiz (nMsgBufferSize
),
977 GenerateHeader (FALSE
);
979 pMsgBuffer
= new sal_uInt8
[nMsgBufSiz
];
980 pMsgRead
= pMsgWrite
= pMsgBuffer
;
982 pTokBuffer
= new sal_Char
[nTokBufSiz
];
983 pTokRead
= pTokWrite
= pTokBuffer
;
987 * ~INetMessageEncode64Stream_Impl.
989 INetMessageEncode64Stream_Impl::~INetMessageEncode64Stream_Impl (void)
992 delete [] pMsgBuffer
;
993 delete [] pTokBuffer
;
999 int INetMessageEncode64Stream_Impl::GetMsgLine (sal_Char
*pData
, ULONG nSize
)
1001 INetMessage
*pMsg
= GetSourceMessage ();
1002 if (pMsg
== NULL
) return INETSTREAM_STATUS_ERROR
;
1004 if (pMsg
->GetDocumentLB() == NULL
) return 0;
1005 if (pMsgStrm
== NULL
) pMsgStrm
= new SvStream (pMsg
->GetDocumentLB());
1007 sal_Char
*pWBuf
= pData
;
1008 while (pWBuf
< (pData
+ nSize
))
1010 // Caller's buffer not yet filled.
1011 if ((pMsgRead
- pMsgWrite
) > 0)
1013 // Bytes still in message buffer.
1014 if ((pTokRead
- pTokBuffer
) < 72)
1016 // Token buffer not yet filled.
1017 switch ((pTokRead
- pTokBuffer
) % 4)
1020 *pTokRead
++ = six2pr
[(int)(*pMsgWrite
>> 2)];
1024 *pTokRead
++ = six2pr
[
1025 (int)(((*pMsgWrite
<< 4) & 060) |
1026 (((*(pMsgWrite
+ 1)) >> 4) & 017))];
1031 *pTokRead
++ = six2pr
[
1032 (int)(((*pMsgWrite
<< 2) & 074) |
1033 (((*(pMsgWrite
+ 1)) >> 6) & 003))];
1037 default: // == case 3
1038 *pTokRead
++ = six2pr
[(int)(*pMsgWrite
& 077)];
1043 else if ((pTokRead
- pTokBuffer
) == 72)
1045 // Maximum line length. Append <CR><LF>.
1051 if ((pTokRead
- pTokWrite
) > 0)
1053 // Bytes still in token buffer.
1054 *pWBuf
++ = *pTokWrite
++;
1058 // Token buffer empty. Reset to <Begin-of-Buffer>.
1059 pTokRead
= pTokWrite
= pTokBuffer
;
1065 // Message buffer empty. Reset to <Begin-of-Buffer>.
1066 pMsgRead
= pMsgWrite
= pMsgBuffer
;
1068 // Read next message block.
1069 ULONG nRead
= pMsgStrm
->Read (pMsgBuffer
, nMsgBufSiz
);
1072 // Set read pointer.
1073 pMsgRead
= (pMsgBuffer
+ nRead
);
1077 // Nothing more to read.
1080 // Append pad character(s) and final <CR><LF>.
1081 switch ((pTokRead
- pTokBuffer
) % 4)
1085 // Fall through for 2nd pad character.
1102 // Already done all encoding.
1103 if ((pTokRead
- pTokWrite
) > 0)
1105 // Bytes still in token buffer.
1106 *pWBuf
++ = *pTokWrite
++;
1110 // Token buffer empty. Reset to <Begin-of-Buffer>.
1111 pTokRead
= pTokWrite
= pTokBuffer
;
1113 // Reset done flag, if everything has been done.
1114 // if (pWBuf == pData) bDone = FALSE;
1117 return (pWBuf
- pData
);
1122 } // while (pWBuf < (pData + nSize))
1123 return (pWBuf
- pData
);
1126 /*======================================================================
1128 * INetMessageDecode64Stream_Impl Implementation.
1131 *====================================================================*/
1132 static const sal_uInt8 pr2six
[256] = {
1133 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1134 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1135 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1136 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1138 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1139 0x40, 0x40, 0x40, 0x3E, 0x40, 0x40, 0x40, 0x3F,
1140 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
1141 0x3C, 0x3D, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1143 0x40, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
1144 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
1145 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
1146 0x17, 0x18, 0x19, 0x40, 0x40, 0x40, 0x40, 0x40,
1148 0x40, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
1149 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
1150 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
1151 0x31, 0x32, 0x33, 0x40, 0x40, 0x40, 0x40, 0x40,
1153 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1154 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1155 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1156 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 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1161 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 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1166 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1168 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1169 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1170 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
1171 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
1175 * INetMessageDecode64Stream_Impl.
1177 INetMessageDecode64Stream_Impl::INetMessageDecode64Stream_Impl (
1178 ULONG nMsgBufferSize
)
1179 : INetMessageOStream (),
1180 eState (INETMSG_EOL_SCR
),
1181 nMsgBufSiz (nMsgBufferSize
)
1183 ParseHeader (FALSE
);
1185 pMsgBuffer
= new sal_Char
[nMsgBufSiz
];
1186 pMsgRead
= pMsgWrite
= pMsgBuffer
;
1190 * ~INetMessageDecode64Stream_Impl.
1192 INetMessageDecode64Stream_Impl::~INetMessageDecode64Stream_Impl (void)
1194 delete [] pMsgBuffer
;
1200 int INetMessageDecode64Stream_Impl::PutMsgLine (
1201 const sal_Char
*pData
, ULONG nSize
)
1203 INetMessage
*pMsg
= GetTargetMessage ();
1204 if (pMsg
== NULL
) return INETSTREAM_STATUS_ERROR
;
1206 SvOpenLockBytes
* pLB
= PTR_CAST(SvOpenLockBytes
, pMsg
->GetDocumentLB());
1207 if (pLB
== NULL
) return INETSTREAM_STATUS_WOULDBLOCK
;
1209 const sal_Char
*pStop
= (pData
+ nSize
);
1210 while (pData
< pStop
)
1212 if (pr2six
[(int)(*pData
)] > 63)
1215 * Character not in base64 alphabet.
1216 * Check for <End-of-Stream> or Junk.
1220 // Final pad character -> Done.
1221 sal_Size nDocSiz
= pMsg
->GetDocumentSize();
1222 sal_Size nRead
= pMsgWrite
- pMsgBuffer
;
1223 sal_Size nWrite
= 0;
1225 pLB
->FillAppend (pMsgBuffer
, nRead
, &nWrite
);
1226 pMsg
->SetDocumentSize (nDocSiz
+ nWrite
);
1229 return INETSTREAM_STATUS_ERROR
;
1231 return INETSTREAM_STATUS_LOADED
;
1233 else if (eState
== INETMSG_EOL_FCR
)
1235 // Skip any line break character.
1236 if ((*pData
== '\r') || (*pData
== '\n')) pData
++;
1238 // Store decoded message buffer contents.
1239 sal_Size nDocSiz
= pMsg
->GetDocumentSize();
1240 sal_Size nRead
= pMsgWrite
- pMsgBuffer
;
1241 sal_Size nWrite
= 0;
1243 pLB
->FillAppend (pMsgBuffer
, nRead
, &nWrite
);
1244 pMsg
->SetDocumentSize (nDocSiz
+ nWrite
);
1246 if (nWrite
< nRead
) return INETSTREAM_STATUS_ERROR
;
1248 // Reset to <Begin-of-Buffer>.
1249 pMsgWrite
= pMsgBuffer
;
1250 eState
= INETMSG_EOL_SCR
;
1252 else if ((*pData
== '\r') || (*pData
== '\n'))
1254 // Skip any line break character.
1256 eState
= INETMSG_EOL_FCR
;
1260 // Skip any junk character (may be transmission error).
1266 // Decode any other character into message buffer.
1267 switch ((pMsgRead
- pMsgBuffer
) % 4)
1270 *pMsgWrite
= (pr2six
[(int)(*pData
++)] << 2);
1275 *pMsgWrite
++ |= (pr2six
[(int)(*pData
)] >> 4);
1276 *pMsgWrite
= (pr2six
[(int)(*pData
++)] << 4);
1281 *pMsgWrite
++ |= (pr2six
[(int)(*pData
)] >> 2);
1282 *pMsgWrite
= (pr2six
[(int)(*pData
++)] << 6);
1286 default: // == case 3
1287 *pMsgWrite
++ |= (pr2six
[(int)(*pData
++)]);
1288 pMsgRead
= pMsgBuffer
;
1290 } // switch ((pMsgRead - pMsgBuffer) % 4)
1292 } // while (pData < pStop)
1293 return INETSTREAM_STATUS_OK
;
1296 /*=========================================================================
1298 * INetMIMEMessageStream Implementation.
1300 *=======================================================================*/
1302 * INetMIMEMessageStream.
1304 INetMIMEMessageStream::INetMIMEMessageStream (ULONG nBufferSize
)
1305 : INetMessageIOStream (nBufferSize
),
1306 eState (INETMSG_EOL_BEGIN
),
1309 eEncoding (INETMSG_ENCODING_BINARY
),
1317 * ~INetMIMEMessageStream.
1319 INetMIMEMessageStream::~INetMIMEMessageStream (void)
1331 INetMIMEMessageStream::GetMsgEncoding (const String
& rContentType
)
1333 if ((rContentType
.CompareIgnoreCaseToAscii ("message" , 7) == 0) ||
1334 (rContentType
.CompareIgnoreCaseToAscii ("multipart", 9) == 0) )
1335 return INETMSG_ENCODING_7BIT
;
1337 if (rContentType
.CompareIgnoreCaseToAscii ("text", 4) == 0)
1339 if (rContentType
.CompareIgnoreCaseToAscii ("text/plain", 10) == 0)
1341 if (rContentType
.GetTokenCount ('=') > 1)
1343 String
aCharset (rContentType
.GetToken (1, '='));
1344 aCharset
.EraseLeadingChars (' ');
1345 aCharset
.EraseLeadingChars ('"');
1347 if (aCharset
.CompareIgnoreCaseToAscii ("us-ascii", 8) == 0)
1348 return INETMSG_ENCODING_7BIT
;
1350 return INETMSG_ENCODING_QUOTED
;
1353 return INETMSG_ENCODING_7BIT
;
1356 return INETMSG_ENCODING_QUOTED
;
1359 return INETMSG_ENCODING_BASE64
;
1364 * (Message Generator).
1366 int INetMIMEMessageStream::GetMsgLine (sal_Char
*pData
, ULONG nSize
)
1368 // Check for message container.
1369 INetMIMEMessage
*pMsg
= GetSourceMessage();
1370 if (pMsg
== NULL
) return INETSTREAM_STATUS_ERROR
;
1372 // Check for header or body.
1373 if (!IsHeaderGenerated())
1375 if (eState
== INETMSG_EOL_BEGIN
)
1377 // Prepare special header fields.
1378 if (pMsg
->GetParent())
1380 String
aPCT (pMsg
->GetParent()->GetContentType());
1381 if (aPCT
.CompareIgnoreCaseToAscii ("message/rfc822", 14) == 0)
1382 pMsg
->SetMIMEVersion (
1383 String(CONSTASCII_STRINGPARAM("1.0")));
1385 pMsg
->SetMIMEVersion (String());
1389 pMsg
->SetMIMEVersion (String(CONSTASCII_STRINGPARAM("1.0")));
1392 // Check ContentType.
1393 String
aContentType (pMsg
->GetContentType());
1394 if (aContentType
.Len())
1396 // Determine default Content-Type.
1397 String aDefaultType
;
1398 pMsg
->GetDefaultContentType (aDefaultType
);
1400 if (aDefaultType
.CompareIgnoreCaseToAscii (
1401 aContentType
, aContentType
.Len()) == 0)
1403 // No need to specify default.
1404 pMsg
->SetContentType (String());
1409 String
aEncoding (pMsg
->GetContentTransferEncoding());
1410 if (aEncoding
.Len())
1412 // Use given Encoding.
1413 if (aEncoding
.CompareIgnoreCaseToAscii (
1415 eEncoding
= INETMSG_ENCODING_BASE64
;
1416 else if (aEncoding
.CompareIgnoreCaseToAscii (
1417 "quoted-printable", 16) == 0)
1418 eEncoding
= INETMSG_ENCODING_QUOTED
;
1420 eEncoding
= INETMSG_ENCODING_7BIT
;
1424 // Use default Encoding for (given|default) Content-Type.
1425 if (aContentType
.Len() == 0)
1427 // Determine default Content-Type.
1428 pMsg
->GetDefaultContentType (aContentType
);
1430 eEncoding
= GetMsgEncoding (aContentType
);
1433 // Set Content-Transfer-Encoding header.
1434 if (eEncoding
== INETMSG_ENCODING_BASE64
)
1437 pMsg
->SetContentTransferEncoding (
1438 String(CONSTASCII_STRINGPARAM("base64")));
1440 else if (eEncoding
== INETMSG_ENCODING_QUOTED
)
1442 // Quoted-Printable.
1443 pMsg
->SetContentTransferEncoding (
1444 String(CONSTASCII_STRINGPARAM("quoted-printable")));
1448 // No need to specify default.
1449 pMsg
->SetContentTransferEncoding (String());
1453 eState
= INETMSG_EOL_DONE
;
1456 // Generate the message header.
1457 int nRead
= INetMessageIOStream::GetMsgLine (pData
, nSize
);
1461 eState
= INETMSG_EOL_BEGIN
;
1467 // Generate the message body.
1468 if (pMsg
->IsContainer())
1470 // Encapsulated message body.
1471 while (eState
== INETMSG_EOL_BEGIN
)
1473 if (pChildStrm
== NULL
)
1475 INetMIMEMessage
*pChild
= pMsg
->GetChild (nChildIndex
);
1478 // Increment child index.
1481 // Create child stream.
1482 pChildStrm
= new INetMIMEMessageStream
;
1483 pChildStrm
->SetSourceMessage (pChild
);
1485 if (pMsg
->IsMultipart())
1487 // Insert multipart delimiter.
1488 ByteString
aDelim ("--");
1489 aDelim
+= pMsg
->GetMultipartBoundary();
1493 pData
, aDelim
.GetBuffer(), aDelim
.Len());
1494 return aDelim
.Len();
1499 // No more parts. Mark we're done.
1500 eState
= INETMSG_EOL_DONE
;
1503 if (pMsg
->IsMultipart())
1505 // Insert close delimiter.
1506 ByteString
aDelim ("--");
1507 aDelim
+= pMsg
->GetMultipartBoundary();
1511 pData
, aDelim
.GetBuffer(), aDelim
.Len());
1512 return aDelim
.Len();
1518 // Read current child stream.
1519 int nRead
= pChildStrm
->Read (pData
, nSize
);
1526 // Cleanup exhausted child stream.
1536 // Single part message body.
1537 if (pMsg
->GetDocumentLB() == NULL
)
1539 // Empty message body.
1544 // Check whether message body needs to be encoded.
1545 if (eEncoding
== INETMSG_ENCODING_7BIT
)
1548 return INetMessageIOStream::GetMsgLine (pData
, nSize
);
1552 // Apply appropriate Encoding.
1553 while (eState
== INETMSG_EOL_BEGIN
)
1555 if (pEncodeStrm
== NULL
)
1557 // Create encoder stream.
1558 if (eEncoding
== INETMSG_ENCODING_QUOTED
)
1560 // Quoted-Printable Encoding.
1562 = new INetMessageEncodeQPStream_Impl
;
1568 = new INetMessageEncode64Stream_Impl
;
1570 pEncodeStrm
->SetSourceMessage (pMsg
);
1573 // Read encoded message.
1574 int nRead
= pEncodeStrm
->Read (pData
, nSize
);
1581 // Cleanup exhausted encoder stream.
1586 eState
= INETMSG_EOL_DONE
;
1600 int INetMIMEMessageStream::PutMsgLine (const sal_Char
*pData
, ULONG nSize
)
1602 // Check for message container.
1603 INetMIMEMessage
*pMsg
= GetTargetMessage();
1604 if (pMsg
== NULL
) return INETSTREAM_STATUS_ERROR
;
1606 // Check for header or body.
1607 if (!IsHeaderParsed())
1609 // Parse the message header.
1610 int nRet
= INetMessageIOStream::PutMsgLine (pData
, nSize
);
1615 pMsg
->SetHeaderParsed();
1616 // Parse the message body.
1617 if (pMsg
->IsContainer())
1620 // Content-Transfer-Encoding MUST be "7bit" (RFC1521).
1621 if (pMsg
->IsMessage())
1625 // Encapsulated message.
1626 pMsg
->SetChildCount( pMsg
->GetChildCount() + 1);
1627 INetMIMEMessage
* pNewMessage
= new INetMIMEMessage
;
1628 pNewMessage
->SetDocumentLB (
1629 new SvAsyncLockBytes(new SvCacheStream
, FALSE
));
1630 pMsg
->AttachChild( *pNewMessage
, TRUE
);
1632 // Encapsulated message body. Create message parser stream.
1633 pChildStrm
= new INetMIMEMessageStream
;
1634 pChildStrm
->SetTargetMessage ( pNewMessage
);
1636 // Initialize control variables.
1637 eState
= INETMSG_EOL_BEGIN
;
1641 // Bytes still in buffer. Put message down-stream.
1642 int status
= pChildStrm
->Write( pData
, nSize
);
1643 if (status
!= INETSTREAM_STATUS_OK
)
1647 return INetMessageIOStream::PutMsgLine (pData
, nSize
);
1652 // Multipart message body. Initialize multipart delimiters.
1653 // Multipart message.
1654 if (pMsg
->GetMultipartBoundary().Len() == 0)
1656 // Determine boundary.
1658 pMsg
->GetContentType(), RTL_TEXTENCODING_ASCII_US
);
1659 ByteString
aLowerType (aType
);
1660 aLowerType
.ToLowerAscii();
1662 USHORT nPos
= aLowerType
.Search ("boundary=");
1663 ByteString
aBoundary (aType
.Copy (nPos
+ 9));
1665 aBoundary
.EraseLeadingAndTrailingChars (' ');
1666 aBoundary
.EraseLeadingAndTrailingChars ('"');
1669 pMsg
->SetMultipartBoundary (aBoundary
);
1672 ByteString
aPlainDelim (pMsg
->GetMultipartBoundary());
1673 ByteString
aDelim ("--");
1674 aDelim
+= aPlainDelim
;
1676 ByteString
aPlainClose (aPlainDelim
);
1677 aPlainClose
+= "--";
1679 ByteString
aClose (aDelim
);
1682 if (pMsgBuffer
== NULL
) pMsgBuffer
= new SvMemoryStream
;
1683 pMsgBuffer
->Write (pData
, nSize
);
1684 ULONG nBufSize
= pMsgBuffer
->Tell();
1686 const sal_Char
* pChar
;
1687 const sal_Char
* pOldPos
;
1688 for( pOldPos
= pChar
= (const sal_Char
*) pMsgBuffer
->GetData(); nBufSize
--;
1692 if( *pChar
== '\r' || *pChar
== '\n' )
1694 if( aDelim
.CompareTo (pOldPos
, aDelim
.Len())
1696 aClose
.CompareTo (pOldPos
, aClose
.Len())
1698 aPlainDelim
.CompareTo (pOldPos
, aPlainDelim
.Len())
1700 aPlainClose
.CompareTo(pOldPos
, aPlainClose
.Len())
1704 ( pChar
[1] == '\r' || pChar
[1] == '\n' ) )
1705 nBufSize
--, pChar
++;
1708 status
= pChildStrm
->Write(
1709 pOldPos
, pChar
- pOldPos
+ 1 );
1710 if( status
!= INETSTREAM_STATUS_OK
)
1714 DBG_ERRORFILE( "Die Boundary nicht gefunden" );
1716 status
= INetMessageIOStream::PutMsgLine(
1717 pOldPos
, pChar
- pOldPos
+ 1 );
1718 if( status
!= INETSTREAM_STATUS_OK
)
1720 pOldPos
= pChar
+ 1;
1725 ( pChar
[1] == '\r' || pChar
[1] == '\n' ) )
1726 nBufSize
--, pChar
++;
1727 pOldPos
= pChar
+ 1;
1728 DELETEZ( pChildStrm
);
1730 if (aClose
.CompareTo (pOldPos
, aClose
.Len())
1732 aPlainClose
.CompareTo (pOldPos
, aClose
.Len())
1735 // Encapsulated message.
1736 pMsg
->SetChildCount(pMsg
->GetChildCount() + 1);
1737 INetMIMEMessage
* pNewMessage
=
1738 new INetMIMEMessage
;
1739 pNewMessage
->SetDocumentLB (
1740 new SvAsyncLockBytes (
1741 new SvCacheStream
, FALSE
));
1743 pMsg
->AttachChild( *pNewMessage
, TRUE
);
1745 // Encapsulated message body. Create message parser stream.
1746 pChildStrm
= new INetMIMEMessageStream
;
1747 pChildStrm
->SetTargetMessage ( pNewMessage
);
1749 // Initialize control variables.
1751 eState
= INETMSG_EOL_BEGIN
;
1752 status
= INetMessageIOStream::PutMsgLine(
1753 pOldPos
, pChar
- pOldPos
+ 1 );
1754 if( status
!= INETSTREAM_STATUS_OK
)
1759 if( pOldPos
< pChar
)
1761 SvMemoryStream
* pNewStream
= new SvMemoryStream
;
1762 pNewStream
->Write( pOldPos
, pChar
- pOldPos
);
1763 SvMemoryStream
* pTmp
= pMsgBuffer
;
1764 pMsgBuffer
= pNewStream
;
1769 pMsgBuffer
->Seek( 0L );
1770 pMsgBuffer
->SetStreamSize( 0 );
1772 return INETSTREAM_STATUS_OK
;
1778 * Single part message.
1779 * Remove any ContentTransferEncoding.
1781 if (pMsg
->GetContentType().Len() == 0)
1784 pMsg
->GetDefaultContentType (aDefaultCT
);
1785 pMsg
->SetContentType (aDefaultCT
);
1788 if (eEncoding
== INETMSG_ENCODING_BINARY
)
1790 String
aEncoding (pMsg
->GetContentTransferEncoding());
1791 if (aEncoding
.CompareIgnoreCaseToAscii (
1792 "base64", 6) == COMPARE_EQUAL
)
1793 eEncoding
= INETMSG_ENCODING_BASE64
;
1794 else if (aEncoding
.CompareIgnoreCaseToAscii (
1795 "quoted-printable", 16) == COMPARE_EQUAL
)
1796 eEncoding
= INETMSG_ENCODING_QUOTED
;
1798 eEncoding
= INETMSG_ENCODING_7BIT
;
1801 if (eEncoding
== INETMSG_ENCODING_7BIT
)
1803 // No decoding necessary.
1804 return INetMessageIOStream::PutMsgLine (pData
, nSize
);
1808 if (pDecodeStrm
== NULL
)
1810 if (eEncoding
== INETMSG_ENCODING_QUOTED
)
1811 pDecodeStrm
= new INetMessageDecodeQPStream_Impl
;
1813 pDecodeStrm
= new INetMessageDecode64Stream_Impl
;
1815 pDecodeStrm
->SetTargetMessage (pMsg
);
1817 return pDecodeStrm
->Write (pData
, nSize
);