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