1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
24 #include <sal/types.h>
25 #include <tools/inetmsg.hxx>
26 #include <tools/inetstrm.hxx>
28 int INetMIMEMessageStream::GetHeaderLine(char* pData
, sal_uInt32 nSize
)
34 if (maMsgBuffer
.Tell() == 0)
36 // Insert formatted header into buffer.
37 n
= pSourceMsg
->GetHeaderCount();
38 for (i
= 0; i
< n
; i
++)
40 INetMessageHeader
aHeader (pSourceMsg
->GetHeaderField(i
));
41 if (aHeader
.GetValue().getLength())
43 // NYI: Folding long lines.
44 maMsgBuffer
.WriteOString( aHeader
.GetName() );
45 maMsgBuffer
.WriteOString( ": " );
46 maMsgBuffer
.WriteOString( aHeader
.GetValue() );
47 maMsgBuffer
.WriteOString( "\r\n" );
51 pMsgWrite
= const_cast<char *>(static_cast<char const *>(maMsgBuffer
.GetData()));
52 pMsgRead
= pMsgWrite
+ maMsgBuffer
.Tell();
55 n
= pMsgRead
- pMsgWrite
;
59 if (nSize
< n
) n
= nSize
;
60 for (i
= 0; i
< n
; i
++) *pWBuf
++ = *pMsgWrite
++;
65 maMsgBuffer
.Seek(STREAM_SEEK_TO_BEGIN
);
68 return (pWBuf
- pData
);
71 int INetMIMEMessageStream::GetBodyLine(char* pData
, sal_uInt32 nSize
)
74 char* pWEnd
= pData
+ nSize
;
76 if (pSourceMsg
->GetDocumentLB())
78 if (pMsgStrm
== nullptr)
79 pMsgStrm
.reset(new SvStream (pSourceMsg
->GetDocumentLB()));
81 sal_uInt32 nRead
= pMsgStrm
->ReadBytes(pWBuf
, (pWEnd
- pWBuf
));
85 return (pWBuf
- pData
);
88 int INetMIMEMessageStream::GetMsgLine(char* pData
, sal_uInt32 nSize
)
90 // Check for header or body.
91 if (!bHeaderGenerated
)
95 // Prepare special header fields.
96 if (pSourceMsg
->GetParent())
98 OUString
aPCT(pSourceMsg
->GetParent()->GetContentType());
99 if (aPCT
.startsWithIgnoreAsciiCase("message/rfc822"))
100 pSourceMsg
->SetMIMEVersion("1.0");
102 pSourceMsg
->SetMIMEVersion(OUString());
106 pSourceMsg
->SetMIMEVersion("1.0");
109 // Check ContentType.
110 OUString
aContentType(pSourceMsg
->GetContentType());
111 if (!aContentType
.isEmpty())
113 // Determine default Content-Type.
114 OUString aDefaultType
= pSourceMsg
->GetDefaultContentType();
116 if (aDefaultType
.equalsIgnoreAsciiCase(aContentType
))
118 // No need to specify default.
119 pSourceMsg
->SetContentType(OUString());
123 // No need to specify default.
124 pSourceMsg
->SetContentTransferEncoding(OUString());
130 // Generate the message header.
131 int nRead
= GetHeaderLine(pData
, nSize
);
141 // Generate the message body.
142 if (pSourceMsg
->IsContainer())
144 // Encapsulated message body.
147 if (pChildStrm
== nullptr)
149 INetMIMEMessage
*pChild
= pSourceMsg
->GetChild(nChildIndex
);
152 // Increment child index.
155 // Create child stream.
156 pChildStrm
.reset(new INetMIMEMessageStream(pChild
, false));
158 if (pSourceMsg
->IsMultipart())
160 // Insert multipart delimiter.
161 OString aDelim
= "--" +
162 pSourceMsg
->GetMultipartBoundary() +
165 memcpy(pData
, aDelim
.getStr(),
167 return aDelim
.getLength();
172 // No more parts. Mark we're done.
176 if (pSourceMsg
->IsMultipart())
178 // Insert close delimiter.
179 OString aDelim
= "--" +
180 pSourceMsg
->GetMultipartBoundary() +
183 memcpy(pData
, aDelim
.getStr(),
185 return aDelim
.getLength();
191 // Read current child stream.
192 int nRead
= pChildStrm
->Read(pData
, nSize
);
199 // Cleanup exhausted child stream.
208 // Single part message body.
209 if (pSourceMsg
->GetDocumentLB() == nullptr)
211 // Empty message body.
216 return GetBodyLine(pData
, nSize
);
224 const int BUFFER_SIZE
= 2048;
228 INetMIMEMessageStream::INetMIMEMessageStream(
229 INetMIMEMessage
*pMsg
, bool headerGenerated
):
231 bHeaderGenerated(headerGenerated
),
232 mvBuffer(BUFFER_SIZE
),
238 assert(pMsg
!= nullptr);
239 maMsgBuffer
.SetStreamCharSet(RTL_TEXTENCODING_ASCII_US
);
240 pRead
= pWrite
= mvBuffer
.data();
243 INetMIMEMessageStream::~INetMIMEMessageStream()
248 int INetMIMEMessageStream::Read(char* pData
, sal_uInt32 nSize
)
251 char* pWEnd
= pData
+ nSize
;
253 while (pWBuf
< pWEnd
)
255 // Caller's buffer not yet filled.
256 sal_uInt32 n
= pRead
- pWrite
;
259 // Bytes still in buffer.
260 sal_uInt32 m
= pWEnd
- pWBuf
;
262 for (sal_uInt32 i
= 0; i
< n
; i
++) *pWBuf
++ = *pWrite
++;
266 // Buffer empty. Reset to <Begin-of-Buffer>.
267 pRead
= pWrite
= mvBuffer
.data();
269 // Read next message line.
270 int nRead
= GetMsgLine(mvBuffer
.data(), mvBuffer
.size());
274 pRead
= mvBuffer
.data() + nRead
;
278 if (!bHeaderGenerated
)
280 // Header generated. Insert empty line.
281 bHeaderGenerated
= true;
288 return (pWBuf
- pData
);
293 return (pWBuf
- pData
);
296 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */