merge the formfield patch from ooo-build
[ooovba.git] / tools / source / inet / inetstrm.cxx
blob027610d53a565c849d50d6551043628df6d4bce8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: inetstrm.cxx,v $
10 * $Revision: 1.11 $
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
57 SvStream *pMsgStrm;
59 ULONG nMsgBufSiz;
60 sal_Char *pMsgBuffer;
61 sal_Char *pMsgRead;
62 sal_Char *pMsgWrite;
64 ULONG nTokBufSiz;
65 sal_Char *pTokBuffer;
66 sal_Char *pTokRead;
67 sal_Char *pTokWrite;
69 INetMessageStreamState eState;
70 BOOL bDone;
72 virtual int GetMsgLine (sal_Char *pData, ULONG nSize);
74 public:
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;
90 ULONG nTokBufLen;
91 sal_Char pTokBuffer[4];
93 virtual int PutMsgLine (const sal_Char *pData, ULONG nSize);
95 public:
96 INetMessageDecodeQPStream_Impl (void);
97 virtual ~INetMessageDecodeQPStream_Impl (void);
100 /*======================================================================
102 * INetMessageEncode64Stream Interface.
103 * (Base64 Encoding)
105 *====================================================================*/
106 class INetMessageEncode64Stream_Impl : public INetMessageIStream
108 SvStream *pMsgStrm;
110 ULONG nMsgBufSiz;
111 sal_uInt8 *pMsgBuffer;
112 sal_uInt8 *pMsgRead;
113 sal_uInt8 *pMsgWrite;
115 ULONG nTokBufSiz;
116 sal_Char *pTokBuffer;
117 sal_Char *pTokRead;
118 sal_Char *pTokWrite;
120 BOOL bDone;
122 virtual int GetMsgLine (sal_Char *pData, ULONG nSize);
124 public:
125 INetMessageEncode64Stream_Impl (ULONG nMsgBufferSize = 2048);
126 virtual ~INetMessageEncode64Stream_Impl (void);
129 /*======================================================================
131 * INetMessageDecode64Stream Interface.
132 * (Base64 Decoding)
134 *====================================================================*/
135 class INetMessageDecode64Stream_Impl : public INetMessageOStream
137 INetMessageStreamState eState;
139 ULONG nMsgBufSiz;
140 sal_Char *pMsgBuffer;
141 sal_Char *pMsgRead;
142 sal_Char *pMsgWrite;
144 virtual int PutMsgLine (const sal_Char *pData, ULONG nSize);
146 public:
147 INetMessageDecode64Stream_Impl (ULONG nMsgBufferSize = 128);
148 virtual ~INetMessageDecode64Stream_Impl (void);
151 /*=========================================================================
153 * INetIStream Implementation.
155 *=======================================================================*/
157 * INetIStream.
159 INetIStream::INetIStream ()
164 * ~INetIStream.
166 INetIStream::~INetIStream (void)
171 * Read.
173 int INetIStream::Read (sal_Char *pData, ULONG nSize)
175 return GetData (pData, nSize);
179 * Decode64.
181 void INetIStream::Decode64 (SvStream& rIn, SvStream& rOut)
183 INetMessage aMsg;
184 aMsg.SetDocumentLB(new SvAsyncLockBytes(&rOut, FALSE));
186 INetMessageDecode64Stream_Impl aStream (8192);
187 aStream.SetTargetMessage (&aMsg);
189 sal_Char* pBuf = new sal_Char[8192];
191 int nRead = 0;
192 while ((nRead = rIn.Read (pBuf, 8192)) > 0)
193 aStream.Write( pBuf, nRead );
194 aStream.Write ("\r\n", 2);
196 delete[] pBuf;
200 * Encode64.
202 void INetIStream::Encode64 (SvStream& rIn, SvStream& rOut)
204 INetMessage aMsg;
205 aMsg.SetDocumentLB (
206 new SvLockBytes (&rIn, FALSE));
208 INetMessageEncode64Stream_Impl aStream (8192);
209 aStream.SetSourceMessage (&aMsg);
211 sal_Char* pBuf = new sal_Char[8192];
213 int nRead = 0;
214 while ((nRead = aStream.Read (pBuf, 8192)) > 0)
215 rOut.Write( pBuf, nRead );
217 delete[] pBuf;
220 /*=========================================================================
222 * INetOStream Implementation.
224 *=======================================================================*/
226 * INetOStream.
228 INetOStream::INetOStream ()
233 * ~INetOStream.
235 INetOStream::~INetOStream (void)
240 * Write.
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)
256 : pSourceMsg (NULL),
257 bHeaderGenerated (FALSE),
258 nBufSiz (nBufferSize),
259 pMsgStrm (NULL),
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)
272 delete [] pBuffer;
273 delete pMsgBuffer;
274 delete pMsgStrm;
278 * GetData.
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;
291 if (n > 0)
293 // Bytes still in buffer.
294 ULONG m = pWEnd - pWBuf;
295 if (m < n) n = m;
296 for (ULONG i = 0; i < n; i++) *pWBuf++ = *pWrite++;
298 else
300 // Buffer empty. Reset to <Begin-of-Buffer>.
301 pRead = pWrite = pBuffer;
303 // Read next message line.
304 int nRead = GetMsgLine (pBuffer, nBufSiz);
305 if (nRead > 0)
307 // Set read pointer.
308 pRead = pBuffer + nRead;
310 else
312 if (!bHeaderGenerated)
314 // Header generated. Insert empty line.
315 bHeaderGenerated = TRUE;
316 *pRead++ = '\r';
317 *pRead++ = '\n';
319 else
321 // Body generated.
322 return (pWBuf - pData);
327 return (pWBuf - pData);
331 * GetMsgLine.
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)
342 ULONG i, n;
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());
355 *pMsgBuffer << ": ";
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;
366 if (n > 0)
368 // Move to caller.
369 if (nSize < n) n = nSize;
370 for (i = 0; i < n; i++) *pWBuf++ = *pMsgWrite++;
372 else
374 // Reset buffer.
375 pMsgBuffer->Seek (STREAM_SEEK_TO_BEGIN);
378 else
380 if (pSourceMsg->GetDocumentLB())
382 if (pMsgStrm == NULL)
383 pMsgStrm = new SvStream (pSourceMsg->GetDocumentLB());
385 ULONG nRead = pMsgStrm->Read (pWBuf, (pWEnd - pWBuf));
386 pWBuf += nRead;
389 return (pWBuf - pData);
392 /*=========================================================================
394 * INetMessageOStream Implementation.
396 *=======================================================================*/
398 * INetMessageOStream.
400 INetMessageOStream::INetMessageOStream (void)
401 : pTargetMsg (NULL),
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());
415 delete pMsgBuffer;
417 if (pTargetMsg)
419 SvOpenLockBytes *pLB =
420 PTR_CAST (SvOpenLockBytes, pTargetMsg->GetDocumentLB());
421 if (pLB)
423 pLB->Flush();
424 pLB->Terminate();
430 * PutData.
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).
449 pData++;
450 if ((pData < pStop) && ((*pData == '\r') || (*pData == '\n')))
451 pData++;
453 // Emit any buffered last header field.
454 if (pMsgBuffer->Tell() > 0)
456 *pMsgBuffer << '\0';
457 int status = PutMsgLine (
458 (const sal_Char *) pMsgBuffer->GetData(),
459 pMsgBuffer->Tell());
460 if (status != INETSTREAM_STATUS_OK) return status;
463 // Reset to begin.
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.
473 *pMsgBuffer << ' ';
474 pData++;
476 else
478 // Begin of new header field.
479 if (pMsgBuffer->Tell() > 0)
481 // Emit buffered header field now.
482 *pMsgBuffer << '\0';
483 int status = PutMsgLine (
484 (const sal_Char *) pMsgBuffer->GetData(),
485 pMsgBuffer->Tell());
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.
502 pData++;
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.
519 pData++;
521 else
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;
538 * PutMsgLine.
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)
552 ByteString aName (
553 aField.Copy (0, nPos));
554 ByteString aValue (
555 aField.Copy (nPos + 1, aField.Len() - nPos + 1));
556 aValue.EraseLeadingChars (' ');
558 pTargetMsg->SetHeaderField (
559 INetMessageHeader (aName, aValue));
562 else
564 SvOpenLockBytes *pLB =
565 PTR_CAST(SvOpenLockBytes, pTargetMsg->GetDocumentLB());
566 if (pLB == NULL)
567 return INETSTREAM_STATUS_WOULDBLOCK;
569 sal_Size nDocSiz = pTargetMsg->GetDocumentSize();
570 sal_Size nWrite = 0;
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 (),
622 pMsgStrm (NULL),
623 nMsgBufSiz (nMsgBufferSize),
624 nTokBufSiz (80),
625 eState (INETMSG_EOL_SCR),
626 bDone (FALSE)
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)
642 delete pMsgStrm;
643 delete [] pMsgBuffer;
644 delete [] pTokBuffer;
648 * GetMsgLine.
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.
675 *pTokRead++ = '\n';
677 *pTokRead++ = *pMsgWrite++;
679 else if ((*pMsgWrite == ' ') || (*pMsgWrite == '\t'))
681 eState = INETMSG_EOL_FSP;
682 *pTokRead++ = *pMsgWrite++;
684 else if (*pMsgWrite == '\r')
686 // Found <CR>.
687 if (eState == INETMSG_EOL_FSP)
689 // Encode last (trailing space) character.
690 sal_uInt8 c = (sal_uInt8)(*(--pTokRead));
691 *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')
700 // Found <LF> only.
701 if (eState == INETMSG_EOL_FSP)
703 // Encode last (trailing space) character.
704 sal_uInt8 c = (sal_uInt8)(*(--pTokRead));
705 *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.
712 *pTokRead++ = '\r';
713 *pTokRead++ = *pMsgWrite++;
715 else if (*pMsgWrite == '=')
717 // Escape character itself MUST be encoded, of course.
718 sal_uInt8 c = (sal_uInt8)(*pMsgWrite++);
719 *pTokRead++ = '=';
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;
735 else
737 // Encode any other character.
738 sal_uInt8 c = (sal_uInt8)(*pMsgWrite++);
739 *pTokRead++ = '=';
740 *pTokRead++ = hex2pr[((c & 0xf0) >> 4)];
741 *pTokRead++ = hex2pr[((c & 0x0f) )];
743 eState = INETMSG_EOL_SCR;
746 else
748 // Check for maximum line length.
749 if (eState != INETMSG_EOL_BEGIN)
751 // Insert soft line break.
752 *pTokRead++ = '=';
753 *pTokRead++ = '\r';
754 *pTokRead++ = '\n';
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++;
765 else
767 // Token buffer empty. Reset to <Begin-of-Buffer>.
768 pTokRead = pTokWrite = pTokBuffer;
769 eState = INETMSG_EOL_SCR;
773 else
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);
780 if (nRead > 0)
782 // Set read pointer.
783 pMsgRead = (pMsgBuffer + nRead);
785 else
787 // Nothing more ro read.
788 if (!bDone)
790 // Append final <CR><LF> and mark we're done.
791 *pTokRead++ = '\r';
792 *pTokRead++ = '\n';
794 bDone = TRUE;
796 else
798 // Already done all encoding.
799 if ((pTokRead - pTokWrite) > 0)
801 // Bytes still in token buffer.
802 *pWBuf++ = *pTokWrite++;
804 else
806 // Token buffer empty. Reset to <Begin-of-Buffer>.
807 pTokRead = pTokWrite = pTokBuffer;
809 // Return.
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),
854 nTokBufLen (0)
856 ParseHeader (FALSE);
860 * ~INetMessageDecodeQPStream_Impl.
862 INetMessageDecodeQPStream_Impl::~INetMessageDecodeQPStream_Impl (void)
864 delete pMsgBuffer;
868 * PutMsgLine.
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));
885 pData++;
886 if (nTokBufLen == 2)
888 if ((*pTokBuffer == '\r') || (*pTokBuffer == '\n'))
890 // Soft line break (=<CR><LF>). Emit buffer now.
891 eState = INETMSG_EOL_BEGIN;
893 else
895 // Decode token.
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.
905 nTokBufLen = 0;
908 else if (*pData == '=')
910 // Found escape character.
911 pData++;
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;
924 else
926 *pMsgBuffer << *pData++;
929 if (eState == INETMSG_EOL_BEGIN)
931 sal_Size nRead = pMsgBuffer->Tell();
932 if (nRead > 0)
934 // Emit buffer.
935 sal_Size nDocSiz = pMsg->GetDocumentSize();
936 sal_Size nWrite = 0;
938 pLB->FillAppend (
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.
955 * (Base64 Encoding)
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 (),
972 pMsgStrm (NULL),
973 nMsgBufSiz (nMsgBufferSize),
974 nTokBufSiz (80),
975 bDone (FALSE)
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)
991 delete pMsgStrm;
992 delete [] pMsgBuffer;
993 delete [] pTokBuffer;
997 * GetMsgLine.
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)
1019 case 0:
1020 *pTokRead++ = six2pr[(int)(*pMsgWrite >> 2)];
1021 break;
1023 case 1:
1024 *pTokRead++ = six2pr[
1025 (int)(((*pMsgWrite << 4) & 060) |
1026 (((*(pMsgWrite + 1)) >> 4) & 017))];
1027 pMsgWrite++;
1028 break;
1030 case 2:
1031 *pTokRead++ = six2pr[
1032 (int)(((*pMsgWrite << 2) & 074) |
1033 (((*(pMsgWrite + 1)) >> 6) & 003))];
1034 pMsgWrite++;
1035 break;
1037 default: // == case 3
1038 *pTokRead++ = six2pr[(int)(*pMsgWrite & 077)];
1039 pMsgWrite++;
1040 break;
1043 else if ((pTokRead - pTokBuffer) == 72)
1045 // Maximum line length. Append <CR><LF>.
1046 *pTokRead++ = '\r';
1047 *pTokRead++ = '\n';
1049 else
1051 if ((pTokRead - pTokWrite) > 0)
1053 // Bytes still in token buffer.
1054 *pWBuf++ = *pTokWrite++;
1056 else
1058 // Token buffer empty. Reset to <Begin-of-Buffer>.
1059 pTokRead = pTokWrite = pTokBuffer;
1063 else
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);
1070 if (nRead > 0)
1072 // Set read pointer.
1073 pMsgRead = (pMsgBuffer + nRead);
1075 else
1077 // Nothing more to read.
1078 if (!bDone)
1080 // Append pad character(s) and final <CR><LF>.
1081 switch ((pTokRead - pTokBuffer) % 4)
1083 case 2:
1084 *pTokRead++ = '=';
1085 // Fall through for 2nd pad character.
1087 case 3:
1088 *pTokRead++ = '=';
1089 break;
1091 default:
1092 break;
1094 *pTokRead++ = '\r';
1095 *pTokRead++ = '\n';
1097 // Mark we're done.
1098 bDone = TRUE;
1100 else
1102 // Already done all encoding.
1103 if ((pTokRead - pTokWrite) > 0)
1105 // Bytes still in token buffer.
1106 *pWBuf++ = *pTokWrite++;
1108 else
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;
1116 // Return.
1117 return (pWBuf - pData);
1122 } // while (pWBuf < (pData + nSize))
1123 return (pWBuf - pData);
1126 /*======================================================================
1128 * INetMessageDecode64Stream_Impl Implementation.
1129 * (Base64 Decoding)
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;
1198 * PutMsgLine.
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.
1218 if (*pData == '=')
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);
1228 if (nWrite < nRead)
1229 return INETSTREAM_STATUS_ERROR;
1230 else
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.
1255 pData++;
1256 eState = INETMSG_EOL_FCR;
1258 else
1260 // Skip any junk character (may be transmission error).
1261 pData++;
1264 else
1266 // Decode any other character into message buffer.
1267 switch ((pMsgRead - pMsgBuffer) % 4)
1269 case 0:
1270 *pMsgWrite = (pr2six[(int)(*pData++)] << 2);
1271 pMsgRead++;
1272 break;
1274 case 1:
1275 *pMsgWrite++ |= (pr2six[(int)(*pData )] >> 4);
1276 *pMsgWrite = (pr2six[(int)(*pData++)] << 4);
1277 pMsgRead++;
1278 break;
1280 case 2:
1281 *pMsgWrite++ |= (pr2six[(int)(*pData )] >> 2);
1282 *pMsgWrite = (pr2six[(int)(*pData++)] << 6);
1283 pMsgRead++;
1284 break;
1286 default: // == case 3
1287 *pMsgWrite++ |= (pr2six[(int)(*pData++)]);
1288 pMsgRead = pMsgBuffer;
1289 break;
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),
1307 nChildIndex (0),
1308 pChildStrm (NULL),
1309 eEncoding (INETMSG_ENCODING_BINARY),
1310 pEncodeStrm (NULL),
1311 pDecodeStrm (NULL),
1312 pMsgBuffer (NULL)
1317 * ~INetMIMEMessageStream.
1319 INetMIMEMessageStream::~INetMIMEMessageStream (void)
1321 delete pChildStrm;
1322 delete pEncodeStrm;
1323 delete pDecodeStrm;
1324 delete pMsgBuffer;
1328 * GetMsgEncoding.
1330 INetMessageEncoding
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;
1349 else
1350 return INETMSG_ENCODING_QUOTED;
1352 else
1353 return INETMSG_ENCODING_7BIT;
1355 else
1356 return INETMSG_ENCODING_QUOTED;
1359 return INETMSG_ENCODING_BASE64;
1363 * GetMsgLine.
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")));
1384 else
1385 pMsg->SetMIMEVersion (String());
1387 else
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());
1408 // Check Encoding.
1409 String aEncoding (pMsg->GetContentTransferEncoding());
1410 if (aEncoding.Len())
1412 // Use given Encoding.
1413 if (aEncoding.CompareIgnoreCaseToAscii (
1414 "base64", 6) == 0)
1415 eEncoding = INETMSG_ENCODING_BASE64;
1416 else if (aEncoding.CompareIgnoreCaseToAscii (
1417 "quoted-printable", 16) == 0)
1418 eEncoding = INETMSG_ENCODING_QUOTED;
1419 else
1420 eEncoding = INETMSG_ENCODING_7BIT;
1422 else
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)
1436 // 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")));
1446 else
1448 // No need to specify default.
1449 pMsg->SetContentTransferEncoding (String());
1452 // Mark we're done.
1453 eState = INETMSG_EOL_DONE;
1456 // Generate the message header.
1457 int nRead = INetMessageIOStream::GetMsgLine (pData, nSize);
1458 if (nRead <= 0)
1460 // Reset state.
1461 eState = INETMSG_EOL_BEGIN;
1463 return nRead;
1465 else
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);
1476 if (pChild)
1478 // Increment child index.
1479 nChildIndex++;
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();
1490 aDelim += "\r\n";
1492 rtl_copyMemory (
1493 pData, aDelim.GetBuffer(), aDelim.Len());
1494 return aDelim.Len();
1497 else
1499 // No more parts. Mark we're done.
1500 eState = INETMSG_EOL_DONE;
1501 nChildIndex = 0;
1503 if (pMsg->IsMultipart())
1505 // Insert close delimiter.
1506 ByteString aDelim ("--");
1507 aDelim += pMsg->GetMultipartBoundary();
1508 aDelim += "--\r\n";
1510 rtl_copyMemory (
1511 pData, aDelim.GetBuffer(), aDelim.Len());
1512 return aDelim.Len();
1516 else
1518 // Read current child stream.
1519 int nRead = pChildStrm->Read (pData, nSize);
1520 if (nRead > 0)
1522 return nRead;
1524 else
1526 // Cleanup exhausted child stream.
1527 delete pChildStrm;
1528 pChildStrm = NULL;
1532 return 0;
1534 else
1536 // Single part message body.
1537 if (pMsg->GetDocumentLB() == NULL)
1539 // Empty message body.
1540 return 0;
1542 else
1544 // Check whether message body needs to be encoded.
1545 if (eEncoding == INETMSG_ENCODING_7BIT)
1547 // No Encoding.
1548 return INetMessageIOStream::GetMsgLine (pData, nSize);
1550 else
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.
1561 pEncodeStrm
1562 = new INetMessageEncodeQPStream_Impl;
1564 else
1566 // Base64 Encoding.
1567 pEncodeStrm
1568 = new INetMessageEncode64Stream_Impl;
1570 pEncodeStrm->SetSourceMessage (pMsg);
1573 // Read encoded message.
1574 int nRead = pEncodeStrm->Read (pData, nSize);
1575 if (nRead > 0)
1577 return nRead;
1579 else
1581 // Cleanup exhausted encoder stream.
1582 delete pEncodeStrm;
1583 pEncodeStrm = NULL;
1585 // Mark we're done.
1586 eState = INETMSG_EOL_DONE;
1589 return 0;
1597 * PutMsgLine.
1598 * (Message Parser).
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);
1611 return nRet;
1613 else
1615 pMsg->SetHeaderParsed();
1616 // Parse the message body.
1617 if (pMsg->IsContainer())
1620 // Content-Transfer-Encoding MUST be "7bit" (RFC1521).
1621 if (pMsg->IsMessage())
1623 if( !pChildStrm )
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;
1639 if ( nSize > 0)
1641 // Bytes still in buffer. Put message down-stream.
1642 int status = pChildStrm->Write( pData, nSize );
1643 if (status != INETSTREAM_STATUS_OK)
1644 return status;
1647 return INetMessageIOStream::PutMsgLine (pData, nSize);
1649 else
1652 // Multipart message body. Initialize multipart delimiters.
1653 // Multipart message.
1654 if (pMsg->GetMultipartBoundary().Len() == 0)
1656 // Determine boundary.
1657 ByteString aType (
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 ('"');
1668 // Save boundary.
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);
1680 aClose += "--";
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--;
1689 pChar++ )
1691 int status;
1692 if( *pChar == '\r' || *pChar == '\n' )
1694 if( aDelim.CompareTo (pOldPos, aDelim.Len())
1695 != COMPARE_EQUAL &&
1696 aClose.CompareTo (pOldPos, aClose.Len())
1697 != COMPARE_EQUAL &&
1698 aPlainDelim.CompareTo (pOldPos, aPlainDelim.Len())
1699 != COMPARE_EQUAL &&
1700 aPlainClose.CompareTo(pOldPos, aPlainClose.Len())
1701 != COMPARE_EQUAL )
1703 if( nBufSize &&
1704 ( pChar[1] == '\r' || pChar[1] == '\n' ) )
1705 nBufSize--, pChar++;
1706 if( pChildStrm )
1708 status = pChildStrm->Write(
1709 pOldPos, pChar - pOldPos + 1 );
1710 if( status != INETSTREAM_STATUS_OK )
1711 return status;
1713 else {
1714 DBG_ERRORFILE( "Die Boundary nicht gefunden" );
1716 status = INetMessageIOStream::PutMsgLine(
1717 pOldPos, pChar - pOldPos + 1 );
1718 if( status != INETSTREAM_STATUS_OK )
1719 return status;
1720 pOldPos = pChar + 1;
1722 else
1724 if( nBufSize &&
1725 ( pChar[1] == '\r' || pChar[1] == '\n' ) )
1726 nBufSize--, pChar++;
1727 pOldPos = pChar + 1;
1728 DELETEZ( pChildStrm );
1730 if (aClose.CompareTo (pOldPos, aClose.Len())
1731 != COMPARE_EQUAL &&
1732 aPlainClose.CompareTo (pOldPos, aClose.Len())
1733 != COMPARE_EQUAL )
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 )
1755 return status;
1759 if( pOldPos < pChar )
1761 SvMemoryStream* pNewStream = new SvMemoryStream;
1762 pNewStream->Write( pOldPos, pChar - pOldPos );
1763 SvMemoryStream* pTmp = pMsgBuffer;
1764 pMsgBuffer = pNewStream;
1765 delete pTmp;
1767 else
1769 pMsgBuffer->Seek( 0L );
1770 pMsgBuffer->SetStreamSize( 0 );
1772 return INETSTREAM_STATUS_OK;
1775 else
1778 * Single part message.
1779 * Remove any ContentTransferEncoding.
1781 if (pMsg->GetContentType().Len() == 0)
1783 String aDefaultCT;
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;
1797 else
1798 eEncoding = INETMSG_ENCODING_7BIT;
1801 if (eEncoding == INETMSG_ENCODING_7BIT)
1803 // No decoding necessary.
1804 return INetMessageIOStream::PutMsgLine (pData, nSize);
1806 else
1808 if (pDecodeStrm == NULL)
1810 if (eEncoding == INETMSG_ENCODING_QUOTED)
1811 pDecodeStrm = new INetMessageDecodeQPStream_Impl;
1812 else
1813 pDecodeStrm = new INetMessageDecode64Stream_Impl;
1815 pDecodeStrm->SetTargetMessage (pMsg);
1817 return pDecodeStrm->Write (pData, nSize);