Bump version to 6.4-15
[LibreOffice.git] / tools / source / inet / inetstrm.cxx
bloba26212fa17610551987e1c812302f14695fded1a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include <cassert>
24 #include <sal/types.h>
25 #include <rtl/strbuf.hxx>
26 #include <tools/inetmsg.hxx>
27 #include <tools/inetstrm.hxx>
29 int INetMIMEMessageStream::GetHeaderLine(sal_Char* pData, sal_uInt32 nSize)
31 sal_Char* pWBuf = pData;
33 sal_uInt32 i, n;
35 if (maMsgBuffer.Tell() == 0)
37 // Insert formatted header into buffer.
38 n = pSourceMsg->GetHeaderCount();
39 for (i = 0; i < n; i++)
41 INetMessageHeader aHeader (pSourceMsg->GetHeaderField(i));
42 if (aHeader.GetValue().getLength())
44 // NYI: Folding long lines.
45 maMsgBuffer.WriteOString( aHeader.GetName() );
46 maMsgBuffer.WriteCharPtr( ": " );
47 maMsgBuffer.WriteOString( aHeader.GetValue() );
48 maMsgBuffer.WriteCharPtr( "\r\n" );
52 pMsgWrite = const_cast<char *>(static_cast<sal_Char const *>(maMsgBuffer.GetData()));
53 pMsgRead = pMsgWrite + maMsgBuffer.Tell();
56 n = pMsgRead - pMsgWrite;
57 if (n > 0)
59 // Move to caller.
60 if (nSize < n) n = nSize;
61 for (i = 0; i < n; i++) *pWBuf++ = *pMsgWrite++;
63 else
65 // Reset buffer.
66 maMsgBuffer.Seek(STREAM_SEEK_TO_BEGIN);
69 return (pWBuf - pData);
72 int INetMIMEMessageStream::GetBodyLine(sal_Char* pData, sal_uInt32 nSize)
74 sal_Char* pWBuf = pData;
75 sal_Char* pWEnd = pData + nSize;
77 if (pSourceMsg->GetDocumentLB())
79 if (pMsgStrm == nullptr)
80 pMsgStrm.reset(new SvStream (pSourceMsg->GetDocumentLB()));
82 sal_uInt32 nRead = pMsgStrm->ReadBytes(pWBuf, (pWEnd - pWBuf));
83 pWBuf += nRead;
86 return (pWBuf - pData);
89 int INetMIMEMessageStream::GetMsgLine(sal_Char* pData, sal_uInt32 nSize)
91 // Check for header or body.
92 if (!bHeaderGenerated)
94 if (!done)
96 // Prepare special header fields.
97 if (pSourceMsg->GetParent())
99 OUString aPCT(pSourceMsg->GetParent()->GetContentType());
100 if (aPCT.startsWithIgnoreAsciiCase("message/rfc822"))
101 pSourceMsg->SetMIMEVersion("1.0");
102 else
103 pSourceMsg->SetMIMEVersion(OUString());
105 else
107 pSourceMsg->SetMIMEVersion("1.0");
110 // Check ContentType.
111 OUString aContentType(pSourceMsg->GetContentType());
112 if (!aContentType.isEmpty())
114 // Determine default Content-Type.
115 OUString aDefaultType = pSourceMsg->GetDefaultContentType();
117 if (aDefaultType.equalsIgnoreAsciiCase(aContentType))
119 // No need to specify default.
120 pSourceMsg->SetContentType(OUString());
124 // No need to specify default.
125 pSourceMsg->SetContentTransferEncoding(OUString());
127 // Mark we're done.
128 done = true;
131 // Generate the message header.
132 int nRead = GetHeaderLine(pData, nSize);
133 if (nRead <= 0)
135 // Reset state.
136 done = false;
138 return nRead;
140 else
142 // Generate the message body.
143 if (pSourceMsg->IsContainer())
145 // Encapsulated message body.
146 while (!done)
148 if (pChildStrm == nullptr)
150 INetMIMEMessage *pChild = pSourceMsg->GetChild(nChildIndex);
151 if (pChild)
153 // Increment child index.
154 nChildIndex++;
156 // Create child stream.
157 pChildStrm.reset(new INetMIMEMessageStream(pChild, false));
159 if (pSourceMsg->IsMultipart())
161 // Insert multipart delimiter.
162 OStringBuffer aDelim("--");
163 aDelim.append(pSourceMsg->GetMultipartBoundary());
164 aDelim.append("\r\n");
166 memcpy(pData, aDelim.getStr(),
167 aDelim.getLength());
168 return aDelim.getLength();
171 else
173 // No more parts. Mark we're done.
174 done = true;
175 nChildIndex = 0;
177 if (pSourceMsg->IsMultipart())
179 // Insert close delimiter.
180 OStringBuffer aDelim("--");
181 aDelim.append(pSourceMsg->GetMultipartBoundary());
182 aDelim.append("--\r\n");
184 memcpy(pData, aDelim.getStr(),
185 aDelim.getLength());
186 return aDelim.getLength();
190 else
192 // Read current child stream.
193 int nRead = pChildStrm->Read(pData, nSize);
194 if (nRead > 0)
196 return nRead;
198 else
200 // Cleanup exhausted child stream.
201 pChildStrm.reset();
205 return 0;
207 else
209 // Single part message body.
210 if (pSourceMsg->GetDocumentLB() == nullptr)
212 // Empty message body.
213 return 0;
216 // No Encoding.
217 return GetBodyLine(pData, nSize);
222 namespace
225 const int BUFFER_SIZE = 2048;
229 INetMIMEMessageStream::INetMIMEMessageStream(
230 INetMIMEMessage *pMsg, bool headerGenerated):
231 pSourceMsg(pMsg),
232 bHeaderGenerated(headerGenerated),
233 mvBuffer(BUFFER_SIZE),
234 pMsgRead(nullptr),
235 pMsgWrite(nullptr),
236 done(false),
237 nChildIndex(0)
239 assert(pMsg != nullptr);
240 maMsgBuffer.SetStreamCharSet(RTL_TEXTENCODING_ASCII_US);
241 pRead = pWrite = mvBuffer.data();
244 INetMIMEMessageStream::~INetMIMEMessageStream()
246 pChildStrm.reset();
249 int INetMIMEMessageStream::Read(sal_Char* pData, sal_uInt32 nSize)
251 sal_Char* pWBuf = pData;
252 sal_Char* pWEnd = pData + nSize;
254 while (pWBuf < pWEnd)
256 // Caller's buffer not yet filled.
257 sal_uInt32 n = pRead - pWrite;
258 if (n > 0)
260 // Bytes still in buffer.
261 sal_uInt32 m = pWEnd - pWBuf;
262 if (m < n) n = m;
263 for (sal_uInt32 i = 0; i < n; i++) *pWBuf++ = *pWrite++;
265 else
267 // Buffer empty. Reset to <Begin-of-Buffer>.
268 pRead = pWrite = mvBuffer.data();
270 // Read next message line.
271 int nRead = GetMsgLine(mvBuffer.data(), mvBuffer.size());
272 if (nRead > 0)
274 // Set read pointer.
275 pRead = mvBuffer.data() + nRead;
277 else
279 if (!bHeaderGenerated)
281 // Header generated. Insert empty line.
282 bHeaderGenerated = true;
283 *pRead++ = '\r';
284 *pRead++ = '\n';
286 else
288 // Body generated.
289 return (pWBuf - pData);
294 return (pWBuf - pData);
297 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */