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
ParsedAddrSpecunnamed_svl_adrparse::ParsedAddrSpec47 ParsedAddrSpec() { reset(); }
48
isPoorlyValidunnamed_svl_adrparse::ParsedAddrSpec49 bool isPoorlyValid() const { return m_eLastElem >= ELEMENT_ITEM; }
50
isValidunnamed_svl_adrparse::ParsedAddrSpec51 bool isValid() const { return isPoorlyValid() && m_bAtFound; }
52
53 inline void reset();
54
55 inline void finish();
56 };
57
reset()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
finish()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
resetRealNameAndFirstComment()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
reset()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
addTokenToAddrSpec(ElementType eTokenElem)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
addTokenToRealName()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
readToken()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
reparse(sal_Unicode const * pBegin,sal_Unicode const * pEnd,bool bAddrSpec)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
reparseComment(sal_Unicode const * pBegin,sal_Unicode const * pEnd)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 //============================================================================
SvAddressParser_Impl(SvAddressParser * pParser,UniString const & rInput)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
SvAddressParser(UniString const & rInput)765 SvAddressParser::SvAddressParser(UniString const & rInput): m_bHasFirst(false)
766 {
767 SvAddressParser_Impl(this, rInput);
768 }
769
770 //============================================================================
~SvAddressParser()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
createRFC822Mailbox(String const & rPhrase,String const & rAddrSpec,String & rMailbox)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