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