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