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