1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <rtl/ustrbuf.hxx>
21 #include <svl/adrparse.hxx>
26 enum ElementType
{ ELEMENT_START
, ELEMENT_DELIM
, ELEMENT_ITEM
, ELEMENT_END
};
30 sal_Unicode
const * m_pBegin
;
31 sal_Unicode
const * m_pEnd
;
32 ElementType m_eLastElem
;
36 ParsedAddrSpec() { reset(); }
38 bool isPoorlyValid() const { return m_eLastElem
>= ELEMENT_ITEM
; }
40 bool isValid() const { return isPoorlyValid() && m_bAtFound
; }
47 void ParsedAddrSpec::reset()
51 m_eLastElem
= ELEMENT_START
;
56 void ParsedAddrSpec::finish()
59 m_eLastElem
= ELEMENT_END
;
66 class SvAddressParser_Impl
68 enum State
{ BEFORE_COLON
, BEFORE_LESS
, AFTER_LESS
, AFTER_GREATER
};
70 enum TokenType
: sal_uInt32
{
71 TOKEN_QUOTED
= 0x80000000, TOKEN_DOMAIN
, TOKEN_COMMENT
, TOKEN_ATOM
};
73 sal_Unicode
const * m_pInputPos
;
74 sal_Unicode
const * m_pInputEnd
;
75 sal_uInt32 m_nCurToken
;
76 sal_Unicode
const * m_pCurTokenBegin
;
77 sal_Unicode
const * m_pCurTokenEnd
;
78 ParsedAddrSpec m_aOuterAddrSpec
;
79 ParsedAddrSpec m_aInnerAddrSpec
;
80 ParsedAddrSpec
* m_pAddrSpec
;
86 void addTokenToAddrSpec(ElementType eTokenElem
);
90 static OUString
reparse(sal_Unicode
const * pBegin
,
91 sal_Unicode
const * pEnd
);
94 SvAddressParser_Impl(SvAddressParser
* pParser
, const OUString
& rIn
);
97 inline void SvAddressParser_Impl::reset()
99 m_aOuterAddrSpec
.reset();
100 m_aInnerAddrSpec
.reset();
101 m_pAddrSpec
= &m_aOuterAddrSpec
;
102 m_eState
= BEFORE_COLON
;
103 m_eType
= TOKEN_ATOM
;
106 void SvAddressParser_Impl::addTokenToAddrSpec(ElementType eTokenElem
)
108 if (!m_pAddrSpec
->m_pBegin
)
109 m_pAddrSpec
->m_pBegin
= m_pCurTokenBegin
;
110 else if (m_pAddrSpec
->m_pEnd
< m_pCurTokenBegin
)
111 m_pAddrSpec
->m_bReparse
= true;
112 m_pAddrSpec
->m_pEnd
= m_pCurTokenEnd
;
113 m_pAddrSpec
->m_eLastElem
= eTokenElem
;
117 // SvAddressParser_Impl
120 bool SvAddressParser_Impl::readToken()
122 m_nCurToken
= m_eType
;
127 m_pCurTokenBegin
= m_pInputPos
- 1;
128 bool bEscaped
= false;
131 if (m_pInputPos
>= m_pInputEnd
)
133 sal_Unicode cChar
= *m_pInputPos
++;
138 else if (cChar
== '"')
140 m_pCurTokenEnd
= m_pInputPos
;
143 else if (cChar
== '\\')
150 m_pCurTokenBegin
= m_pInputPos
- 1;
151 bool bEscaped
= false;
154 if (m_pInputPos
>= m_pInputEnd
)
156 sal_Unicode cChar
= *m_pInputPos
++;
159 else if (cChar
== ']')
161 m_pCurTokenEnd
= m_pInputPos
;
164 else if (cChar
== '\\')
171 m_pCurTokenBegin
= m_pInputPos
- 1;
172 bool bEscaped
= false;
176 if (m_pInputPos
>= m_pInputEnd
)
178 sal_Unicode cChar
= *m_pInputPos
++;
183 else if (cChar
== '(')
187 else if (cChar
== ')')
194 else if (cChar
== '\\')
206 if (m_pInputPos
>= m_pInputEnd
)
208 cChar
= *m_pInputPos
++;
209 if (cChar
> ' ' && cChar
!= 0x7F) // DEL
212 m_pCurTokenBegin
= m_pInputPos
- 1;
213 if (cChar
== '"' || cChar
== '(' || cChar
== ')' || cChar
== ','
214 || cChar
== '.' || cChar
== ':' || cChar
== ';'
215 || cChar
== '<' || cChar
== '>' || cChar
== '@'
216 || cChar
== '[' || cChar
== '\\' || cChar
== ']')
219 m_pCurTokenEnd
= m_pInputPos
;
225 if (m_pInputPos
>= m_pInputEnd
)
227 m_pCurTokenEnd
= m_pInputPos
;
230 cChar
= *m_pInputPos
++;
231 if (cChar
<= ' ' || cChar
== '"' || cChar
== '('
232 || cChar
== ')' || cChar
== ',' || cChar
== '.'
233 || cChar
== ':' || cChar
== ';' || cChar
== '<'
234 || cChar
== '>' || cChar
== '@' || cChar
== '['
235 || cChar
== '\\' || cChar
== ']'
236 || cChar
== 0x7F) // DEL
238 m_pCurTokenEnd
= --m_pInputPos
;
247 OUString
SvAddressParser_Impl::reparse(sal_Unicode
const * pBegin
,
248 sal_Unicode
const * pEnd
)
250 OUStringBuffer aResult
;
251 TokenType eMode
= TOKEN_ATOM
;
252 bool bEscaped
= false;
254 while (pBegin
< pEnd
)
256 sal_Unicode cChar
= *pBegin
++;
262 aResult
.append(cChar
);
265 else if (cChar
== '"')
267 aResult
.append(cChar
);
270 else if (cChar
== '\\')
272 aResult
.append(cChar
);
276 aResult
.append(cChar
);
282 aResult
.append(cChar
);
285 else if (cChar
== ']')
287 aResult
.append(cChar
);
290 else if (cChar
== '\\')
292 aResult
.append(cChar
);
296 aResult
.append(cChar
);
302 else if (cChar
== '(')
304 else if (cChar
== ')')
309 else if (cChar
== '\\')
314 if (cChar
<= ' ' || cChar
== 0x7F) // DEL
317 else if (cChar
== '(')
319 eMode
= TOKEN_COMMENT
;
325 aResult
.append(cChar
);
326 eMode
= TOKEN_QUOTED
;
328 else if (cChar
== '[')
330 aResult
.append(cChar
);
331 eMode
= TOKEN_QUOTED
;
334 aResult
.append(cChar
);
339 return aResult
.makeStringAndClear();
342 SvAddressParser_Impl::SvAddressParser_Impl(SvAddressParser
* pParser
,
343 const OUString
& rInput
)
344 : m_pCurTokenBegin(nullptr)
345 , m_pCurTokenEnd(nullptr)
347 m_pInputPos
= rInput
.getStr();
348 m_pInputEnd
= m_pInputPos
+ rInput
.getLength();
356 if (m_eState
== AFTER_LESS
)
367 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_END
)
369 if (m_pAddrSpec
->m_bAtFound
370 || m_pAddrSpec
->m_eLastElem
<= ELEMENT_DELIM
)
371 m_pAddrSpec
->reset();
372 addTokenToAddrSpec(ELEMENT_ITEM
);
374 m_eType
= TOKEN_ATOM
;
378 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_END
)
380 if (m_pAddrSpec
->m_bAtFound
&& m_pAddrSpec
->m_eLastElem
== ELEMENT_DELIM
)
381 addTokenToAddrSpec(ELEMENT_ITEM
);
383 m_pAddrSpec
->reset();
385 m_eType
= TOKEN_ATOM
;
389 m_eType
= TOKEN_ATOM
;
393 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_END
)
395 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_DELIM
)
396 m_pAddrSpec
->reset();
397 addTokenToAddrSpec(ELEMENT_ITEM
);
402 m_eType
= TOKEN_COMMENT
;
408 m_pAddrSpec
->finish();
416 m_aOuterAddrSpec
.finish();
417 m_pAddrSpec
= &m_aInnerAddrSpec
;
418 m_eState
= AFTER_LESS
;
422 m_aInnerAddrSpec
.finish();
426 m_aOuterAddrSpec
.finish();
432 if (m_eState
== AFTER_LESS
)
434 m_aInnerAddrSpec
.finish();
435 if (m_aInnerAddrSpec
.isValid())
436 m_aOuterAddrSpec
.m_eLastElem
= ELEMENT_END
;
437 m_pAddrSpec
= &m_aOuterAddrSpec
;
438 m_eState
= AFTER_GREATER
;
442 m_aOuterAddrSpec
.finish();
447 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_END
)
449 if (!m_pAddrSpec
->m_bAtFound
450 && m_pAddrSpec
->m_eLastElem
== ELEMENT_ITEM
)
452 addTokenToAddrSpec(ELEMENT_DELIM
);
453 m_pAddrSpec
->m_bAtFound
= true;
456 m_pAddrSpec
->reset();
462 if (m_eState
== AFTER_LESS
)
463 if (m_nCurToken
== ',')
465 if (m_aInnerAddrSpec
.m_eLastElem
!= ELEMENT_END
)
466 m_aInnerAddrSpec
.reset();
469 m_aInnerAddrSpec
.finish();
472 if(m_aInnerAddrSpec
.isValid() || (!m_aOuterAddrSpec
.isValid() && m_aInnerAddrSpec
.isPoorlyValid()))
474 m_pAddrSpec
= &m_aInnerAddrSpec
;
476 else if(m_aOuterAddrSpec
.isPoorlyValid())
478 m_pAddrSpec
= &m_aOuterAddrSpec
;
482 m_pAddrSpec
= nullptr;
487 OUString aTheAddrSpec
;
488 if (m_pAddrSpec
->m_bReparse
)
489 aTheAddrSpec
= reparse(m_pAddrSpec
->m_pBegin
, m_pAddrSpec
->m_pEnd
);
492 sal_Int32 nLen
= m_pAddrSpec
->m_pEnd
- m_pAddrSpec
->m_pBegin
;
493 if (nLen
== rInput
.getLength())
494 aTheAddrSpec
= rInput
;
496 aTheAddrSpec
= rInput
.copy( (m_pAddrSpec
->m_pBegin
- rInput
.getStr()),
499 pParser
->m_vAddresses
.emplace_back( aTheAddrSpec
);
511 m_aOuterAddrSpec
.reset();
512 m_eState
= BEFORE_LESS
;
517 m_aOuterAddrSpec
.finish();
521 m_aInnerAddrSpec
.reset();
527 m_eType
= TOKEN_QUOTED
;
531 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_END
)
533 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_DELIM
)
534 addTokenToAddrSpec(ELEMENT_DELIM
);
536 m_pAddrSpec
->reset();
541 m_eType
= TOKEN_DOMAIN
;
547 SvAddressParser::SvAddressParser(const OUString
& rInput
)
549 SvAddressParser_Impl
aDoParse(this, rInput
);
552 SvAddressParser::~SvAddressParser()
556 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */