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_svl.hxx" 26 #include <tools/inetmime.hxx> 27 #include <svl/adrparse.hxx> 28 29 namespace unnamed_svl_adrparse {} 30 using namespace unnamed_svl_adrparse; 31 // unnamed namespaces don't work well yet 32 33 //============================================================================ 34 namespace unnamed_svl_adrparse { 35 36 enum ElementType { ELEMENT_START, ELEMENT_DELIM, ELEMENT_ITEM, ELEMENT_END }; 37 38 //============================================================================ 39 struct ParsedAddrSpec 40 { 41 sal_Unicode const * m_pBegin; 42 sal_Unicode const * m_pEnd; 43 ElementType m_eLastElem; 44 bool m_bAtFound; 45 bool m_bReparse; 46 47 ParsedAddrSpec() { reset(); } 48 49 bool isPoorlyValid() const { return m_eLastElem >= ELEMENT_ITEM; } 50 51 bool isValid() const { return isPoorlyValid() && m_bAtFound; } 52 53 inline void reset(); 54 55 inline void finish(); 56 }; 57 58 inline void ParsedAddrSpec::reset() 59 { 60 m_pBegin = 0; 61 m_pEnd = 0; 62 m_eLastElem = ELEMENT_START; 63 m_bAtFound = false; 64 m_bReparse = false; 65 } 66 67 inline void ParsedAddrSpec::finish() 68 { 69 if (isPoorlyValid()) 70 m_eLastElem = ELEMENT_END; 71 else 72 reset(); 73 } 74 75 } 76 77 //============================================================================ 78 class SvAddressParser_Impl 79 { 80 enum State { BEFORE_COLON, BEFORE_LESS, AFTER_LESS, AFTER_GREATER }; 81 82 enum TokenType { TOKEN_QUOTED = 0x80000000, TOKEN_DOMAIN, TOKEN_COMMENT, 83 TOKEN_ATOM }; 84 85 sal_Unicode const * m_pInputPos; 86 sal_Unicode const * m_pInputEnd; 87 sal_uInt32 m_nCurToken; 88 sal_Unicode const * m_pCurTokenBegin; 89 sal_Unicode const * m_pCurTokenEnd; 90 sal_Unicode const * m_pCurTokenContentBegin; 91 sal_Unicode const * m_pCurTokenContentEnd; 92 bool m_bCurTokenReparse; 93 ParsedAddrSpec m_aOuterAddrSpec; 94 ParsedAddrSpec m_aInnerAddrSpec; 95 ParsedAddrSpec * m_pAddrSpec; 96 sal_Unicode const * m_pRealNameBegin; 97 sal_Unicode const * m_pRealNameEnd; 98 sal_Unicode const * m_pRealNameContentBegin; 99 sal_Unicode const * m_pRealNameContentEnd; 100 bool m_bRealNameReparse; 101 bool m_bRealNameFinished; 102 sal_Unicode const * m_pFirstCommentBegin; 103 sal_Unicode const * m_pFirstCommentEnd; 104 bool m_bFirstCommentReparse; 105 State m_eState; 106 TokenType m_eType; 107 108 inline void resetRealNameAndFirstComment(); 109 110 inline void reset(); 111 112 inline void addTokenToAddrSpec(ElementType eTokenElem); 113 114 inline void addTokenToRealName(); 115 116 bool readToken(); 117 118 static UniString reparse(sal_Unicode const * pBegin, 119 sal_Unicode const * pEnd, bool bAddrSpec); 120 121 static UniString reparseComment(sal_Unicode const * pBegin, 122 sal_Unicode const * pEnd); 123 124 public: 125 SvAddressParser_Impl(SvAddressParser * pParser, UniString const & rInput); 126 }; 127 128 inline void SvAddressParser_Impl::resetRealNameAndFirstComment() 129 { 130 m_pRealNameBegin = 0; 131 m_pRealNameEnd = 0; 132 m_pRealNameContentBegin = 0; 133 m_pRealNameContentEnd = 0; 134 m_bRealNameReparse = false; 135 m_bRealNameFinished = false; 136 m_pFirstCommentBegin = 0; 137 m_pFirstCommentEnd = 0; 138 m_bFirstCommentReparse = false; 139 } 140 141 inline void SvAddressParser_Impl::reset() 142 { 143 m_aOuterAddrSpec.reset(); 144 m_aInnerAddrSpec.reset(); 145 m_pAddrSpec = &m_aOuterAddrSpec; 146 resetRealNameAndFirstComment(); 147 m_eState = BEFORE_COLON; 148 m_eType = TOKEN_ATOM; 149 } 150 151 inline void SvAddressParser_Impl::addTokenToAddrSpec(ElementType eTokenElem) 152 { 153 if (!m_pAddrSpec->m_pBegin) 154 m_pAddrSpec->m_pBegin = m_pCurTokenBegin; 155 else if (m_pAddrSpec->m_pEnd < m_pCurTokenBegin) 156 m_pAddrSpec->m_bReparse = true; 157 m_pAddrSpec->m_pEnd = m_pCurTokenEnd; 158 m_pAddrSpec->m_eLastElem = eTokenElem; 159 } 160 161 inline void SvAddressParser_Impl::addTokenToRealName() 162 { 163 if (!m_bRealNameFinished && m_eState != AFTER_LESS) 164 { 165 if (!m_pRealNameBegin) 166 m_pRealNameBegin = m_pRealNameContentBegin = m_pCurTokenBegin; 167 else if (m_pRealNameEnd < m_pCurTokenBegin - 1 168 || (m_pRealNameEnd == m_pCurTokenBegin - 1 169 && *m_pRealNameEnd != ' ')) 170 m_bRealNameReparse = true; 171 m_pRealNameEnd = m_pRealNameContentEnd = m_pCurTokenEnd; 172 } 173 } 174 175 //============================================================================ 176 // 177 // SvAddressParser_Impl 178 // 179 //============================================================================ 180 181 bool SvAddressParser_Impl::readToken() 182 { 183 m_nCurToken = m_eType; 184 m_bCurTokenReparse = false; 185 switch (m_eType) 186 { 187 case TOKEN_QUOTED: 188 { 189 m_pCurTokenBegin = m_pInputPos - 1; 190 m_pCurTokenContentBegin = m_pInputPos; 191 bool bEscaped = false; 192 for (;;) 193 { 194 if (m_pInputPos >= m_pInputEnd) 195 return false; 196 sal_Unicode cChar = *m_pInputPos++; 197 if (bEscaped) 198 { 199 m_bCurTokenReparse = true; 200 bEscaped = false; 201 } 202 else if (cChar == '"') 203 { 204 m_pCurTokenEnd = m_pInputPos; 205 m_pCurTokenContentEnd = m_pInputPos - 1; 206 return true; 207 } 208 else if (cChar == '\\') 209 bEscaped = true; 210 } 211 } 212 213 case TOKEN_DOMAIN: 214 { 215 m_pCurTokenBegin = m_pInputPos - 1; 216 m_pCurTokenContentBegin = m_pInputPos; 217 bool bEscaped = false; 218 for (;;) 219 { 220 if (m_pInputPos >= m_pInputEnd) 221 return false; 222 sal_Unicode cChar = *m_pInputPos++; 223 if (bEscaped) 224 bEscaped = false; 225 else if (cChar == ']') 226 { 227 m_pCurTokenEnd = m_pInputPos; 228 return true; 229 } 230 else if (cChar == '\\') 231 bEscaped = true; 232 } 233 } 234 235 case TOKEN_COMMENT: 236 { 237 m_pCurTokenBegin = m_pInputPos - 1; 238 m_pCurTokenContentBegin = 0; 239 m_pCurTokenContentEnd = 0; 240 bool bEscaped = false; 241 xub_StrLen nLevel = 0; 242 for (;;) 243 { 244 if (m_pInputPos >= m_pInputEnd) 245 return false; 246 sal_Unicode cChar = *m_pInputPos++; 247 if (bEscaped) 248 { 249 m_bCurTokenReparse = true; 250 m_pCurTokenContentEnd = m_pInputPos; 251 bEscaped = false; 252 } 253 else if (cChar == '(') 254 { 255 if (!m_pCurTokenContentBegin) 256 m_pCurTokenContentBegin = m_pInputPos - 1; 257 m_pCurTokenContentEnd = m_pInputPos; 258 ++nLevel; 259 } 260 else if (cChar == ')') 261 if (nLevel) 262 { 263 m_pCurTokenContentEnd = m_pInputPos; 264 --nLevel; 265 } 266 else 267 return true; 268 else if (cChar == '\\') 269 { 270 if (!m_pCurTokenContentBegin) 271 m_pCurTokenContentBegin = m_pInputPos - 1; 272 bEscaped = true; 273 } 274 else if (cChar > ' ' && cChar != 0x7F) // DEL 275 { 276 if (!m_pCurTokenContentBegin) 277 m_pCurTokenContentBegin = m_pInputPos - 1; 278 m_pCurTokenContentEnd = m_pInputPos; 279 } 280 } 281 } 282 283 default: 284 { 285 sal_Unicode cChar; 286 for (;;) 287 { 288 if (m_pInputPos >= m_pInputEnd) 289 return false; 290 cChar = *m_pInputPos++; 291 if (cChar > ' ' && cChar != 0x7F) // DEL 292 break; 293 } 294 m_pCurTokenBegin = m_pInputPos - 1; 295 if (cChar == '"' || cChar == '(' || cChar == ')' || cChar == ',' 296 || cChar == '.' || cChar == ':' || cChar == ';' 297 || cChar == '<' || cChar == '>' || cChar == '@' 298 || cChar == '[' || cChar == '\\' || cChar == ']') 299 { 300 m_nCurToken = cChar; 301 m_pCurTokenEnd = m_pInputPos; 302 return true; 303 } 304 else 305 for (;;) 306 { 307 if (m_pInputPos >= m_pInputEnd) 308 { 309 m_pCurTokenEnd = m_pInputPos; 310 return true; 311 } 312 cChar = *m_pInputPos++; 313 if (cChar <= ' ' || cChar == '"' || cChar == '(' 314 || cChar == ')' || cChar == ',' || cChar == '.' 315 || cChar == ':' || cChar == ';' || cChar == '<' 316 || cChar == '>' || cChar == '@' || cChar == '[' 317 || cChar == '\\' || cChar == ']' 318 || cChar == 0x7F) // DEL 319 { 320 m_pCurTokenEnd = --m_pInputPos; 321 return true; 322 } 323 } 324 } 325 } 326 } 327 328 //============================================================================ 329 // static 330 UniString SvAddressParser_Impl::reparse(sal_Unicode const * pBegin, 331 sal_Unicode const * pEnd, 332 bool bAddrSpec) 333 { 334 UniString aResult; 335 TokenType eMode = TOKEN_ATOM; 336 bool bEscaped = false; 337 bool bEndsWithSpace = false; 338 xub_StrLen nLevel = 0; 339 while (pBegin < pEnd) 340 { 341 sal_Unicode cChar = *pBegin++; 342 switch (eMode) 343 { 344 case TOKEN_QUOTED: 345 if (bEscaped) 346 { 347 aResult += cChar; 348 bEscaped = false; 349 } 350 else if (cChar == '"') 351 { 352 if (bAddrSpec) 353 aResult += cChar; 354 eMode = TOKEN_ATOM; 355 } 356 else if (cChar == '\\') 357 { 358 if (bAddrSpec) 359 aResult += cChar; 360 bEscaped = true; 361 } 362 else 363 aResult += cChar; 364 break; 365 366 case TOKEN_DOMAIN: 367 if (bEscaped) 368 { 369 aResult += cChar; 370 bEscaped = false; 371 } 372 else if (cChar == ']') 373 { 374 aResult += cChar; 375 eMode = TOKEN_ATOM; 376 } 377 else if (cChar == '\\') 378 { 379 if (bAddrSpec) 380 aResult += cChar; 381 bEscaped = true; 382 } 383 else 384 aResult += cChar; 385 break; 386 387 case TOKEN_COMMENT: 388 if (bEscaped) 389 bEscaped = false; 390 else if (cChar == '(') 391 ++nLevel; 392 else if (cChar == ')') 393 if (nLevel) 394 --nLevel; 395 else 396 eMode = TOKEN_ATOM; 397 else if (cChar == '\\') 398 bEscaped = true; 399 break; 400 401 case TOKEN_ATOM: 402 if (cChar <= ' ' || cChar == 0x7F) // DEL 403 { 404 if (!bAddrSpec && !bEndsWithSpace) 405 { 406 aResult += ' '; 407 bEndsWithSpace = true; 408 } 409 } 410 else if (cChar == '(') 411 { 412 if (!bAddrSpec && !bEndsWithSpace) 413 { 414 aResult += ' '; 415 bEndsWithSpace = true; 416 } 417 eMode = TOKEN_COMMENT; 418 } 419 else 420 { 421 bEndsWithSpace = false; 422 if (cChar == '"') 423 { 424 if (bAddrSpec) 425 aResult += cChar; 426 eMode = TOKEN_QUOTED; 427 } 428 else if (cChar == '[') 429 { 430 aResult += cChar; 431 eMode = TOKEN_QUOTED; 432 } 433 else 434 aResult += cChar; 435 } 436 break; 437 } 438 } 439 return aResult; 440 } 441 442 //============================================================================ 443 // static 444 UniString SvAddressParser_Impl::reparseComment(sal_Unicode const * pBegin, 445 sal_Unicode const * pEnd) 446 { 447 UniString aResult; 448 while (pBegin < pEnd) 449 { 450 sal_Unicode cChar = *pBegin++; 451 if (cChar == '\\') 452 cChar = *pBegin++; 453 aResult += cChar; 454 } 455 return aResult; 456 } 457 458 //============================================================================ 459 SvAddressParser_Impl::SvAddressParser_Impl(SvAddressParser * pParser, 460 UniString const & rInput) 461 { 462 m_pInputPos = rInput.GetBuffer(); 463 m_pInputEnd = m_pInputPos + rInput.Len(); 464 465 reset(); 466 bool bDone = false; 467 for (;;) 468 { 469 if (!readToken()) 470 { 471 m_bRealNameFinished = true; 472 if (m_eState == AFTER_LESS) 473 m_nCurToken = '>'; 474 else 475 { 476 m_nCurToken = ','; 477 bDone = true; 478 } 479 } 480 switch (m_nCurToken) 481 { 482 case TOKEN_QUOTED: 483 if (m_pAddrSpec->m_eLastElem != ELEMENT_END) 484 { 485 if (m_pAddrSpec->m_bAtFound 486 || m_pAddrSpec->m_eLastElem <= ELEMENT_DELIM) 487 m_pAddrSpec->reset(); 488 addTokenToAddrSpec(ELEMENT_ITEM); 489 } 490 if (!m_bRealNameFinished && m_eState != AFTER_LESS) 491 { 492 if (m_bCurTokenReparse) 493 { 494 if (!m_pRealNameBegin) 495 m_pRealNameBegin = m_pCurTokenBegin; 496 m_pRealNameEnd = m_pCurTokenEnd; 497 m_bRealNameReparse = true; 498 } 499 else if (m_bRealNameReparse) 500 m_pRealNameEnd = m_pCurTokenEnd; 501 else if (!m_pRealNameBegin) 502 { 503 m_pRealNameBegin = m_pCurTokenBegin; 504 m_pRealNameContentBegin = m_pCurTokenContentBegin; 505 m_pRealNameEnd = m_pRealNameContentEnd 506 = m_pCurTokenContentEnd; 507 } 508 else 509 { 510 m_pRealNameEnd = m_pCurTokenEnd; 511 m_bRealNameReparse = true; 512 } 513 } 514 m_eType = TOKEN_ATOM; 515 break; 516 517 case TOKEN_DOMAIN: 518 if (m_pAddrSpec->m_eLastElem != ELEMENT_END) 519 { 520 if (m_pAddrSpec->m_bAtFound 521 && m_pAddrSpec->m_eLastElem == ELEMENT_DELIM) 522 addTokenToAddrSpec(ELEMENT_ITEM); 523 else 524 m_pAddrSpec->reset(); 525 } 526 addTokenToRealName(); 527 m_eType = TOKEN_ATOM; 528 break; 529 530 case TOKEN_COMMENT: 531 if (!m_bRealNameFinished && m_eState != AFTER_LESS 532 && !m_pFirstCommentBegin && m_pCurTokenContentBegin) 533 { 534 m_pFirstCommentBegin = m_pCurTokenContentBegin; 535 m_pFirstCommentEnd = m_pCurTokenContentEnd; 536 m_bFirstCommentReparse = m_bCurTokenReparse; 537 } 538 m_eType = TOKEN_ATOM; 539 break; 540 541 case TOKEN_ATOM: 542 if (m_pAddrSpec->m_eLastElem != ELEMENT_END) 543 { 544 if (m_pAddrSpec->m_eLastElem != ELEMENT_DELIM) 545 m_pAddrSpec->reset(); 546 addTokenToAddrSpec(ELEMENT_ITEM); 547 } 548 addTokenToRealName(); 549 break; 550 551 case '(': 552 m_eType = TOKEN_COMMENT; 553 break; 554 555 case ')': 556 case '\\': 557 case ']': 558 m_pAddrSpec->finish(); 559 addTokenToRealName(); 560 break; 561 562 case '<': 563 switch (m_eState) 564 { 565 case BEFORE_COLON: 566 case BEFORE_LESS: 567 m_aOuterAddrSpec.finish(); 568 if (m_pRealNameBegin) 569 m_bRealNameFinished = true; 570 m_pAddrSpec = &m_aInnerAddrSpec; 571 m_eState = AFTER_LESS; 572 break; 573 574 case AFTER_LESS: 575 m_aInnerAddrSpec.finish(); 576 break; 577 578 case AFTER_GREATER: 579 m_aOuterAddrSpec.finish(); 580 addTokenToRealName(); 581 break; 582 } 583 break; 584 585 case '>': 586 if (m_eState == AFTER_LESS) 587 { 588 m_aInnerAddrSpec.finish(); 589 if (m_aInnerAddrSpec.isValid()) 590 m_aOuterAddrSpec.m_eLastElem = ELEMENT_END; 591 m_pAddrSpec = &m_aOuterAddrSpec; 592 m_eState = AFTER_GREATER; 593 } 594 else 595 { 596 m_aOuterAddrSpec.finish(); 597 addTokenToRealName(); 598 } 599 break; 600 601 case '@': 602 if (m_pAddrSpec->m_eLastElem != ELEMENT_END) 603 { 604 if (!m_pAddrSpec->m_bAtFound 605 && m_pAddrSpec->m_eLastElem == ELEMENT_ITEM) 606 { 607 addTokenToAddrSpec(ELEMENT_DELIM); 608 m_pAddrSpec->m_bAtFound = true; 609 } 610 else 611 m_pAddrSpec->reset(); 612 } 613 addTokenToRealName(); 614 break; 615 616 case ',': 617 case ';': 618 if (m_eState == AFTER_LESS) 619 if (m_nCurToken == ',') 620 { 621 if (m_aInnerAddrSpec.m_eLastElem 622 != ELEMENT_END) 623 m_aInnerAddrSpec.reset(); 624 } 625 else 626 m_aInnerAddrSpec.finish(); 627 else 628 { 629 m_pAddrSpec = m_aInnerAddrSpec.isValid() 630 || (!m_aOuterAddrSpec.isValid() 631 && m_aInnerAddrSpec.isPoorlyValid()) ? 632 &m_aInnerAddrSpec : 633 m_aOuterAddrSpec.isPoorlyValid() ? 634 &m_aOuterAddrSpec : 0; 635 if (m_pAddrSpec) 636 { 637 UniString aTheAddrSpec; 638 if (m_pAddrSpec->m_bReparse) 639 aTheAddrSpec = reparse(m_pAddrSpec->m_pBegin, 640 m_pAddrSpec->m_pEnd, true); 641 else 642 { 643 xub_StrLen nLen = 644 sal::static_int_cast< xub_StrLen >( 645 m_pAddrSpec->m_pEnd 646 - m_pAddrSpec->m_pBegin); 647 if (nLen == rInput.Len()) 648 aTheAddrSpec = rInput; 649 else 650 aTheAddrSpec 651 = rInput.Copy( 652 sal::static_int_cast< xub_StrLen >( 653 m_pAddrSpec->m_pBegin 654 - rInput.GetBuffer()), 655 nLen); 656 } 657 UniString aTheRealName; 658 if (!m_pRealNameBegin 659 || (m_pAddrSpec == &m_aOuterAddrSpec 660 && m_pRealNameBegin 661 == m_aOuterAddrSpec.m_pBegin 662 && m_pRealNameEnd == m_aOuterAddrSpec.m_pEnd 663 && m_pFirstCommentBegin)) 664 if (!m_pFirstCommentBegin) 665 aTheRealName = aTheAddrSpec; 666 else if (m_bFirstCommentReparse) 667 aTheRealName 668 = reparseComment(m_pFirstCommentBegin, 669 m_pFirstCommentEnd); 670 else 671 aTheRealName 672 = rInput.Copy( 673 sal::static_int_cast< xub_StrLen >( 674 m_pFirstCommentBegin 675 - rInput.GetBuffer()), 676 sal::static_int_cast< xub_StrLen >( 677 m_pFirstCommentEnd 678 - m_pFirstCommentBegin)); 679 else if (m_bRealNameReparse) 680 aTheRealName = reparse(m_pRealNameBegin, 681 m_pRealNameEnd, false); 682 else 683 { 684 xub_StrLen nLen = 685 sal::static_int_cast< xub_StrLen >( 686 m_pRealNameContentEnd 687 - m_pRealNameContentBegin); 688 if (nLen == rInput.Len()) 689 aTheRealName = rInput; 690 else 691 aTheRealName 692 = rInput.Copy( 693 sal::static_int_cast< xub_StrLen >( 694 m_pRealNameContentBegin 695 - rInput.GetBuffer()), 696 nLen); 697 } 698 if (pParser->m_bHasFirst) 699 pParser->m_aRest.Insert(new SvAddressEntry_Impl( 700 aTheAddrSpec, 701 aTheRealName), 702 LIST_APPEND); 703 else 704 { 705 pParser->m_bHasFirst = true; 706 pParser->m_aFirst.m_aAddrSpec = aTheAddrSpec; 707 pParser->m_aFirst.m_aRealName = aTheRealName; 708 } 709 } 710 if (bDone) 711 return; 712 reset(); 713 } 714 break; 715 716 case ':': 717 switch (m_eState) 718 { 719 case BEFORE_COLON: 720 m_aOuterAddrSpec.reset(); 721 resetRealNameAndFirstComment(); 722 m_eState = BEFORE_LESS; 723 break; 724 725 case BEFORE_LESS: 726 case AFTER_GREATER: 727 m_aOuterAddrSpec.finish(); 728 addTokenToRealName(); 729 break; 730 731 case AFTER_LESS: 732 m_aInnerAddrSpec.reset(); 733 break; 734 } 735 break; 736 737 case '"': 738 m_eType = TOKEN_QUOTED; 739 break; 740 741 case '.': 742 if (m_pAddrSpec->m_eLastElem != ELEMENT_END) 743 { 744 if (m_pAddrSpec->m_eLastElem != ELEMENT_DELIM) 745 addTokenToAddrSpec(ELEMENT_DELIM); 746 else 747 m_pAddrSpec->reset(); 748 } 749 addTokenToRealName(); 750 break; 751 752 case '[': 753 m_eType = TOKEN_DOMAIN; 754 break; 755 } 756 } 757 } 758 759 //============================================================================ 760 // 761 // SvAddressParser 762 // 763 //============================================================================ 764 765 SvAddressParser::SvAddressParser(UniString const & rInput): m_bHasFirst(false) 766 { 767 SvAddressParser_Impl(this, rInput); 768 } 769 770 //============================================================================ 771 SvAddressParser::~SvAddressParser() 772 { 773 for (sal_uLong i = m_aRest.Count(); i != 0;) 774 delete m_aRest.Remove(--i); 775 } 776 777 //============================================================================ 778 // static 779 bool SvAddressParser::createRFC822Mailbox(String const & rPhrase, 780 String const & rAddrSpec, 781 String & rMailbox) 782 { 783 String aTheAddrSpec; 784 sal_Unicode const * p = rAddrSpec.GetBuffer(); 785 sal_Unicode const * pEnd = p + rAddrSpec.Len(); 786 {for (bool bSegment = false;;) 787 { 788 p = INetMIME::skipLinearWhiteSpaceComment(p, pEnd); 789 if (p == pEnd) 790 return false; 791 if (bSegment) 792 { 793 sal_Unicode c = *p++; 794 if (c == '@') 795 break; 796 else if (c != '.') 797 return false; 798 aTheAddrSpec += '.'; 799 p = INetMIME::skipLinearWhiteSpaceComment(p, pEnd); 800 if (p == pEnd) 801 return false; 802 } 803 else 804 bSegment = true; 805 if (*p == '"') 806 { 807 aTheAddrSpec += *p++; 808 for (;;) 809 { 810 if (INetMIME::startsWithLineFolding(p, pEnd)) 811 p += 2; 812 if (p == pEnd) 813 return false; 814 if (*p == '"') 815 break; 816 if (*p == '\x0D' || (*p == '\\' && ++p == pEnd) 817 || !INetMIME::isUSASCII(*p)) 818 return false; 819 if (INetMIME::needsQuotedStringEscape(*p)) 820 aTheAddrSpec += '\\'; 821 aTheAddrSpec += *p++; 822 } 823 aTheAddrSpec += *p++; 824 } 825 else if (INetMIME::isAtomChar(*p)) 826 while (p != pEnd && INetMIME::isAtomChar(*p)) 827 aTheAddrSpec += *p++; 828 else 829 return false; 830 }} 831 aTheAddrSpec += '@'; 832 {for (bool bSegment = false;;) 833 { 834 p = INetMIME::skipLinearWhiteSpaceComment(p, pEnd); 835 if (p == pEnd) 836 { 837 if (bSegment) 838 break; 839 else 840 return false; 841 } 842 if (bSegment) 843 { 844 if (*p++ != '.') 845 return false; 846 aTheAddrSpec += '.'; 847 p = INetMIME::skipLinearWhiteSpaceComment(p, pEnd); 848 if (p == pEnd) 849 return false; 850 } 851 else 852 bSegment = true; 853 if (*p == '[') 854 { 855 aTheAddrSpec += *p++; 856 for (;;) 857 { 858 if (INetMIME::startsWithLineFolding(p, pEnd)) 859 p += 2; 860 if (p == pEnd) 861 return false; 862 if (*p == ']') 863 break; 864 if (*p == '\x0D' || *p == '[' || (*p == '\\' && ++p == pEnd) 865 || !INetMIME::isUSASCII(*p)) 866 return false; 867 if (*p >= '[' && *p <= ']') 868 aTheAddrSpec += '\\'; 869 aTheAddrSpec += *p++; 870 } 871 aTheAddrSpec += *p++; 872 } 873 else if (INetMIME::isAtomChar(*p)) 874 while (p != pEnd && INetMIME::isAtomChar(*p)) 875 aTheAddrSpec += *p++; 876 else 877 return false; 878 }} 879 880 if (rPhrase.Len() == 0) 881 rMailbox = aTheAddrSpec; 882 else 883 { 884 bool bQuotedString = false; 885 p = rPhrase.GetBuffer(); 886 pEnd = p + rPhrase.Len(); 887 for (;p != pEnd; ++p) 888 if (!(INetMIME::isAtomChar(*p))) 889 { 890 bQuotedString = true; 891 break; 892 } 893 String aTheMailbox; 894 if (bQuotedString) 895 { 896 aTheMailbox = '"'; 897 for (p = rPhrase.GetBuffer(); p != pEnd; ++p) 898 { 899 if (INetMIME::needsQuotedStringEscape(*p)) 900 aTheMailbox += '\\'; 901 aTheMailbox += *p; 902 } 903 aTheMailbox += '"'; 904 } 905 else 906 aTheMailbox = rPhrase; 907 aTheMailbox.AppendAscii(RTL_CONSTASCII_STRINGPARAM(" <")); 908 aTheMailbox += aTheAddrSpec; 909 aTheMailbox += '>'; 910 rMailbox = aTheMailbox; 911 } 912 return true; 913 } 914 915