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 <tools/datetime.hxx> 28 #ifndef _TOOLS_INETMIME_HXX 29 #include <tools/inetmime.hxx> 30 #endif 31 #include <tools/inetmsg.hxx> 32 #include <tools/inetstrm.hxx> 33 #include <rtl/instance.hxx> 34 35 #include <stdio.h> 36 37 //======================================================================= 38 39 inline sal_Bool ascii_isDigit( sal_Unicode ch ) 40 { 41 return ((ch >= 0x0030) && (ch <= 0x0039)); 42 } 43 44 inline sal_Bool ascii_isLetter( sal_Unicode ch ) 45 { 46 return (( (ch >= 0x0041) && (ch <= 0x005A)) || ((ch >= 0x0061) && (ch <= 0x007A))); 47 } 48 49 inline sal_Unicode ascii_toLowerCase( sal_Unicode ch ) 50 { 51 if ( (ch >= 0x0041) && (ch <= 0x005A) ) 52 return ch + 0x20; 53 else 54 return ch; 55 } 56 57 /*======================================================================= 58 * 59 * INetMessage Implementation. 60 * 61 *=====================================================================*/ 62 #define CONSTASCII_STRINGPARAM(a) (a), RTL_TEXTENCODING_ASCII_US 63 #define HEADERFIELD INetMessageHeader 64 65 /* 66 * ~INetMessage. 67 */ 68 INetMessage::~INetMessage (void) 69 { 70 ListCleanup_Impl(); 71 } 72 73 /* 74 * ListCleanup_Impl. 75 */ 76 void INetMessage::ListCleanup_Impl (void) 77 { 78 // Cleanup. 79 sal_uIntPtr i, n = m_aHeaderList.Count(); 80 for (i = 0; i < n; i++) 81 delete ((HEADERFIELD*)(m_aHeaderList.GetObject(i))); 82 m_aHeaderList.Clear(); 83 } 84 85 /* 86 * ListCopy. 87 */ 88 void INetMessage::ListCopy (const INetMessage &rMsg) 89 { 90 if (!(this == &rMsg)) 91 { 92 // Cleanup. 93 ListCleanup_Impl(); 94 95 // Copy. 96 sal_uIntPtr i, n = rMsg.GetHeaderCount(); 97 for (i = 0; i < n; i++) 98 { 99 HEADERFIELD *p = (HEADERFIELD*)(rMsg.m_aHeaderList.GetObject(i)); 100 m_aHeaderList.Insert (new HEADERFIELD(*p), LIST_APPEND); 101 } 102 } 103 } 104 105 /* 106 * SetHeaderField_Impl. 107 */ 108 void INetMessage::SetHeaderField_Impl ( 109 INetMIME::HeaderFieldType eType, 110 const ByteString &rName, 111 const UniString &rValue, 112 sal_uIntPtr &rnIndex) 113 { 114 INetMIMEStringOutputSink aSink (0, STRING_MAXLEN); 115 INetMIME::writeHeaderFieldBody ( 116 aSink, eType, rValue, gsl_getSystemTextEncoding(), false); 117 SetHeaderField_Impl ( 118 INetMessageHeader (rName, aSink.takeBuffer()), rnIndex); 119 } 120 121 /* 122 * SetHeaderField. 123 */ 124 sal_uIntPtr INetMessage::SetHeaderField ( 125 const UniString& rName, const UniString& rValue, sal_uIntPtr nIndex) 126 { 127 sal_uIntPtr nResult = nIndex; 128 SetHeaderField_Impl ( 129 INetMIME::HEADER_FIELD_TEXT, 130 ByteString (rName, RTL_TEXTENCODING_ASCII_US), rValue, 131 nResult); 132 return nResult; 133 } 134 135 /* 136 * SetHeaderField. 137 */ 138 sal_uIntPtr INetMessage::SetHeaderField ( 139 const INetMessageHeader &rHeader, sal_uIntPtr nIndex) 140 { 141 sal_uIntPtr nResult = nIndex; 142 SetHeaderField_Impl (rHeader, nResult); 143 return nResult; 144 } 145 146 147 /* 148 * operator<< 149 */ 150 SvStream& INetMessage::operator<< (SvStream& rStrm) const 151 { 152 rStrm << static_cast<sal_uInt32>(m_nDocSize); 153 rStrm.WriteByteString (m_aDocName, RTL_TEXTENCODING_UTF8); 154 155 sal_uIntPtr i, n = m_aHeaderList.Count(); 156 rStrm << static_cast<sal_uInt32>(n); 157 158 for (i = 0; i < n; i++) 159 rStrm << *((HEADERFIELD *)(m_aHeaderList.GetObject(i))); 160 161 return rStrm; 162 } 163 164 /* 165 * operator>> 166 */ 167 SvStream& INetMessage::operator>> (SvStream& rStrm) 168 { 169 // Cleanup. 170 m_nDocSize = 0; 171 m_xDocLB.Clear(); 172 ListCleanup_Impl(); 173 174 sal_uInt32 nTemp; 175 176 // Copy. 177 rStrm >> nTemp; 178 m_nDocSize = nTemp; 179 rStrm.ReadByteString (m_aDocName, RTL_TEXTENCODING_UTF8); 180 181 sal_uIntPtr i, n = 0; 182 rStrm >> nTemp; 183 n = nTemp; 184 185 for (i = 0; i < n; i++) 186 { 187 HEADERFIELD *p = new HEADERFIELD(); 188 rStrm >> *p; 189 m_aHeaderList.Insert (p, LIST_APPEND); 190 } 191 192 // Done. 193 return rStrm; 194 } 195 196 /*======================================================================= 197 * 198 * INetMessageHeaderIterator Implementation. 199 * 200 *=====================================================================*/ 201 INetMessageHeaderIterator::INetMessageHeaderIterator ( 202 const INetMessage& rMsg, const UniString& rHdrName) 203 { 204 sal_uIntPtr i, n = rMsg.GetHeaderCount(); 205 for (i = 0; i < n; i++) 206 { 207 if (rHdrName.CompareIgnoreCaseToAscii (rMsg.GetHeaderName(i)) == 0) 208 { 209 UniString *pValue = new UniString (rMsg.GetHeaderValue(i)); 210 aValueList.Insert (pValue, LIST_APPEND); 211 } 212 } 213 nValueCount = aValueList.Count(); 214 } 215 216 INetMessageHeaderIterator::~INetMessageHeaderIterator (void) 217 { 218 sal_uIntPtr i, n = aValueList.Count(); 219 for (i = 0; i < n; i++) 220 delete ((UniString*)(aValueList.GetObject(i))); 221 aValueList.Clear(); 222 } 223 224 /*======================================================================= 225 * 226 * INetRFC822Message Implementation. 227 * 228 *=====================================================================*/ 229 /* 230 * ImplINetRFC822MessageHeaderData. 231 */ 232 namespace 233 { 234 struct ImplINetRFC822MessageHeaderDataImpl 235 { 236 const ByteString* operator()() 237 { 238 static const ByteString _ImplINetRFC822MessageHeaderData[] = 239 { 240 ByteString ("BCC"), 241 ByteString ("CC"), 242 ByteString ("Comments"), 243 ByteString ("Date"), 244 ByteString ("From"), 245 ByteString ("In-Reply-To"), 246 ByteString ("Keywords"), 247 ByteString ("Message-ID"), 248 ByteString ("References"), 249 ByteString ("Reply-To"), 250 ByteString ("Return-Path"), 251 ByteString ("Subject"), 252 ByteString ("Sender"), 253 ByteString ("To"), 254 ByteString ("X-Mailer"), 255 ByteString ("Return-Receipt-To") 256 }; 257 return &_ImplINetRFC822MessageHeaderData[0]; 258 } 259 }; 260 261 struct ImplINetRFC822MessageHeaderData 262 : public rtl::StaticAggregate< const ByteString, ImplINetRFC822MessageHeaderDataImpl > {}; 263 } 264 265 #define HDR(n) ImplINetRFC822MessageHeaderData::get()[(n)] 266 267 /* 268 * _ImplINetRFC822MessageHeaderState. 269 */ 270 enum _ImplINetRFC822MessageHeaderState 271 { 272 INETMSG_RFC822_BEGIN, 273 INETMSG_RFC822_CHECK, 274 INETMSG_RFC822_OK, 275 INETMSG_RFC822_JUNK, 276 277 INETMSG_RFC822_TOKEN_RE, 278 INETMSG_RFC822_TOKEN_RETURNMINUS, 279 INETMSG_RFC822_TOKEN_XMINUS, 280 INETMSG_RFC822_LETTER_C, 281 INETMSG_RFC822_LETTER_S 282 }; 283 284 /* 285 * INetRFC822Message. 286 */ 287 INetRFC822Message::INetRFC822Message (void) 288 : INetMessage() 289 { 290 for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++) 291 m_nIndex[i] = LIST_ENTRY_NOTFOUND; 292 } 293 294 INetRFC822Message::INetRFC822Message (const INetRFC822Message& rMsg) 295 : INetMessage (rMsg) 296 { 297 for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++) 298 m_nIndex[i] = rMsg.m_nIndex[i]; 299 } 300 301 /* 302 * operator= 303 */ 304 INetRFC822Message& INetRFC822Message::operator= (const INetRFC822Message& rMsg) 305 { 306 if (this != &rMsg) 307 { 308 INetMessage::operator= (rMsg); 309 310 for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++) 311 m_nIndex[i] = rMsg.m_nIndex[i]; 312 } 313 return *this; 314 } 315 316 /* 317 * ~INetRFC822Message. 318 */ 319 INetRFC822Message::~INetRFC822Message (void) 320 { 321 } 322 323 /* 324 * <Generate|Parse>DateField and local helper functions. 325 * 326 * GenerateDateField. 327 * Generates a String from Date and Time objects in format: 328 * Wkd, 00 Mon 0000 00:00:00 [GMT] (rfc822, rfc1123) 329 * 330 * ParseDateField. 331 * Parses a String in (implied) GMT format into class Date and Time objects. 332 * Four formats are accepted: 333 * 334 * [Wkd,] 1*2DIGIT Mon 2*4DIGIT 00:00:00 [GMT] (rfc1123) 335 * [Wkd,] 00 Mon 0000 00:00:00 [GMT]) (rfc822, rfc1123) 336 * Weekday, 00-Mon-00 00:00:00 [GMT] (rfc850, rfc1036) 337 * Wkd Mon 00 00:00:00 0000 [GMT] (ctime) 338 * 1*DIGIT (delta seconds) 339 * 340 */ 341 342 // Months and Weekdays. 343 static const sal_Char *months[12] = 344 { 345 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 346 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 347 }; 348 349 static const sal_Char *wkdays[7] = 350 { 351 "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" 352 }; 353 354 /* 355 * GenerateDateField. 356 */ 357 sal_Bool INetRFC822Message::GenerateDateField ( 358 const DateTime& rDateTime, UniString& rDateFieldW) 359 { 360 // Check arguments. 361 if (!rDateTime.IsValid() || 362 (rDateTime.GetSec() > 59) || 363 (rDateTime.GetMin() > 59) || 364 (rDateTime.GetHour() > 23) ) return sal_False; 365 366 // Prepare output string. 367 ByteString rDateField; 368 369 // Insert Date. 370 rDateField += wkdays[(sal_uInt16)(rDateTime.GetDayOfWeek())]; 371 rDateField += ", "; 372 373 sal_uInt16 nNum = rDateTime.GetDay(); 374 if (nNum < 10) rDateField += '0'; 375 rDateField += ByteString::CreateFromInt32(nNum); 376 rDateField += ' '; 377 378 rDateField += months[(sal_uInt16)(rDateTime.GetMonth() - 1)]; 379 rDateField += ' '; 380 381 rDateField += ByteString::CreateFromInt32(rDateTime.GetYear()); 382 rDateField += ' '; 383 384 // Insert Time. 385 nNum = rDateTime.GetHour(); 386 if (nNum < 10) rDateField += '0'; 387 rDateField += ByteString::CreateFromInt32(nNum); 388 rDateField += ':'; 389 390 nNum = rDateTime.GetMin(); 391 if (nNum < 10) rDateField += '0'; 392 rDateField += ByteString::CreateFromInt32(nNum); 393 rDateField += ':'; 394 395 nNum = rDateTime.GetSec(); 396 if (nNum < 10) rDateField += '0'; 397 rDateField += ByteString::CreateFromInt32(nNum); 398 rDateField += " GMT"; 399 400 // Done. 401 rDateFieldW = UniString (rDateField, RTL_TEXTENCODING_ASCII_US); 402 return sal_True; 403 } 404 405 /* 406 * ParseDateField and local helper functions. 407 */ 408 static sal_uInt16 ParseNumber (const ByteString& rStr, sal_uInt16& nIndex) 409 { 410 sal_uInt16 n = nIndex; 411 while ((n < rStr.Len()) && ascii_isDigit(rStr.GetChar(n))) n++; 412 413 ByteString aNum (rStr.Copy (nIndex, (n - nIndex))); 414 nIndex = n; 415 416 return (sal_uInt16)(aNum.ToInt32()); 417 } 418 419 static sal_uInt16 ParseMonth (const ByteString& rStr, sal_uInt16& nIndex) 420 { 421 sal_uInt16 n = nIndex; 422 while ((n < rStr.Len()) && ascii_isLetter(rStr.GetChar(n))) n++; 423 424 ByteString aMonth (rStr.Copy (nIndex, 3)); 425 nIndex = n; 426 427 sal_uInt16 i; 428 for (i = 0; i < 12; i++) 429 if (aMonth.CompareIgnoreCaseToAscii (months[i]) == 0) break; 430 return (i + 1); 431 } 432 433 sal_Bool INetRFC822Message::ParseDateField ( 434 const UniString& rDateFieldW, DateTime& rDateTime) 435 { 436 ByteString rDateField (rDateFieldW, RTL_TEXTENCODING_ASCII_US); 437 if (rDateField.Len() == 0) return sal_False; 438 439 if (rDateField.Search (':') != STRING_NOTFOUND) 440 { 441 // Some DateTime format. 442 sal_uInt16 nIndex = 0; 443 444 // Skip over <Wkd> or <Weekday>, leading and trailing space. 445 while ((nIndex < rDateField.Len()) && 446 (rDateField.GetChar(nIndex) == ' ')) 447 nIndex++; 448 449 while ( 450 (nIndex < rDateField.Len()) && 451 (ascii_isLetter (rDateField.GetChar(nIndex)) || 452 (rDateField.GetChar(nIndex) == ',') )) 453 nIndex++; 454 455 while ((nIndex < rDateField.Len()) && 456 (rDateField.GetChar(nIndex) == ' ')) 457 nIndex++; 458 459 if (ascii_isLetter (rDateField.GetChar(nIndex))) 460 { 461 // Format: ctime(). 462 if ((rDateField.Len() - nIndex) < 20) return sal_False; 463 464 rDateTime.SetMonth (ParseMonth (rDateField, nIndex)); nIndex++; 465 rDateTime.SetDay (ParseNumber (rDateField, nIndex)); nIndex++; 466 467 rDateTime.SetHour (ParseNumber (rDateField, nIndex)); nIndex++; 468 rDateTime.SetMin (ParseNumber (rDateField, nIndex)); nIndex++; 469 rDateTime.SetSec (ParseNumber (rDateField, nIndex)); nIndex++; 470 rDateTime.Set100Sec (0); 471 472 sal_uInt16 nYear = ParseNumber (rDateField, nIndex); 473 if (nYear < 100) nYear += 1900; 474 rDateTime.SetYear (nYear); 475 } 476 else 477 { 478 // Format: RFC1036 or RFC1123. 479 if ((rDateField.Len() - nIndex) < 17) return sal_False; 480 481 rDateTime.SetDay (ParseNumber (rDateField, nIndex)); nIndex++; 482 rDateTime.SetMonth (ParseMonth (rDateField, nIndex)); nIndex++; 483 484 sal_uInt16 nYear = ParseNumber (rDateField, nIndex); nIndex++; 485 if (nYear < 100) nYear += 1900; 486 rDateTime.SetYear (nYear); 487 488 rDateTime.SetHour (ParseNumber (rDateField, nIndex)); nIndex++; 489 rDateTime.SetMin (ParseNumber (rDateField, nIndex)); nIndex++; 490 rDateTime.SetSec (ParseNumber (rDateField, nIndex)); nIndex++; 491 rDateTime.Set100Sec (0); 492 493 if ((rDateField.GetChar(nIndex) == '+') || 494 (rDateField.GetChar(nIndex) == '-') ) 495 { 496 // Offset from GMT: "(+|-)HHMM". 497 sal_Bool bEast = (rDateField.GetChar(nIndex++) == '+'); 498 sal_uInt16 nOffset = ParseNumber (rDateField, nIndex); 499 if (nOffset > 0) 500 { 501 Time aDiff; 502 aDiff.SetHour (nOffset / 100); 503 aDiff.SetMin (nOffset % 100); 504 aDiff.SetSec (0); 505 aDiff.Set100Sec (0); 506 507 if (bEast) 508 rDateTime -= aDiff; 509 else 510 rDateTime += aDiff; 511 } 512 } 513 } 514 } 515 else if (rDateField.IsNumericAscii()) 516 { 517 // Format: delta seconds. 518 Time aDelta (0); 519 aDelta.SetTime (rDateField.ToInt32() * 100); 520 521 DateTime aNow; 522 aNow += aDelta; 523 aNow.ConvertToUTC(); 524 525 rDateTime.SetDate (aNow.GetDate()); 526 rDateTime.SetTime (aNow.GetTime()); 527 } 528 else 529 { 530 // Junk. 531 return sal_False; 532 } 533 534 return (rDateTime.IsValid() && 535 !((rDateTime.GetSec() > 59) || 536 (rDateTime.GetMin() > 59) || 537 (rDateTime.GetHour() > 23) )); 538 } 539 540 /* 541 * SetHeaderField. 542 * (Header Field Parser). 543 */ 544 sal_uIntPtr INetRFC822Message::SetHeaderField ( 545 const INetMessageHeader &rHeader, sal_uIntPtr nNewIndex) 546 { 547 ByteString aName (rHeader.GetName()); 548 const sal_Char *pData = aName.GetBuffer(); 549 const sal_Char *pStop = pData + aName.Len() + 1; 550 const sal_Char *check = ""; 551 552 sal_uIntPtr nIdx = LIST_APPEND; 553 int eState = INETMSG_RFC822_BEGIN; 554 int eOkState = INETMSG_RFC822_OK; 555 556 while (pData < pStop) 557 { 558 switch (eState) 559 { 560 case INETMSG_RFC822_BEGIN: 561 eState = INETMSG_RFC822_CHECK; 562 eOkState = INETMSG_RFC822_OK; 563 564 switch (ascii_toLowerCase (*pData)) 565 { 566 case 'b': 567 check = "cc"; 568 nIdx = INETMSG_RFC822_BCC; 569 break; 570 571 case 'c': 572 eState = INETMSG_RFC822_LETTER_C; 573 break; 574 575 case 'd': 576 check = "ate"; 577 nIdx = INETMSG_RFC822_DATE; 578 break; 579 580 case 'f': 581 check = "rom"; 582 nIdx = INETMSG_RFC822_FROM; 583 break; 584 585 case 'i': 586 check = "n-reply-to"; 587 nIdx = INETMSG_RFC822_IN_REPLY_TO; 588 break; 589 590 case 'k': 591 check = "eywords"; 592 nIdx = INETMSG_RFC822_KEYWORDS; 593 break; 594 595 case 'm': 596 check = "essage-id"; 597 nIdx = INETMSG_RFC822_MESSAGE_ID; 598 break; 599 600 case 'r': 601 check = "e"; 602 eOkState = INETMSG_RFC822_TOKEN_RE; 603 break; 604 605 case 's': 606 eState = INETMSG_RFC822_LETTER_S; 607 break; 608 609 case 't': 610 check = "o"; 611 nIdx = INETMSG_RFC822_TO; 612 break; 613 614 case 'x': 615 check = "-"; 616 eOkState = INETMSG_RFC822_TOKEN_XMINUS; 617 break; 618 619 default: 620 eState = INETMSG_RFC822_JUNK; 621 break; 622 } 623 pData++; 624 break; 625 626 case INETMSG_RFC822_TOKEN_RE: 627 eState = INETMSG_RFC822_CHECK; 628 eOkState = INETMSG_RFC822_OK; 629 630 switch (ascii_toLowerCase (*pData)) 631 { 632 case 'f': 633 check = "erences"; 634 nIdx = INETMSG_RFC822_REFERENCES; 635 break; 636 637 case 'p': 638 check = "ly-to"; 639 nIdx = INETMSG_RFC822_REPLY_TO; 640 break; 641 642 case 't': 643 check = "urn-"; 644 eOkState = INETMSG_RFC822_TOKEN_RETURNMINUS; 645 break; 646 647 default: 648 eState = INETMSG_RFC822_JUNK; 649 break; 650 } 651 pData++; 652 break; 653 654 case INETMSG_RFC822_TOKEN_RETURNMINUS: 655 eState = INETMSG_RFC822_CHECK; 656 eOkState = INETMSG_RFC822_OK; 657 658 switch (ascii_toLowerCase (*pData)) 659 { 660 case 'p': 661 check = "ath"; 662 nIdx = INETMSG_RFC822_RETURN_PATH; 663 break; 664 665 case 'r': 666 check = "eceipt-to"; 667 nIdx = INETMSG_RFC822_RETURN_RECEIPT_TO; 668 break; 669 670 default: 671 eState = INETMSG_RFC822_JUNK; 672 break; 673 } 674 pData++; 675 break; 676 677 case INETMSG_RFC822_TOKEN_XMINUS: 678 eState = INETMSG_RFC822_CHECK; 679 eOkState = INETMSG_RFC822_OK; 680 681 switch (ascii_toLowerCase (*pData)) 682 { 683 case 'm': 684 check = "ailer"; 685 nIdx = INETMSG_RFC822_X_MAILER; 686 break; 687 688 #if 0 /* NYI */ 689 case 'p': 690 check = "riority"; 691 eOkState = INETMSG_RFC822_X_PRIORITY; 692 break; 693 #endif /* NYI */ 694 695 default: 696 eState = INETMSG_RFC822_JUNK; 697 break; 698 } 699 pData++; 700 break; 701 702 case INETMSG_RFC822_LETTER_C: 703 eState = INETMSG_RFC822_CHECK; 704 eOkState = INETMSG_RFC822_OK; 705 706 switch (ascii_toLowerCase (*pData)) 707 { 708 case 'c': 709 check = ""; 710 nIdx = INETMSG_RFC822_CC; 711 break; 712 713 case 'o': 714 check = "mments"; 715 nIdx = INETMSG_RFC822_COMMENTS; 716 break; 717 718 default: 719 eState = INETMSG_RFC822_JUNK; 720 break; 721 } 722 pData++; 723 break; 724 725 case INETMSG_RFC822_LETTER_S: 726 eState = INETMSG_RFC822_CHECK; 727 eOkState = INETMSG_RFC822_OK; 728 729 switch (ascii_toLowerCase (*pData)) 730 { 731 case 'e': 732 check = "nder"; 733 nIdx = INETMSG_RFC822_SENDER; 734 break; 735 736 case 'u': 737 check = "bject"; 738 nIdx = INETMSG_RFC822_SUBJECT; 739 break; 740 741 default: 742 eState = INETMSG_RFC822_JUNK; 743 break; 744 } 745 pData++; 746 break; 747 748 case INETMSG_RFC822_CHECK: 749 if (*check) 750 { 751 while (*pData && *check && 752 (ascii_toLowerCase (*pData) == *check)) 753 { 754 pData++; 755 check++; 756 } 757 } 758 else 759 { 760 check = pData; 761 } 762 eState = (*check == '\0') ? eOkState : INETMSG_RFC822_JUNK; 763 break; 764 765 case INETMSG_RFC822_OK: 766 pData = pStop; 767 SetHeaderField_Impl ( 768 HEADERFIELD (HDR(nIdx), rHeader.GetValue()), 769 m_nIndex[nIdx]); 770 nNewIndex = m_nIndex[nIdx]; 771 break; 772 773 default: // INETMSG_RFC822_JUNK 774 pData = pStop; 775 nNewIndex = INetMessage::SetHeaderField (rHeader, nNewIndex); 776 break; 777 } 778 } 779 return nNewIndex; 780 } 781 782 /* 783 * Specific Set-Methods. 784 */ 785 void INetRFC822Message::SetBCC (const UniString& rBCC) 786 { 787 SetHeaderField_Impl ( 788 INetMIME::HEADER_FIELD_ADDRESS, 789 HDR(INETMSG_RFC822_BCC), rBCC, 790 m_nIndex[INETMSG_RFC822_BCC]); 791 } 792 793 void INetRFC822Message::SetCC (const UniString& rCC) 794 { 795 SetHeaderField_Impl ( 796 INetMIME::HEADER_FIELD_ADDRESS, 797 HDR(INETMSG_RFC822_CC), rCC, 798 m_nIndex[INETMSG_RFC822_CC]); 799 } 800 801 void INetRFC822Message::SetComments (const UniString& rComments) 802 { 803 SetHeaderField_Impl ( 804 INetMIME::HEADER_FIELD_TEXT, 805 HDR(INETMSG_RFC822_COMMENTS), rComments, 806 m_nIndex[INETMSG_RFC822_COMMENTS]); 807 } 808 809 void INetRFC822Message::SetDate (const UniString& rDate) 810 { 811 SetHeaderField_Impl ( 812 INetMIME::HEADER_FIELD_STRUCTURED, 813 HDR(INETMSG_RFC822_DATE), rDate, 814 m_nIndex[INETMSG_RFC822_DATE]); 815 } 816 817 void INetRFC822Message::SetFrom (const UniString& rFrom) 818 { 819 SetHeaderField_Impl ( 820 INetMIME::HEADER_FIELD_ADDRESS, 821 HDR(INETMSG_RFC822_FROM), rFrom, 822 m_nIndex[INETMSG_RFC822_FROM]); 823 } 824 825 void INetRFC822Message::SetInReplyTo (const UniString& rInReplyTo) 826 { 827 SetHeaderField_Impl ( 828 INetMIME::HEADER_FIELD_ADDRESS, // ??? MESSAGE_ID ??? 829 HDR(INETMSG_RFC822_IN_REPLY_TO), rInReplyTo, 830 m_nIndex[INETMSG_RFC822_IN_REPLY_TO]); 831 } 832 833 void INetRFC822Message::SetKeywords (const UniString& rKeywords) 834 { 835 SetHeaderField_Impl ( 836 INetMIME::HEADER_FIELD_PHRASE, 837 HDR(INETMSG_RFC822_KEYWORDS), rKeywords, 838 m_nIndex[INETMSG_RFC822_KEYWORDS]); 839 } 840 841 void INetRFC822Message::SetMessageID (const UniString& rMessageID) 842 { 843 SetHeaderField_Impl ( 844 INetMIME::HEADER_FIELD_MESSAGE_ID, 845 HDR(INETMSG_RFC822_MESSAGE_ID), rMessageID, 846 m_nIndex[INETMSG_RFC822_MESSAGE_ID]); 847 } 848 849 void INetRFC822Message::SetReferences (const UniString& rReferences) 850 { 851 SetHeaderField_Impl ( 852 INetMIME::HEADER_FIELD_MESSAGE_ID, 853 HDR(INETMSG_RFC822_REFERENCES), rReferences, 854 m_nIndex[INETMSG_RFC822_REFERENCES]); 855 } 856 857 void INetRFC822Message::SetReplyTo (const UniString& rReplyTo) 858 { 859 SetHeaderField_Impl ( 860 INetMIME::HEADER_FIELD_ADDRESS, 861 HDR(INETMSG_RFC822_REPLY_TO), rReplyTo, 862 m_nIndex[INETMSG_RFC822_REPLY_TO]); 863 } 864 865 void INetRFC822Message::SetReturnPath (const UniString& rReturnPath) 866 { 867 SetHeaderField_Impl ( 868 INetMIME::HEADER_FIELD_ADDRESS, 869 HDR(INETMSG_RFC822_RETURN_PATH), rReturnPath, 870 m_nIndex[INETMSG_RFC822_RETURN_PATH]); 871 } 872 873 void INetRFC822Message::SetReturnReceiptTo (const UniString& rValue) 874 { 875 SetHeaderField_Impl ( 876 INetMIME::HEADER_FIELD_ADDRESS, 877 HDR(INETMSG_RFC822_RETURN_RECEIPT_TO), rValue, 878 m_nIndex[INETMSG_RFC822_RETURN_RECEIPT_TO]); 879 } 880 881 void INetRFC822Message::SetSender (const UniString& rSender) 882 { 883 SetHeaderField_Impl ( 884 INetMIME::HEADER_FIELD_ADDRESS, 885 HDR(INETMSG_RFC822_SENDER), rSender, 886 m_nIndex[INETMSG_RFC822_SENDER]); 887 } 888 889 void INetRFC822Message::SetSubject (const UniString& rSubject) 890 { 891 SetHeaderField_Impl ( 892 INetMIME::HEADER_FIELD_TEXT, 893 HDR(INETMSG_RFC822_SUBJECT), rSubject, 894 m_nIndex[INETMSG_RFC822_SUBJECT]); 895 } 896 897 void INetRFC822Message::SetTo (const UniString& rTo) 898 { 899 SetHeaderField_Impl ( 900 INetMIME::HEADER_FIELD_ADDRESS, 901 HDR(INETMSG_RFC822_TO), rTo, 902 m_nIndex[INETMSG_RFC822_TO]); 903 } 904 905 void INetRFC822Message::SetXMailer (const UniString& rXMailer) 906 { 907 SetHeaderField_Impl ( 908 INetMIME::HEADER_FIELD_TEXT, 909 HDR(INETMSG_RFC822_X_MAILER), rXMailer, 910 m_nIndex[INETMSG_RFC822_X_MAILER]); 911 } 912 913 /* 914 * operator<< 915 */ 916 SvStream& INetRFC822Message::operator<< (SvStream& rStrm) const 917 { 918 INetMessage::operator<< (rStrm); 919 920 for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++) 921 rStrm << static_cast<sal_uInt32>(m_nIndex[i]); 922 923 return rStrm; 924 } 925 926 /* 927 * operator>> 928 */ 929 SvStream& INetRFC822Message::operator>> (SvStream& rStrm) 930 { 931 INetMessage::operator>> (rStrm); 932 933 sal_uInt32 nTemp; 934 for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++) 935 { 936 rStrm >> nTemp; 937 m_nIndex[i] = nTemp; 938 } 939 940 return rStrm; 941 } 942 943 /*======================================================================= 944 * 945 * INetMIMEMessage Implementation. 946 * 947 *=====================================================================*/ 948 /* 949 * _ImplINetMIMEMessageHeaderData. 950 */ 951 namespace 952 { 953 struct ImplINetMIMEMessageHeaderDataImpl 954 { 955 const ByteString* operator()() 956 { 957 static const ByteString _ImplINetMIMEMessageHeaderData[] = 958 { 959 ByteString ("MIME-Version"), 960 ByteString ("Content-Description"), 961 ByteString ("Content-Disposition"), 962 ByteString ("Content-ID"), 963 ByteString ("Content-Type"), 964 ByteString ("Content-Transfer-Encoding") 965 }; 966 return &_ImplINetMIMEMessageHeaderData[0]; 967 } 968 }; 969 970 struct ImplINetMIMEMessageHeaderData 971 : public rtl::StaticAggregate< const ByteString, ImplINetMIMEMessageHeaderDataImpl > {}; 972 } 973 974 #define MIMEHDR(n) ImplINetMIMEMessageHeaderData::get()[(n)] 975 976 /* 977 * _ImplINetMIMEMessageHeaderState. 978 */ 979 enum _ImplINetMIMEMessageHeaderState 980 { 981 INETMSG_MIME_BEGIN, 982 INETMSG_MIME_CHECK, 983 INETMSG_MIME_OK, 984 INETMSG_MIME_JUNK, 985 986 INETMSG_MIME_TOKEN_CONTENT, 987 INETMSG_MIME_TOKEN_CONTENT_D, 988 INETMSG_MIME_TOKEN_CONTENT_T 989 }; 990 991 /* 992 * INetMIMEMessage. 993 */ 994 INetMIMEMessage::INetMIMEMessage (void) 995 : INetRFC822Message (), 996 pParent (NULL), 997 nNumChildren (0), 998 bHeaderParsed (sal_False) 999 { 1000 for (sal_uInt16 i = 0; i < INETMSG_MIME_NUMHDR; i++) 1001 m_nIndex[i] = LIST_ENTRY_NOTFOUND; 1002 } 1003 1004 INetMIMEMessage::INetMIMEMessage (const INetMIMEMessage& rMsg) 1005 : INetRFC822Message (rMsg) 1006 { 1007 // Copy. 1008 CopyImp (rMsg); 1009 } 1010 1011 /* 1012 * operator= 1013 */ 1014 INetMIMEMessage& INetMIMEMessage::operator= ( 1015 const INetMIMEMessage& rMsg) 1016 { 1017 if (this != &rMsg) 1018 { 1019 // Assign base. 1020 INetRFC822Message::operator= (rMsg); 1021 1022 // Cleanup. 1023 CleanupImp(); 1024 1025 // Copy. 1026 CopyImp (rMsg); 1027 } 1028 return *this; 1029 } 1030 1031 /* 1032 * ~INetMIMEMessage. 1033 */ 1034 INetMIMEMessage::~INetMIMEMessage (void) 1035 { 1036 // Cleanup. 1037 CleanupImp(); 1038 } 1039 1040 /* 1041 * CleanupImp. 1042 */ 1043 void INetMIMEMessage::CleanupImp (void) 1044 { 1045 INetMIMEMessage *pChild = NULL; 1046 while ((pChild = (INetMIMEMessage *)(aChildren.Remove())) != NULL) 1047 if (pChild->pParent == this) delete pChild; 1048 } 1049 1050 /* 1051 * CopyImp. 1052 */ 1053 void INetMIMEMessage::CopyImp (const INetMIMEMessage& rMsg) 1054 { 1055 bHeaderParsed = rMsg.bHeaderParsed; 1056 1057 sal_uInt16 i; 1058 for (i = 0; i < INETMSG_MIME_NUMHDR; i++) 1059 m_nIndex[i] = rMsg.m_nIndex[i]; 1060 1061 m_aBoundary = rMsg.m_aBoundary; 1062 nNumChildren = rMsg.nNumChildren; 1063 1064 for (i = 0; i < rMsg.aChildren.Count(); i++) 1065 { 1066 INetMIMEMessage *pChild = 1067 (INetMIMEMessage *)(rMsg.aChildren.GetObject (i)); 1068 1069 if (pChild->pParent == &rMsg) 1070 { 1071 pChild = pChild->CreateMessage (*pChild); 1072 pChild->pParent = this; 1073 } 1074 aChildren.Insert (pChild, LIST_APPEND); 1075 } 1076 } 1077 1078 /* 1079 * CreateMessage. 1080 */ 1081 INetMIMEMessage *INetMIMEMessage::CreateMessage ( 1082 const INetMIMEMessage& rMsg) const 1083 { 1084 return (new INetMIMEMessage (rMsg)); 1085 } 1086 1087 /* 1088 * SetHeaderField. 1089 * (Header Field Parser). 1090 */ 1091 sal_uIntPtr INetMIMEMessage::SetHeaderField ( 1092 const INetMessageHeader &rHeader, sal_uIntPtr nNewIndex) 1093 { 1094 ByteString aName (rHeader.GetName()); 1095 const sal_Char *pData = aName.GetBuffer(); 1096 const sal_Char *pStop = pData + aName.Len() + 1; 1097 const sal_Char *check = ""; 1098 1099 sal_uIntPtr nIdx = LIST_APPEND; 1100 int eState = INETMSG_MIME_BEGIN; 1101 int eOkState = INETMSG_MIME_OK; 1102 1103 while (pData < pStop) 1104 { 1105 switch (eState) 1106 { 1107 case INETMSG_MIME_BEGIN: 1108 eState = INETMSG_MIME_CHECK; 1109 eOkState = INETMSG_MIME_OK; 1110 1111 switch (ascii_toLowerCase (*pData)) 1112 { 1113 case 'c': 1114 check = "ontent-"; 1115 eOkState = INETMSG_MIME_TOKEN_CONTENT; 1116 break; 1117 1118 case 'm': 1119 check = "ime-version"; 1120 nIdx = INETMSG_MIME_VERSION; 1121 break; 1122 1123 default: 1124 eState = INETMSG_MIME_JUNK; 1125 break; 1126 } 1127 pData++; 1128 break; 1129 1130 case INETMSG_MIME_TOKEN_CONTENT: 1131 eState = INETMSG_MIME_CHECK; 1132 eOkState = INETMSG_MIME_OK; 1133 1134 switch (ascii_toLowerCase (*pData)) 1135 { 1136 case 'd': 1137 eState = INETMSG_MIME_TOKEN_CONTENT_D; 1138 break; 1139 1140 case 'i': 1141 check = "d"; 1142 nIdx = INETMSG_MIME_CONTENT_ID; 1143 break; 1144 1145 case 't': 1146 eState = INETMSG_MIME_TOKEN_CONTENT_T; 1147 break; 1148 1149 default: 1150 eState = INETMSG_MIME_JUNK; 1151 break; 1152 } 1153 pData++; 1154 break; 1155 1156 case INETMSG_MIME_TOKEN_CONTENT_D: 1157 eState = INETMSG_MIME_CHECK; 1158 eOkState = INETMSG_MIME_OK; 1159 1160 switch (ascii_toLowerCase (*pData)) 1161 { 1162 case 'e': 1163 check = "scription"; 1164 nIdx = INETMSG_MIME_CONTENT_DESCRIPTION; 1165 break; 1166 1167 case 'i': 1168 check = "sposition"; 1169 nIdx = INETMSG_MIME_CONTENT_DISPOSITION; 1170 break; 1171 1172 default: 1173 eState = INETMSG_MIME_JUNK; 1174 break; 1175 } 1176 pData++; 1177 break; 1178 1179 case INETMSG_MIME_TOKEN_CONTENT_T: 1180 eState = INETMSG_MIME_CHECK; 1181 eOkState = INETMSG_MIME_OK; 1182 1183 switch (ascii_toLowerCase (*pData)) 1184 { 1185 case 'r': 1186 check = "ansfer-encoding"; 1187 nIdx = INETMSG_MIME_CONTENT_TRANSFER_ENCODING; 1188 break; 1189 1190 case 'y': 1191 check = "pe"; 1192 nIdx = INETMSG_MIME_CONTENT_TYPE; 1193 break; 1194 1195 default: 1196 eState = INETMSG_MIME_JUNK; 1197 break; 1198 } 1199 pData++; 1200 break; 1201 1202 case INETMSG_MIME_CHECK: 1203 if (*check) 1204 { 1205 while (*pData && *check && 1206 (ascii_toLowerCase (*pData) == *check)) 1207 { 1208 pData++; 1209 check++; 1210 } 1211 } 1212 else 1213 { 1214 check = pData; 1215 } 1216 eState = (*check == '\0') ? eOkState : INETMSG_MIME_JUNK; 1217 break; 1218 1219 case INETMSG_MIME_OK: 1220 pData = pStop; 1221 SetHeaderField_Impl ( 1222 HEADERFIELD (MIMEHDR(nIdx), rHeader.GetValue()), 1223 m_nIndex[nIdx]); 1224 nNewIndex = m_nIndex[nIdx]; 1225 break; 1226 1227 default: // INETMSG_MIME_JUNK 1228 pData = pStop; 1229 nNewIndex = INetRFC822Message::SetHeaderField ( 1230 rHeader, nNewIndex); 1231 break; 1232 } 1233 } 1234 return nNewIndex; 1235 } 1236 1237 /* 1238 * Specific Set-Methods. 1239 */ 1240 void INetMIMEMessage::SetMIMEVersion (const UniString& rVersion) 1241 { 1242 SetHeaderField_Impl ( 1243 INetMIME::HEADER_FIELD_TEXT, 1244 MIMEHDR(INETMSG_MIME_VERSION), rVersion, 1245 m_nIndex[INETMSG_MIME_VERSION]); 1246 } 1247 1248 void INetMIMEMessage::SetContentDescription (const String& rDescription) 1249 { 1250 SetHeaderField_Impl ( 1251 INetMIME::HEADER_FIELD_TEXT, 1252 MIMEHDR(INETMSG_MIME_CONTENT_DESCRIPTION), rDescription, 1253 m_nIndex[INETMSG_MIME_CONTENT_DESCRIPTION]); 1254 } 1255 1256 void INetMIMEMessage::SetContentDisposition (const String& rDisposition) 1257 { 1258 SetHeaderField_Impl ( 1259 INetMIME::HEADER_FIELD_TEXT, 1260 MIMEHDR(INETMSG_MIME_CONTENT_DISPOSITION), rDisposition, 1261 m_nIndex[INETMSG_MIME_CONTENT_DISPOSITION]); 1262 } 1263 1264 void INetMIMEMessage::SetContentID (const String& rID) 1265 { 1266 SetHeaderField_Impl ( 1267 INetMIME::HEADER_FIELD_TEXT, 1268 MIMEHDR(INETMSG_MIME_CONTENT_ID), rID, 1269 m_nIndex[INETMSG_MIME_CONTENT_ID]); 1270 } 1271 1272 void INetMIMEMessage::SetContentType (const String& rType) 1273 { 1274 SetHeaderField_Impl ( 1275 INetMIME::HEADER_FIELD_TEXT, 1276 MIMEHDR(INETMSG_MIME_CONTENT_TYPE), rType, 1277 m_nIndex[INETMSG_MIME_CONTENT_TYPE]); 1278 } 1279 1280 void INetMIMEMessage::SetContentTransferEncoding ( 1281 const String& rEncoding) 1282 { 1283 SetHeaderField_Impl ( 1284 INetMIME::HEADER_FIELD_TEXT, 1285 MIMEHDR(INETMSG_MIME_CONTENT_TRANSFER_ENCODING), rEncoding, 1286 m_nIndex[INETMSG_MIME_CONTENT_TRANSFER_ENCODING]); 1287 } 1288 1289 /* 1290 * GetDefaultContentType. 1291 */ 1292 void INetMIMEMessage::GetDefaultContentType (String& rContentType) 1293 { 1294 String aDefaultCT ( 1295 "text/plain; charset=us-ascii", RTL_TEXTENCODING_ASCII_US); 1296 if (pParent == NULL) 1297 { 1298 rContentType = aDefaultCT; 1299 } 1300 else 1301 { 1302 String aParentCT (pParent->GetContentType()); 1303 if (aParentCT.Len() == 0) 1304 pParent->GetDefaultContentType (aParentCT); 1305 1306 if (aParentCT.CompareIgnoreCaseToAscii ("message/", 8) == 0) 1307 { 1308 rContentType = aDefaultCT; 1309 } 1310 else if (aParentCT.CompareIgnoreCaseToAscii ("multipart/", 10) == 0) 1311 { 1312 if (aParentCT.CompareIgnoreCaseToAscii ("multipart/digest") == 0) 1313 rContentType.AssignAscii ("message/rfc822"); 1314 else 1315 rContentType = aDefaultCT; 1316 } 1317 else 1318 { 1319 rContentType = aDefaultCT; 1320 } 1321 } 1322 } 1323 1324 /* 1325 * EnableAttachChild. 1326 */ 1327 sal_Bool INetMIMEMessage::EnableAttachChild (INetMessageContainerType eType) 1328 { 1329 // Check context. 1330 if (IsContainer()) 1331 return sal_False; 1332 1333 // Setup Content-Type header field. 1334 ByteString aContentType; 1335 switch (eType) 1336 { 1337 case INETMSG_MESSAGE_RFC822: 1338 aContentType = "message/rfc822"; 1339 break; 1340 1341 case INETMSG_MULTIPART_ALTERNATIVE: 1342 aContentType = "multipart/alternative"; 1343 break; 1344 1345 case INETMSG_MULTIPART_DIGEST: 1346 aContentType = "multipart/digest"; 1347 break; 1348 1349 case INETMSG_MULTIPART_PARALLEL: 1350 aContentType = "multipart/parallel"; 1351 break; 1352 1353 case INETMSG_MULTIPART_RELATED: 1354 aContentType = "multipart/related"; 1355 break; 1356 1357 case INETMSG_MULTIPART_FORM_DATA: 1358 aContentType = "multipart/form-data"; 1359 break; 1360 1361 default: 1362 aContentType = "multipart/mixed"; 1363 break; 1364 } 1365 1366 // Setup boundary for multipart types. 1367 if (aContentType.CompareIgnoreCaseToAscii ("multipart/", 10) == 0) 1368 { 1369 // Generate a unique boundary from current time. 1370 sal_Char sTail[16 + 1]; 1371 Time aCurTime; 1372 sal_uInt64 nThis = reinterpret_cast< sal_uIntPtr >( this ); // we can be on a 64bit architecture 1373 nThis = ( ( nThis >> 32 ) ^ nThis ) & SAL_MAX_UINT32; 1374 sprintf (sTail, "%08X%08X", 1375 static_cast< unsigned int >(aCurTime.GetTime()), 1376 static_cast< unsigned int >(nThis)); 1377 m_aBoundary = "------------_4D48"; 1378 m_aBoundary += sTail; 1379 1380 // Append boundary as ContentType parameter. 1381 aContentType += "; boundary="; 1382 aContentType += m_aBoundary; 1383 } 1384 1385 // Set header fields. 1386 SetMIMEVersion (String (CONSTASCII_STRINGPARAM("1.0"))); 1387 SetContentType (String (aContentType, RTL_TEXTENCODING_ASCII_US)); 1388 SetContentTransferEncoding (String (CONSTASCII_STRINGPARAM("7bit"))); 1389 1390 // Done. 1391 return sal_True; 1392 } 1393 1394 /* 1395 * AttachChild. 1396 */ 1397 sal_Bool INetMIMEMessage::AttachChild ( 1398 INetMIMEMessage& rChildMsg, sal_Bool bOwner) 1399 { 1400 if (IsContainer() /*&& rChildMsg.GetContentType().Len() */) 1401 { 1402 if (bOwner) rChildMsg.pParent = this; 1403 aChildren.Insert (&rChildMsg, LIST_APPEND); 1404 nNumChildren = aChildren.Count(); 1405 1406 return sal_True; 1407 } 1408 return sal_False; 1409 } 1410 1411 /* 1412 * DetachChild. 1413 */ 1414 sal_Bool INetMIMEMessage::DetachChild ( 1415 sal_uIntPtr nIndex, INetMIMEMessage& rChildMsg) const 1416 { 1417 if (IsContainer()) 1418 { 1419 // Check document stream. 1420 if (GetDocumentLB() == NULL) return sal_False; 1421 SvStream *pDocStrm = new SvStream (GetDocumentLB()); 1422 1423 // Initialize message buffer. 1424 char pMsgBuffer[1024]; 1425 char *pMsgRead, *pMsgWrite; 1426 pMsgRead = pMsgWrite = pMsgBuffer; 1427 1428 // Initialize message parser stream. 1429 INetMIMEMessageStream *pMsgStrm = NULL; 1430 1431 // Check for "multipart/uvw" or "message/xyz". 1432 if (IsMultipart()) 1433 { 1434 // Multipart message body. Initialize multipart delimiters. 1435 ByteString aDelim ("--"); 1436 aDelim += GetMultipartBoundary(); 1437 ByteString aClose = aDelim; 1438 aClose += "--"; 1439 1440 // Initialize line buffer. 1441 SvMemoryStream aLineBuf; 1442 1443 // Initialize control variables. 1444 INetMessageStreamState eState = INETMSG_EOL_SCR; 1445 int nCurIndex = -1; 1446 1447 // Go! 1448 while (nCurIndex < (int)(nIndex + 1)) 1449 { 1450 if ((pMsgRead - pMsgWrite) > 0) 1451 { 1452 // Bytes still in buffer. 1453 if (eState == INETMSG_EOL_FCR) 1454 { 1455 // Check for 2nd line break character. 1456 if ((*pMsgWrite == '\r') || (*pMsgWrite == '\n')) 1457 aLineBuf << *pMsgWrite++; 1458 1459 // Check current index. 1460 if (nCurIndex == (int)nIndex) 1461 { 1462 // Found requested part. 1463 if (pMsgStrm == NULL) 1464 { 1465 // Create message parser stream. 1466 pMsgStrm = new INetMIMEMessageStream; 1467 pMsgStrm->SetTargetMessage (&rChildMsg); 1468 } 1469 1470 // Put message down-stream. 1471 int status = pMsgStrm->Write ( 1472 (const sal_Char *) aLineBuf.GetData(), aLineBuf.Tell()); 1473 if (status != INETSTREAM_STATUS_OK) 1474 { 1475 // Cleanup. 1476 delete pDocStrm; 1477 delete pMsgStrm; 1478 1479 // Finish. 1480 return (!(status == INETSTREAM_STATUS_OK)); 1481 } 1482 } 1483 1484 // Reset to <Begin-of-Line>. 1485 aLineBuf.Seek (STREAM_SEEK_TO_BEGIN); 1486 eState = INETMSG_EOL_SCR; 1487 } 1488 else if ((*pMsgWrite == '\r') || (*pMsgWrite == '\n')) 1489 { 1490 /* 1491 * Found any line break character. 1492 * Compare buffered line with part/close delimiter. 1493 * Increment current part index upon match. 1494 */ 1495 sal_uInt16 nLen = (sal_uInt16)(aLineBuf.Tell() & 0xffff); 1496 if (nLen == aDelim.Len()) 1497 { 1498 if (aDelim.CompareTo ((const sal_Char *) aLineBuf.GetData(), nLen) 1499 == COMPARE_EQUAL) nCurIndex++; 1500 } 1501 else if (nLen == aClose.Len()) 1502 { 1503 if (aClose.CompareTo ((const sal_Char *) aLineBuf.GetData(), nLen) 1504 == COMPARE_EQUAL) nCurIndex++; 1505 } 1506 aLineBuf << *pMsgWrite++; 1507 eState = INETMSG_EOL_FCR; 1508 } 1509 else 1510 { 1511 // Insert into line buffer. 1512 aLineBuf << *pMsgWrite; 1513 } 1514 } 1515 else 1516 { 1517 // Buffer empty. Reset to <Begin-of-Buffer>. 1518 pMsgRead = pMsgWrite = pMsgBuffer; 1519 1520 // Read document stream. 1521 sal_uIntPtr nRead = pDocStrm->Read ( 1522 pMsgBuffer, sizeof (pMsgBuffer)); 1523 if (nRead > 0) 1524 { 1525 // Set read pointer. 1526 pMsgRead += nRead; 1527 } 1528 else 1529 { 1530 // Premature end. 1531 if (pMsgStrm) 1532 { 1533 // Assume end of requested part. 1534 nCurIndex++; 1535 } 1536 else 1537 { 1538 // Requested part not found. 1539 delete pDocStrm; 1540 return sal_False; 1541 } 1542 } 1543 } 1544 } // while (nCurIndex < (nIndex + 1)) 1545 } 1546 else 1547 { 1548 // Encapsulated message body. Create message parser stream. 1549 pMsgStrm = new INetMIMEMessageStream; 1550 pMsgStrm->SetTargetMessage (&rChildMsg); 1551 1552 // Initialize control variables. 1553 INetMessageStreamState eState = INETMSG_EOL_BEGIN; 1554 1555 // Go. 1556 while (eState == INETMSG_EOL_BEGIN) 1557 { 1558 if ((pMsgRead - pMsgWrite) > 0) 1559 { 1560 // Bytes still in buffer. Put message down-stream. 1561 int status = pMsgStrm->Write ( 1562 pMsgBuffer, (pMsgRead - pMsgWrite)); 1563 if (status != INETSTREAM_STATUS_OK) 1564 { 1565 // Cleanup. 1566 delete pDocStrm; 1567 delete pMsgStrm; 1568 1569 // Finish. 1570 return (!(status == INETSTREAM_STATUS_ERROR)); 1571 } 1572 pMsgWrite = pMsgBuffer + (pMsgRead - pMsgWrite); 1573 } 1574 else 1575 { 1576 // Buffer empty. Reset to <Begin-of-Buffer>. 1577 pMsgRead = pMsgWrite = pMsgBuffer; 1578 1579 // Read document stream. 1580 sal_uIntPtr nRead = pDocStrm->Read ( 1581 pMsgBuffer, sizeof (pMsgBuffer)); 1582 if (nRead > 0) 1583 { 1584 // Set read pointer. 1585 pMsgRead += nRead; 1586 } 1587 else 1588 { 1589 // Mark we're done. 1590 eState = INETMSG_EOL_DONE; 1591 } 1592 } 1593 } // while (eState == INETMSG_EOL_BEGIN) 1594 } 1595 1596 // Done. 1597 if (pDocStrm) delete pDocStrm; 1598 if (pMsgStrm) delete pMsgStrm; 1599 return sal_True; 1600 } 1601 return sal_False; 1602 } 1603 1604 /* 1605 * operator<< 1606 */ 1607 SvStream& INetMIMEMessage::operator<< (SvStream& rStrm) const 1608 { 1609 INetRFC822Message::operator<< (rStrm); 1610 1611 for (sal_uInt16 i = 0; i < INETMSG_MIME_NUMHDR; i++) 1612 rStrm << static_cast<sal_uInt32>(m_nIndex[i]); 1613 1614 #ifdef ENABLE_BYTESTRING_STREAM_OPERATORS 1615 rStrm << m_aBoundary; 1616 #else 1617 rStrm.WriteByteString (m_aBoundary); 1618 #endif 1619 rStrm << static_cast<sal_uInt32>(nNumChildren); 1620 1621 return rStrm; 1622 } 1623 1624 /* 1625 * operator>> 1626 */ 1627 SvStream& INetMIMEMessage::operator>> (SvStream& rStrm) 1628 { 1629 INetRFC822Message::operator>> (rStrm); 1630 1631 sal_uInt32 nTemp; 1632 for (sal_uInt16 i = 0; i < INETMSG_MIME_NUMHDR; i++) 1633 { 1634 rStrm >> nTemp; 1635 m_nIndex[i] = nTemp; 1636 } 1637 1638 #ifdef ENABLE_BYTESTRING_STREAM_OPERATORS 1639 rStrm >> m_aBoundary; 1640 #else 1641 rStrm.ReadByteString (m_aBoundary); 1642 #endif 1643 rStrm >> nTemp; 1644 nNumChildren = nTemp; 1645 1646 return rStrm; 1647 } 1648 1649 1650