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