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