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 sal_uInt32 nRead
= pSourceMsg
->GetDocumentLB()->ReadBytes(pWBuf
, (pWEnd
- pWBuf
));
82 return (pWBuf
- pData
);
85 int INetMIMEMessageStream::GetMsgLine(char* pData
, sal_uInt32 nSize
)
87 // Check for header or body.
88 if (!bHeaderGenerated
)
92 // Prepare special header fields.
93 if (pSourceMsg
->GetParent())
95 OUString
aPCT(pSourceMsg
->GetParent()->GetContentType());
96 if (aPCT
.startsWithIgnoreAsciiCase("message/rfc822"))
97 pSourceMsg
->SetMIMEVersion(u
"1.0"_ustr
);
99 pSourceMsg
->SetMIMEVersion(OUString());
103 pSourceMsg
->SetMIMEVersion(u
"1.0"_ustr
);
106 // Check ContentType.
107 OUString
aContentType(pSourceMsg
->GetContentType());
108 if (!aContentType
.isEmpty())
110 // Determine default Content-Type.
111 OUString aDefaultType
= pSourceMsg
->GetDefaultContentType();
113 if (aDefaultType
.equalsIgnoreAsciiCase(aContentType
))
115 // No need to specify default.
116 pSourceMsg
->SetContentType(OUString());
120 // No need to specify default.
121 pSourceMsg
->SetContentTransferEncoding(OUString());
127 // Generate the message header.
128 int nRead
= GetHeaderLine(pData
, nSize
);
138 // Generate the message body.
139 if (pSourceMsg
->IsContainer())
141 // Encapsulated message body.
144 if (pChildStrm
== nullptr)
146 INetMIMEMessage
*pChild
= pSourceMsg
->GetChild(nChildIndex
);
149 // Increment child index.
152 // Create child stream.
153 pChildStrm
.reset(new INetMIMEMessageStream(pChild
, false));
155 if (pSourceMsg
->IsMultipart())
157 // Insert multipart delimiter.
158 OString aDelim
= "--" +
159 pSourceMsg
->GetMultipartBoundary() +
162 memcpy(pData
, aDelim
.getStr(),
164 return aDelim
.getLength();
169 // No more parts. Mark we're done.
173 if (pSourceMsg
->IsMultipart())
175 // Insert close delimiter.
176 OString aDelim
= "--" +
177 pSourceMsg
->GetMultipartBoundary() +
180 memcpy(pData
, aDelim
.getStr(),
182 return aDelim
.getLength();
188 // Read current child stream.
189 int nRead
= pChildStrm
->Read(pData
, nSize
);
196 // Cleanup exhausted child stream.
205 // Single part message body.
206 if (pSourceMsg
->GetDocumentLB() == nullptr)
208 // Empty message body.
213 return GetBodyLine(pData
, nSize
);
221 const int BUFFER_SIZE
= 2048;
225 INetMIMEMessageStream::INetMIMEMessageStream(
226 INetMIMEMessage
*pMsg
, bool headerGenerated
):
228 bHeaderGenerated(headerGenerated
),
229 mvBuffer(BUFFER_SIZE
),
235 assert(pMsg
!= nullptr);
236 maMsgBuffer
.SetStreamCharSet(RTL_TEXTENCODING_ASCII_US
);
237 pRead
= pWrite
= mvBuffer
.data();
240 INetMIMEMessageStream::~INetMIMEMessageStream()
245 int INetMIMEMessageStream::Read(char* pData
, sal_uInt32 nSize
)
248 char* pWEnd
= pData
+ nSize
;
250 while (pWBuf
< pWEnd
)
252 // Caller's buffer not yet filled.
253 sal_uInt32 n
= pRead
- pWrite
;
256 // Bytes still in buffer.
257 sal_uInt32 m
= pWEnd
- pWBuf
;
259 for (sal_uInt32 i
= 0; i
< n
; i
++) *pWBuf
++ = *pWrite
++;
263 // Buffer empty. Reset to <Begin-of-Buffer>.
264 pRead
= pWrite
= mvBuffer
.data();
266 // Read next message line.
267 int nRead
= GetMsgLine(mvBuffer
.data(), mvBuffer
.size());
271 pRead
= mvBuffer
.data() + nRead
;
275 if (!bHeaderGenerated
)
277 // Header generated. Insert empty line.
278 bHeaderGenerated
= true;
285 return (pWBuf
- pData
);
290 return (pWBuf
- pData
);
293 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */