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
, bool bAddrSpec
);
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
, bool bAddrSpec
)
250 OUStringBuffer aResult
;
251 TokenType eMode
= TOKEN_ATOM
;
252 bool bEscaped
= false;
253 bool bEndsWithSpace
= false;
255 while (pBegin
< pEnd
)
257 sal_Unicode cChar
= *pBegin
++;
263 aResult
.append(cChar
);
266 else if (cChar
== '"')
269 aResult
.append(cChar
);
272 else if (cChar
== '\\')
275 aResult
.append(cChar
);
279 aResult
.append(cChar
);
285 aResult
.append(cChar
);
288 else if (cChar
== ']')
290 aResult
.append(cChar
);
293 else if (cChar
== '\\')
296 aResult
.append(cChar
);
300 aResult
.append(cChar
);
306 else if (cChar
== '(')
308 else if (cChar
== ')')
313 else if (cChar
== '\\')
318 if (cChar
<= ' ' || cChar
== 0x7F) // DEL
320 if (!bAddrSpec
&& !bEndsWithSpace
)
323 bEndsWithSpace
= true;
326 else if (cChar
== '(')
328 if (!bAddrSpec
&& !bEndsWithSpace
)
331 bEndsWithSpace
= true;
333 eMode
= TOKEN_COMMENT
;
337 bEndsWithSpace
= false;
341 aResult
.append(cChar
);
342 eMode
= TOKEN_QUOTED
;
344 else if (cChar
== '[')
346 aResult
.append(cChar
);
347 eMode
= TOKEN_QUOTED
;
350 aResult
.append(cChar
);
355 return aResult
.makeStringAndClear();
358 SvAddressParser_Impl::SvAddressParser_Impl(SvAddressParser
* pParser
,
359 const OUString
& rInput
)
360 : m_pCurTokenBegin(nullptr)
361 , m_pCurTokenEnd(nullptr)
363 m_pInputPos
= rInput
.getStr();
364 m_pInputEnd
= m_pInputPos
+ rInput
.getLength();
372 if (m_eState
== AFTER_LESS
)
383 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_END
)
385 if (m_pAddrSpec
->m_bAtFound
386 || m_pAddrSpec
->m_eLastElem
<= ELEMENT_DELIM
)
387 m_pAddrSpec
->reset();
388 addTokenToAddrSpec(ELEMENT_ITEM
);
390 m_eType
= TOKEN_ATOM
;
394 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_END
)
396 if (m_pAddrSpec
->m_bAtFound
&& m_pAddrSpec
->m_eLastElem
== ELEMENT_DELIM
)
397 addTokenToAddrSpec(ELEMENT_ITEM
);
399 m_pAddrSpec
->reset();
401 m_eType
= TOKEN_ATOM
;
405 m_eType
= TOKEN_ATOM
;
409 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_END
)
411 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_DELIM
)
412 m_pAddrSpec
->reset();
413 addTokenToAddrSpec(ELEMENT_ITEM
);
418 m_eType
= TOKEN_COMMENT
;
424 m_pAddrSpec
->finish();
432 m_aOuterAddrSpec
.finish();
433 m_pAddrSpec
= &m_aInnerAddrSpec
;
434 m_eState
= AFTER_LESS
;
438 m_aInnerAddrSpec
.finish();
442 m_aOuterAddrSpec
.finish();
448 if (m_eState
== AFTER_LESS
)
450 m_aInnerAddrSpec
.finish();
451 if (m_aInnerAddrSpec
.isValid())
452 m_aOuterAddrSpec
.m_eLastElem
= ELEMENT_END
;
453 m_pAddrSpec
= &m_aOuterAddrSpec
;
454 m_eState
= AFTER_GREATER
;
458 m_aOuterAddrSpec
.finish();
463 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_END
)
465 if (!m_pAddrSpec
->m_bAtFound
466 && m_pAddrSpec
->m_eLastElem
== ELEMENT_ITEM
)
468 addTokenToAddrSpec(ELEMENT_DELIM
);
469 m_pAddrSpec
->m_bAtFound
= true;
472 m_pAddrSpec
->reset();
478 if (m_eState
== AFTER_LESS
)
479 if (m_nCurToken
== ',')
481 if (m_aInnerAddrSpec
.m_eLastElem
!= ELEMENT_END
)
482 m_aInnerAddrSpec
.reset();
485 m_aInnerAddrSpec
.finish();
488 if(m_aInnerAddrSpec
.isValid() || (!m_aOuterAddrSpec
.isValid() && m_aInnerAddrSpec
.isPoorlyValid()))
490 m_pAddrSpec
= &m_aInnerAddrSpec
;
492 else if(m_aOuterAddrSpec
.isPoorlyValid())
494 m_pAddrSpec
= &m_aOuterAddrSpec
;
498 m_pAddrSpec
= nullptr;
503 OUString aTheAddrSpec
;
504 if (m_pAddrSpec
->m_bReparse
)
505 aTheAddrSpec
= reparse(m_pAddrSpec
->m_pBegin
, m_pAddrSpec
->m_pEnd
, true);
508 sal_Int32 nLen
= m_pAddrSpec
->m_pEnd
- m_pAddrSpec
->m_pBegin
;
509 if (nLen
== rInput
.getLength())
510 aTheAddrSpec
= rInput
;
512 aTheAddrSpec
= rInput
.copy( (m_pAddrSpec
->m_pBegin
- rInput
.getStr()),
515 pParser
->m_vAddresses
.emplace_back( aTheAddrSpec
);
527 m_aOuterAddrSpec
.reset();
528 m_eState
= BEFORE_LESS
;
533 m_aOuterAddrSpec
.finish();
537 m_aInnerAddrSpec
.reset();
543 m_eType
= TOKEN_QUOTED
;
547 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_END
)
549 if (m_pAddrSpec
->m_eLastElem
!= ELEMENT_DELIM
)
550 addTokenToAddrSpec(ELEMENT_DELIM
);
552 m_pAddrSpec
->reset();
557 m_eType
= TOKEN_DOMAIN
;
563 SvAddressParser::SvAddressParser(const OUString
& rInput
)
565 SvAddressParser_Impl
aDoParse(this, rInput
);
568 SvAddressParser::~SvAddressParser()
572 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */