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