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