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