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 .
23 #include <osl/diagnose.h>
24 #include <rtl/ustring.hxx>
25 #include <rtl/strbuf.hxx>
26 #include <rtl/tencinfo.h>
27 #include <tools/inetmime.hxx>
28 #include <rtl/character.hxx>
30 namespace unnamed_tools_inetmime
{} using namespace unnamed_tools_inetmime
;
31 // unnamed namespaces don't work well yet
33 namespace unnamed_tools_inetmime
{
37 rtl_TextEncoding m_eEncoding
;
38 const sal_uInt32
* m_pRanges
;
41 inline Charset(rtl_TextEncoding eTheEncoding
,
42 const sal_uInt32
* pTheRanges
);
44 rtl_TextEncoding
getEncoding() const { return m_eEncoding
; }
46 bool contains(sal_uInt32 nChar
) const;
49 inline Charset::Charset(rtl_TextEncoding eTheEncoding
,
50 const sal_uInt32
* pTheRanges
):
51 m_eEncoding(eTheEncoding
),
54 DBG_ASSERT(m_pRanges
, "Charset::Charset(): Bad ranges");
57 void appendISO88591(OUString
& rText
, sal_Char
const * pBegin
,
58 sal_Char
const * pEnd
);
62 class INetMIMECharsetList_Impl
70 inline Node(const Charset
& rTheCharset
, bool bTheDisabled
,
77 INetMIMECharsetList_Impl(): m_pFirst(0) {}
79 ~INetMIMECharsetList_Impl();
81 void prepend(const Charset
& rCharset
)
82 { m_pFirst
= new Node(rCharset
, false, m_pFirst
); }
84 void includes(sal_uInt32 nChar
);
86 rtl_TextEncoding
getPreferredEncoding(rtl_TextEncoding eDefault
87 = RTL_TEXTENCODING_DONTKNOW
)
93 inline INetMIMECharsetList_Impl::Node::Node(const Charset
& rTheCharset
,
96 m_aCharset(rTheCharset
),
97 m_bDisabled(bTheDisabled
),
101 namespace unnamed_tools_inetmime
{
106 OString m_aAttribute
;
110 sal_uInt32 m_nSection
;
113 inline Parameter(Parameter
* pTheNext
, const OString
& rTheAttribute
,
114 const OString
& rTheCharset
,
115 const OString
& rTheLanguage
,
116 const OString
& rTheValue
, sal_uInt32 nTheSection
,
120 inline Parameter::Parameter(Parameter
* pTheNext
,
121 const OString
& rTheAttribute
,
122 const OString
& rTheCharset
,
123 const OString
& rTheLanguage
,
124 const OString
& rTheValue
,
125 sal_uInt32 nTheSection
, bool bTheExtended
):
127 m_aAttribute(rTheAttribute
),
128 m_aCharset(rTheCharset
),
129 m_aLanguage(rTheLanguage
),
131 m_nSection(nTheSection
),
132 m_bExtended(bTheExtended
)
139 ParameterList(): m_pList(0) {}
141 inline ~ParameterList();
143 Parameter
** find(const OString
& rAttribute
, sal_uInt32 nSection
,
147 inline ParameterList::~ParameterList()
151 Parameter
* pNext
= m_pList
->m_pNext
;
157 bool parseParameters(ParameterList
const & rInput
,
158 INetContentTypeParameterList
* pOutput
);
164 bool Charset::contains(sal_uInt32 nChar
) const
166 for (const sal_uInt32
* p
= m_pRanges
;;)
177 namespace unnamed_tools_inetmime
{
179 void appendISO88591(OUString
& rText
, sal_Char
const * pBegin
,
180 sal_Char
const * pEnd
)
182 sal_Int32 nLength
= pEnd
- pBegin
;
183 sal_Unicode
* pBuffer
= new sal_Unicode
[nLength
];
184 for (sal_Unicode
* p
= pBuffer
; pBegin
!= pEnd
;)
185 *p
++ = static_cast<unsigned char>(*pBegin
++);
186 rText
+= OUString(pBuffer
, nLength
);
192 // INetMIMECharsetList_Impl
194 INetMIMECharsetList_Impl::~INetMIMECharsetList_Impl()
198 Node
* pRemove
= m_pFirst
;
199 m_pFirst
= m_pFirst
->m_pNext
;
204 void INetMIMECharsetList_Impl::includes(sal_uInt32 nChar
)
206 for (Node
* p
= m_pFirst
; p
; p
= p
->m_pNext
)
207 if (!(p
->m_bDisabled
|| p
->m_aCharset
.contains(nChar
)))
208 p
->m_bDisabled
= true;
211 rtl_TextEncoding
INetMIMECharsetList_Impl::getPreferredEncoding(rtl_TextEncoding eDefault
)
214 for (Node
* p
= m_pFirst
; p
; p
= p
->m_pNext
)
216 return p
->m_aCharset
.getEncoding();
220 void INetMIMECharsetList_Impl::reset()
222 for (Node
* p
= m_pFirst
; p
; p
= p
->m_pNext
)
223 p
->m_bDisabled
= false;
228 Parameter
** ParameterList::find(const OString
& rAttribute
,
229 sal_uInt32 nSection
, bool & rPresent
)
231 Parameter
** p
= &m_pList
;
232 for (; *p
; p
= &(*p
)->m_pNext
)
234 sal_Int32 nCompare
= rAttribute
.compareTo((*p
)->m_aAttribute
);
237 else if (nCompare
== 0)
239 if (nSection
> (*p
)->m_nSection
)
241 else if (nSection
== (*p
)->m_nSection
)
254 namespace unnamed_tools_inetmime
{
256 bool parseParameters(ParameterList
const & rInput
,
257 INetContentTypeParameterList
* pOutput
)
262 Parameter
* pPrev
= 0;
263 for (Parameter
* p
= rInput
.m_pList
; p
; p
= p
->m_pNext
)
265 if (p
->m_nSection
> 0
267 || pPrev
->m_nSection
!= p
->m_nSection
- 1
268 || pPrev
->m_aAttribute
!= p
->m_aAttribute
))
274 for (Parameter
* p
= rInput
.m_pList
; p
;)
276 bool bCharset
= !p
->m_aCharset
.isEmpty();
277 rtl_TextEncoding eEncoding
= RTL_TEXTENCODING_DONTKNOW
;
280 = INetMIME::getCharsetEncoding(p
->m_aCharset
.getStr(),
281 p
->m_aCharset
.getStr()
286 bool bBadEncoding
= false;
287 Parameter
* pNext
= p
;
291 sal_Unicode
* pUnicode
292 = INetMIME::convertToUnicode(pNext
->m_aValue
.getStr(),
293 pNext
->m_aValue
.getStr()
294 + pNext
->m_aValue
.getLength(),
295 bCharset
&& p
->m_bExtended
?
297 RTL_TEXTENCODING_UTF8
,
299 if (!pUnicode
&& !(bCharset
&& p
->m_bExtended
))
300 pUnicode
= INetMIME::convertToUnicode(
301 pNext
->m_aValue
.getStr(),
302 pNext
->m_aValue
.getStr()
303 + pNext
->m_aValue
.getLength(),
304 RTL_TEXTENCODING_ISO_8859_1
, nSize
);
310 aValue
+= OUString(pUnicode
, static_cast<sal_Int32
>(nSize
));
312 pNext
= pNext
->m_pNext
;
314 while (pNext
&& pNext
->m_nSection
> 0);
320 if (pNext
->m_bExtended
)
322 for (sal_Int32 i
= 0; i
< pNext
->m_aValue
.getLength(); ++i
)
323 aValue
+= OUString(sal_Unicode(
325 static_cast<unsigned char>(pNext
->m_aValue
[i
]))
330 for (sal_Int32 i
= 0; i
< pNext
->m_aValue
.getLength(); ++i
)
331 aValue
+= OUString( sal_Unicode(static_cast<unsigned char>(pNext
->m_aValue
[i
])) );
333 pNext
= pNext
->m_pNext
;
334 if (!pNext
|| pNext
->m_nSection
== 0)
338 pOutput
->Append(new INetContentTypeParameter(p
->m_aAttribute
,
353 bool INetMIME::isAtomChar(sal_uInt32 nChar
)
355 static const bool aMap
[128]
356 = { false, false, false, false, false, false, false, false,
357 false, false, false, false, false, false, false, false,
358 false, false, false, false, false, false, false, false,
359 false, false, false, false, false, false, false, false,
360 false, true, false, true, true, true, true, true, // !"#$%&'
361 false, false, true, true, false, true, false, true, //()*+,-./
362 true, true, true, true, true, true, true, true, //01234567
363 true, true, false, false, false, true, false, true, //89:;<=>?
364 false, true, true, true, true, true, true, true, //@ABCDEFG
365 true, true, true, true, true, true, true, true, //HIJKLMNO
366 true, true, true, true, true, true, true, true, //PQRSTUVW
367 true, true, true, false, false, false, true, true, //XYZ[\]^_
368 true, true, true, true, true, true, true, true, //`abcdefg
369 true, true, true, true, true, true, true, true, //hijklmno
370 true, true, true, true, true, true, true, true, //pqrstuvw
371 true, true, true, true, true, true, true, false //xyz{|}~
373 return rtl::isAscii(nChar
) && aMap
[nChar
];
377 bool INetMIME::isTokenChar(sal_uInt32 nChar
)
379 static const bool aMap
[128]
380 = { false, false, false, false, false, false, false, false,
381 false, false, false, false, false, false, false, false,
382 false, false, false, false, false, false, false, false,
383 false, false, false, false, false, false, false, false,
384 false, true, false, true, true, true, true, true, // !"#$%&'
385 false, false, true, true, false, true, true, false, //()*+,-./
386 true, true, true, true, true, true, true, true, //01234567
387 true, true, false, false, false, false, false, false, //89:;<=>?
388 false, true, true, true, true, true, true, true, //@ABCDEFG
389 true, true, true, true, true, true, true, true, //HIJKLMNO
390 true, true, true, true, true, true, true, true, //PQRSTUVW
391 true, true, true, false, false, false, true, true, //XYZ[\]^_
392 true, true, true, true, true, true, true, true, //`abcdefg
393 true, true, true, true, true, true, true, true, //hijklmno
394 true, true, true, true, true, true, true, true, //pqrstuvw
395 true, true, true, true, true, true, true, false //xyz{|}~
397 return rtl::isAscii(nChar
) && aMap
[nChar
];
401 bool INetMIME::isEncodedWordTokenChar(sal_uInt32 nChar
)
403 static const bool aMap
[128]
404 = { false, false, false, false, false, false, false, false,
405 false, false, false, false, false, false, false, false,
406 false, false, false, false, false, false, false, false,
407 false, false, false, false, false, false, false, false,
408 false, true, false, true, true, true, true, true, // !"#$%&'
409 false, false, true, true, false, true, false, false, //()*+,-./
410 true, true, true, true, true, true, true, true, //01234567
411 true, true, false, false, false, false, false, false, //89:;<=>?
412 false, true, true, true, true, true, true, true, //@ABCDEFG
413 true, true, true, true, true, true, true, true, //HIJKLMNO
414 true, true, true, true, true, true, true, true, //PQRSTUVW
415 true, true, true, false, false, false, true, true, //XYZ[\]^_
416 true, true, true, true, true, true, true, true, //`abcdefg
417 true, true, true, true, true, true, true, true, //hijklmno
418 true, true, true, true, true, true, true, true, //pqrstuvw
419 true, true, true, true, true, true, true, false //xyz{|}~
421 return rtl::isAscii(nChar
) && aMap
[nChar
];
425 bool INetMIME::isIMAPAtomChar(sal_uInt32 nChar
)
427 static const bool aMap
[128]
428 = { false, false, false, false, false, false, false, false,
429 false, false, false, false, false, false, false, false,
430 false, false, false, false, false, false, false, false,
431 false, false, false, false, false, false, false, false,
432 false, true, false, true, true, false, true, true, // !"#$%&'
433 false, false, false, true, true, true, true, true, //()*+,-./
434 true, true, true, true, true, true, true, true, //01234567
435 true, true, true, true, true, true, true, true, //89:;<=>?
436 true, true, true, true, true, true, true, true, //@ABCDEFG
437 true, true, true, true, true, true, true, true, //HIJKLMNO
438 true, true, true, true, true, true, true, true, //PQRSTUVW
439 true, true, true, true, false, true, true, true, //XYZ[\]^_
440 true, true, true, true, true, true, true, true, //`abcdefg
441 true, true, true, true, true, true, true, true, //hijklmno
442 true, true, true, true, true, true, true, true, //pqrstuvw
443 true, true, true, false, true, true, true, false //xyz{|}~
445 return rtl::isAscii(nChar
) && aMap
[nChar
];
449 sal_uInt32
INetMIME::getHexDigit(int nWeight
)
451 DBG_ASSERT(nWeight
>= 0 && nWeight
< 16,
452 "INetMIME::getHexDigit(): Bad weight");
454 static const sal_Char aDigits
[16]
455 = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
457 return aDigits
[nWeight
];
461 bool INetMIME::equalIgnoreCase(const sal_Char
* pBegin1
,
462 const sal_Char
* pEnd1
,
463 const sal_Char
* pString2
)
465 DBG_ASSERT(pBegin1
&& pBegin1
<= pEnd1
&& pString2
,
466 "INetMIME::equalIgnoreCase(): Bad sequences");
468 while (*pString2
!= 0)
470 || rtl::toAsciiUpperCase(*pBegin1
++) != rtl::toAsciiUpperCase(*pString2
++))
472 return pBegin1
== pEnd1
;
476 bool INetMIME::equalIgnoreCase(const sal_Unicode
* pBegin1
,
477 const sal_Unicode
* pEnd1
,
478 const sal_Char
* pString2
)
480 DBG_ASSERT(pBegin1
&& pBegin1
<= pEnd1
&& pString2
,
481 "INetMIME::equalIgnoreCase(): Bad sequences");
483 while (*pString2
!= 0)
485 || rtl::toAsciiUpperCase(*pBegin1
++) != rtl::toAsciiUpperCase(*pString2
++))
487 return pBegin1
== pEnd1
;
491 const sal_Unicode
* INetMIME::skipLinearWhiteSpace(const sal_Unicode
* pBegin
,
492 const sal_Unicode
* pEnd
)
494 DBG_ASSERT(pBegin
&& pBegin
<= pEnd
,
495 "INetMIME::skipLinearWhiteSpace(): Bad sequence");
497 while (pBegin
!= pEnd
)
506 if (startsWithLineFolding(pBegin
, pEnd
))
519 const sal_Unicode
* INetMIME::skipComment(const sal_Unicode
* pBegin
,
520 const sal_Unicode
* pEnd
)
522 DBG_ASSERT(pBegin
&& pBegin
<= pEnd
,
523 "INetMIME::skipComment(): Bad sequence");
525 if (pBegin
!= pEnd
&& *pBegin
== '(')
527 sal_uInt32 nLevel
= 0;
528 for (const sal_Unicode
* p
= pBegin
; p
!= pEnd
;)
550 const sal_Unicode
* INetMIME::skipLinearWhiteSpaceComment(const sal_Unicode
*
555 DBG_ASSERT(pBegin
&& pBegin
<= pEnd
,
556 "INetMIME::skipLinearWhiteSpaceComment(): Bad sequence");
558 while (pBegin
!= pEnd
)
567 if (startsWithLineFolding(pBegin
, pEnd
))
575 const sal_Unicode
* p
= skipComment(pBegin
, pEnd
);
589 const sal_Char
* INetMIME::skipQuotedString(const sal_Char
* pBegin
,
590 const sal_Char
* pEnd
)
592 DBG_ASSERT(pBegin
&& pBegin
<= pEnd
,
593 "INetMIME::skipQuotedString(): Bad sequence");
595 if (pBegin
!= pEnd
&& *pBegin
== '"')
596 for (const sal_Char
* p
= pBegin
+ 1; p
!= pEnd
;)
600 if (pEnd
- p
< 2 || *p
++ != 0x0A // LF
601 || !isWhiteSpace(*p
++))
617 const sal_Unicode
* INetMIME::skipQuotedString(const sal_Unicode
* pBegin
,
618 const sal_Unicode
* pEnd
)
620 DBG_ASSERT(pBegin
&& pBegin
<= pEnd
,
621 "INetMIME::skipQuotedString(): Bad sequence");
623 if (pBegin
!= pEnd
&& *pBegin
== '"')
624 for (const sal_Unicode
* p
= pBegin
+ 1; p
!= pEnd
;)
628 if (pEnd
- p
< 2 || *p
++ != 0x0A // LF
629 || !isWhiteSpace(*p
++))
645 bool INetMIME::scanUnsigned(const sal_Unicode
*& rBegin
,
646 const sal_Unicode
* pEnd
, bool bLeadingZeroes
,
649 sal_uInt64 nTheValue
= 0;
650 const sal_Unicode
* p
= rBegin
;
651 for ( ; p
!= pEnd
; ++p
)
653 int nWeight
= getWeight(*p
);
656 nTheValue
= 10 * nTheValue
+ nWeight
;
657 if (nTheValue
> std::numeric_limits
< sal_uInt32
>::max())
660 if (nTheValue
== 0 && (p
== rBegin
|| (!bLeadingZeroes
&& p
- rBegin
!= 1)))
663 rValue
= sal_uInt32(nTheValue
);
668 const sal_Unicode
* INetMIME::scanQuotedBlock(const sal_Unicode
* pBegin
,
669 const sal_Unicode
* pEnd
,
675 DBG_ASSERT(pBegin
&& pBegin
<= pEnd
,
676 "INetMIME::scanQuotedBlock(): Bad sequence");
678 if (pBegin
!= pEnd
&& *pBegin
== nOpening
)
682 while (pBegin
!= pEnd
)
683 if (*pBegin
== nClosing
)
690 sal_uInt32 c
= *pBegin
++;
694 if (pBegin
!= pEnd
&& *pBegin
== 0x0A) // LF
695 if (pEnd
- pBegin
>= 2 && isWhiteSpace(pBegin
[1]))
715 if (startsWithLineBreak(pBegin
, pEnd
)
716 && (pEnd
- pBegin
< 3
717 || !isWhiteSpace(pBegin
[2])))
730 if (!rtl::isAscii(c
))
740 sal_Unicode
const * INetMIME::scanParameters(sal_Unicode
const * pBegin
,
741 sal_Unicode
const * pEnd
,
742 INetContentTypeParameterList
*
746 sal_Unicode
const * pParameterBegin
= pBegin
;
747 for (sal_Unicode
const * p
= pParameterBegin
;; pParameterBegin
= p
)
749 pParameterBegin
= skipLinearWhiteSpaceComment(p
, pEnd
);
750 if (pParameterBegin
== pEnd
|| *pParameterBegin
!= ';')
752 p
= pParameterBegin
+ 1;
754 sal_Unicode
const * pAttributeBegin
755 = skipLinearWhiteSpaceComment(p
, pEnd
);
757 bool bDowncaseAttribute
= false;
758 while (p
!= pEnd
&& isTokenChar(*p
) && *p
!= '*')
760 bDowncaseAttribute
= bDowncaseAttribute
|| rtl::isAsciiUpperCase(*p
);
763 if (p
== pAttributeBegin
)
765 OString aAttribute
= OString(
766 pAttributeBegin
, p
- pAttributeBegin
,
767 RTL_TEXTENCODING_ASCII_US
);
768 if (bDowncaseAttribute
)
769 aAttribute
= aAttribute
.toAsciiLowerCase();
771 sal_uInt32 nSection
= 0;
772 if (p
!= pEnd
&& *p
== '*')
775 if (p
!= pEnd
&& rtl::isAsciiDigit(*p
)
776 && !scanUnsigned(p
, pEnd
, false, nSection
))
781 Parameter
** pPos
= aList
.find(aAttribute
, nSection
, bPresent
);
785 bool bExtended
= false;
786 if (p
!= pEnd
&& *p
== '*')
792 p
= skipLinearWhiteSpaceComment(p
, pEnd
);
794 if (p
== pEnd
|| *p
!= '=')
797 p
= skipLinearWhiteSpaceComment(p
+ 1, pEnd
);
806 sal_Unicode
const * pCharsetBegin
= p
;
807 bool bDowncaseCharset
= false;
808 while (p
!= pEnd
&& isTokenChar(*p
) && *p
!= '\'')
810 bDowncaseCharset
= bDowncaseCharset
|| rtl::isAsciiUpperCase(*p
);
813 if (p
== pCharsetBegin
)
820 RTL_TEXTENCODING_ASCII_US
);
821 if (bDowncaseCharset
)
822 aCharset
= aCharset
.toAsciiLowerCase();
825 if (p
== pEnd
|| *p
!= '\'')
829 sal_Unicode
const * pLanguageBegin
= p
;
830 bool bDowncaseLanguage
= false;
832 for (; p
!= pEnd
; ++p
)
833 if (rtl::isAsciiAlpha(*p
))
837 bDowncaseLanguage
= bDowncaseLanguage
838 || rtl::isAsciiUpperCase(*p
);
848 if (nLetters
== 0 || nLetters
> 8)
855 RTL_TEXTENCODING_ASCII_US
);
856 if (bDowncaseLanguage
)
857 aLanguage
= aLanguage
.toAsciiLowerCase();
860 if (p
== pEnd
|| *p
!= '\'')
866 INetMIMEStringOutputSink
867 aSink(0, INetMIMEOutputSink::NO_LINE_LENGTH_LIMIT
);
870 sal_uInt32 nChar
= INetMIME::getUTF32Character(p
, pEnd
);
871 if (rtl::isAscii(nChar
) && !isTokenChar(nChar
))
873 if (nChar
== '%' && p
+ 1 < pEnd
)
875 int nWeight1
= getHexWeight(p
[0]);
876 int nWeight2
= getHexWeight(p
[1]);
877 if (nWeight1
>= 0 && nWeight2
>= 0)
879 aSink
<< sal_Char(nWeight1
<< 4 | nWeight2
);
884 INetMIME::writeUTF8(aSink
, nChar
);
886 aValue
= aSink
.takeBuffer();
889 while (p
!= pEnd
&& (isTokenChar(*p
) || !rtl::isAscii(*p
)))
892 else if (p
!= pEnd
&& *p
== '"')
895 INetMIMEStringOutputSink
896 aSink(0, INetMIMEOutputSink::NO_LINE_LENGTH_LIMIT
);
897 bool bInvalid
= false;
905 sal_uInt32 nChar
= INetMIME::getUTF32Character(p
, pEnd
);
908 else if (nChar
== 0x0D) // CR
910 if (pEnd
- p
< 2 || *p
++ != 0x0A // LF
911 || !isWhiteSpace(*p
))
916 nChar
= static_cast<unsigned char>(*p
++);
918 else if (nChar
== '\\')
925 nChar
= INetMIME::getUTF32Character(p
, pEnd
);
927 INetMIME::writeUTF8(aSink
, nChar
);
931 aValue
= aSink
.takeBuffer();
935 sal_Unicode
const * pStringEnd
= skipQuotedString(p
, pEnd
);
942 sal_Unicode
const * pTokenBegin
= p
;
943 while (p
!= pEnd
&& (isTokenChar(*p
) || !rtl::isAscii(*p
)))
945 if (p
== pTokenBegin
)
949 pTokenBegin
, p
- pTokenBegin
,
950 RTL_TEXTENCODING_UTF8
);
953 *pPos
= new Parameter(*pPos
, aAttribute
, aCharset
, aLanguage
, aValue
,
954 nSection
, bExtended
);
956 return parseParameters(aList
, pParameters
) ? pParameterBegin
: pBegin
;
960 sal_Unicode
const * INetMIME::scanContentType(
961 sal_Unicode
const * pBegin
, sal_Unicode
const * pEnd
, OUString
* pType
,
962 OUString
* pSubType
, INetContentTypeParameterList
* pParameters
)
964 sal_Unicode
const * p
= INetMIME::skipLinearWhiteSpaceComment(pBegin
, pEnd
);
965 sal_Unicode
const * pTypeBegin
= p
;
966 while (p
!= pEnd
&& INetMIME::isTokenChar(*p
))
972 sal_Unicode
const * pTypeEnd
= p
;
974 p
= INetMIME::skipLinearWhiteSpaceComment(p
, pEnd
);
975 if (p
== pEnd
|| *p
++ != '/')
978 p
= INetMIME::skipLinearWhiteSpaceComment(p
, pEnd
);
979 sal_Unicode
const * pSubTypeBegin
= p
;
980 while (p
!= pEnd
&& INetMIME::isTokenChar(*p
))
984 if (p
== pSubTypeBegin
)
986 sal_Unicode
const * pSubTypeEnd
= p
;
990 *pType
= OUString(pTypeBegin
, pTypeEnd
- pTypeBegin
).toAsciiLowerCase();
994 *pSubType
= OUString(pSubTypeBegin
, pSubTypeEnd
- pSubTypeBegin
)
998 return INetMIME::scanParameters(p
, pEnd
, pParameters
);
1002 const sal_Char
* INetMIME::getCharsetName(rtl_TextEncoding eEncoding
)
1004 if (rtl_isOctetTextEncoding(eEncoding
))
1006 char const * p
= rtl_getMimeCharsetFromTextEncoding(eEncoding
);
1007 DBG_ASSERT(p
, "INetMIME::getCharsetName(): Unsupported encoding");
1013 case RTL_TEXTENCODING_UCS4
:
1014 return "ISO-10646-UCS-4";
1016 case RTL_TEXTENCODING_UCS2
:
1017 return "ISO-10646-UCS-2";
1020 OSL_FAIL("INetMIME::getCharsetName(): Unsupported encoding");
1025 namespace unnamed_tools_inetmime
{
1027 struct EncodingEntry
1029 sal_Char
const * m_aName
;
1030 rtl_TextEncoding m_eEncoding
;
1033 // The source for the following table is <ftp://ftp.iana.org/in-notes/iana/
1034 // assignments/character-sets> as of Jan, 21 2000 12:46:00, unless otherwise
1036 EncodingEntry
const aEncodingMap
[]
1037 = { { "US-ASCII", RTL_TEXTENCODING_ASCII_US
},
1038 { "ANSI_X3.4-1968", RTL_TEXTENCODING_ASCII_US
},
1039 { "ISO-IR-6", RTL_TEXTENCODING_ASCII_US
},
1040 { "ANSI_X3.4-1986", RTL_TEXTENCODING_ASCII_US
},
1041 { "ISO_646.IRV:1991", RTL_TEXTENCODING_ASCII_US
},
1042 { "ASCII", RTL_TEXTENCODING_ASCII_US
},
1043 { "ISO646-US", RTL_TEXTENCODING_ASCII_US
},
1044 { "US", RTL_TEXTENCODING_ASCII_US
},
1045 { "IBM367", RTL_TEXTENCODING_ASCII_US
},
1046 { "CP367", RTL_TEXTENCODING_ASCII_US
},
1047 { "CSASCII", RTL_TEXTENCODING_ASCII_US
},
1048 { "ISO-8859-1", RTL_TEXTENCODING_ISO_8859_1
},
1049 { "ISO_8859-1:1987", RTL_TEXTENCODING_ISO_8859_1
},
1050 { "ISO-IR-100", RTL_TEXTENCODING_ISO_8859_1
},
1051 { "ISO_8859-1", RTL_TEXTENCODING_ISO_8859_1
},
1052 { "LATIN1", RTL_TEXTENCODING_ISO_8859_1
},
1053 { "L1", RTL_TEXTENCODING_ISO_8859_1
},
1054 { "IBM819", RTL_TEXTENCODING_ISO_8859_1
},
1055 { "CP819", RTL_TEXTENCODING_ISO_8859_1
},
1056 { "CSISOLATIN1", RTL_TEXTENCODING_ISO_8859_1
},
1057 { "ISO-8859-2", RTL_TEXTENCODING_ISO_8859_2
},
1058 { "ISO_8859-2:1987", RTL_TEXTENCODING_ISO_8859_2
},
1059 { "ISO-IR-101", RTL_TEXTENCODING_ISO_8859_2
},
1060 { "ISO_8859-2", RTL_TEXTENCODING_ISO_8859_2
},
1061 { "LATIN2", RTL_TEXTENCODING_ISO_8859_2
},
1062 { "L2", RTL_TEXTENCODING_ISO_8859_2
},
1063 { "CSISOLATIN2", RTL_TEXTENCODING_ISO_8859_2
},
1064 { "ISO-8859-3", RTL_TEXTENCODING_ISO_8859_3
},
1065 { "ISO_8859-3:1988", RTL_TEXTENCODING_ISO_8859_3
},
1066 { "ISO-IR-109", RTL_TEXTENCODING_ISO_8859_3
},
1067 { "ISO_8859-3", RTL_TEXTENCODING_ISO_8859_3
},
1068 { "LATIN3", RTL_TEXTENCODING_ISO_8859_3
},
1069 { "L3", RTL_TEXTENCODING_ISO_8859_3
},
1070 { "CSISOLATIN3", RTL_TEXTENCODING_ISO_8859_3
},
1071 { "ISO-8859-4", RTL_TEXTENCODING_ISO_8859_4
},
1072 { "ISO_8859-4:1988", RTL_TEXTENCODING_ISO_8859_4
},
1073 { "ISO-IR-110", RTL_TEXTENCODING_ISO_8859_4
},
1074 { "ISO_8859-4", RTL_TEXTENCODING_ISO_8859_4
},
1075 { "LATIN4", RTL_TEXTENCODING_ISO_8859_4
},
1076 { "L4", RTL_TEXTENCODING_ISO_8859_4
},
1077 { "CSISOLATIN4", RTL_TEXTENCODING_ISO_8859_4
},
1078 { "ISO-8859-5", RTL_TEXTENCODING_ISO_8859_5
},
1079 { "ISO_8859-5:1988", RTL_TEXTENCODING_ISO_8859_5
},
1080 { "ISO-IR-144", RTL_TEXTENCODING_ISO_8859_5
},
1081 { "ISO_8859-5", RTL_TEXTENCODING_ISO_8859_5
},
1082 { "CYRILLIC", RTL_TEXTENCODING_ISO_8859_5
},
1083 { "CSISOLATINCYRILLIC", RTL_TEXTENCODING_ISO_8859_5
},
1084 { "ISO-8859-6", RTL_TEXTENCODING_ISO_8859_6
},
1085 { "ISO_8859-6:1987", RTL_TEXTENCODING_ISO_8859_6
},
1086 { "ISO-IR-127", RTL_TEXTENCODING_ISO_8859_6
},
1087 { "ISO_8859-6", RTL_TEXTENCODING_ISO_8859_6
},
1088 { "ECMA-114", RTL_TEXTENCODING_ISO_8859_6
},
1089 { "ASMO-708", RTL_TEXTENCODING_ISO_8859_6
},
1090 { "ARABIC", RTL_TEXTENCODING_ISO_8859_6
},
1091 { "CSISOLATINARABIC", RTL_TEXTENCODING_ISO_8859_6
},
1092 { "ISO-8859-7", RTL_TEXTENCODING_ISO_8859_7
},
1093 { "ISO_8859-7:1987", RTL_TEXTENCODING_ISO_8859_7
},
1094 { "ISO-IR-126", RTL_TEXTENCODING_ISO_8859_7
},
1095 { "ISO_8859-7", RTL_TEXTENCODING_ISO_8859_7
},
1096 { "ELOT_928", RTL_TEXTENCODING_ISO_8859_7
},
1097 { "ECMA-118", RTL_TEXTENCODING_ISO_8859_7
},
1098 { "GREEK", RTL_TEXTENCODING_ISO_8859_7
},
1099 { "GREEK8", RTL_TEXTENCODING_ISO_8859_7
},
1100 { "CSISOLATINGREEK", RTL_TEXTENCODING_ISO_8859_7
},
1101 { "ISO-8859-8", RTL_TEXTENCODING_ISO_8859_8
},
1102 { "ISO_8859-8:1988", RTL_TEXTENCODING_ISO_8859_8
},
1103 { "ISO-IR-138", RTL_TEXTENCODING_ISO_8859_8
},
1104 { "ISO_8859-8", RTL_TEXTENCODING_ISO_8859_8
},
1105 { "HEBREW", RTL_TEXTENCODING_ISO_8859_8
},
1106 { "CSISOLATINHEBREW", RTL_TEXTENCODING_ISO_8859_8
},
1107 { "ISO-8859-9", RTL_TEXTENCODING_ISO_8859_9
},
1108 { "ISO_8859-9:1989", RTL_TEXTENCODING_ISO_8859_9
},
1109 { "ISO-IR-148", RTL_TEXTENCODING_ISO_8859_9
},
1110 { "ISO_8859-9", RTL_TEXTENCODING_ISO_8859_9
},
1111 { "LATIN5", RTL_TEXTENCODING_ISO_8859_9
},
1112 { "L5", RTL_TEXTENCODING_ISO_8859_9
},
1113 { "CSISOLATIN5", RTL_TEXTENCODING_ISO_8859_9
},
1114 { "ISO-8859-14", RTL_TEXTENCODING_ISO_8859_14
}, // RFC 2047
1115 { "ISO_8859-15", RTL_TEXTENCODING_ISO_8859_15
},
1116 { "ISO-8859-15", RTL_TEXTENCODING_ISO_8859_15
}, // RFC 2047
1117 { "MACINTOSH", RTL_TEXTENCODING_APPLE_ROMAN
},
1118 { "MAC", RTL_TEXTENCODING_APPLE_ROMAN
},
1119 { "CSMACINTOSH", RTL_TEXTENCODING_APPLE_ROMAN
},
1120 { "IBM437", RTL_TEXTENCODING_IBM_437
},
1121 { "CP437", RTL_TEXTENCODING_IBM_437
},
1122 { "437", RTL_TEXTENCODING_IBM_437
},
1123 { "CSPC8CODEPAGE437", RTL_TEXTENCODING_IBM_437
},
1124 { "IBM850", RTL_TEXTENCODING_IBM_850
},
1125 { "CP850", RTL_TEXTENCODING_IBM_850
},
1126 { "850", RTL_TEXTENCODING_IBM_850
},
1127 { "CSPC850MULTILINGUAL", RTL_TEXTENCODING_IBM_850
},
1128 { "IBM860", RTL_TEXTENCODING_IBM_860
},
1129 { "CP860", RTL_TEXTENCODING_IBM_860
},
1130 { "860", RTL_TEXTENCODING_IBM_860
},
1131 { "CSIBM860", RTL_TEXTENCODING_IBM_860
},
1132 { "IBM861", RTL_TEXTENCODING_IBM_861
},
1133 { "CP861", RTL_TEXTENCODING_IBM_861
},
1134 { "861", RTL_TEXTENCODING_IBM_861
},
1135 { "CP-IS", RTL_TEXTENCODING_IBM_861
},
1136 { "CSIBM861", RTL_TEXTENCODING_IBM_861
},
1137 { "IBM863", RTL_TEXTENCODING_IBM_863
},
1138 { "CP863", RTL_TEXTENCODING_IBM_863
},
1139 { "863", RTL_TEXTENCODING_IBM_863
},
1140 { "CSIBM863", RTL_TEXTENCODING_IBM_863
},
1141 { "IBM865", RTL_TEXTENCODING_IBM_865
},
1142 { "CP865", RTL_TEXTENCODING_IBM_865
},
1143 { "865", RTL_TEXTENCODING_IBM_865
},
1144 { "CSIBM865", RTL_TEXTENCODING_IBM_865
},
1145 { "IBM775", RTL_TEXTENCODING_IBM_775
},
1146 { "CP775", RTL_TEXTENCODING_IBM_775
},
1147 { "CSPC775BALTIC", RTL_TEXTENCODING_IBM_775
},
1148 { "IBM852", RTL_TEXTENCODING_IBM_852
},
1149 { "CP852", RTL_TEXTENCODING_IBM_852
},
1150 { "852", RTL_TEXTENCODING_IBM_852
},
1151 { "CSPCP852", RTL_TEXTENCODING_IBM_852
},
1152 { "IBM855", RTL_TEXTENCODING_IBM_855
},
1153 { "CP855", RTL_TEXTENCODING_IBM_855
},
1154 { "855", RTL_TEXTENCODING_IBM_855
},
1155 { "CSIBM855", RTL_TEXTENCODING_IBM_855
},
1156 { "IBM857", RTL_TEXTENCODING_IBM_857
},
1157 { "CP857", RTL_TEXTENCODING_IBM_857
},
1158 { "857", RTL_TEXTENCODING_IBM_857
},
1159 { "CSIBM857", RTL_TEXTENCODING_IBM_857
},
1160 { "IBM862", RTL_TEXTENCODING_IBM_862
},
1161 { "CP862", RTL_TEXTENCODING_IBM_862
},
1162 { "862", RTL_TEXTENCODING_IBM_862
},
1163 { "CSPC862LATINHEBREW", RTL_TEXTENCODING_IBM_862
},
1164 { "IBM864", RTL_TEXTENCODING_IBM_864
},
1165 { "CP864", RTL_TEXTENCODING_IBM_864
},
1166 { "CSIBM864", RTL_TEXTENCODING_IBM_864
},
1167 { "IBM866", RTL_TEXTENCODING_IBM_866
},
1168 { "CP866", RTL_TEXTENCODING_IBM_866
},
1169 { "866", RTL_TEXTENCODING_IBM_866
},
1170 { "CSIBM866", RTL_TEXTENCODING_IBM_866
},
1171 { "IBM869", RTL_TEXTENCODING_IBM_869
},
1172 { "CP869", RTL_TEXTENCODING_IBM_869
},
1173 { "869", RTL_TEXTENCODING_IBM_869
},
1174 { "CP-GR", RTL_TEXTENCODING_IBM_869
},
1175 { "CSIBM869", RTL_TEXTENCODING_IBM_869
},
1176 { "WINDOWS-1250", RTL_TEXTENCODING_MS_1250
},
1177 { "WINDOWS-1251", RTL_TEXTENCODING_MS_1251
},
1178 { "WINDOWS-1253", RTL_TEXTENCODING_MS_1253
},
1179 { "WINDOWS-1254", RTL_TEXTENCODING_MS_1254
},
1180 { "WINDOWS-1255", RTL_TEXTENCODING_MS_1255
},
1181 { "WINDOWS-1256", RTL_TEXTENCODING_MS_1256
},
1182 { "WINDOWS-1257", RTL_TEXTENCODING_MS_1257
},
1183 { "WINDOWS-1258", RTL_TEXTENCODING_MS_1258
},
1184 { "SHIFT_JIS", RTL_TEXTENCODING_SHIFT_JIS
},
1185 { "MS_KANJI", RTL_TEXTENCODING_SHIFT_JIS
},
1186 { "CSSHIFTJIS", RTL_TEXTENCODING_SHIFT_JIS
},
1187 { "GB2312", RTL_TEXTENCODING_GB_2312
},
1188 { "CSGB2312", RTL_TEXTENCODING_GB_2312
},
1189 { "BIG5", RTL_TEXTENCODING_BIG5
},
1190 { "CSBIG5", RTL_TEXTENCODING_BIG5
},
1191 { "EUC-JP", RTL_TEXTENCODING_EUC_JP
},
1192 { "EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE",
1193 RTL_TEXTENCODING_EUC_JP
},
1194 { "CSEUCPKDFMTJAPANESE", RTL_TEXTENCODING_EUC_JP
},
1195 { "ISO-2022-JP", RTL_TEXTENCODING_ISO_2022_JP
},
1196 { "CSISO2022JP", RTL_TEXTENCODING_ISO_2022_JP
},
1197 { "ISO-2022-CN", RTL_TEXTENCODING_ISO_2022_CN
},
1198 { "KOI8-R", RTL_TEXTENCODING_KOI8_R
},
1199 { "CSKOI8R", RTL_TEXTENCODING_KOI8_R
},
1200 { "UTF-7", RTL_TEXTENCODING_UTF7
},
1201 { "UTF-8", RTL_TEXTENCODING_UTF8
},
1202 { "ISO-8859-10", RTL_TEXTENCODING_ISO_8859_10
}, // RFC 2047
1203 { "ISO-8859-13", RTL_TEXTENCODING_ISO_8859_13
}, // RFC 2047
1204 { "EUC-KR", RTL_TEXTENCODING_EUC_KR
},
1205 { "CSEUCKR", RTL_TEXTENCODING_EUC_KR
},
1206 { "ISO-2022-KR", RTL_TEXTENCODING_ISO_2022_KR
},
1207 { "CSISO2022KR", RTL_TEXTENCODING_ISO_2022_KR
},
1208 { "ISO-10646-UCS-4", RTL_TEXTENCODING_UCS4
},
1209 { "CSUCS4", RTL_TEXTENCODING_UCS4
},
1210 { "ISO-10646-UCS-2", RTL_TEXTENCODING_UCS2
},
1211 { "CSUNICODE", RTL_TEXTENCODING_UCS2
} };
1213 template< typename T
>
1214 inline rtl_TextEncoding
getCharsetEncoding_Impl(T
const * pBegin
,
1217 for (sal_Size i
= 0; i
< sizeof aEncodingMap
/ sizeof (EncodingEntry
);
1219 if (INetMIME::equalIgnoreCase(pBegin
, pEnd
, aEncodingMap
[i
].m_aName
))
1220 return aEncodingMap
[i
].m_eEncoding
;
1221 return RTL_TEXTENCODING_DONTKNOW
;
1227 rtl_TextEncoding
INetMIME::getCharsetEncoding(sal_Char
const * pBegin
,
1228 sal_Char
const * pEnd
)
1230 return getCharsetEncoding_Impl(pBegin
, pEnd
);
1234 INetMIMECharsetList_Impl
*
1235 INetMIME::createPreferredCharsetList(rtl_TextEncoding eEncoding
)
1237 static const sal_uInt32 aUSASCIIRanges
[] = { 0, 0x7F, sal_uInt32(-1) };
1239 static const sal_uInt32 aISO88591Ranges
[] = { 0, 0xFF, sal_uInt32(-1) };
1240 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-1.TXT> version
1241 // 1.0 of 1999 July 27
1243 static const sal_uInt32 aISO88592Ranges
[]
1244 = { 0, 0xA0, 0xA4, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xB0, 0xB0,
1245 0xB4, 0xB4, 0xB8, 0xB8, 0xC1, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7,
1246 0xC9, 0xC9, 0xCB, 0xCB, 0xCD, 0xCE, 0xD3, 0xD4, 0xD6, 0xD7,
1247 0xDA, 0xDA, 0xDC, 0xDD, 0xDF, 0xDF, 0xE1, 0xE2, 0xE4, 0xE4,
1248 0xE7, 0xE7, 0xE9, 0xE9, 0xEB, 0xEB, 0xED, 0xEE, 0xF3, 0xF4,
1249 0xF6, 0xF7, 0xFA, 0xFA, 0xFC, 0xFD, 0x102, 0x107, 0x10C, 0x111,
1250 0x118, 0x11B, 0x139, 0x13A, 0x13D, 0x13E, 0x141, 0x144,
1251 0x147, 0x148, 0x150, 0x151, 0x154, 0x155, 0x158, 0x15B,
1252 0x15E, 0x165, 0x16E, 0x171, 0x179, 0x17E, 0x2C7, 0x2C7,
1253 0x2D8, 0x2D9, 0x2DB, 0x2DB, 0x2DD, 0x2DD, sal_uInt32(-1) };
1254 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-2.TXT> version
1255 // 1.0 of 1999 July 27
1257 static const sal_uInt32 aISO88593Ranges
[]
1258 = { 0, 0xA0, 0xA3, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xB0, 0xB0,
1259 0xB2, 0xB5, 0xB7, 0xB8, 0xBD, 0xBD, 0xC0, 0xC2, 0xC4, 0xC4,
1260 0xC7, 0xCF, 0xD1, 0xD4, 0xD6, 0xD7, 0xD9, 0xDC, 0xDF, 0xE2,
1261 0xE4, 0xE4, 0xE7, 0xEF, 0xF1, 0xF4, 0xF6, 0xF7, 0xF9, 0xFC,
1262 0x108, 0x10B, 0x11C, 0x121, 0x124, 0x127, 0x130, 0x131,
1263 0x134, 0x135, 0x15C, 0x15F, 0x16C, 0x16D, 0x17B, 0x17C,
1264 0x2D8, 0x2D9, sal_uInt32(-1) };
1265 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-3.TXT> version
1266 // 1.0 of 1999 July 27
1268 static const sal_uInt32 aISO88594Ranges
[]
1269 = { 0, 0xA0, 0xA4, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xAF, 0xB0,
1270 0xB4, 0xB4, 0xB8, 0xB8, 0xC1, 0xC6, 0xC9, 0xC9, 0xCB, 0xCB,
1271 0xCD, 0xCE, 0xD4, 0xD8, 0xDA, 0xDC, 0xDF, 0xDF, 0xE1, 0xE6,
1272 0xE9, 0xE9, 0xEB, 0xEB, 0xED, 0xEE, 0xF4, 0xF8, 0xFA, 0xFC,
1273 0x100, 0x101, 0x104, 0x105, 0x10C, 0x10D, 0x110, 0x113,
1274 0x116, 0x119, 0x122, 0x123, 0x128, 0x12B, 0x12E, 0x12F,
1275 0x136, 0x138, 0x13B, 0x13C, 0x145, 0x146, 0x14A, 0x14D,
1276 0x156, 0x157, 0x160, 0x161, 0x166, 0x16B, 0x172, 0x173,
1277 0x17D, 0x17E, 0x2C7, 0x2C7, 0x2D9, 0x2D9, 0x2DB, 0x2DB,
1279 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-4.TXT> version
1280 // 1.0 of 1999 July 27
1282 static const sal_uInt32 aISO88595Ranges
[]
1283 = { 0, 0xA0, 0xA7, 0xA7, 0xAD, 0xAD, 0x401, 0x40C, 0x40E, 0x44F,
1284 0x451, 0x45C, 0x45E, 0x45F, 0x2116, 0x2116, sal_uInt32(-1) };
1285 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-5.TXT> version
1286 // 1.0 of 1999 July 27
1288 static const sal_uInt32 aISO88596Ranges
[]
1289 = { 0, 0xA0, 0xA4, 0xA4, 0xAD, 0xAD, 0x60C, 0x60C, 0x61B, 0x61B,
1290 0x61F, 0x61F, 0x621, 0x63A, 0x640, 0x652, sal_uInt32(-1) };
1291 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-6.TXT> version
1292 // 1.0 of 1999 July 27
1294 static const sal_uInt32 aISO88597Ranges
[]
1295 = { 0, 0xA0, 0xA3, 0xA3, 0xA6, 0xA9, 0xAB, 0xAD, 0xB0, 0xB3,
1296 0xB7, 0xB7, 0xBB, 0xBB, 0xBD, 0xBD, 0x384, 0x386, 0x388, 0x38A,
1297 0x38C, 0x38C, 0x38E, 0x3A1, 0x3A3, 0x3CE, 0x2015, 0x2015,
1298 0x2018, 0x2019, sal_uInt32(-1) };
1299 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-7.TXT> version
1300 // 1.0 of 1999 July 27
1302 static const sal_uInt32 aISO88598Ranges
[]
1303 = { 0, 0xA0, 0xA2, 0xA9, 0xAB, 0xB9, 0xBB, 0xBE, 0xD7, 0xD7,
1304 0xF7, 0xF7, 0x5D0, 0x5EA, 0x200E, 0x200F, 0x2017, 0x2017,
1306 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-8.TXT> version
1307 // 1.1 of 2000-Jan-03
1309 static const sal_uInt32 aISO88599Ranges
[]
1310 = { 0, 0xCF, 0xD1, 0xDC, 0xDF, 0xEF, 0xF1, 0xFC, 0xFF, 0xFF,
1311 0x11E, 0x11F, 0x130, 0x131, 0x15E, 0x15F, sal_uInt32(-1) };
1312 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-9.TXT> version
1313 // 1.0 of 1999 July 27
1315 static const sal_uInt32 aISO885910Ranges
[]
1316 = { 0, 0xA0, 0xA7, 0xA7, 0xAD, 0xAD, 0xB0, 0xB0, 0xB7, 0xB7,
1317 0xC1, 0xC6, 0xC9, 0xC9, 0xCB, 0xCB, 0xCD, 0xD0, 0xD3, 0xD6,
1318 0xD8, 0xD8, 0xDA, 0xDF, 0xE1, 0xE6, 0xE9, 0xE9, 0xEB, 0xEB,
1319 0xED, 0xF0, 0xF3, 0xF6, 0xF8, 0xF8, 0xFA, 0xFE, 0x100, 0x101,
1320 0x104, 0x105, 0x10C, 0x10D, 0x110, 0x113, 0x116, 0x119,
1321 0x122, 0x123, 0x128, 0x12B, 0x12E, 0x12F, 0x136, 0x138,
1322 0x13B, 0x13C, 0x145, 0x146, 0x14A, 0x14D, 0x160, 0x161,
1323 0x166, 0x16B, 0x172, 0x173, 0x17D, 0x17E, 0x2015, 0x2015,
1325 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-10.TXT> version
1326 // 1.1 of 1999 October 11
1328 static const sal_uInt32 aISO885913Ranges
[]
1329 = { 0, 0xA0, 0xA2, 0xA4, 0xA6, 0xA7, 0xA9, 0xA9, 0xAB, 0xAE,
1330 0xB0, 0xB3, 0xB5, 0xB7, 0xB9, 0xB9, 0xBB, 0xBE, 0xC4, 0xC6,
1331 0xC9, 0xC9, 0xD3, 0xD3, 0xD5, 0xD8, 0xDC, 0xDC, 0xDF, 0xDF,
1332 0xE4, 0xE6, 0xE9, 0xE9, 0xF3, 0xF3, 0xF5, 0xF8, 0xFC, 0xFC,
1333 0x100, 0x101, 0x104, 0x107, 0x10C, 0x10D, 0x112, 0x113,
1334 0x116, 0x119, 0x122, 0x123, 0x12A, 0x12B, 0x12E, 0x12F,
1335 0x136, 0x137, 0x13B, 0x13C, 0x141, 0x146, 0x14C, 0x14D,
1336 0x156, 0x157, 0x15A, 0x15B, 0x160, 0x161, 0x16A, 0x16B,
1337 0x172, 0x173, 0x179, 0x17E, 0x2019, 0x2019, 0x201C, 0x201E,
1339 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-13.TXT> version
1340 // 1.0 of 1999 July 27
1342 static const sal_uInt32 aISO885914Ranges
[]
1343 = { 0, 0xA0, 0xA3, 0xA3, 0xA7, 0xA7, 0xA9, 0xA9, 0xAD, 0xAE,
1344 0xB6, 0xB6, 0xC0, 0xCF, 0xD1, 0xD6, 0xD8, 0xDD, 0xDF, 0xEF,
1345 0xF1, 0xF6, 0xF8, 0xFD, 0xFF, 0xFF, 0x10A, 0x10B, 0x120, 0x121,
1346 0x174, 0x178, 0x1E02, 0x1E03, 0x1E0A, 0x1E0B, 0x1E1E, 0x1E1F,
1347 0x1E40, 0x1E41, 0x1E56, 0x1E57, 0x1E60, 0x1E61, 0x1E6A, 0x1E6B,
1348 0x1E80, 0x1E85, 0x1EF2, 0x1EF3, sal_uInt32(-1) };
1349 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-14.TXT> version
1350 // 1.0 of 1999 July 27
1352 static const sal_uInt32 aISO885915Ranges
[]
1353 = { 0, 0xA3, 0xA5, 0xA5, 0xA7, 0xA7, 0xA9, 0xB3, 0xB5, 0xB7,
1354 0xB9, 0xBB, 0xBF, 0xFF, 0x152, 0x153, 0x160, 0x161, 0x178, 0x178,
1355 0x17D, 0x17E, 0x20AC, 0x20AC, sal_uInt32(-1) };
1356 // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-15.TXT> version
1357 // 1.0 of 1999 July 27
1359 static const sal_uInt32 aKOI8RRanges
[]
1360 = { 0, 0x7F, 0xA0, 0xA0, 0xA9, 0xA9, 0xB0, 0xB0, 0xB2, 0xB2,
1361 0xB7, 0xB7, 0xF7, 0xF7, 0x401, 0x401, 0x410, 0x44F, 0x451, 0x451,
1362 0x2219, 0x221A, 0x2248, 0x2248, 0x2264, 0x2265, 0x2320, 0x2321,
1363 0x2500, 0x2500, 0x2502, 0x2502, 0x250C, 0x250C, 0x2510, 0x2510,
1364 0x2514, 0x2514, 0x2518, 0x2518, 0x251C, 0x251C, 0x2524, 0x2524,
1365 0x252C, 0x252C, 0x2534, 0x2534, 0x253C, 0x253C, 0x2550, 0x256C,
1366 0x2580, 0x2580, 0x2584, 0x2584, 0x2588, 0x2588, 0x258C, 0x258C,
1367 0x2590, 0x2593, 0x25A0, 0x25A0, sal_uInt32(-1) };
1368 // <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MISC/KOI8-R.TXT>
1369 // version 1.0 of 18 August 1999
1372 static const sal_uInt32 aWindows1252Ranges
[]
1373 = { 0, 0x7F, 0xA0, 0xFF, 0x152, 0x153, 0x160, 0x161, 0x178, 0x178,
1374 0x17D, 0x17E, 0x192, 0x192, 0x2C6, 0x2C6, 0x2DC, 0x2DC,
1375 0x2013, 0x2014, 0x2018, 0x201A, 0x201C, 0x201E, 0x2020, 0x2022,
1376 0x2026, 0x2026, 0x2030, 0x2030, 0x2039, 0x203A, 0x20AC, 0x20AC,
1377 0x2122, 0x2122, sal_uInt32(-1) };
1378 // <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/
1379 // CP1252.TXT> version 2.01 of 04/15/98
1382 INetMIMECharsetList_Impl
* pList
= new INetMIMECharsetList_Impl
;
1385 case RTL_TEXTENCODING_MS_1252
:
1387 pList
->prepend(Charset(RTL_TEXTENCODING_MS_1252
,
1388 aWindows1252Ranges
));
1390 case RTL_TEXTENCODING_ISO_8859_1
:
1391 case RTL_TEXTENCODING_UTF7
:
1392 case RTL_TEXTENCODING_UTF8
:
1395 case RTL_TEXTENCODING_ISO_8859_2
:
1396 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_2
,
1400 case RTL_TEXTENCODING_ISO_8859_3
:
1401 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_3
,
1405 case RTL_TEXTENCODING_ISO_8859_4
:
1406 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_4
,
1410 case RTL_TEXTENCODING_ISO_8859_5
:
1411 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5
,
1415 case RTL_TEXTENCODING_ISO_8859_6
:
1416 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_6
,
1420 case RTL_TEXTENCODING_ISO_8859_7
:
1421 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_7
,
1425 case RTL_TEXTENCODING_ISO_8859_8
:
1426 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_8
,
1430 case RTL_TEXTENCODING_ISO_8859_9
:
1431 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_9
,
1435 case RTL_TEXTENCODING_ISO_8859_10
:
1436 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_10
,
1440 case RTL_TEXTENCODING_ISO_8859_13
:
1441 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_13
,
1445 case RTL_TEXTENCODING_ISO_8859_14
:
1446 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_14
,
1450 case RTL_TEXTENCODING_ISO_8859_15
:
1451 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_15
,
1455 case RTL_TEXTENCODING_MS_1250
:
1456 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_2
,
1460 case RTL_TEXTENCODING_MS_1251
:
1461 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5
,
1465 case RTL_TEXTENCODING_MS_1253
:
1466 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_7
,
1470 case RTL_TEXTENCODING_MS_1254
:
1471 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_9
,
1475 case RTL_TEXTENCODING_MS_1255
:
1476 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_8
,
1480 case RTL_TEXTENCODING_MS_1256
:
1481 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_6
,
1485 case RTL_TEXTENCODING_MS_1257
:
1486 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_4
,
1490 case RTL_TEXTENCODING_KOI8_R
:
1491 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5
,
1493 pList
->prepend(Charset(RTL_TEXTENCODING_KOI8_R
, aKOI8RRanges
));
1496 default: //@@@ more cases are missing!
1497 OSL_FAIL("INetMIME::createPreferredCharsetList():"
1498 " Unsupported encoding");
1501 pList
->prepend(Charset(RTL_TEXTENCODING_ISO_8859_1
, aISO88591Ranges
));
1502 pList
->prepend(Charset(RTL_TEXTENCODING_ASCII_US
, aUSASCIIRanges
));
1507 sal_Unicode
* INetMIME::convertToUnicode(const sal_Char
* pBegin
,
1508 const sal_Char
* pEnd
,
1509 rtl_TextEncoding eEncoding
,
1512 if (eEncoding
== RTL_TEXTENCODING_DONTKNOW
)
1514 rtl_TextToUnicodeConverter hConverter
1515 = rtl_createTextToUnicodeConverter(eEncoding
);
1516 rtl_TextToUnicodeContext hContext
1517 = rtl_createTextToUnicodeContext(hConverter
);
1518 sal_Unicode
* pBuffer
;
1520 for (sal_Size nBufferSize
= pEnd
- pBegin
;;
1521 nBufferSize
+= nBufferSize
/ 3 + 1)
1523 pBuffer
= new sal_Unicode
[nBufferSize
];
1524 sal_Size nSrcCvtBytes
;
1525 rSize
= rtl_convertTextToUnicode(
1526 hConverter
, hContext
, pBegin
, pEnd
- pBegin
, pBuffer
,
1528 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
1529 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
1530 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR
,
1531 &nInfo
, &nSrcCvtBytes
);
1532 if (nInfo
!= RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL
)
1535 rtl_resetTextToUnicodeContext(hConverter
, hContext
);
1537 rtl_destroyTextToUnicodeContext(hConverter
, hContext
);
1538 rtl_destroyTextToUnicodeConverter(hConverter
);
1548 sal_Char
* INetMIME::convertFromUnicode(const sal_Unicode
* pBegin
,
1549 const sal_Unicode
* pEnd
,
1550 rtl_TextEncoding eEncoding
,
1553 if (eEncoding
== RTL_TEXTENCODING_DONTKNOW
)
1555 rtl_UnicodeToTextConverter hConverter
1556 = rtl_createUnicodeToTextConverter(eEncoding
);
1557 rtl_UnicodeToTextContext hContext
1558 = rtl_createUnicodeToTextContext(hConverter
);
1561 for (sal_Size nBufferSize
= pEnd
- pBegin
;;
1562 nBufferSize
+= nBufferSize
/ 3 + 1)
1564 pBuffer
= new sal_Char
[nBufferSize
];
1565 sal_Size nSrcCvtBytes
;
1566 rSize
= rtl_convertUnicodeToText(
1567 hConverter
, hContext
, pBegin
, pEnd
- pBegin
, pBuffer
,
1569 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
1570 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
1571 | RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE
1572 | RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACESTR
,
1573 &nInfo
, &nSrcCvtBytes
);
1574 if (nInfo
!= RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL
)
1577 rtl_resetUnicodeToTextContext(hConverter
, hContext
);
1579 rtl_destroyUnicodeToTextContext(hConverter
, hContext
);
1580 rtl_destroyUnicodeToTextConverter(hConverter
);
1590 void INetMIME::writeUTF8(INetMIMEOutputSink
& rSink
, sal_uInt32 nChar
)
1592 // See RFC 2279 for a discussion of UTF-8.
1593 DBG_ASSERT(nChar
< 0x80000000, "INetMIME::writeUTF8(): Bad char");
1596 rSink
<< sal_Char(nChar
);
1597 else if (nChar
< 0x800)
1598 rSink
<< sal_Char(nChar
>> 6 | 0xC0)
1599 << sal_Char((nChar
& 0x3F) | 0x80);
1600 else if (nChar
< 0x10000)
1601 rSink
<< sal_Char(nChar
>> 12 | 0xE0)
1602 << sal_Char((nChar
>> 6 & 0x3F) | 0x80)
1603 << sal_Char((nChar
& 0x3F) | 0x80);
1604 else if (nChar
< 0x200000)
1605 rSink
<< sal_Char(nChar
>> 18 | 0xF0)
1606 << sal_Char((nChar
>> 12 & 0x3F) | 0x80)
1607 << sal_Char((nChar
>> 6 & 0x3F) | 0x80)
1608 << sal_Char((nChar
& 0x3F) | 0x80);
1609 else if (nChar
< 0x4000000)
1610 rSink
<< sal_Char(nChar
>> 24 | 0xF8)
1611 << sal_Char((nChar
>> 18 & 0x3F) | 0x80)
1612 << sal_Char((nChar
>> 12 & 0x3F) | 0x80)
1613 << sal_Char((nChar
>> 6 & 0x3F) | 0x80)
1614 << sal_Char((nChar
& 0x3F) | 0x80);
1616 rSink
<< sal_Char(nChar
>> 30 | 0xFC)
1617 << sal_Char((nChar
>> 24 & 0x3F) | 0x80)
1618 << sal_Char((nChar
>> 18 & 0x3F) | 0x80)
1619 << sal_Char((nChar
>> 12 & 0x3F) | 0x80)
1620 << sal_Char((nChar
>> 6 & 0x3F) | 0x80)
1621 << sal_Char((nChar
& 0x3F) | 0x80);
1625 void INetMIME::writeHeaderFieldBody(INetMIMEOutputSink
& rSink
,
1626 HeaderFieldType eType
,
1627 const OUString
& rBody
,
1628 rtl_TextEncoding ePreferredEncoding
,
1631 if (eType
== HEADER_FIELD_TEXT
)
1633 INetMIMEEncodedWordOutputSink
1634 aOutput(rSink
, INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
,
1636 INetMIMEEncodedWordOutputSink::SPACE_ALWAYS
:
1637 INetMIMEEncodedWordOutputSink::SPACE_NO
,
1638 ePreferredEncoding
);
1639 aOutput
.write(rBody
.getStr(), rBody
.getStr() + rBody
.getLength());
1644 enum Brackets
{ BRACKETS_OUTSIDE
, BRACKETS_OPENING
, BRACKETS_INSIDE
};
1645 Brackets eBrackets
= BRACKETS_OUTSIDE
;
1647 const sal_Unicode
* pBodyPtr
= rBody
.getStr();
1648 const sal_Unicode
* pBodyEnd
= pBodyPtr
+ rBody
.getLength();
1649 while (pBodyPtr
!= pBodyEnd
)
1654 // A WSP adds to accumulated space:
1655 bInitialSpace
= true;
1661 // Write a pending '<' if necessary:
1662 if (eBrackets
== BRACKETS_OPENING
)
1664 if (rSink
.getColumn() + (bInitialSpace
? 1 : 0)
1665 >= rSink
.getLineLengthLimit())
1666 rSink
<< INetMIMEOutputSink::endl
<< ' ';
1667 else if (bInitialSpace
)
1670 bInitialSpace
= false;
1671 eBrackets
= BRACKETS_INSIDE
;
1674 // Write the comment, introducing encoded-words where
1677 INetMIMEEncodedWordOutputSink
1680 INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
,
1681 INetMIMEEncodedWordOutputSink::SPACE_NO
,
1682 ePreferredEncoding
);
1683 while (pBodyPtr
!= pBodyEnd
)
1688 if (rSink
.getColumn()
1689 + (bInitialSpace
? 1 : 0)
1690 >= rSink
.getLineLengthLimit())
1691 rSink
<< INetMIMEOutputSink::endl
<< ' ';
1692 else if (bInitialSpace
)
1695 bInitialSpace
= false;
1702 if (rSink
.getColumn()
1703 >= rSink
.getLineLengthLimit())
1704 rSink
<< INetMIMEOutputSink::endl
<< ' ';
1712 if (++pBodyPtr
== pBodyEnd
)
1715 aOutput
.WriteUInt32( *pBodyPtr
++ );
1723 // Write an already pending '<' if necessary:
1724 if (eBrackets
== BRACKETS_OPENING
)
1726 if (rSink
.getColumn() + (bInitialSpace
? 1 : 0)
1727 >= rSink
.getLineLengthLimit())
1728 rSink
<< INetMIMEOutputSink::endl
<< ' ';
1729 else if (bInitialSpace
)
1732 bInitialSpace
= false;
1735 // Remember this '<' as pending, and open a bracketed
1737 eBrackets
= BRACKETS_OPENING
;
1742 // Write a pending '<' if necessary:
1743 if (eBrackets
== BRACKETS_OPENING
)
1745 if (rSink
.getColumn() + (bInitialSpace
? 1 : 0)
1746 >= rSink
.getLineLengthLimit())
1747 rSink
<< INetMIMEOutputSink::endl
<< ' ';
1748 else if (bInitialSpace
)
1751 bInitialSpace
= false;
1754 // Write this '>', and close any bracketed block:
1755 if (rSink
.getColumn() + (bInitialSpace
? 1 : 0)
1756 >= rSink
.getLineLengthLimit())
1757 rSink
<< INetMIMEOutputSink::endl
<< ' ';
1758 else if (bInitialSpace
)
1761 bInitialSpace
= false;
1762 eBrackets
= BRACKETS_OUTSIDE
;
1771 // Write a pending '<' if necessary:
1772 if (eBrackets
== BRACKETS_OPENING
)
1774 if (rSink
.getColumn() + (bInitialSpace
? 1 : 0)
1775 >= rSink
.getLineLengthLimit())
1776 rSink
<< INetMIMEOutputSink::endl
<< ' ';
1777 else if (bInitialSpace
)
1780 bInitialSpace
= false;
1781 eBrackets
= BRACKETS_INSIDE
;
1784 // Write this specials:
1785 if (rSink
.getColumn() + (bInitialSpace
? 1 : 0)
1786 >= rSink
.getLineLengthLimit())
1787 rSink
<< INetMIMEOutputSink::endl
<< ' ';
1788 else if (bInitialSpace
)
1790 rSink
<< sal_Char(*pBodyPtr
++);
1791 bInitialSpace
= false;
1795 // A <CRLF WSP> adds to accumulated space, a <CR> not
1796 // followed by <LF WSP> starts 'junk':
1797 if (startsWithLineFolding(pBodyPtr
, pBodyEnd
))
1799 bInitialSpace
= true;
1805 // The next token is either one of <"." / "@" / atom /
1806 // quoted-string / domain-literal>, or it's 'junk'; if it
1807 // is not 'junk', it is either a 'phrase' (i.e., it may
1808 // contain encoded-words) or a 'non-phrase' (i.e., it may
1809 // not contain encoded-words):
1810 enum Entity
{ ENTITY_JUNK
, ENTITY_NON_PHRASE
,
1812 Entity eEntity
= ENTITY_JUNK
;
1818 // A token of <"." / "@" / domain-literal> always
1819 // starts a 'non-phrase':
1820 eEntity
= ENTITY_NON_PHRASE
;
1824 if (rtl::isAscii(*pBodyPtr
)
1825 && !isAtomChar(*pBodyPtr
))
1827 eEntity
= ENTITY_JUNK
;
1831 // A token of <atom / quoted-string> can either be
1832 // a 'phrase' or a 'non-phrase':
1835 case HEADER_FIELD_STRUCTURED
:
1836 eEntity
= ENTITY_NON_PHRASE
;
1839 case HEADER_FIELD_PHRASE
:
1840 eEntity
= ENTITY_PHRASE
;
1843 case HEADER_FIELD_MESSAGE_ID
:
1844 // A 'phrase' if and only if outside any
1847 = eBrackets
== BRACKETS_OUTSIDE
?
1852 case HEADER_FIELD_ADDRESS
:
1854 // A 'non-phrase' if and only if, after
1855 // skipping this token and any following
1856 // <linear-white-space> and <comment>s,
1857 // there is no token left, or the next
1858 // token is any of <"." / "@" / ">" / ","
1859 // / ";">, or the next token is <":"> and
1860 // is within a bracketed block:
1861 const sal_Unicode
* pLookAhead
= pBodyPtr
;
1862 if (*pLookAhead
== '"')
1865 = skipQuotedString(pLookAhead
,
1867 if (pLookAhead
== pBodyPtr
)
1868 pLookAhead
= pBodyEnd
;
1871 while (pLookAhead
!= pBodyEnd
1872 && (isAtomChar(*pLookAhead
)
1876 while (pLookAhead
!= pBodyEnd
)
1877 switch (*pLookAhead
)
1886 const sal_Unicode
* pPast
1887 = skipComment(pLookAhead
,
1890 = pPast
== pLookAhead
?
1900 eEntity
= ENTITY_NON_PHRASE
;
1901 goto entity_determined
;
1906 == BRACKETS_OUTSIDE
?
1909 goto entity_determined
;
1912 if (startsWithLineFolding(
1913 pLookAhead
, pBodyEnd
))
1919 eEntity
= ENTITY_PHRASE
;
1920 goto entity_determined
;
1922 eEntity
= ENTITY_NON_PHRASE
;
1927 case HEADER_FIELD_TEXT
:
1932 // In a 'non-phrase', a non-US-ASCII character
1933 // cannot be part of an <atom>, but instead the
1934 // whole entity is 'junk' rather than 'non-
1936 if (eEntity
== ENTITY_NON_PHRASE
1937 && !rtl::isAscii(*pBodyPtr
))
1938 eEntity
= ENTITY_JUNK
;
1946 // Write a pending '<' if necessary:
1947 if (eBrackets
== BRACKETS_OPENING
)
1949 if (rSink
.getColumn()
1950 + (bInitialSpace
? 1 : 0)
1951 >= rSink
.getLineLengthLimit())
1952 rSink
<< INetMIMEOutputSink::endl
<< ' ';
1953 else if (bInitialSpace
)
1956 bInitialSpace
= false;
1957 eBrackets
= BRACKETS_INSIDE
;
1960 // Calculate the length of in- and output:
1961 const sal_Unicode
* pStart
= pBodyPtr
;
1962 sal_Size nLength
= 0;
1963 bool bModify
= false;
1965 while (pBodyPtr
!= pBodyEnd
&& !bEnd
)
1969 if (startsWithLineFolding(pBodyPtr
,
1972 else if (startsWithLineBreak(
1973 pBodyPtr
, pBodyEnd
))
1992 if (isVisible(*pBodyPtr
))
1994 else if (rtl::isAscii(*pBodyPtr
))
2001 nLength
+= getUTF8OctetCount(
2008 // Write the output:
2009 if (rSink
.getColumn() + (bInitialSpace
? 1 : 0)
2011 > rSink
.getLineLengthLimit())
2012 rSink
<< INetMIMEOutputSink::endl
<< ' ';
2013 else if (bInitialSpace
)
2015 bInitialSpace
= false;
2017 while (pStart
!= pBodyPtr
)
2018 if (startsWithLineBreak(pStart
, pBodyPtr
))
2020 rSink
<< "\x0D\\\x0A"; // CR, '\', LF
2024 writeUTF8(rSink
, *pStart
++);
2026 rSink
.write(pStart
, pBodyPtr
);
2030 case ENTITY_NON_PHRASE
:
2032 // Calculate the length of in- and output:
2033 const sal_Unicode
* pStart
= pBodyPtr
;
2034 sal_Size nLength
= 0;
2035 bool bBracketedBlock
= false;
2036 bool bSymbol
= *pStart
!= '.' && *pStart
!= '@';
2037 bool bModify
= false;
2039 while (pBodyPtr
!= pBodyEnd
&& !bEnd
)
2046 const sal_Unicode
* pLookAhead
2047 = skipLinearWhiteSpace(pBodyPtr
,
2049 if (pLookAhead
< pBodyEnd
2051 isAtomChar(*pLookAhead
)
2052 || *pLookAhead
== '"'
2053 || *pLookAhead
== '[' :
2055 || *pLookAhead
== '@'
2056 || (*pLookAhead
== '>'
2058 >= HEADER_FIELD_MESSAGE_ID
2060 == BRACKETS_OPENING
)))
2063 pBodyPtr
= pLookAhead
;
2074 = scanQuotedBlock(pBodyPtr
,
2089 = scanQuotedBlock(pBodyPtr
,
2113 if (eBrackets
== BRACKETS_OPENING
2115 >= HEADER_FIELD_MESSAGE_ID
)
2118 bBracketedBlock
= true;
2125 if (isAtomChar(*pBodyPtr
) && bSymbol
)
2127 while (pBodyPtr
!= pBodyEnd
2128 && isAtomChar(*pBodyPtr
))
2137 if (!rtl::isAscii(*pBodyPtr
))
2144 // Write a pending '<' if necessary:
2145 if (eBrackets
== BRACKETS_OPENING
2146 && !bBracketedBlock
)
2148 if (rSink
.getColumn()
2149 + (bInitialSpace
? 1 : 0)
2150 >= rSink
.getLineLengthLimit())
2151 rSink
<< INetMIMEOutputSink::endl
<< ' ';
2152 else if (bInitialSpace
)
2155 bInitialSpace
= false;
2156 eBrackets
= BRACKETS_INSIDE
;
2159 // Write the output:
2160 if (rSink
.getColumn() + (bInitialSpace
? 1 : 0)
2162 > rSink
.getLineLengthLimit())
2163 rSink
<< INetMIMEOutputSink::endl
<< ' ';
2164 else if (bInitialSpace
)
2166 bInitialSpace
= false;
2167 if (bBracketedBlock
)
2170 eBrackets
= BRACKETS_OUTSIDE
;
2174 enum Mode
{ MODE_PLAIN
, MODE_QUOTED_STRING
,
2175 MODE_DOMAIN_LITERAL
};
2176 Mode eMode
= MODE_PLAIN
;
2177 while (pStart
!= pBodyPtr
)
2181 if (startsWithLineFolding(
2184 if (eMode
!= MODE_PLAIN
)
2189 else if (startsWithLineBreak(
2192 rSink
<< "\x0D\\\x0A";
2198 rSink
<< '\x0D'; // CR
2205 if (eMode
!= MODE_PLAIN
)
2206 rSink
<< sal_Char(*pStart
);
2211 if (eMode
== MODE_PLAIN
)
2212 eMode
= MODE_QUOTED_STRING
;
2214 == MODE_QUOTED_STRING
)
2221 if (eMode
== MODE_PLAIN
)
2222 eMode
= MODE_DOMAIN_LITERAL
;
2228 if (eMode
== MODE_DOMAIN_LITERAL
)
2236 if (++pStart
< pBodyPtr
)
2237 writeUTF8(rSink
, *pStart
++);
2241 writeUTF8(rSink
, *pStart
++);
2246 rSink
.write(pStart
, pBodyPtr
);
2252 // Write a pending '<' if necessary:
2253 if (eBrackets
== BRACKETS_OPENING
)
2255 if (rSink
.getColumn()
2256 + (bInitialSpace
? 1 : 0)
2257 >= rSink
.getLineLengthLimit())
2258 rSink
<< INetMIMEOutputSink::endl
<< ' ';
2259 else if (bInitialSpace
)
2262 bInitialSpace
= false;
2263 eBrackets
= BRACKETS_INSIDE
;
2266 // Calculate the length of in- and output:
2267 const sal_Unicode
* pStart
= pBodyPtr
;
2268 bool bQuotedString
= false;
2270 while (pBodyPtr
!= pBodyEnd
&& !bEnd
)
2280 const sal_Unicode
* pLookAhead
2281 = skipLinearWhiteSpace(
2282 pBodyPtr
, pBodyEnd
);
2283 if (pLookAhead
!= pBodyEnd
2284 && (isAtomChar(*pLookAhead
)
2285 || !rtl::isAscii(*pLookAhead
)
2286 || *pLookAhead
== '"'))
2287 pBodyPtr
= pLookAhead
;
2294 bQuotedString
= !bQuotedString
;
2301 if (++pBodyPtr
!= pBodyEnd
)
2310 || isAtomChar(*pBodyPtr
)
2311 || !rtl::isAscii(*pBodyPtr
))
2318 // Write the phrase, introducing encoded-words
2320 INetMIMEEncodedWordOutputSink
2323 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
,
2325 INetMIMEEncodedWordOutputSink::SPACE_ALWAYS
:
2326 INetMIMEEncodedWordOutputSink::SPACE_ENCODED
,
2327 ePreferredEncoding
);
2328 while (pStart
!= pBodyPtr
)
2336 if (++pStart
!= pBodyPtr
)
2337 aOutput
.WriteUInt32( *pStart
++ );
2342 aOutput
.WriteUInt32( *pStart
++ );
2346 aOutput
.WriteUInt32( *pStart
++ );
2349 bInitialSpace
= aOutput
.flush();
2360 bool INetMIME::translateUTF8Char(const sal_Char
*& rBegin
,
2361 const sal_Char
* pEnd
,
2362 rtl_TextEncoding eEncoding
,
2363 sal_uInt32
& rCharacter
)
2365 if (rBegin
== pEnd
|| static_cast< unsigned char >(*rBegin
) < 0x80
2366 || static_cast< unsigned char >(*rBegin
) >= 0xFE)
2372 const sal_Char
* p
= rBegin
;
2373 if (static_cast< unsigned char >(*p
) < 0xE0)
2377 nUCS4
= static_cast< unsigned char >(*p
) & 0x1F;
2379 else if (static_cast< unsigned char >(*p
) < 0xF0)
2383 nUCS4
= static_cast< unsigned char >(*p
) & 0xF;
2385 else if (static_cast< unsigned char >(*p
) < 0xF8)
2389 nUCS4
= static_cast< unsigned char >(*p
) & 7;
2391 else if (static_cast< unsigned char >(*p
) < 0xFC)
2395 nUCS4
= static_cast< unsigned char >(*p
) & 3;
2401 nUCS4
= static_cast< unsigned char >(*p
) & 1;
2405 for (; nCount
-- > 0; ++p
)
2406 if ((static_cast< unsigned char >(*p
) & 0xC0) == 0x80)
2407 nUCS4
= (nUCS4
<< 6) | (static_cast< unsigned char >(*p
) & 0x3F);
2411 if (nUCS4
< nMin
|| nUCS4
> 0x10FFFF)
2414 if (eEncoding
>= RTL_TEXTENCODING_UCS4
)
2418 sal_Unicode aUTF16
[2];
2419 const sal_Unicode
* pUTF16End
= putUTF32Character(aUTF16
, nUCS4
);
2421 sal_Char
* pBuffer
= convertFromUnicode(aUTF16
, pUTF16End
, eEncoding
,
2425 DBG_ASSERT(nSize
== 1,
2426 "INetMIME::translateUTF8Char(): Bad conversion");
2427 rCharacter
= *pBuffer
;
2435 OUString
INetMIME::decodeHeaderFieldBody(HeaderFieldType eType
,
2436 const OString
& rBody
)
2438 // Due to a bug in INetCoreRFC822MessageStream::ConvertTo7Bit(), old
2439 // versions of StarOffice send mails with header fields where encoded
2440 // words can be preceded by '=', ',', '.', '"', or '(', and followed by
2441 // '=', ',', '.', '"', ')', without any required white space in between.
2442 // And there appear to exist some broken mailers that only encode single
2443 // letters within words, like "Appel
2444 // =?iso-8859-1?Q?=E0?=t=?iso-8859-1?Q?=E9?=moin", so it seems best to
2445 // detect encoded words even when not properly surrounded by white space.
2447 // Non US-ASCII characters in rBody are treated as ISO-8859-1.
2449 // encoded-word = "=?"
2450 // 1*(%x21 / %x23-27 / %x2A-2B / %x2D / %30-39 / %x41-5A / %x5E-7E)
2451 // ["*" 1*8ALPHA *("-" 1*8ALPHA)] "?"
2452 // ("B?" *(4base64) (4base64 / 3base64 "=" / 2base64 "==")
2453 // / "Q?" 1*(%x21-3C / %x3E / %x40-7E / "=" 2HEXDIG))
2456 // base64 = ALPHA / DIGIT / "+" / "/"
2458 const sal_Char
* pBegin
= rBody
.getStr();
2459 const sal_Char
* pEnd
= pBegin
+ rBody
.getLength();
2462 const sal_Char
* pCopyBegin
= pBegin
;
2464 /* bool bStartEncodedWord = true; */
2465 const sal_Char
* pWSPBegin
= pBegin
;
2466 bool bQuotedEncodedText
= false;
2467 sal_uInt32 nCommentLevel
= 0;
2469 for (const sal_Char
* p
= pBegin
; p
!= pEnd
;)
2471 OUString sEncodedText
;
2472 if (p
!= pEnd
&& *p
== '=' /* && bStartEncodedWord */)
2474 const sal_Char
* q
= p
+ 1;
2475 bool bEncodedWord
= q
!= pEnd
&& *q
++ == '?';
2477 rtl_TextEncoding eCharsetEncoding
= RTL_TEXTENCODING_DONTKNOW
;
2480 const sal_Char
* pCharsetBegin
= q
;
2481 const sal_Char
* pLanguageBegin
= 0;
2482 int nAlphaCount
= 0;
2483 for (bool bDone
= false; !bDone
;)
2486 bEncodedWord
= false;
2491 sal_Char cChar
= *q
++;
2495 pLanguageBegin
= q
- 1;
2500 if (pLanguageBegin
!= 0)
2502 if (nAlphaCount
== 0)
2510 if (pCharsetBegin
== q
- 1)
2511 bEncodedWord
= false;
2515 = getCharsetEncoding(
2518 || nAlphaCount
== 0 ?
2519 q
- 1 : pLanguageBegin
);
2520 bEncodedWord
= isMIMECharsetEncoding(
2523 = translateFromMIME(eCharsetEncoding
);
2529 if (pLanguageBegin
!= 0
2530 && (!rtl::isAsciiAlpha(cChar
) || ++nAlphaCount
> 8))
2537 bool bEncodingB
= false;
2541 bEncodedWord
= false;
2557 bEncodedWord
= false;
2563 bEncodedWord
= bEncodedWord
&& q
!= pEnd
&& *q
++ == '?';
2565 OStringBuffer sText
;
2570 for (bool bDone
= false; !bDone
;)
2574 bEncodedWord
= false;
2579 bool bFinal
= false;
2581 sal_uInt32 nValue
= 0;
2582 for (int nShift
= 18; nShift
>= 0; nShift
-= 6)
2584 int nWeight
= getBase64Weight(*q
++);
2587 bEncodedWord
= false;
2597 bEncodedWord
= false;
2602 nCount
= nShift
== 6 ? 1 : 2;
2606 nValue
|= nWeight
<< nShift
;
2610 for (int nShift
= 16; nCount
-- > 0; nShift
-= 8)
2611 sText
.append(sal_Char(nValue
>> nShift
& 0xFF));
2617 if (bFinal
&& !bDone
)
2619 bEncodedWord
= false;
2628 const sal_Char
* pEncodedTextBegin
= q
;
2629 const sal_Char
* pEncodedTextCopyBegin
= q
;
2630 for (bool bDone
= false; !bDone
;)
2633 bEncodedWord
= false;
2638 sal_uInt32 nChar
= *q
++;
2645 bEncodedWord
= false;
2649 int nDigit1
= getHexWeight(q
[0]);
2650 int nDigit2
= getHexWeight(q
[1]);
2651 if (nDigit1
< 0 || nDigit2
< 0)
2653 bEncodedWord
= false;
2657 sText
.append(rBody
.copy(
2658 (pEncodedTextCopyBegin
- pBegin
),
2659 (q
- 1 - pEncodedTextCopyBegin
)));
2660 sText
.append(sal_Char(nDigit1
<< 4 | nDigit2
));
2662 pEncodedTextCopyBegin
= q
;
2667 if (q
- pEncodedTextBegin
> 1)
2668 sText
.append(rBody
.copy(
2669 (pEncodedTextCopyBegin
- pBegin
),
2670 (q
- 1 - pEncodedTextCopyBegin
)));
2672 bEncodedWord
= false;
2677 sText
.append(rBody
.copy(
2678 (pEncodedTextCopyBegin
- pBegin
),
2679 (q
- 1 - pEncodedTextCopyBegin
)));
2681 pEncodedTextCopyBegin
= q
;
2685 if (!isVisible(nChar
))
2687 bEncodedWord
= false;
2696 bEncodedWord
= bEncodedWord
&& q
!= pEnd
&& *q
++ == '=';
2698 sal_Unicode
* pUnicodeBuffer
= 0;
2699 sal_Size nUnicodeSize
= 0;
2703 = convertToUnicode(sText
.getStr(),
2704 sText
.getStr() + sText
.getLength(),
2705 eCharsetEncoding
, nUnicodeSize
);
2706 if (pUnicodeBuffer
== 0)
2707 bEncodedWord
= false;
2712 appendISO88591(sDecoded
, pCopyBegin
, pWSPBegin
);
2713 if (eType
== HEADER_FIELD_TEXT
)
2714 sDecoded
+= OUString(
2716 static_cast< sal_Int32
>(nUnicodeSize
));
2717 else if (nCommentLevel
== 0)
2719 sEncodedText
= OUString(pUnicodeBuffer
, nUnicodeSize
);
2720 if (!bQuotedEncodedText
)
2722 const sal_Unicode
* pTextPtr
= pUnicodeBuffer
;
2723 const sal_Unicode
* pTextEnd
= pTextPtr
2725 for (; pTextPtr
!= pTextEnd
; ++pTextPtr
)
2726 if (!isEncodedWordTokenChar(*pTextPtr
))
2728 bQuotedEncodedText
= true;
2735 const sal_Unicode
* pTextPtr
= pUnicodeBuffer
;
2736 const sal_Unicode
* pTextEnd
= pTextPtr
+ nUnicodeSize
;
2737 for (; pTextPtr
!= pTextEnd
; ++pTextPtr
)
2749 sDecoded
+= OUString(*pTextPtr
);
2752 delete[] pUnicodeBuffer
;
2757 while (p
!= pEnd
&& isWhiteSpace(*p
))
2759 /* bStartEncodedWord = p != pWSPBegin; */
2764 if (!sEncodedText
.isEmpty())
2766 if (bQuotedEncodedText
)
2769 const sal_Unicode
* pTextPtr
= sEncodedText
.getStr();
2770 const sal_Unicode
* pTextEnd
= pTextPtr
+ sEncodedText
.getLength();
2771 for (;pTextPtr
!= pTextEnd
; ++pTextPtr
)
2781 sDecoded
+= OUString(*pTextPtr
);
2786 sDecoded
+= sEncodedText
;
2787 bQuotedEncodedText
= false;
2796 if (eType
!= HEADER_FIELD_TEXT
&& nCommentLevel
== 0)
2798 const sal_Char
* pQuotedStringEnd
2799 = skipQuotedString(p
- 1, pEnd
);
2800 p
= pQuotedStringEnd
== p
- 1 ? pEnd
: pQuotedStringEnd
;
2802 /* bStartEncodedWord = true; */
2806 if (eType
!= HEADER_FIELD_TEXT
)
2808 /* bStartEncodedWord = true; */
2812 if (nCommentLevel
> 0)
2814 /* bStartEncodedWord = false; */
2819 const sal_Char
* pUTF8Begin
= p
- 1;
2820 const sal_Char
* pUTF8End
= pUTF8Begin
;
2821 sal_uInt32 nCharacter
= 0;
2822 if (translateUTF8Char(pUTF8End
, pEnd
, RTL_TEXTENCODING_UCS4
,
2825 appendISO88591(sDecoded
, pCopyBegin
, p
- 1);
2826 sal_Unicode aUTF16Buf
[2];
2827 sal_Int32 nUTF16Len
= putUTF32Character(aUTF16Buf
, nCharacter
) - aUTF16Buf
;
2828 sDecoded
+= OUString(aUTF16Buf
, nUTF16Len
);
2832 /* bStartEncodedWord = false; */
2839 appendISO88591(sDecoded
, pCopyBegin
, pEnd
);
2843 // INetMIMEOutputSink
2846 sal_Size
INetMIMEOutputSink::writeSequence(const sal_Char
* pSequence
)
2848 sal_Size nLength
= rtl_str_getLength(pSequence
);
2849 writeSequence(pSequence
, pSequence
+ nLength
);
2854 void INetMIMEOutputSink::writeSequence(const sal_Unicode
* pBegin
,
2855 const sal_Unicode
* pEnd
)
2857 assert(pBegin
&& pBegin
<= pEnd
&&
2858 "INetMIMEOutputSink::writeSequence(): Bad sequence");
2860 sal_Char
* pBufferBegin
= new sal_Char
[pEnd
- pBegin
];
2861 sal_Char
* pBufferEnd
= pBufferBegin
;
2862 while (pBegin
!= pEnd
)
2864 DBG_ASSERT(*pBegin
< 256,
2865 "INetMIMEOutputSink::writeSequence(): Bad octet");
2866 *pBufferEnd
++ = sal_Char(*pBegin
++);
2868 writeSequence(pBufferBegin
, pBufferEnd
);
2869 delete[] pBufferBegin
;
2873 ErrCode
INetMIMEOutputSink::getError() const
2875 return ERRCODE_NONE
;
2878 void INetMIMEOutputSink::writeLineEnd()
2880 static const sal_Char aCRLF
[2] = { 0x0D, 0x0A };
2881 writeSequence(aCRLF
, aCRLF
+ 2);
2885 // INetMIMEStringOutputSink
2888 void INetMIMEStringOutputSink::writeSequence(const sal_Char
* pBegin
,
2889 const sal_Char
* pEnd
)
2891 OSL_ENSURE(pBegin
&& pBegin
<= pEnd
,
2892 "INetMIMEStringOutputSink::writeSequence(): Bad sequence");
2894 m_aBuffer
.append(pBegin
, pEnd
- pBegin
);
2898 ErrCode
INetMIMEStringOutputSink::getError() const
2900 return ERRCODE_NONE
;
2903 // INetMIMEEncodedWordOutputSink
2905 static const sal_Char aEscape
[128]
2906 = { INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x00
2907 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x01
2908 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x02
2909 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x03
2910 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x04
2911 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x05
2912 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x06
2913 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x07
2914 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x08
2915 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x09
2916 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x0A
2917 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x0B
2918 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x0C
2919 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x0D
2920 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x0E
2921 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x0F
2922 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x10
2923 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x11
2924 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x12
2925 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x13
2926 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x14
2927 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x15
2928 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x16
2929 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x17
2930 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x18
2931 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x19
2932 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x1A
2933 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x1B
2934 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x1C
2935 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x1D
2936 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x1E
2937 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // 0x1F
2940 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '"'
2941 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '#'
2942 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '$'
2943 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '%'
2944 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '&'
2945 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '''
2946 INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '('
2947 INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // ')'
2950 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // ','
2952 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '.'
2964 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // ':'
2965 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // ';'
2966 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '<'
2967 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '='
2968 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '>'
2969 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '?'
2970 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '@'
2997 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '['
2998 INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '\'
2999 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // ']'
3000 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '^'
3001 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '_'
3002 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '`'
3029 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '{'
3030 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '|'
3031 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '}'
3032 INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
, // '~'
3033 INetMIMEEncodedWordOutputSink::CONTEXT_TEXT
| INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT
| INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE
}; // DEL
3036 INetMIMEEncodedWordOutputSink::needsEncodedWordEscape(sal_uInt32 nChar
) const
3038 return !rtl::isAscii(nChar
) || aEscape
[nChar
] & m_eContext
;
3041 void INetMIMEEncodedWordOutputSink::finish(bool bWriteTrailer
)
3043 if (m_eInitialSpace
== SPACE_ALWAYS
&& m_nExtraSpaces
== 0)
3046 if (m_eEncodedWordState
== STATE_SECOND_EQUALS
)
3048 // If the text is already an encoded word, copy it verbatim:
3049 sal_uInt32 nSize
= m_pBufferEnd
- m_pBuffer
;
3050 switch (m_ePrevCoding
)
3055 if (m_eInitialSpace
== SPACE_ENCODED
&& m_nExtraSpaces
== 0)
3057 for (; m_nExtraSpaces
> 1; --m_nExtraSpaces
)
3059 if (m_rSink
.getColumn() >= m_rSink
.getLineLengthLimit())
3060 m_rSink
<< INetMIMEOutputSink::endl
;
3063 if (m_nExtraSpaces
== 1)
3065 if (m_rSink
.getColumn() + nSize
3066 >= m_rSink
.getLineLengthLimit())
3067 m_rSink
<< INetMIMEOutputSink::endl
;
3072 case CODING_ENCODED
:
3074 const sal_Char
* pCharsetName
3075 = INetMIME::getCharsetName(m_ePrevMIMEEncoding
);
3076 while (m_nExtraSpaces
-- > 0)
3078 if (m_rSink
.getColumn()
3079 > m_rSink
.getLineLengthLimit() - 3)
3080 m_rSink
<< "?=" << INetMIMEOutputSink::endl
<< " =?"
3081 << pCharsetName
<< "?Q?";
3087 case CODING_ENCODED_TERMINATED
:
3088 if (m_rSink
.getColumn() + nSize
3089 > m_rSink
.getLineLengthLimit() - 1)
3090 m_rSink
<< INetMIMEOutputSink::endl
;
3094 m_rSink
.write(m_pBuffer
, m_pBufferEnd
);
3095 m_eCoding
= CODING_ENCODED_TERMINATED
;
3099 // If the text itself is too long to fit into a single line, make it
3100 // into multiple encoded words:
3104 if (m_nExtraSpaces
== 0)
3106 DBG_ASSERT(m_ePrevCoding
== CODING_NONE
3107 || m_pBuffer
== m_pBufferEnd
,
3108 "INetMIMEEncodedWordOutputSink::finish():"
3110 if (m_rSink
.getColumn() + (m_pBufferEnd
- m_pBuffer
)
3111 > m_rSink
.getLineLengthLimit())
3112 m_eCoding
= CODING_ENCODED
;
3116 OSL_ASSERT(m_pBufferEnd
>= m_pBuffer
);
3117 if (static_cast< std::size_t >(m_pBufferEnd
- m_pBuffer
)
3118 > m_rSink
.getLineLengthLimit() - 1)
3120 m_eCoding
= CODING_ENCODED
;
3126 if (m_nExtraSpaces
== 0)
3128 DBG_ASSERT(m_ePrevCoding
== CODING_NONE
,
3129 "INetMIMEEncodedWordOutputSink::finish():"
3131 if (m_rSink
.getColumn() + (m_pBufferEnd
- m_pBuffer
)
3133 > m_rSink
.getLineLengthLimit() - 2)
3134 m_eCoding
= CODING_ENCODED
;
3136 else if ((m_pBufferEnd
- m_pBuffer
) + m_nQuotedEscaped
3137 > m_rSink
.getLineLengthLimit() - 3)
3138 m_eCoding
= CODING_ENCODED
;
3148 switch (m_ePrevCoding
)
3151 if (m_rSink
.getColumn() + m_nExtraSpaces
3152 + (m_pBufferEnd
- m_pBuffer
)
3153 < m_rSink
.getLineLengthLimit())
3154 m_eCoding
= CODING_QUOTED
;
3159 case CODING_ENCODED
:
3166 for (; m_nExtraSpaces
> 1; --m_nExtraSpaces
)
3168 if (m_rSink
.getColumn() >= m_rSink
.getLineLengthLimit())
3169 m_rSink
<< INetMIMEOutputSink::endl
;
3172 if (m_nExtraSpaces
== 1)
3174 if (m_rSink
.getColumn() + (m_pBufferEnd
- m_pBuffer
)
3175 >= m_rSink
.getLineLengthLimit())
3176 m_rSink
<< INetMIMEOutputSink::endl
;
3179 m_rSink
.write(m_pBuffer
, m_pBufferEnd
);
3180 if (m_eCoding
== CODING_QUOTED
&& bWriteTrailer
)
3183 m_eCoding
= CODING_NONE
;
3189 bool bInsertLeadingQuote
= true;
3190 sal_uInt32 nSize
= (m_pBufferEnd
- m_pBuffer
)
3191 + m_nQuotedEscaped
+ 2;
3192 switch (m_ePrevCoding
)
3195 if (m_rSink
.getColumn() + m_nExtraSpaces
+ nSize
- 1
3196 < m_rSink
.getLineLengthLimit())
3198 bInsertLeadingQuote
= false;
3205 case CODING_ENCODED
:
3212 for (; m_nExtraSpaces
> 1; --m_nExtraSpaces
)
3214 if (m_rSink
.getColumn() >= m_rSink
.getLineLengthLimit())
3215 m_rSink
<< INetMIMEOutputSink::endl
;
3218 if (m_nExtraSpaces
== 1)
3220 if (m_rSink
.getColumn() + nSize
3221 >= m_rSink
.getLineLengthLimit())
3222 m_rSink
<< INetMIMEOutputSink::endl
;
3225 if (bInsertLeadingQuote
)
3227 for (const sal_Unicode
* p
= m_pBuffer
; p
!= m_pBufferEnd
;
3230 if (INetMIME::needsQuotedStringEscape(*p
))
3232 m_rSink
<< sal_Char(*p
);
3237 m_eCoding
= CODING_NONE
;
3242 case CODING_ENCODED
:
3244 rtl_TextEncoding eCharsetEncoding
3246 getPreferredEncoding(RTL_TEXTENCODING_UTF8
);
3247 rtl_TextEncoding eMIMEEncoding
3248 = INetMIME::translateToMIME(eCharsetEncoding
);
3250 // The non UTF-8 code will only work for stateless single byte
3251 // character encodings (see also below):
3252 sal_Char
* pTargetBuffer
= NULL
;
3253 sal_Size nTargetSize
= 0;
3255 if (eMIMEEncoding
== RTL_TEXTENCODING_UTF8
)
3258 for (sal_Unicode
const * p
= m_pBuffer
;
3262 = INetMIME::getUTF32Character(p
, m_pBufferEnd
);
3263 nSize
+= needsEncodedWordEscape(nUTF32
) ?
3264 3 * INetMIME::getUTF8OctetCount(nUTF32
) :
3266 // only US-ASCII characters (that are converted to
3267 // a single byte by UTF-8) need no encoded word
3273 rtl_UnicodeToTextConverter hConverter
3274 = rtl_createUnicodeToTextConverter(eCharsetEncoding
);
3275 rtl_UnicodeToTextContext hContext
3276 = rtl_createUnicodeToTextContext(hConverter
);
3277 for (sal_Size nBufferSize
= m_pBufferEnd
- m_pBuffer
;;
3278 nBufferSize
+= nBufferSize
/ 3 + 1)
3280 pTargetBuffer
= new sal_Char
[nBufferSize
];
3282 sal_Size nSrcCvtBytes
;
3284 = rtl_convertUnicodeToText(
3285 hConverter
, hContext
, m_pBuffer
,
3286 m_pBufferEnd
- m_pBuffer
, pTargetBuffer
,
3288 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_IGNORE
3289 | RTL_UNICODETOTEXT_FLAGS_INVALID_IGNORE
,
3290 &nInfo
, &nSrcCvtBytes
);
3292 & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL
))
3294 delete[] pTargetBuffer
;
3295 pTargetBuffer
= NULL
;
3296 rtl_resetUnicodeToTextContext(hConverter
, hContext
);
3298 rtl_destroyUnicodeToTextContext(hConverter
, hContext
);
3299 rtl_destroyUnicodeToTextConverter(hConverter
);
3301 nSize
= nTargetSize
;
3302 for (sal_Size k
= 0; k
< nTargetSize
; ++k
)
3303 if (needsEncodedWordEscape(static_cast<unsigned char>(
3308 const sal_Char
* pCharsetName
3309 = INetMIME::getCharsetName(eMIMEEncoding
);
3310 sal_uInt32 nWrapperSize
= rtl_str_getLength(pCharsetName
) + 7;
3311 // '=?', '?Q?', '?='
3313 switch (m_ePrevCoding
)
3318 if (m_eInitialSpace
== SPACE_ENCODED
3319 && m_nExtraSpaces
== 0)
3321 nSize
+= nWrapperSize
;
3322 for (; m_nExtraSpaces
> 1; --m_nExtraSpaces
)
3324 if (m_rSink
.getColumn() >= m_rSink
.getLineLengthLimit())
3325 m_rSink
<< INetMIMEOutputSink::endl
;
3328 if (m_nExtraSpaces
== 1)
3330 if (m_rSink
.getColumn() + nSize
>= m_rSink
.getLineLengthLimit())
3331 m_rSink
<< INetMIMEOutputSink::endl
;
3334 m_rSink
<< "=?" << pCharsetName
<< "?Q?";
3337 case CODING_ENCODED
:
3338 if (m_ePrevMIMEEncoding
!= eMIMEEncoding
3339 || m_rSink
.getColumn() + m_nExtraSpaces
+ nSize
3340 > m_rSink
.getLineLengthLimit() - 2)
3343 if (m_rSink
.getColumn() + nWrapperSize
3344 + m_nExtraSpaces
+ nSize
3345 > m_rSink
.getLineLengthLimit() - 1)
3346 m_rSink
<< INetMIMEOutputSink::endl
;
3347 m_rSink
<< " =?" << pCharsetName
<< "?Q?";
3349 while (m_nExtraSpaces
-- > 0)
3351 if (m_rSink
.getColumn()
3352 > m_rSink
.getLineLengthLimit() - 3)
3353 m_rSink
<< "?=" << INetMIMEOutputSink::endl
3354 << " =?" << pCharsetName
<< "?Q?";
3359 case CODING_ENCODED_TERMINATED
:
3360 if (m_rSink
.getColumn() + nWrapperSize
3361 + m_nExtraSpaces
+ nSize
3362 > m_rSink
.getLineLengthLimit() - 1)
3363 m_rSink
<< INetMIMEOutputSink::endl
;
3364 m_rSink
<< " =?" << pCharsetName
<< "?Q?";
3365 while (m_nExtraSpaces
-- > 0)
3367 if (m_rSink
.getColumn()
3368 > m_rSink
.getLineLengthLimit() - 3)
3369 m_rSink
<< "?=" << INetMIMEOutputSink::endl
3370 << " =?" << pCharsetName
<< "?Q?";
3376 // The non UTF-8 code will only work for stateless single byte
3377 // character encodings (see also above):
3378 if (eMIMEEncoding
== RTL_TEXTENCODING_UTF8
)
3380 bool bInitial
= true;
3381 for (sal_Unicode
const * p
= m_pBuffer
;
3385 = INetMIME::getUTF32Character(p
, m_pBufferEnd
);
3386 bool bEscape
= needsEncodedWordEscape(nUTF32
);
3389 3 * INetMIME::getUTF8OctetCount(nUTF32
) : 1;
3390 // only US-ASCII characters (that are converted to
3391 // a single byte by UTF-8) need no encoded word
3394 && m_rSink
.getColumn() + nWidth
+ 2
3395 > m_rSink
.getLineLengthLimit())
3396 m_rSink
<< "?=" << INetMIMEOutputSink::endl
3397 << " =?" << pCharsetName
<< "?Q?";
3402 "INetMIMEEncodedWordOutputSink::finish():"
3405 INetMIME::writeEscapeSequence(m_rSink
,
3407 else if (nUTF32
< 0x800)
3409 INetMIME::writeEscapeSequence(m_rSink
,
3412 INetMIME::writeEscapeSequence(m_rSink
,
3416 else if (nUTF32
< 0x10000)
3418 INetMIME::writeEscapeSequence(m_rSink
,
3421 INetMIME::writeEscapeSequence(m_rSink
,
3425 INetMIME::writeEscapeSequence(m_rSink
,
3431 INetMIME::writeEscapeSequence(m_rSink
,
3434 INetMIME::writeEscapeSequence(m_rSink
,
3438 INetMIME::writeEscapeSequence(m_rSink
,
3442 INetMIME::writeEscapeSequence(m_rSink
,
3448 m_rSink
<< sal_Char(nUTF32
);
3454 for (sal_Size k
= 0; k
< nTargetSize
; ++k
)
3456 sal_uInt32 nUCS4
= static_cast<unsigned char>(pTargetBuffer
[k
]);
3457 bool bEscape
= needsEncodedWordEscape(nUCS4
);
3459 && m_rSink
.getColumn() + (bEscape
? 5 : 3)
3460 > m_rSink
.getLineLengthLimit())
3461 m_rSink
<< "?=" << INetMIMEOutputSink::endl
3462 << " =?" << pCharsetName
<< "?Q?";
3464 INetMIME::writeEscapeSequence(m_rSink
, nUCS4
);
3466 m_rSink
<< sal_Char(nUCS4
);
3468 delete[] pTargetBuffer
;
3474 m_eCoding
= CODING_ENCODED_TERMINATED
;
3477 m_ePrevMIMEEncoding
= eMIMEEncoding
;
3487 m_eInitialSpace
= SPACE_NO
;
3489 m_pEncodingList
->reset();
3490 m_pBufferEnd
= m_pBuffer
;
3491 m_ePrevCoding
= m_eCoding
;
3492 m_eCoding
= CODING_NONE
;
3493 m_nQuotedEscaped
= 0;
3494 m_eEncodedWordState
= STATE_INITIAL
;
3497 INetMIMEEncodedWordOutputSink::~INetMIMEEncodedWordOutputSink()
3499 rtl_freeMemory(m_pBuffer
);
3500 delete m_pEncodingList
;
3503 INetMIMEEncodedWordOutputSink
&
3504 INetMIMEEncodedWordOutputSink::WriteUInt32(sal_uInt32 nChar
)
3508 if (m_pBufferEnd
!= m_pBuffer
)
3514 // Check for an already encoded word:
3515 switch (m_eEncodedWordState
)
3519 m_eEncodedWordState
= STATE_FIRST_EQUALS
;
3521 m_eEncodedWordState
= STATE_BAD
;
3524 case STATE_FIRST_EQUALS
:
3526 m_eEncodedWordState
= STATE_FIRST_EQUALS
;
3528 m_eEncodedWordState
= STATE_BAD
;
3531 case STATE_FIRST_QUESTION
:
3532 if (INetMIME::isEncodedWordTokenChar(nChar
))
3533 m_eEncodedWordState
= STATE_CHARSET
;
3535 m_eEncodedWordState
= STATE_BAD
;
3540 m_eEncodedWordState
= STATE_SECOND_QUESTION
;
3541 else if (!INetMIME::isEncodedWordTokenChar(nChar
))
3542 m_eEncodedWordState
= STATE_BAD
;
3545 case STATE_SECOND_QUESTION
:
3546 if (nChar
== 'B' || nChar
== 'Q'
3547 || nChar
== 'b' || nChar
== 'q')
3548 m_eEncodedWordState
= STATE_ENCODING
;
3550 m_eEncodedWordState
= STATE_BAD
;
3553 case STATE_ENCODING
:
3555 m_eEncodedWordState
= STATE_THIRD_QUESTION
;
3557 m_eEncodedWordState
= STATE_BAD
;
3560 case STATE_THIRD_QUESTION
:
3561 if (INetMIME::isVisible(nChar
) && nChar
!= '?')
3562 m_eEncodedWordState
= STATE_ENCODED_TEXT
;
3564 m_eEncodedWordState
= STATE_BAD
;
3567 case STATE_ENCODED_TEXT
:
3569 m_eEncodedWordState
= STATE_FOURTH_QUESTION
;
3570 else if (!INetMIME::isVisible(nChar
))
3571 m_eEncodedWordState
= STATE_BAD
;
3574 case STATE_FOURTH_QUESTION
:
3576 m_eEncodedWordState
= STATE_SECOND_EQUALS
;
3578 m_eEncodedWordState
= STATE_BAD
;
3581 case STATE_SECOND_EQUALS
:
3582 m_eEncodedWordState
= STATE_BAD
;
3590 m_pEncodingList
->includes(nChar
);
3593 enum { TENQ
= 1, // CONTEXT_TEXT, CODING_ENCODED
3594 CENQ
= 2, // CONTEXT_COMMENT, CODING_ENCODED
3595 PQTD
= 4, // CONTEXT_PHRASE, CODING_QUOTED
3596 PENQ
= 8 }; // CONTEXT_PHRASE, CODING_ENCODED
3597 static const sal_Char aMinimal
[128]
3598 = { TENQ
| CENQ
| PENQ
, // 0x00
3599 TENQ
| CENQ
| PENQ
, // 0x01
3600 TENQ
| CENQ
| PENQ
, // 0x02
3601 TENQ
| CENQ
| PENQ
, // 0x03
3602 TENQ
| CENQ
| PENQ
, // 0x04
3603 TENQ
| CENQ
| PENQ
, // 0x05
3604 TENQ
| CENQ
| PENQ
, // 0x06
3605 TENQ
| CENQ
| PENQ
, // 0x07
3606 TENQ
| CENQ
| PENQ
, // 0x08
3607 TENQ
| CENQ
| PENQ
, // 0x09
3608 TENQ
| CENQ
| PENQ
, // 0x0A
3609 TENQ
| CENQ
| PENQ
, // 0x0B
3610 TENQ
| CENQ
| PENQ
, // 0x0C
3611 TENQ
| CENQ
| PENQ
, // 0x0D
3612 TENQ
| CENQ
| PENQ
, // 0x0E
3613 TENQ
| CENQ
| PENQ
, // 0x0F
3614 TENQ
| CENQ
| PENQ
, // 0x10
3615 TENQ
| CENQ
| PENQ
, // 0x11
3616 TENQ
| CENQ
| PENQ
, // 0x12
3617 TENQ
| CENQ
| PENQ
, // 0x13
3618 TENQ
| CENQ
| PENQ
, // 0x14
3619 TENQ
| CENQ
| PENQ
, // 0x15
3620 TENQ
| CENQ
| PENQ
, // 0x16
3621 TENQ
| CENQ
| PENQ
, // 0x17
3622 TENQ
| CENQ
| PENQ
, // 0x18
3623 TENQ
| CENQ
| PENQ
, // 0x19
3624 TENQ
| CENQ
| PENQ
, // 0x1A
3625 TENQ
| CENQ
| PENQ
, // 0x1B
3626 TENQ
| CENQ
| PENQ
, // 0x1C
3627 TENQ
| CENQ
| PENQ
, // 0x1D
3628 TENQ
| CENQ
| PENQ
, // 0x1E
3629 TENQ
| CENQ
| PENQ
, // 0x1F
3638 CENQ
| PQTD
, // '('
3639 CENQ
| PQTD
, // ')'
3690 CENQ
| PQTD
, // '\'
3725 TENQ
| CENQ
| PENQ
}; // DEL
3726 Coding eNewCoding
= !rtl::isAscii(nChar
) ? CODING_ENCODED
:
3727 m_eContext
== CONTEXT_PHRASE
?
3728 Coding(aMinimal
[nChar
] >> 2) :
3729 aMinimal
[nChar
] & m_eContext
? CODING_ENCODED
:
3731 if (eNewCoding
> m_eCoding
)
3732 m_eCoding
= eNewCoding
;
3733 if (m_eCoding
== CODING_QUOTED
3734 && INetMIME::needsQuotedStringEscape(nChar
))
3737 // Append to buffer:
3738 if (sal_uInt32(m_pBufferEnd
- m_pBuffer
) == m_nBufferSize
)
3741 = static_cast< sal_Unicode
* >(
3742 rtl_reallocateMemory(m_pBuffer
,
3743 (m_nBufferSize
+ BUFFER_SIZE
)
3744 * sizeof (sal_Unicode
)));
3745 m_pBufferEnd
= m_pBuffer
+ m_nBufferSize
;
3746 m_nBufferSize
+= BUFFER_SIZE
;
3748 *m_pBufferEnd
++ = sal_Unicode(nChar
);
3753 // INetContentTypeParameterList
3755 void INetContentTypeParameterList::Clear()
3760 const INetContentTypeParameter
*
3761 INetContentTypeParameterList::find(const OString
& rAttribute
) const
3763 boost::ptr_vector
<INetContentTypeParameter
>::const_iterator iter
;
3764 for (iter
= maEntries
.begin(); iter
!= maEntries
.end(); ++iter
)
3766 if (iter
->m_sAttribute
.equalsIgnoreAsciiCase(rAttribute
))
3773 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */