Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <cstddef>
21 : #include <limits>
22 :
23 : #include <rtl/ustring.hxx>
24 : #include <rtl/strbuf.hxx>
25 : #include <rtl/tencinfo.h>
26 : #include <tools/inetmime.hxx>
27 : #include <rtl/character.hxx>
28 :
29 : namespace unnamed_tools_inetmime {} using namespace unnamed_tools_inetmime;
30 : // unnamed namespaces don't work well yet
31 :
32 : namespace unnamed_tools_inetmime {
33 :
34 : class Charset
35 : {
36 : rtl_TextEncoding m_eEncoding;
37 : const sal_uInt32 * m_pRanges;
38 :
39 : public:
40 : inline Charset(rtl_TextEncoding eTheEncoding,
41 : const sal_uInt32 * pTheRanges);
42 :
43 0 : rtl_TextEncoding getEncoding() const { return m_eEncoding; }
44 :
45 : bool contains(sal_uInt32 nChar) const;
46 : };
47 :
48 0 : inline Charset::Charset(rtl_TextEncoding eTheEncoding,
49 : const sal_uInt32 * pTheRanges):
50 : m_eEncoding(eTheEncoding),
51 0 : m_pRanges(pTheRanges)
52 : {
53 : DBG_ASSERT(m_pRanges, "Charset::Charset(): Bad ranges");
54 0 : }
55 :
56 : void appendISO88591(OUString & rText, sal_Char const * pBegin,
57 : sal_Char const * pEnd);
58 :
59 : }
60 :
61 : class INetMIMECharsetList_Impl
62 : {
63 : struct Node
64 : {
65 : Charset m_aCharset;
66 : bool m_bDisabled;
67 : Node * m_pNext;
68 :
69 : inline Node(const Charset & rTheCharset, bool bTheDisabled,
70 : Node * pTheNext);
71 : };
72 :
73 : Node * m_pFirst;
74 :
75 : public:
76 0 : INetMIMECharsetList_Impl(): m_pFirst(0) {}
77 :
78 : ~INetMIMECharsetList_Impl();
79 :
80 0 : void prepend(const Charset & rCharset)
81 0 : { m_pFirst = new Node(rCharset, false, m_pFirst); }
82 :
83 : void includes(sal_uInt32 nChar);
84 :
85 : rtl_TextEncoding getPreferredEncoding(rtl_TextEncoding eDefault
86 : = RTL_TEXTENCODING_DONTKNOW)
87 : const;
88 :
89 : void reset();
90 : };
91 :
92 0 : inline INetMIMECharsetList_Impl::Node::Node(const Charset & rTheCharset,
93 : bool bTheDisabled,
94 : Node * pTheNext):
95 : m_aCharset(rTheCharset),
96 : m_bDisabled(bTheDisabled),
97 0 : m_pNext(pTheNext)
98 0 : {}
99 :
100 : namespace unnamed_tools_inetmime {
101 :
102 30 : struct Parameter
103 : {
104 : Parameter * m_pNext;
105 : OString m_aAttribute;
106 : OString m_aCharset;
107 : OString m_aLanguage;
108 : OString m_aValue;
109 : sal_uInt32 m_nSection;
110 : bool m_bExtended;
111 :
112 : inline Parameter(Parameter * pTheNext, const OString& rTheAttribute,
113 : const OString& rTheCharset,
114 : const OString& rTheLanguage,
115 : const OString& rTheValue, sal_uInt32 nTheSection,
116 : bool bTheExtended);
117 : };
118 :
119 30 : inline Parameter::Parameter(Parameter * pTheNext,
120 : const OString& rTheAttribute,
121 : const OString& rTheCharset,
122 : const OString& rTheLanguage,
123 : const OString& rTheValue,
124 : sal_uInt32 nTheSection, bool bTheExtended):
125 : m_pNext(pTheNext),
126 : m_aAttribute(rTheAttribute),
127 : m_aCharset(rTheCharset),
128 : m_aLanguage(rTheLanguage),
129 : m_aValue(rTheValue),
130 : m_nSection(nTheSection),
131 30 : m_bExtended(bTheExtended)
132 30 : {}
133 :
134 : struct ParameterList
135 : {
136 : Parameter * m_pList;
137 :
138 44 : ParameterList(): m_pList(0) {}
139 :
140 : inline ~ParameterList();
141 :
142 : Parameter ** find(const OString& rAttribute, sal_uInt32 nSection,
143 : bool & rPresent);
144 : };
145 :
146 44 : inline ParameterList::~ParameterList()
147 : {
148 118 : while (m_pList)
149 : {
150 30 : Parameter * pNext = m_pList->m_pNext;
151 30 : delete m_pList;
152 30 : m_pList = pNext;
153 : }
154 44 : }
155 :
156 : bool parseParameters(ParameterList const & rInput,
157 : INetContentTypeParameterList * pOutput);
158 :
159 : }
160 :
161 : // Charset
162 :
163 0 : bool Charset::contains(sal_uInt32 nChar) const
164 : {
165 0 : for (const sal_uInt32 * p = m_pRanges;;)
166 : {
167 0 : if (nChar < *p++)
168 0 : return false;
169 0 : if (nChar <= *p++)
170 0 : return true;
171 0 : }
172 : }
173 :
174 : // appendISO88591
175 :
176 : namespace unnamed_tools_inetmime {
177 :
178 12 : void appendISO88591(OUString & rText, sal_Char const * pBegin,
179 : sal_Char const * pEnd)
180 : {
181 12 : sal_Int32 nLength = pEnd - pBegin;
182 12 : sal_Unicode * pBuffer = new sal_Unicode[nLength];
183 24 : for (sal_Unicode * p = pBuffer; pBegin != pEnd;)
184 0 : *p++ = static_cast<unsigned char>(*pBegin++);
185 12 : rText += OUString(pBuffer, nLength);
186 12 : delete[] pBuffer;
187 12 : }
188 :
189 : }
190 :
191 : // INetMIMECharsetList_Impl
192 :
193 0 : INetMIMECharsetList_Impl::~INetMIMECharsetList_Impl()
194 : {
195 0 : while (m_pFirst)
196 : {
197 0 : Node * pRemove = m_pFirst;
198 0 : m_pFirst = m_pFirst->m_pNext;
199 0 : delete pRemove;
200 : }
201 0 : }
202 :
203 0 : void INetMIMECharsetList_Impl::includes(sal_uInt32 nChar)
204 : {
205 0 : for (Node * p = m_pFirst; p; p = p->m_pNext)
206 0 : if (!(p->m_bDisabled || p->m_aCharset.contains(nChar)))
207 0 : p->m_bDisabled = true;
208 0 : }
209 :
210 0 : rtl_TextEncoding INetMIMECharsetList_Impl::getPreferredEncoding(rtl_TextEncoding eDefault)
211 : const
212 : {
213 0 : for (Node * p = m_pFirst; p; p = p->m_pNext)
214 0 : if (!p->m_bDisabled)
215 0 : return p->m_aCharset.getEncoding();
216 0 : return eDefault;
217 : }
218 :
219 0 : void INetMIMECharsetList_Impl::reset()
220 : {
221 0 : for (Node * p = m_pFirst; p; p = p->m_pNext)
222 0 : p->m_bDisabled = false;
223 0 : }
224 :
225 : // ParameterList
226 :
227 36 : Parameter ** ParameterList::find(const OString& rAttribute,
228 : sal_uInt32 nSection, bool & rPresent)
229 : {
230 36 : Parameter ** p = &m_pList;
231 40 : for (; *p; p = &(*p)->m_pNext)
232 : {
233 4 : sal_Int32 nCompare = rAttribute.compareTo((*p)->m_aAttribute);
234 4 : if (nCompare > 0)
235 0 : break;
236 4 : else if (nCompare == 0)
237 : {
238 0 : if (nSection > (*p)->m_nSection)
239 0 : break;
240 0 : else if (nSection == (*p)->m_nSection)
241 : {
242 0 : rPresent = true;
243 0 : return p;
244 : }
245 : }
246 : }
247 36 : rPresent = false;
248 36 : return p;
249 : }
250 :
251 : // parseParameters
252 :
253 : namespace unnamed_tools_inetmime {
254 :
255 44 : bool parseParameters(ParameterList const & rInput,
256 : INetContentTypeParameterList * pOutput)
257 : {
258 44 : if (pOutput)
259 34 : pOutput->Clear();
260 :
261 44 : Parameter * pPrev = 0;
262 74 : for (Parameter * p = rInput.m_pList; p; p = p->m_pNext)
263 : {
264 60 : if (p->m_nSection > 0
265 30 : && (!pPrev
266 0 : || pPrev->m_nSection != p->m_nSection - 1
267 0 : || pPrev->m_aAttribute != p->m_aAttribute))
268 0 : return false;
269 30 : pPrev = p;
270 : }
271 :
272 44 : if (pOutput)
273 90 : for (Parameter * p = rInput.m_pList; p;)
274 : {
275 22 : bool bCharset = !p->m_aCharset.isEmpty();
276 22 : rtl_TextEncoding eEncoding = RTL_TEXTENCODING_DONTKNOW;
277 22 : if (bCharset)
278 : eEncoding
279 : = INetMIME::getCharsetEncoding(p->m_aCharset.getStr(),
280 0 : p->m_aCharset.getStr()
281 : + rInput.m_pList->
282 : m_aCharset.
283 0 : getLength());
284 22 : OUString aValue;
285 22 : bool bBadEncoding = false;
286 22 : Parameter * pNext = p;
287 22 : do
288 : {
289 : sal_Size nSize;
290 : sal_Unicode * pUnicode
291 : = INetMIME::convertToUnicode(pNext->m_aValue.getStr(),
292 22 : pNext->m_aValue.getStr()
293 22 : + pNext->m_aValue.getLength(),
294 0 : bCharset && p->m_bExtended ?
295 : eEncoding :
296 : RTL_TEXTENCODING_UTF8,
297 44 : nSize);
298 22 : if (!pUnicode && !(bCharset && p->m_bExtended))
299 : pUnicode = INetMIME::convertToUnicode(
300 : pNext->m_aValue.getStr(),
301 0 : pNext->m_aValue.getStr()
302 0 : + pNext->m_aValue.getLength(),
303 0 : RTL_TEXTENCODING_ISO_8859_1, nSize);
304 22 : if (!pUnicode)
305 : {
306 0 : bBadEncoding = true;
307 0 : break;
308 : }
309 22 : aValue += OUString(pUnicode, static_cast<sal_Int32>(nSize));
310 22 : delete[] pUnicode;
311 22 : pNext = pNext->m_pNext;
312 : }
313 0 : while (pNext && pNext->m_nSection > 0);
314 22 : if (bBadEncoding)
315 : {
316 0 : aValue = OUString();
317 0 : for (pNext = p;;)
318 : {
319 0 : if (pNext->m_bExtended)
320 : {
321 0 : for (sal_Int32 i = 0; i < pNext->m_aValue.getLength(); ++i)
322 0 : aValue += OUString(sal_Unicode(
323 : sal_Unicode(
324 0 : static_cast<unsigned char>(pNext->m_aValue[i]))
325 0 : | 0xF800));
326 : }
327 : else
328 : {
329 0 : for (sal_Int32 i = 0; i < pNext->m_aValue.getLength(); ++i)
330 0 : aValue += OUString( sal_Unicode(static_cast<unsigned char>(pNext->m_aValue[i])) );
331 : }
332 0 : pNext = pNext->m_pNext;
333 0 : if (!pNext || pNext->m_nSection == 0)
334 : break;
335 0 : };
336 : }
337 : pOutput->Append(new INetContentTypeParameter(p->m_aAttribute,
338 : p->m_aCharset,
339 : p->m_aLanguage,
340 : aValue,
341 22 : !bBadEncoding));
342 22 : p = pNext;
343 22 : }
344 44 : return true;
345 : }
346 :
347 : }
348 :
349 : // INetMIME
350 :
351 : // static
352 2452 : bool INetMIME::isAtomChar(sal_uInt32 nChar)
353 : {
354 : static const bool aMap[128]
355 : = { false, false, false, false, false, false, false, false,
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, true, false, true, true, true, true, true, // !"#$%&'
360 : false, false, true, true, false, true, false, true, //()*+,-./
361 : true, true, true, true, true, true, true, true, //01234567
362 : true, true, false, false, false, true, false, true, //89:;<=>?
363 : false, true, true, true, true, true, true, true, //@ABCDEFG
364 : true, true, true, true, true, true, true, true, //HIJKLMNO
365 : true, true, true, true, true, true, true, true, //PQRSTUVW
366 : true, true, true, false, false, false, true, true, //XYZ[\]^_
367 : true, true, true, true, true, true, true, true, //`abcdefg
368 : true, true, true, true, true, true, true, true, //hijklmno
369 : true, true, true, true, true, true, true, true, //pqrstuvw
370 : true, true, true, true, true, true, true, false //xyz{|}~
371 : };
372 2452 : return rtl::isAscii(nChar) && aMap[nChar];
373 : }
374 :
375 : // static
376 1342 : bool INetMIME::isTokenChar(sal_uInt32 nChar)
377 : {
378 : static const bool aMap[128]
379 : = { false, false, false, false, false, false, false, false,
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, true, false, true, true, true, true, true, // !"#$%&'
384 : false, false, true, true, false, true, true, false, //()*+,-./
385 : true, true, true, true, true, true, true, true, //01234567
386 : true, true, false, false, false, false, false, false, //89:;<=>?
387 : false, true, true, true, true, true, true, true, //@ABCDEFG
388 : true, true, true, true, true, true, true, true, //HIJKLMNO
389 : true, true, true, true, true, true, true, true, //PQRSTUVW
390 : true, true, true, false, false, false, true, true, //XYZ[\]^_
391 : true, true, true, true, true, true, true, true, //`abcdefg
392 : true, true, true, true, true, true, true, true, //hijklmno
393 : true, true, true, true, true, true, true, true, //pqrstuvw
394 : true, true, true, true, true, true, true, false //xyz{|}~
395 : };
396 1342 : return rtl::isAscii(nChar) && aMap[nChar];
397 : }
398 :
399 : // static
400 0 : bool INetMIME::isEncodedWordTokenChar(sal_uInt32 nChar)
401 : {
402 : static const bool aMap[128]
403 : = { false, false, false, false, false, false, false, false,
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, true, false, true, true, true, true, true, // !"#$%&'
408 : false, false, true, true, false, true, false, false, //()*+,-./
409 : true, true, true, true, true, true, true, true, //01234567
410 : true, true, false, false, false, false, false, false, //89:;<=>?
411 : false, true, true, true, true, true, true, true, //@ABCDEFG
412 : true, true, true, true, true, true, true, true, //HIJKLMNO
413 : true, true, true, true, true, true, true, true, //PQRSTUVW
414 : true, true, true, false, false, false, true, true, //XYZ[\]^_
415 : true, true, true, true, true, true, true, true, //`abcdefg
416 : true, true, true, true, true, true, true, true, //hijklmno
417 : true, true, true, true, true, true, true, true, //pqrstuvw
418 : true, true, true, true, true, true, true, false //xyz{|}~
419 : };
420 0 : return rtl::isAscii(nChar) && aMap[nChar];
421 : }
422 :
423 : // static
424 0 : bool INetMIME::isIMAPAtomChar(sal_uInt32 nChar)
425 : {
426 : static const bool aMap[128]
427 : = { false, false, false, false, false, false, false, false,
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, true, false, true, true, false, true, true, // !"#$%&'
432 : false, false, false, true, true, true, true, true, //()*+,-./
433 : true, true, true, true, true, true, true, true, //01234567
434 : true, true, true, true, true, true, true, true, //89:;<=>?
435 : true, true, true, true, true, true, true, true, //@ABCDEFG
436 : true, true, true, true, true, true, true, true, //HIJKLMNO
437 : true, true, true, true, true, true, true, true, //PQRSTUVW
438 : true, true, true, true, false, true, true, true, //XYZ[\]^_
439 : true, true, true, true, true, true, true, true, //`abcdefg
440 : true, true, true, true, true, true, true, true, //hijklmno
441 : true, true, true, true, true, true, true, true, //pqrstuvw
442 : true, true, true, false, true, true, true, false //xyz{|}~
443 : };
444 0 : return rtl::isAscii(nChar) && aMap[nChar];
445 : }
446 :
447 : // static
448 405516 : sal_uInt32 INetMIME::getHexDigit(int nWeight)
449 : {
450 : DBG_ASSERT(nWeight >= 0 && nWeight < 16,
451 : "INetMIME::getHexDigit(): Bad weight");
452 :
453 : static const sal_Char aDigits[16]
454 : = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C',
455 : 'D', 'E', 'F' };
456 405516 : return aDigits[nWeight];
457 : }
458 :
459 : // static
460 72 : bool INetMIME::equalIgnoreCase(const sal_Char * pBegin1,
461 : const sal_Char * pEnd1,
462 : const sal_Char * pString2)
463 : {
464 : DBG_ASSERT(pBegin1 && pBegin1 <= pEnd1 && pString2,
465 : "INetMIME::equalIgnoreCase(): Bad sequences");
466 :
467 270 : while (*pString2 != 0)
468 192 : if (pBegin1 == pEnd1
469 192 : || rtl::toAsciiUpperCase(*pBegin1++) != rtl::toAsciiUpperCase(*pString2++))
470 66 : return false;
471 6 : return pBegin1 == pEnd1;
472 : }
473 :
474 : // static
475 761572 : bool INetMIME::equalIgnoreCase(const sal_Unicode * pBegin1,
476 : const sal_Unicode * pEnd1,
477 : const sal_Char * pString2)
478 : {
479 : DBG_ASSERT(pBegin1 && pBegin1 <= pEnd1 && pString2,
480 : "INetMIME::equalIgnoreCase(): Bad sequences");
481 :
482 1523144 : while (*pString2 != 0)
483 761572 : if (pBegin1 == pEnd1
484 761572 : || rtl::toAsciiUpperCase(*pBegin1++) != rtl::toAsciiUpperCase(*pString2++))
485 761572 : return false;
486 0 : return pBegin1 == pEnd1;
487 : }
488 :
489 : // static
490 0 : const sal_Unicode * INetMIME::skipLinearWhiteSpace(const sal_Unicode * pBegin,
491 : const sal_Unicode * pEnd)
492 : {
493 : DBG_ASSERT(pBegin && pBegin <= pEnd,
494 : "INetMIME::skipLinearWhiteSpace(): Bad sequence");
495 :
496 0 : while (pBegin != pEnd)
497 0 : switch (*pBegin)
498 : {
499 : case '\t':
500 : case ' ':
501 0 : ++pBegin;
502 0 : break;
503 :
504 : case 0x0D: // CR
505 0 : if (startsWithLineFolding(pBegin, pEnd))
506 0 : pBegin += 3;
507 : else
508 0 : return pBegin;
509 0 : break;
510 :
511 : default:
512 0 : return pBegin;
513 : }
514 0 : return pBegin;
515 : }
516 :
517 : // static
518 0 : const sal_Unicode * INetMIME::skipComment(const sal_Unicode * pBegin,
519 : const sal_Unicode * pEnd)
520 : {
521 : DBG_ASSERT(pBegin && pBegin <= pEnd,
522 : "INetMIME::skipComment(): Bad sequence");
523 :
524 0 : if (pBegin != pEnd && *pBegin == '(')
525 : {
526 0 : sal_uInt32 nLevel = 0;
527 0 : for (const sal_Unicode * p = pBegin; p != pEnd;)
528 0 : switch (*p++)
529 : {
530 : case '(':
531 0 : ++nLevel;
532 0 : break;
533 :
534 : case ')':
535 0 : if (--nLevel == 0)
536 0 : return p;
537 0 : break;
538 :
539 : case '\\':
540 0 : if (p != pEnd)
541 0 : ++p;
542 0 : break;
543 : }
544 : }
545 0 : return pBegin;
546 : }
547 :
548 : // static
549 336 : const sal_Unicode * INetMIME::skipLinearWhiteSpaceComment(const sal_Unicode *
550 : pBegin,
551 : const sal_Unicode *
552 : pEnd)
553 : {
554 : DBG_ASSERT(pBegin && pBegin <= pEnd,
555 : "INetMIME::skipLinearWhiteSpaceComment(): Bad sequence");
556 :
557 686 : while (pBegin != pEnd)
558 312 : switch (*pBegin)
559 : {
560 : case '\t':
561 : case ' ':
562 14 : ++pBegin;
563 14 : break;
564 :
565 : case 0x0D: // CR
566 0 : if (startsWithLineFolding(pBegin, pEnd))
567 0 : pBegin += 3;
568 : else
569 0 : return pBegin;
570 0 : break;
571 :
572 : case '(':
573 : {
574 0 : const sal_Unicode * p = skipComment(pBegin, pEnd);
575 0 : if (p == pBegin)
576 0 : return pBegin;
577 0 : pBegin = p;
578 0 : break;
579 : }
580 :
581 : default:
582 298 : return pBegin;
583 : }
584 38 : return pBegin;
585 : }
586 :
587 : // static
588 0 : const sal_Char * INetMIME::skipQuotedString(const sal_Char * pBegin,
589 : const sal_Char * pEnd)
590 : {
591 : DBG_ASSERT(pBegin && pBegin <= pEnd,
592 : "INetMIME::skipQuotedString(): Bad sequence");
593 :
594 0 : if (pBegin != pEnd && *pBegin == '"')
595 0 : for (const sal_Char * p = pBegin + 1; p != pEnd;)
596 0 : switch (*p++)
597 : {
598 : case 0x0D: // CR
599 0 : if (pEnd - p < 2 || *p++ != 0x0A // LF
600 0 : || !isWhiteSpace(*p++))
601 0 : return pBegin;
602 0 : break;
603 :
604 : case '"':
605 0 : return p;
606 :
607 : case '\\':
608 0 : if (p != pEnd)
609 0 : ++p;
610 0 : break;
611 : }
612 0 : return pBegin;
613 : }
614 :
615 : // static
616 2 : const sal_Unicode * INetMIME::skipQuotedString(const sal_Unicode * pBegin,
617 : const sal_Unicode * pEnd)
618 : {
619 : DBG_ASSERT(pBegin && pBegin <= pEnd,
620 : "INetMIME::skipQuotedString(): Bad sequence");
621 :
622 2 : if (pBegin != pEnd && *pBegin == '"')
623 20 : for (const sal_Unicode * p = pBegin + 1; p != pEnd;)
624 18 : switch (*p++)
625 : {
626 : case 0x0D: // CR
627 0 : if (pEnd - p < 2 || *p++ != 0x0A // LF
628 0 : || !isWhiteSpace(*p++))
629 0 : return pBegin;
630 0 : break;
631 :
632 : case '"':
633 2 : return p;
634 :
635 : case '\\':
636 0 : if (p != pEnd)
637 0 : ++p;
638 0 : break;
639 : }
640 0 : return pBegin;
641 : }
642 :
643 : // static
644 0 : bool INetMIME::scanUnsigned(const sal_Unicode *& rBegin,
645 : const sal_Unicode * pEnd, bool bLeadingZeroes,
646 : sal_uInt32 & rValue)
647 : {
648 0 : sal_uInt64 nTheValue = 0;
649 0 : const sal_Unicode * p = rBegin;
650 0 : for ( ; p != pEnd; ++p)
651 : {
652 0 : int nWeight = getWeight(*p);
653 0 : if (nWeight < 0)
654 0 : break;
655 0 : nTheValue = 10 * nTheValue + nWeight;
656 0 : if (nTheValue > std::numeric_limits< sal_uInt32 >::max())
657 0 : return false;
658 : }
659 0 : if (nTheValue == 0 && (p == rBegin || (!bLeadingZeroes && p - rBegin != 1)))
660 0 : return false;
661 0 : rBegin = p;
662 0 : rValue = sal_uInt32(nTheValue);
663 0 : return true;
664 : }
665 :
666 : // static
667 0 : const sal_Unicode * INetMIME::scanQuotedBlock(const sal_Unicode * pBegin,
668 : const sal_Unicode * pEnd,
669 : sal_uInt32 nOpening,
670 : sal_uInt32 nClosing,
671 : sal_Size & rLength,
672 : bool & rModify)
673 : {
674 : DBG_ASSERT(pBegin && pBegin <= pEnd,
675 : "INetMIME::scanQuotedBlock(): Bad sequence");
676 :
677 0 : if (pBegin != pEnd && *pBegin == nOpening)
678 : {
679 0 : ++rLength;
680 0 : ++pBegin;
681 0 : while (pBegin != pEnd)
682 0 : if (*pBegin == nClosing)
683 : {
684 0 : ++rLength;
685 0 : return ++pBegin;
686 : }
687 : else
688 : {
689 0 : sal_uInt32 c = *pBegin++;
690 0 : switch (c)
691 : {
692 : case 0x0D: // CR
693 0 : if (pBegin != pEnd && *pBegin == 0x0A) // LF
694 0 : if (pEnd - pBegin >= 2 && isWhiteSpace(pBegin[1]))
695 : {
696 0 : ++rLength;
697 0 : rModify = true;
698 0 : pBegin += 2;
699 : }
700 : else
701 : {
702 0 : rLength += 3;
703 0 : rModify = true;
704 0 : ++pBegin;
705 : }
706 : else
707 0 : ++rLength;
708 0 : break;
709 :
710 : case '\\':
711 0 : ++rLength;
712 0 : if (pBegin != pEnd)
713 : {
714 0 : if (startsWithLineBreak(pBegin, pEnd)
715 0 : && (pEnd - pBegin < 3
716 0 : || !isWhiteSpace(pBegin[2])))
717 : {
718 0 : rLength += 3;
719 0 : rModify = true;
720 0 : pBegin += 2;
721 : }
722 : else
723 0 : ++pBegin;
724 : }
725 0 : break;
726 :
727 : default:
728 0 : ++rLength;
729 0 : if (!rtl::isAscii(c))
730 0 : rModify = true;
731 0 : break;
732 : }
733 : }
734 : }
735 0 : return pBegin;
736 : }
737 :
738 : // static
739 44 : sal_Unicode const * INetMIME::scanParameters(sal_Unicode const * pBegin,
740 : sal_Unicode const * pEnd,
741 : INetContentTypeParameterList *
742 : pParameters)
743 : {
744 44 : ParameterList aList;
745 44 : sal_Unicode const * pParameterBegin = pBegin;
746 74 : for (sal_Unicode const * p = pParameterBegin;; pParameterBegin = p)
747 : {
748 74 : pParameterBegin = skipLinearWhiteSpaceComment(p, pEnd);
749 74 : if (pParameterBegin == pEnd || *pParameterBegin != ';')
750 : break;
751 36 : p = pParameterBegin + 1;
752 :
753 : sal_Unicode const * pAttributeBegin
754 36 : = skipLinearWhiteSpaceComment(p, pEnd);
755 36 : p = pAttributeBegin;
756 36 : bool bDowncaseAttribute = false;
757 264 : while (p != pEnd && isTokenChar(*p) && *p != '*')
758 : {
759 192 : bDowncaseAttribute = bDowncaseAttribute || rtl::isAsciiUpperCase(*p);
760 192 : ++p;
761 : }
762 36 : if (p == pAttributeBegin)
763 0 : break;
764 : OString aAttribute = OString(
765 36 : pAttributeBegin, p - pAttributeBegin,
766 36 : RTL_TEXTENCODING_ASCII_US);
767 36 : if (bDowncaseAttribute)
768 0 : aAttribute = aAttribute.toAsciiLowerCase();
769 :
770 36 : sal_uInt32 nSection = 0;
771 36 : if (p != pEnd && *p == '*')
772 : {
773 0 : ++p;
774 0 : if (p != pEnd && rtl::isAsciiDigit(*p)
775 0 : && !scanUnsigned(p, pEnd, false, nSection))
776 0 : break;
777 : }
778 :
779 : bool bPresent;
780 36 : Parameter ** pPos = aList.find(aAttribute, nSection, bPresent);
781 36 : if (bPresent)
782 0 : break;
783 :
784 36 : bool bExtended = false;
785 36 : if (p != pEnd && *p == '*')
786 : {
787 0 : ++p;
788 0 : bExtended = true;
789 : }
790 :
791 36 : p = skipLinearWhiteSpaceComment(p, pEnd);
792 :
793 36 : if (p == pEnd || *p != '=')
794 : break;
795 :
796 30 : p = skipLinearWhiteSpaceComment(p + 1, pEnd);
797 :
798 60 : OString aCharset;
799 60 : OString aLanguage;
800 60 : OString aValue;
801 30 : if (bExtended)
802 : {
803 0 : if (nSection == 0)
804 : {
805 0 : sal_Unicode const * pCharsetBegin = p;
806 0 : bool bDowncaseCharset = false;
807 0 : while (p != pEnd && isTokenChar(*p) && *p != '\'')
808 : {
809 0 : bDowncaseCharset = bDowncaseCharset || rtl::isAsciiUpperCase(*p);
810 0 : ++p;
811 : }
812 0 : if (p == pCharsetBegin)
813 0 : break;
814 0 : if (pParameters)
815 : {
816 0 : aCharset = OString(
817 : pCharsetBegin,
818 0 : p - pCharsetBegin,
819 0 : RTL_TEXTENCODING_ASCII_US);
820 0 : if (bDowncaseCharset)
821 0 : aCharset = aCharset.toAsciiLowerCase();
822 : }
823 :
824 0 : if (p == pEnd || *p != '\'')
825 : break;
826 0 : ++p;
827 :
828 0 : sal_Unicode const * pLanguageBegin = p;
829 0 : bool bDowncaseLanguage = false;
830 0 : int nLetters = 0;
831 0 : for (; p != pEnd; ++p)
832 0 : if (rtl::isAsciiAlpha(*p))
833 : {
834 0 : if (++nLetters > 8)
835 0 : break;
836 : bDowncaseLanguage = bDowncaseLanguage
837 0 : || rtl::isAsciiUpperCase(*p);
838 : }
839 0 : else if (*p == '-')
840 : {
841 0 : if (nLetters == 0)
842 0 : break;
843 0 : nLetters = 0;
844 : }
845 : else
846 0 : break;
847 0 : if (nLetters == 0 || nLetters > 8)
848 : break;
849 0 : if (pParameters)
850 : {
851 0 : aLanguage = OString(
852 : pLanguageBegin,
853 0 : p - pLanguageBegin,
854 0 : RTL_TEXTENCODING_ASCII_US);
855 0 : if (bDowncaseLanguage)
856 0 : aLanguage = aLanguage.toAsciiLowerCase();
857 : }
858 :
859 0 : if (p == pEnd || *p != '\'')
860 : break;
861 0 : ++p;
862 : }
863 0 : if (pParameters)
864 : {
865 : INetMIMEStringOutputSink
866 0 : aSink(0, INetMIMEOutputSink::NO_LINE_LENGTH_LIMIT);
867 0 : while (p != pEnd)
868 : {
869 0 : sal_uInt32 nChar = INetMIME::getUTF32Character(p, pEnd);
870 0 : if (rtl::isAscii(nChar) && !isTokenChar(nChar))
871 0 : break;
872 0 : if (nChar == '%' && p + 1 < pEnd)
873 : {
874 0 : int nWeight1 = getHexWeight(p[0]);
875 0 : int nWeight2 = getHexWeight(p[1]);
876 0 : if (nWeight1 >= 0 && nWeight2 >= 0)
877 : {
878 0 : aSink << sal_Char(nWeight1 << 4 | nWeight2);
879 0 : p += 2;
880 0 : continue;
881 : }
882 : }
883 0 : INetMIME::writeUTF8(aSink, nChar);
884 : }
885 0 : aValue = aSink.takeBuffer();
886 : }
887 : else
888 0 : while (p != pEnd && (isTokenChar(*p) || !rtl::isAscii(*p)))
889 0 : ++p;
890 : }
891 30 : else if (p != pEnd && *p == '"')
892 2 : if (pParameters)
893 : {
894 : INetMIMEStringOutputSink
895 0 : aSink(0, INetMIMEOutputSink::NO_LINE_LENGTH_LIMIT);
896 0 : bool bInvalid = false;
897 0 : for (++p;;)
898 : {
899 0 : if (p == pEnd)
900 : {
901 0 : bInvalid = true;
902 0 : break;
903 : }
904 0 : sal_uInt32 nChar = INetMIME::getUTF32Character(p, pEnd);
905 0 : if (nChar == '"')
906 0 : break;
907 0 : else if (nChar == 0x0D) // CR
908 : {
909 0 : if (pEnd - p < 2 || *p++ != 0x0A // LF
910 0 : || !isWhiteSpace(*p))
911 : {
912 0 : bInvalid = true;
913 0 : break;
914 : }
915 0 : nChar = static_cast<unsigned char>(*p++);
916 : }
917 0 : else if (nChar == '\\')
918 : {
919 0 : if (p == pEnd)
920 : {
921 0 : bInvalid = true;
922 0 : break;
923 : }
924 0 : nChar = INetMIME::getUTF32Character(p, pEnd);
925 : }
926 0 : INetMIME::writeUTF8(aSink, nChar);
927 0 : }
928 0 : if (bInvalid)
929 0 : break;
930 0 : aValue = aSink.takeBuffer();
931 : }
932 : else
933 : {
934 2 : sal_Unicode const * pStringEnd = skipQuotedString(p, pEnd);
935 2 : if (p == pStringEnd)
936 0 : break;
937 2 : p = pStringEnd;
938 2 : }
939 : else
940 : {
941 28 : sal_Unicode const * pTokenBegin = p;
942 174 : while (p != pEnd && (isTokenChar(*p) || !rtl::isAscii(*p)))
943 118 : ++p;
944 28 : if (p == pTokenBegin)
945 0 : break;
946 28 : if (pParameters)
947 44 : aValue = OString(
948 22 : pTokenBegin, p - pTokenBegin,
949 22 : RTL_TEXTENCODING_UTF8);
950 : }
951 :
952 : *pPos = new Parameter(*pPos, aAttribute, aCharset, aLanguage, aValue,
953 30 : nSection, bExtended);
954 60 : }
955 44 : return parseParameters(aList, pParameters) ? pParameterBegin : pBegin;
956 : }
957 :
958 : // static
959 66 : sal_Unicode const * INetMIME::scanContentType(
960 : sal_Unicode const * pBegin, sal_Unicode const * pEnd, OUString * pType,
961 : OUString * pSubType, INetContentTypeParameterList * pParameters)
962 : {
963 66 : sal_Unicode const * p = INetMIME::skipLinearWhiteSpaceComment(pBegin, pEnd);
964 66 : sal_Unicode const * pTypeBegin = p;
965 452 : while (p != pEnd && INetMIME::isTokenChar(*p))
966 : {
967 320 : ++p;
968 : }
969 66 : if (p == pTypeBegin)
970 16 : return 0;
971 50 : sal_Unicode const * pTypeEnd = p;
972 :
973 50 : p = INetMIME::skipLinearWhiteSpaceComment(p, pEnd);
974 50 : if (p == pEnd || *p++ != '/')
975 6 : return 0;
976 :
977 44 : p = INetMIME::skipLinearWhiteSpaceComment(p, pEnd);
978 44 : sal_Unicode const * pSubTypeBegin = p;
979 664 : while (p != pEnd && INetMIME::isTokenChar(*p))
980 : {
981 576 : ++p;
982 : }
983 44 : if (p == pSubTypeBegin)
984 0 : return 0;
985 44 : sal_Unicode const * pSubTypeEnd = p;
986 :
987 44 : if (pType != 0)
988 : {
989 36 : *pType = OUString(pTypeBegin, pTypeEnd - pTypeBegin).toAsciiLowerCase();
990 : }
991 44 : if (pSubType != 0)
992 : {
993 72 : *pSubType = OUString(pSubTypeBegin, pSubTypeEnd - pSubTypeBegin)
994 36 : .toAsciiLowerCase();
995 : }
996 :
997 44 : return INetMIME::scanParameters(p, pEnd, pParameters);
998 : }
999 :
1000 : // static
1001 0 : const sal_Char * INetMIME::getCharsetName(rtl_TextEncoding eEncoding)
1002 : {
1003 0 : if (rtl_isOctetTextEncoding(eEncoding))
1004 : {
1005 0 : char const * p = rtl_getMimeCharsetFromTextEncoding(eEncoding);
1006 : DBG_ASSERT(p, "INetMIME::getCharsetName(): Unsupported encoding");
1007 0 : return p;
1008 : }
1009 : else
1010 0 : switch (eEncoding)
1011 : {
1012 : case RTL_TEXTENCODING_UCS4:
1013 0 : return "ISO-10646-UCS-4";
1014 :
1015 : case RTL_TEXTENCODING_UCS2:
1016 0 : return "ISO-10646-UCS-2";
1017 :
1018 : default:
1019 : OSL_FAIL("INetMIME::getCharsetName(): Unsupported encoding");
1020 0 : return 0;
1021 : }
1022 : }
1023 :
1024 : namespace unnamed_tools_inetmime {
1025 :
1026 : struct EncodingEntry
1027 : {
1028 : sal_Char const * m_aName;
1029 : rtl_TextEncoding m_eEncoding;
1030 : };
1031 :
1032 : // The source for the following table is <ftp://ftp.iana.org/in-notes/iana/
1033 : // assignments/character-sets> as of Jan, 21 2000 12:46:00, unless otherwise
1034 : // noted:
1035 : EncodingEntry const aEncodingMap[]
1036 : = { { "US-ASCII", RTL_TEXTENCODING_ASCII_US },
1037 : { "ANSI_X3.4-1968", RTL_TEXTENCODING_ASCII_US },
1038 : { "ISO-IR-6", RTL_TEXTENCODING_ASCII_US },
1039 : { "ANSI_X3.4-1986", RTL_TEXTENCODING_ASCII_US },
1040 : { "ISO_646.IRV:1991", RTL_TEXTENCODING_ASCII_US },
1041 : { "ASCII", RTL_TEXTENCODING_ASCII_US },
1042 : { "ISO646-US", RTL_TEXTENCODING_ASCII_US },
1043 : { "US", RTL_TEXTENCODING_ASCII_US },
1044 : { "IBM367", RTL_TEXTENCODING_ASCII_US },
1045 : { "CP367", RTL_TEXTENCODING_ASCII_US },
1046 : { "CSASCII", RTL_TEXTENCODING_ASCII_US },
1047 : { "ISO-8859-1", RTL_TEXTENCODING_ISO_8859_1 },
1048 : { "ISO_8859-1:1987", RTL_TEXTENCODING_ISO_8859_1 },
1049 : { "ISO-IR-100", RTL_TEXTENCODING_ISO_8859_1 },
1050 : { "ISO_8859-1", RTL_TEXTENCODING_ISO_8859_1 },
1051 : { "LATIN1", RTL_TEXTENCODING_ISO_8859_1 },
1052 : { "L1", RTL_TEXTENCODING_ISO_8859_1 },
1053 : { "IBM819", RTL_TEXTENCODING_ISO_8859_1 },
1054 : { "CP819", RTL_TEXTENCODING_ISO_8859_1 },
1055 : { "CSISOLATIN1", RTL_TEXTENCODING_ISO_8859_1 },
1056 : { "ISO-8859-2", RTL_TEXTENCODING_ISO_8859_2 },
1057 : { "ISO_8859-2:1987", RTL_TEXTENCODING_ISO_8859_2 },
1058 : { "ISO-IR-101", RTL_TEXTENCODING_ISO_8859_2 },
1059 : { "ISO_8859-2", RTL_TEXTENCODING_ISO_8859_2 },
1060 : { "LATIN2", RTL_TEXTENCODING_ISO_8859_2 },
1061 : { "L2", RTL_TEXTENCODING_ISO_8859_2 },
1062 : { "CSISOLATIN2", RTL_TEXTENCODING_ISO_8859_2 },
1063 : { "ISO-8859-3", RTL_TEXTENCODING_ISO_8859_3 },
1064 : { "ISO_8859-3:1988", RTL_TEXTENCODING_ISO_8859_3 },
1065 : { "ISO-IR-109", RTL_TEXTENCODING_ISO_8859_3 },
1066 : { "ISO_8859-3", RTL_TEXTENCODING_ISO_8859_3 },
1067 : { "LATIN3", RTL_TEXTENCODING_ISO_8859_3 },
1068 : { "L3", RTL_TEXTENCODING_ISO_8859_3 },
1069 : { "CSISOLATIN3", RTL_TEXTENCODING_ISO_8859_3 },
1070 : { "ISO-8859-4", RTL_TEXTENCODING_ISO_8859_4 },
1071 : { "ISO_8859-4:1988", RTL_TEXTENCODING_ISO_8859_4 },
1072 : { "ISO-IR-110", RTL_TEXTENCODING_ISO_8859_4 },
1073 : { "ISO_8859-4", RTL_TEXTENCODING_ISO_8859_4 },
1074 : { "LATIN4", RTL_TEXTENCODING_ISO_8859_4 },
1075 : { "L4", RTL_TEXTENCODING_ISO_8859_4 },
1076 : { "CSISOLATIN4", RTL_TEXTENCODING_ISO_8859_4 },
1077 : { "ISO-8859-5", RTL_TEXTENCODING_ISO_8859_5 },
1078 : { "ISO_8859-5:1988", RTL_TEXTENCODING_ISO_8859_5 },
1079 : { "ISO-IR-144", RTL_TEXTENCODING_ISO_8859_5 },
1080 : { "ISO_8859-5", RTL_TEXTENCODING_ISO_8859_5 },
1081 : { "CYRILLIC", RTL_TEXTENCODING_ISO_8859_5 },
1082 : { "CSISOLATINCYRILLIC", RTL_TEXTENCODING_ISO_8859_5 },
1083 : { "ISO-8859-6", RTL_TEXTENCODING_ISO_8859_6 },
1084 : { "ISO_8859-6:1987", RTL_TEXTENCODING_ISO_8859_6 },
1085 : { "ISO-IR-127", RTL_TEXTENCODING_ISO_8859_6 },
1086 : { "ISO_8859-6", RTL_TEXTENCODING_ISO_8859_6 },
1087 : { "ECMA-114", RTL_TEXTENCODING_ISO_8859_6 },
1088 : { "ASMO-708", RTL_TEXTENCODING_ISO_8859_6 },
1089 : { "ARABIC", RTL_TEXTENCODING_ISO_8859_6 },
1090 : { "CSISOLATINARABIC", RTL_TEXTENCODING_ISO_8859_6 },
1091 : { "ISO-8859-7", RTL_TEXTENCODING_ISO_8859_7 },
1092 : { "ISO_8859-7:1987", RTL_TEXTENCODING_ISO_8859_7 },
1093 : { "ISO-IR-126", RTL_TEXTENCODING_ISO_8859_7 },
1094 : { "ISO_8859-7", RTL_TEXTENCODING_ISO_8859_7 },
1095 : { "ELOT_928", RTL_TEXTENCODING_ISO_8859_7 },
1096 : { "ECMA-118", RTL_TEXTENCODING_ISO_8859_7 },
1097 : { "GREEK", RTL_TEXTENCODING_ISO_8859_7 },
1098 : { "GREEK8", RTL_TEXTENCODING_ISO_8859_7 },
1099 : { "CSISOLATINGREEK", RTL_TEXTENCODING_ISO_8859_7 },
1100 : { "ISO-8859-8", RTL_TEXTENCODING_ISO_8859_8 },
1101 : { "ISO_8859-8:1988", RTL_TEXTENCODING_ISO_8859_8 },
1102 : { "ISO-IR-138", RTL_TEXTENCODING_ISO_8859_8 },
1103 : { "ISO_8859-8", RTL_TEXTENCODING_ISO_8859_8 },
1104 : { "HEBREW", RTL_TEXTENCODING_ISO_8859_8 },
1105 : { "CSISOLATINHEBREW", RTL_TEXTENCODING_ISO_8859_8 },
1106 : { "ISO-8859-9", RTL_TEXTENCODING_ISO_8859_9 },
1107 : { "ISO_8859-9:1989", RTL_TEXTENCODING_ISO_8859_9 },
1108 : { "ISO-IR-148", RTL_TEXTENCODING_ISO_8859_9 },
1109 : { "ISO_8859-9", RTL_TEXTENCODING_ISO_8859_9 },
1110 : { "LATIN5", RTL_TEXTENCODING_ISO_8859_9 },
1111 : { "L5", RTL_TEXTENCODING_ISO_8859_9 },
1112 : { "CSISOLATIN5", RTL_TEXTENCODING_ISO_8859_9 },
1113 : { "ISO-8859-14", RTL_TEXTENCODING_ISO_8859_14 }, // RFC 2047
1114 : { "ISO_8859-15", RTL_TEXTENCODING_ISO_8859_15 },
1115 : { "ISO-8859-15", RTL_TEXTENCODING_ISO_8859_15 }, // RFC 2047
1116 : { "MACINTOSH", RTL_TEXTENCODING_APPLE_ROMAN },
1117 : { "MAC", RTL_TEXTENCODING_APPLE_ROMAN },
1118 : { "CSMACINTOSH", RTL_TEXTENCODING_APPLE_ROMAN },
1119 : { "IBM437", RTL_TEXTENCODING_IBM_437 },
1120 : { "CP437", RTL_TEXTENCODING_IBM_437 },
1121 : { "437", RTL_TEXTENCODING_IBM_437 },
1122 : { "CSPC8CODEPAGE437", RTL_TEXTENCODING_IBM_437 },
1123 : { "IBM850", RTL_TEXTENCODING_IBM_850 },
1124 : { "CP850", RTL_TEXTENCODING_IBM_850 },
1125 : { "850", RTL_TEXTENCODING_IBM_850 },
1126 : { "CSPC850MULTILINGUAL", RTL_TEXTENCODING_IBM_850 },
1127 : { "IBM860", RTL_TEXTENCODING_IBM_860 },
1128 : { "CP860", RTL_TEXTENCODING_IBM_860 },
1129 : { "860", RTL_TEXTENCODING_IBM_860 },
1130 : { "CSIBM860", RTL_TEXTENCODING_IBM_860 },
1131 : { "IBM861", RTL_TEXTENCODING_IBM_861 },
1132 : { "CP861", RTL_TEXTENCODING_IBM_861 },
1133 : { "861", RTL_TEXTENCODING_IBM_861 },
1134 : { "CP-IS", RTL_TEXTENCODING_IBM_861 },
1135 : { "CSIBM861", RTL_TEXTENCODING_IBM_861 },
1136 : { "IBM863", RTL_TEXTENCODING_IBM_863 },
1137 : { "CP863", RTL_TEXTENCODING_IBM_863 },
1138 : { "863", RTL_TEXTENCODING_IBM_863 },
1139 : { "CSIBM863", RTL_TEXTENCODING_IBM_863 },
1140 : { "IBM865", RTL_TEXTENCODING_IBM_865 },
1141 : { "CP865", RTL_TEXTENCODING_IBM_865 },
1142 : { "865", RTL_TEXTENCODING_IBM_865 },
1143 : { "CSIBM865", RTL_TEXTENCODING_IBM_865 },
1144 : { "IBM775", RTL_TEXTENCODING_IBM_775 },
1145 : { "CP775", RTL_TEXTENCODING_IBM_775 },
1146 : { "CSPC775BALTIC", RTL_TEXTENCODING_IBM_775 },
1147 : { "IBM852", RTL_TEXTENCODING_IBM_852 },
1148 : { "CP852", RTL_TEXTENCODING_IBM_852 },
1149 : { "852", RTL_TEXTENCODING_IBM_852 },
1150 : { "CSPCP852", RTL_TEXTENCODING_IBM_852 },
1151 : { "IBM855", RTL_TEXTENCODING_IBM_855 },
1152 : { "CP855", RTL_TEXTENCODING_IBM_855 },
1153 : { "855", RTL_TEXTENCODING_IBM_855 },
1154 : { "CSIBM855", RTL_TEXTENCODING_IBM_855 },
1155 : { "IBM857", RTL_TEXTENCODING_IBM_857 },
1156 : { "CP857", RTL_TEXTENCODING_IBM_857 },
1157 : { "857", RTL_TEXTENCODING_IBM_857 },
1158 : { "CSIBM857", RTL_TEXTENCODING_IBM_857 },
1159 : { "IBM862", RTL_TEXTENCODING_IBM_862 },
1160 : { "CP862", RTL_TEXTENCODING_IBM_862 },
1161 : { "862", RTL_TEXTENCODING_IBM_862 },
1162 : { "CSPC862LATINHEBREW", RTL_TEXTENCODING_IBM_862 },
1163 : { "IBM864", RTL_TEXTENCODING_IBM_864 },
1164 : { "CP864", RTL_TEXTENCODING_IBM_864 },
1165 : { "CSIBM864", RTL_TEXTENCODING_IBM_864 },
1166 : { "IBM866", RTL_TEXTENCODING_IBM_866 },
1167 : { "CP866", RTL_TEXTENCODING_IBM_866 },
1168 : { "866", RTL_TEXTENCODING_IBM_866 },
1169 : { "CSIBM866", RTL_TEXTENCODING_IBM_866 },
1170 : { "IBM869", RTL_TEXTENCODING_IBM_869 },
1171 : { "CP869", RTL_TEXTENCODING_IBM_869 },
1172 : { "869", RTL_TEXTENCODING_IBM_869 },
1173 : { "CP-GR", RTL_TEXTENCODING_IBM_869 },
1174 : { "CSIBM869", RTL_TEXTENCODING_IBM_869 },
1175 : { "WINDOWS-1250", RTL_TEXTENCODING_MS_1250 },
1176 : { "WINDOWS-1251", RTL_TEXTENCODING_MS_1251 },
1177 : { "WINDOWS-1253", RTL_TEXTENCODING_MS_1253 },
1178 : { "WINDOWS-1254", RTL_TEXTENCODING_MS_1254 },
1179 : { "WINDOWS-1255", RTL_TEXTENCODING_MS_1255 },
1180 : { "WINDOWS-1256", RTL_TEXTENCODING_MS_1256 },
1181 : { "WINDOWS-1257", RTL_TEXTENCODING_MS_1257 },
1182 : { "WINDOWS-1258", RTL_TEXTENCODING_MS_1258 },
1183 : { "SHIFT_JIS", RTL_TEXTENCODING_SHIFT_JIS },
1184 : { "MS_KANJI", RTL_TEXTENCODING_SHIFT_JIS },
1185 : { "CSSHIFTJIS", RTL_TEXTENCODING_SHIFT_JIS },
1186 : { "GB2312", RTL_TEXTENCODING_GB_2312 },
1187 : { "CSGB2312", RTL_TEXTENCODING_GB_2312 },
1188 : { "BIG5", RTL_TEXTENCODING_BIG5 },
1189 : { "CSBIG5", RTL_TEXTENCODING_BIG5 },
1190 : { "EUC-JP", RTL_TEXTENCODING_EUC_JP },
1191 : { "EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE",
1192 : RTL_TEXTENCODING_EUC_JP },
1193 : { "CSEUCPKDFMTJAPANESE", RTL_TEXTENCODING_EUC_JP },
1194 : { "ISO-2022-JP", RTL_TEXTENCODING_ISO_2022_JP },
1195 : { "CSISO2022JP", RTL_TEXTENCODING_ISO_2022_JP },
1196 : { "ISO-2022-CN", RTL_TEXTENCODING_ISO_2022_CN },
1197 : { "KOI8-R", RTL_TEXTENCODING_KOI8_R },
1198 : { "CSKOI8R", RTL_TEXTENCODING_KOI8_R },
1199 : { "UTF-7", RTL_TEXTENCODING_UTF7 },
1200 : { "UTF-8", RTL_TEXTENCODING_UTF8 },
1201 : { "ISO-8859-10", RTL_TEXTENCODING_ISO_8859_10 }, // RFC 2047
1202 : { "ISO-8859-13", RTL_TEXTENCODING_ISO_8859_13 }, // RFC 2047
1203 : { "EUC-KR", RTL_TEXTENCODING_EUC_KR },
1204 : { "CSEUCKR", RTL_TEXTENCODING_EUC_KR },
1205 : { "ISO-2022-KR", RTL_TEXTENCODING_ISO_2022_KR },
1206 : { "CSISO2022KR", RTL_TEXTENCODING_ISO_2022_KR },
1207 : { "ISO-10646-UCS-4", RTL_TEXTENCODING_UCS4 },
1208 : { "CSUCS4", RTL_TEXTENCODING_UCS4 },
1209 : { "ISO-10646-UCS-2", RTL_TEXTENCODING_UCS2 },
1210 : { "CSUNICODE", RTL_TEXTENCODING_UCS2 } };
1211 :
1212 : template< typename T >
1213 6 : inline rtl_TextEncoding getCharsetEncoding_Impl(T const * pBegin,
1214 : T const * pEnd)
1215 : {
1216 72 : for (sal_Size i = 0; i < sizeof aEncodingMap / sizeof (EncodingEntry);
1217 : ++i)
1218 72 : if (INetMIME::equalIgnoreCase(pBegin, pEnd, aEncodingMap[i].m_aName))
1219 6 : return aEncodingMap[i].m_eEncoding;
1220 0 : return RTL_TEXTENCODING_DONTKNOW;
1221 : }
1222 :
1223 : }
1224 :
1225 : // static
1226 6 : rtl_TextEncoding INetMIME::getCharsetEncoding(sal_Char const * pBegin,
1227 : sal_Char const * pEnd)
1228 : {
1229 6 : return getCharsetEncoding_Impl(pBegin, pEnd);
1230 : }
1231 :
1232 : // static
1233 : INetMIMECharsetList_Impl *
1234 0 : INetMIME::createPreferredCharsetList(rtl_TextEncoding eEncoding)
1235 : {
1236 : static const sal_uInt32 aUSASCIIRanges[] = { 0, 0x7F, sal_uInt32(-1) };
1237 :
1238 : static const sal_uInt32 aISO88591Ranges[] = { 0, 0xFF, sal_uInt32(-1) };
1239 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-1.TXT> version
1240 : // 1.0 of 1999 July 27
1241 :
1242 : static const sal_uInt32 aISO88592Ranges[]
1243 : = { 0, 0xA0, 0xA4, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xB0, 0xB0,
1244 : 0xB4, 0xB4, 0xB8, 0xB8, 0xC1, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7,
1245 : 0xC9, 0xC9, 0xCB, 0xCB, 0xCD, 0xCE, 0xD3, 0xD4, 0xD6, 0xD7,
1246 : 0xDA, 0xDA, 0xDC, 0xDD, 0xDF, 0xDF, 0xE1, 0xE2, 0xE4, 0xE4,
1247 : 0xE7, 0xE7, 0xE9, 0xE9, 0xEB, 0xEB, 0xED, 0xEE, 0xF3, 0xF4,
1248 : 0xF6, 0xF7, 0xFA, 0xFA, 0xFC, 0xFD, 0x102, 0x107, 0x10C, 0x111,
1249 : 0x118, 0x11B, 0x139, 0x13A, 0x13D, 0x13E, 0x141, 0x144,
1250 : 0x147, 0x148, 0x150, 0x151, 0x154, 0x155, 0x158, 0x15B,
1251 : 0x15E, 0x165, 0x16E, 0x171, 0x179, 0x17E, 0x2C7, 0x2C7,
1252 : 0x2D8, 0x2D9, 0x2DB, 0x2DB, 0x2DD, 0x2DD, sal_uInt32(-1) };
1253 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-2.TXT> version
1254 : // 1.0 of 1999 July 27
1255 :
1256 : static const sal_uInt32 aISO88593Ranges[]
1257 : = { 0, 0xA0, 0xA3, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xB0, 0xB0,
1258 : 0xB2, 0xB5, 0xB7, 0xB8, 0xBD, 0xBD, 0xC0, 0xC2, 0xC4, 0xC4,
1259 : 0xC7, 0xCF, 0xD1, 0xD4, 0xD6, 0xD7, 0xD9, 0xDC, 0xDF, 0xE2,
1260 : 0xE4, 0xE4, 0xE7, 0xEF, 0xF1, 0xF4, 0xF6, 0xF7, 0xF9, 0xFC,
1261 : 0x108, 0x10B, 0x11C, 0x121, 0x124, 0x127, 0x130, 0x131,
1262 : 0x134, 0x135, 0x15C, 0x15F, 0x16C, 0x16D, 0x17B, 0x17C,
1263 : 0x2D8, 0x2D9, sal_uInt32(-1) };
1264 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-3.TXT> version
1265 : // 1.0 of 1999 July 27
1266 :
1267 : static const sal_uInt32 aISO88594Ranges[]
1268 : = { 0, 0xA0, 0xA4, 0xA4, 0xA7, 0xA8, 0xAD, 0xAD, 0xAF, 0xB0,
1269 : 0xB4, 0xB4, 0xB8, 0xB8, 0xC1, 0xC6, 0xC9, 0xC9, 0xCB, 0xCB,
1270 : 0xCD, 0xCE, 0xD4, 0xD8, 0xDA, 0xDC, 0xDF, 0xDF, 0xE1, 0xE6,
1271 : 0xE9, 0xE9, 0xEB, 0xEB, 0xED, 0xEE, 0xF4, 0xF8, 0xFA, 0xFC,
1272 : 0x100, 0x101, 0x104, 0x105, 0x10C, 0x10D, 0x110, 0x113,
1273 : 0x116, 0x119, 0x122, 0x123, 0x128, 0x12B, 0x12E, 0x12F,
1274 : 0x136, 0x138, 0x13B, 0x13C, 0x145, 0x146, 0x14A, 0x14D,
1275 : 0x156, 0x157, 0x160, 0x161, 0x166, 0x16B, 0x172, 0x173,
1276 : 0x17D, 0x17E, 0x2C7, 0x2C7, 0x2D9, 0x2D9, 0x2DB, 0x2DB,
1277 : sal_uInt32(-1) };
1278 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-4.TXT> version
1279 : // 1.0 of 1999 July 27
1280 :
1281 : static const sal_uInt32 aISO88595Ranges[]
1282 : = { 0, 0xA0, 0xA7, 0xA7, 0xAD, 0xAD, 0x401, 0x40C, 0x40E, 0x44F,
1283 : 0x451, 0x45C, 0x45E, 0x45F, 0x2116, 0x2116, sal_uInt32(-1) };
1284 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-5.TXT> version
1285 : // 1.0 of 1999 July 27
1286 :
1287 : static const sal_uInt32 aISO88596Ranges[]
1288 : = { 0, 0xA0, 0xA4, 0xA4, 0xAD, 0xAD, 0x60C, 0x60C, 0x61B, 0x61B,
1289 : 0x61F, 0x61F, 0x621, 0x63A, 0x640, 0x652, sal_uInt32(-1) };
1290 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-6.TXT> version
1291 : // 1.0 of 1999 July 27
1292 :
1293 : static const sal_uInt32 aISO88597Ranges[]
1294 : = { 0, 0xA0, 0xA3, 0xA3, 0xA6, 0xA9, 0xAB, 0xAD, 0xB0, 0xB3,
1295 : 0xB7, 0xB7, 0xBB, 0xBB, 0xBD, 0xBD, 0x384, 0x386, 0x388, 0x38A,
1296 : 0x38C, 0x38C, 0x38E, 0x3A1, 0x3A3, 0x3CE, 0x2015, 0x2015,
1297 : 0x2018, 0x2019, sal_uInt32(-1) };
1298 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-7.TXT> version
1299 : // 1.0 of 1999 July 27
1300 :
1301 : static const sal_uInt32 aISO88598Ranges[]
1302 : = { 0, 0xA0, 0xA2, 0xA9, 0xAB, 0xB9, 0xBB, 0xBE, 0xD7, 0xD7,
1303 : 0xF7, 0xF7, 0x5D0, 0x5EA, 0x200E, 0x200F, 0x2017, 0x2017,
1304 : sal_uInt32(-1) };
1305 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-8.TXT> version
1306 : // 1.1 of 2000-Jan-03
1307 :
1308 : static const sal_uInt32 aISO88599Ranges[]
1309 : = { 0, 0xCF, 0xD1, 0xDC, 0xDF, 0xEF, 0xF1, 0xFC, 0xFF, 0xFF,
1310 : 0x11E, 0x11F, 0x130, 0x131, 0x15E, 0x15F, sal_uInt32(-1) };
1311 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-9.TXT> version
1312 : // 1.0 of 1999 July 27
1313 :
1314 : static const sal_uInt32 aISO885910Ranges[]
1315 : = { 0, 0xA0, 0xA7, 0xA7, 0xAD, 0xAD, 0xB0, 0xB0, 0xB7, 0xB7,
1316 : 0xC1, 0xC6, 0xC9, 0xC9, 0xCB, 0xCB, 0xCD, 0xD0, 0xD3, 0xD6,
1317 : 0xD8, 0xD8, 0xDA, 0xDF, 0xE1, 0xE6, 0xE9, 0xE9, 0xEB, 0xEB,
1318 : 0xED, 0xF0, 0xF3, 0xF6, 0xF8, 0xF8, 0xFA, 0xFE, 0x100, 0x101,
1319 : 0x104, 0x105, 0x10C, 0x10D, 0x110, 0x113, 0x116, 0x119,
1320 : 0x122, 0x123, 0x128, 0x12B, 0x12E, 0x12F, 0x136, 0x138,
1321 : 0x13B, 0x13C, 0x145, 0x146, 0x14A, 0x14D, 0x160, 0x161,
1322 : 0x166, 0x16B, 0x172, 0x173, 0x17D, 0x17E, 0x2015, 0x2015,
1323 : sal_uInt32(-1) };
1324 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-10.TXT> version
1325 : // 1.1 of 1999 October 11
1326 :
1327 : static const sal_uInt32 aISO885913Ranges[]
1328 : = { 0, 0xA0, 0xA2, 0xA4, 0xA6, 0xA7, 0xA9, 0xA9, 0xAB, 0xAE,
1329 : 0xB0, 0xB3, 0xB5, 0xB7, 0xB9, 0xB9, 0xBB, 0xBE, 0xC4, 0xC6,
1330 : 0xC9, 0xC9, 0xD3, 0xD3, 0xD5, 0xD8, 0xDC, 0xDC, 0xDF, 0xDF,
1331 : 0xE4, 0xE6, 0xE9, 0xE9, 0xF3, 0xF3, 0xF5, 0xF8, 0xFC, 0xFC,
1332 : 0x100, 0x101, 0x104, 0x107, 0x10C, 0x10D, 0x112, 0x113,
1333 : 0x116, 0x119, 0x122, 0x123, 0x12A, 0x12B, 0x12E, 0x12F,
1334 : 0x136, 0x137, 0x13B, 0x13C, 0x141, 0x146, 0x14C, 0x14D,
1335 : 0x156, 0x157, 0x15A, 0x15B, 0x160, 0x161, 0x16A, 0x16B,
1336 : 0x172, 0x173, 0x179, 0x17E, 0x2019, 0x2019, 0x201C, 0x201E,
1337 : sal_uInt32(-1) };
1338 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-13.TXT> version
1339 : // 1.0 of 1999 July 27
1340 :
1341 : static const sal_uInt32 aISO885914Ranges[]
1342 : = { 0, 0xA0, 0xA3, 0xA3, 0xA7, 0xA7, 0xA9, 0xA9, 0xAD, 0xAE,
1343 : 0xB6, 0xB6, 0xC0, 0xCF, 0xD1, 0xD6, 0xD8, 0xDD, 0xDF, 0xEF,
1344 : 0xF1, 0xF6, 0xF8, 0xFD, 0xFF, 0xFF, 0x10A, 0x10B, 0x120, 0x121,
1345 : 0x174, 0x178, 0x1E02, 0x1E03, 0x1E0A, 0x1E0B, 0x1E1E, 0x1E1F,
1346 : 0x1E40, 0x1E41, 0x1E56, 0x1E57, 0x1E60, 0x1E61, 0x1E6A, 0x1E6B,
1347 : 0x1E80, 0x1E85, 0x1EF2, 0x1EF3, sal_uInt32(-1) };
1348 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-14.TXT> version
1349 : // 1.0 of 1999 July 27
1350 :
1351 : static const sal_uInt32 aISO885915Ranges[]
1352 : = { 0, 0xA3, 0xA5, 0xA5, 0xA7, 0xA7, 0xA9, 0xB3, 0xB5, 0xB7,
1353 : 0xB9, 0xBB, 0xBF, 0xFF, 0x152, 0x153, 0x160, 0x161, 0x178, 0x178,
1354 : 0x17D, 0x17E, 0x20AC, 0x20AC, sal_uInt32(-1) };
1355 : // <ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/8859-15.TXT> version
1356 : // 1.0 of 1999 July 27
1357 :
1358 : static const sal_uInt32 aKOI8RRanges[]
1359 : = { 0, 0x7F, 0xA0, 0xA0, 0xA9, 0xA9, 0xB0, 0xB0, 0xB2, 0xB2,
1360 : 0xB7, 0xB7, 0xF7, 0xF7, 0x401, 0x401, 0x410, 0x44F, 0x451, 0x451,
1361 : 0x2219, 0x221A, 0x2248, 0x2248, 0x2264, 0x2265, 0x2320, 0x2321,
1362 : 0x2500, 0x2500, 0x2502, 0x2502, 0x250C, 0x250C, 0x2510, 0x2510,
1363 : 0x2514, 0x2514, 0x2518, 0x2518, 0x251C, 0x251C, 0x2524, 0x2524,
1364 : 0x252C, 0x252C, 0x2534, 0x2534, 0x253C, 0x253C, 0x2550, 0x256C,
1365 : 0x2580, 0x2580, 0x2584, 0x2584, 0x2588, 0x2588, 0x258C, 0x258C,
1366 : 0x2590, 0x2593, 0x25A0, 0x25A0, sal_uInt32(-1) };
1367 : // <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MISC/KOI8-R.TXT>
1368 : // version 1.0 of 18 August 1999
1369 :
1370 : #if defined WNT
1371 : static const sal_uInt32 aWindows1252Ranges[]
1372 : = { 0, 0x7F, 0xA0, 0xFF, 0x152, 0x153, 0x160, 0x161, 0x178, 0x178,
1373 : 0x17D, 0x17E, 0x192, 0x192, 0x2C6, 0x2C6, 0x2DC, 0x2DC,
1374 : 0x2013, 0x2014, 0x2018, 0x201A, 0x201C, 0x201E, 0x2020, 0x2022,
1375 : 0x2026, 0x2026, 0x2030, 0x2030, 0x2039, 0x203A, 0x20AC, 0x20AC,
1376 : 0x2122, 0x2122, sal_uInt32(-1) };
1377 : // <ftp://ftp.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/
1378 : // CP1252.TXT> version 2.01 of 04/15/98
1379 : #endif // WNT
1380 :
1381 0 : INetMIMECharsetList_Impl * pList = new INetMIMECharsetList_Impl;
1382 0 : switch (eEncoding)
1383 : {
1384 : case RTL_TEXTENCODING_MS_1252:
1385 : #if defined WNT
1386 : pList->prepend(Charset(RTL_TEXTENCODING_MS_1252,
1387 : aWindows1252Ranges));
1388 : #endif // WNT
1389 : case RTL_TEXTENCODING_ISO_8859_1:
1390 : case RTL_TEXTENCODING_UTF7:
1391 : case RTL_TEXTENCODING_UTF8:
1392 0 : break;
1393 :
1394 : case RTL_TEXTENCODING_ISO_8859_2:
1395 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_2,
1396 0 : aISO88592Ranges));
1397 0 : break;
1398 :
1399 : case RTL_TEXTENCODING_ISO_8859_3:
1400 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_3,
1401 0 : aISO88593Ranges));
1402 0 : break;
1403 :
1404 : case RTL_TEXTENCODING_ISO_8859_4:
1405 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_4,
1406 0 : aISO88594Ranges));
1407 0 : break;
1408 :
1409 : case RTL_TEXTENCODING_ISO_8859_5:
1410 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5,
1411 0 : aISO88595Ranges));
1412 0 : break;
1413 :
1414 : case RTL_TEXTENCODING_ISO_8859_6:
1415 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_6,
1416 0 : aISO88596Ranges));
1417 0 : break;
1418 :
1419 : case RTL_TEXTENCODING_ISO_8859_7:
1420 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_7,
1421 0 : aISO88597Ranges));
1422 0 : break;
1423 :
1424 : case RTL_TEXTENCODING_ISO_8859_8:
1425 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_8,
1426 0 : aISO88598Ranges));
1427 0 : break;
1428 :
1429 : case RTL_TEXTENCODING_ISO_8859_9:
1430 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_9,
1431 0 : aISO88599Ranges));
1432 0 : break;
1433 :
1434 : case RTL_TEXTENCODING_ISO_8859_10:
1435 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_10,
1436 0 : aISO885910Ranges));
1437 0 : break;
1438 :
1439 : case RTL_TEXTENCODING_ISO_8859_13:
1440 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_13,
1441 0 : aISO885913Ranges));
1442 0 : break;
1443 :
1444 : case RTL_TEXTENCODING_ISO_8859_14:
1445 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_14,
1446 0 : aISO885914Ranges));
1447 0 : break;
1448 :
1449 : case RTL_TEXTENCODING_ISO_8859_15:
1450 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_15,
1451 0 : aISO885915Ranges));
1452 0 : break;
1453 :
1454 : case RTL_TEXTENCODING_MS_1250:
1455 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_2,
1456 0 : aISO88592Ranges));
1457 0 : break;
1458 :
1459 : case RTL_TEXTENCODING_MS_1251:
1460 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5,
1461 0 : aISO88595Ranges));
1462 0 : break;
1463 :
1464 : case RTL_TEXTENCODING_MS_1253:
1465 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_7,
1466 0 : aISO88597Ranges));
1467 0 : break;
1468 :
1469 : case RTL_TEXTENCODING_MS_1254:
1470 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_9,
1471 0 : aISO88599Ranges));
1472 0 : break;
1473 :
1474 : case RTL_TEXTENCODING_MS_1255:
1475 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_8,
1476 0 : aISO88598Ranges));
1477 0 : break;
1478 :
1479 : case RTL_TEXTENCODING_MS_1256:
1480 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_6,
1481 0 : aISO88596Ranges));
1482 0 : break;
1483 :
1484 : case RTL_TEXTENCODING_MS_1257:
1485 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_4,
1486 0 : aISO88594Ranges));
1487 0 : break;
1488 :
1489 : case RTL_TEXTENCODING_KOI8_R:
1490 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_5,
1491 0 : aISO88595Ranges));
1492 0 : pList->prepend(Charset(RTL_TEXTENCODING_KOI8_R, aKOI8RRanges));
1493 0 : break;
1494 :
1495 : default: //@@@ more cases are missing!
1496 : OSL_FAIL("INetMIME::createPreferredCharsetList():"
1497 : " Unsupported encoding");
1498 0 : break;
1499 : }
1500 0 : pList->prepend(Charset(RTL_TEXTENCODING_ISO_8859_1, aISO88591Ranges));
1501 0 : pList->prepend(Charset(RTL_TEXTENCODING_ASCII_US, aUSASCIIRanges));
1502 0 : return pList;
1503 : }
1504 :
1505 : // static
1506 28 : sal_Unicode * INetMIME::convertToUnicode(const sal_Char * pBegin,
1507 : const sal_Char * pEnd,
1508 : rtl_TextEncoding eEncoding,
1509 : sal_Size & rSize)
1510 : {
1511 28 : if (eEncoding == RTL_TEXTENCODING_DONTKNOW)
1512 0 : return 0;
1513 : rtl_TextToUnicodeConverter hConverter
1514 28 : = rtl_createTextToUnicodeConverter(eEncoding);
1515 : rtl_TextToUnicodeContext hContext
1516 28 : = rtl_createTextToUnicodeContext(hConverter);
1517 : sal_Unicode * pBuffer;
1518 : sal_uInt32 nInfo;
1519 28 : for (sal_Size nBufferSize = pEnd - pBegin;;
1520 0 : nBufferSize += nBufferSize / 3 + 1)
1521 : {
1522 28 : pBuffer = new sal_Unicode[nBufferSize];
1523 : sal_Size nSrcCvtBytes;
1524 : rSize = rtl_convertTextToUnicode(
1525 28 : hConverter, hContext, pBegin, pEnd - pBegin, pBuffer,
1526 : nBufferSize,
1527 : RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
1528 : | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
1529 : | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR,
1530 28 : &nInfo, &nSrcCvtBytes);
1531 28 : if (nInfo != RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL)
1532 28 : break;
1533 0 : delete[] pBuffer;
1534 0 : rtl_resetTextToUnicodeContext(hConverter, hContext);
1535 0 : }
1536 28 : rtl_destroyTextToUnicodeContext(hConverter, hContext);
1537 28 : rtl_destroyTextToUnicodeConverter(hConverter);
1538 28 : if (nInfo != 0)
1539 : {
1540 0 : delete[] pBuffer;
1541 0 : pBuffer = 0;
1542 : }
1543 28 : return pBuffer;
1544 : }
1545 :
1546 : // static
1547 0 : sal_Char * INetMIME::convertFromUnicode(const sal_Unicode * pBegin,
1548 : const sal_Unicode * pEnd,
1549 : rtl_TextEncoding eEncoding,
1550 : sal_Size & rSize)
1551 : {
1552 0 : if (eEncoding == RTL_TEXTENCODING_DONTKNOW)
1553 0 : return 0;
1554 : rtl_UnicodeToTextConverter hConverter
1555 0 : = rtl_createUnicodeToTextConverter(eEncoding);
1556 : rtl_UnicodeToTextContext hContext
1557 0 : = rtl_createUnicodeToTextContext(hConverter);
1558 : sal_Char * pBuffer;
1559 : sal_uInt32 nInfo;
1560 0 : for (sal_Size nBufferSize = pEnd - pBegin;;
1561 0 : nBufferSize += nBufferSize / 3 + 1)
1562 : {
1563 0 : pBuffer = new sal_Char[nBufferSize];
1564 : sal_Size nSrcCvtBytes;
1565 : rSize = rtl_convertUnicodeToText(
1566 0 : hConverter, hContext, pBegin, pEnd - pBegin, pBuffer,
1567 : nBufferSize,
1568 : RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
1569 : | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
1570 : | RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACE
1571 : | RTL_UNICODETOTEXT_FLAGS_UNDEFINED_REPLACESTR,
1572 0 : &nInfo, &nSrcCvtBytes);
1573 0 : if (nInfo != RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL)
1574 0 : break;
1575 0 : delete[] pBuffer;
1576 0 : rtl_resetUnicodeToTextContext(hConverter, hContext);
1577 0 : }
1578 0 : rtl_destroyUnicodeToTextContext(hConverter, hContext);
1579 0 : rtl_destroyUnicodeToTextConverter(hConverter);
1580 0 : if (nInfo != 0)
1581 : {
1582 0 : delete[] pBuffer;
1583 0 : pBuffer = 0;
1584 : }
1585 0 : return pBuffer;
1586 : }
1587 :
1588 : // static
1589 0 : void INetMIME::writeUTF8(INetMIMEOutputSink & rSink, sal_uInt32 nChar)
1590 : {
1591 : // See RFC 2279 for a discussion of UTF-8.
1592 : DBG_ASSERT(nChar < 0x80000000, "INetMIME::writeUTF8(): Bad char");
1593 :
1594 0 : if (nChar < 0x80)
1595 0 : rSink << sal_Char(nChar);
1596 0 : else if (nChar < 0x800)
1597 0 : rSink << sal_Char(nChar >> 6 | 0xC0)
1598 0 : << sal_Char((nChar & 0x3F) | 0x80);
1599 0 : else if (nChar < 0x10000)
1600 0 : rSink << sal_Char(nChar >> 12 | 0xE0)
1601 0 : << sal_Char((nChar >> 6 & 0x3F) | 0x80)
1602 0 : << sal_Char((nChar & 0x3F) | 0x80);
1603 0 : else if (nChar < 0x200000)
1604 0 : rSink << sal_Char(nChar >> 18 | 0xF0)
1605 0 : << sal_Char((nChar >> 12 & 0x3F) | 0x80)
1606 0 : << sal_Char((nChar >> 6 & 0x3F) | 0x80)
1607 0 : << sal_Char((nChar & 0x3F) | 0x80);
1608 0 : else if (nChar < 0x4000000)
1609 0 : rSink << sal_Char(nChar >> 24 | 0xF8)
1610 0 : << sal_Char((nChar >> 18 & 0x3F) | 0x80)
1611 0 : << sal_Char((nChar >> 12 & 0x3F) | 0x80)
1612 0 : << sal_Char((nChar >> 6 & 0x3F) | 0x80)
1613 0 : << sal_Char((nChar & 0x3F) | 0x80);
1614 : else
1615 0 : rSink << sal_Char(nChar >> 30 | 0xFC)
1616 0 : << sal_Char((nChar >> 24 & 0x3F) | 0x80)
1617 0 : << sal_Char((nChar >> 18 & 0x3F) | 0x80)
1618 0 : << sal_Char((nChar >> 12 & 0x3F) | 0x80)
1619 0 : << sal_Char((nChar >> 6 & 0x3F) | 0x80)
1620 0 : << sal_Char((nChar & 0x3F) | 0x80);
1621 0 : }
1622 :
1623 : // static
1624 0 : void INetMIME::writeHeaderFieldBody(INetMIMEOutputSink & rSink,
1625 : HeaderFieldType eType,
1626 : const OUString& rBody,
1627 : rtl_TextEncoding ePreferredEncoding,
1628 : bool bInitialSpace)
1629 : {
1630 0 : if (eType == HEADER_FIELD_TEXT)
1631 : {
1632 : INetMIMEEncodedWordOutputSink
1633 : aOutput(rSink, INetMIMEEncodedWordOutputSink::CONTEXT_TEXT,
1634 : bInitialSpace ?
1635 : INetMIMEEncodedWordOutputSink::SPACE_ALWAYS :
1636 : INetMIMEEncodedWordOutputSink::SPACE_NO,
1637 0 : ePreferredEncoding);
1638 0 : aOutput.write(rBody.getStr(), rBody.getStr() + rBody.getLength());
1639 0 : aOutput.flush();
1640 : }
1641 : else
1642 : {
1643 : enum Brackets { BRACKETS_OUTSIDE, BRACKETS_OPENING, BRACKETS_INSIDE };
1644 0 : Brackets eBrackets = BRACKETS_OUTSIDE;
1645 :
1646 0 : const sal_Unicode * pBodyPtr = rBody.getStr();
1647 0 : const sal_Unicode * pBodyEnd = pBodyPtr + rBody.getLength();
1648 0 : while (pBodyPtr != pBodyEnd)
1649 0 : switch (*pBodyPtr)
1650 : {
1651 : case '\t':
1652 : case ' ':
1653 : // A WSP adds to accumulated space:
1654 0 : bInitialSpace = true;
1655 0 : ++pBodyPtr;
1656 0 : break;
1657 :
1658 : case '(':
1659 : {
1660 : // Write a pending '<' if necessary:
1661 0 : if (eBrackets == BRACKETS_OPENING)
1662 : {
1663 0 : if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
1664 0 : >= rSink.getLineLengthLimit())
1665 0 : rSink << INetMIMEOutputSink::endl << ' ';
1666 0 : else if (bInitialSpace)
1667 0 : rSink << ' ';
1668 0 : rSink << '<';
1669 0 : bInitialSpace = false;
1670 0 : eBrackets = BRACKETS_INSIDE;
1671 : }
1672 :
1673 : // Write the comment, introducing encoded-words where
1674 : // necessary:
1675 0 : int nLevel = 0;
1676 : INetMIMEEncodedWordOutputSink
1677 : aOutput(
1678 : rSink,
1679 : INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT,
1680 : INetMIMEEncodedWordOutputSink::SPACE_NO,
1681 0 : ePreferredEncoding);
1682 0 : while (pBodyPtr != pBodyEnd)
1683 0 : switch (*pBodyPtr)
1684 : {
1685 : case '(':
1686 0 : aOutput.flush();
1687 0 : if (rSink.getColumn()
1688 0 : + (bInitialSpace ? 1 : 0)
1689 0 : >= rSink.getLineLengthLimit())
1690 0 : rSink << INetMIMEOutputSink::endl << ' ';
1691 0 : else if (bInitialSpace)
1692 0 : rSink << ' ';
1693 0 : rSink << '(';
1694 0 : bInitialSpace = false;
1695 0 : ++nLevel;
1696 0 : ++pBodyPtr;
1697 0 : break;
1698 :
1699 : case ')':
1700 0 : aOutput.flush();
1701 0 : if (rSink.getColumn()
1702 0 : >= rSink.getLineLengthLimit())
1703 0 : rSink << INetMIMEOutputSink::endl << ' ';
1704 0 : rSink << ')';
1705 0 : ++pBodyPtr;
1706 0 : if (--nLevel == 0)
1707 0 : goto comment_done;
1708 0 : break;
1709 :
1710 : case '\\':
1711 0 : if (++pBodyPtr == pBodyEnd)
1712 0 : break;
1713 : default:
1714 0 : aOutput << *pBodyPtr++;
1715 0 : break;
1716 : }
1717 : comment_done:
1718 0 : break;
1719 : }
1720 :
1721 : case '<':
1722 : // Write an already pending '<' if necessary:
1723 0 : if (eBrackets == BRACKETS_OPENING)
1724 : {
1725 0 : if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
1726 0 : >= rSink.getLineLengthLimit())
1727 0 : rSink << INetMIMEOutputSink::endl << ' ';
1728 0 : else if (bInitialSpace)
1729 0 : rSink << ' ';
1730 0 : rSink << '<';
1731 0 : bInitialSpace = false;
1732 : }
1733 :
1734 : // Remember this '<' as pending, and open a bracketed
1735 : // block:
1736 0 : eBrackets = BRACKETS_OPENING;
1737 0 : ++pBodyPtr;
1738 0 : break;
1739 :
1740 : case '>':
1741 : // Write a pending '<' if necessary:
1742 0 : if (eBrackets == BRACKETS_OPENING)
1743 : {
1744 0 : if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
1745 0 : >= rSink.getLineLengthLimit())
1746 0 : rSink << INetMIMEOutputSink::endl << ' ';
1747 0 : else if (bInitialSpace)
1748 0 : rSink << ' ';
1749 0 : rSink << '<';
1750 0 : bInitialSpace = false;
1751 : }
1752 :
1753 : // Write this '>', and close any bracketed block:
1754 0 : if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
1755 0 : >= rSink.getLineLengthLimit())
1756 0 : rSink << INetMIMEOutputSink::endl << ' ';
1757 0 : else if (bInitialSpace)
1758 0 : rSink << ' ';
1759 0 : rSink << '>';
1760 0 : bInitialSpace = false;
1761 0 : eBrackets = BRACKETS_OUTSIDE;
1762 0 : ++pBodyPtr;
1763 0 : break;
1764 :
1765 : case ',':
1766 : case ':':
1767 : case ';':
1768 : case '\\':
1769 : case ']':
1770 : // Write a pending '<' if necessary:
1771 0 : if (eBrackets == BRACKETS_OPENING)
1772 : {
1773 0 : if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
1774 0 : >= rSink.getLineLengthLimit())
1775 0 : rSink << INetMIMEOutputSink::endl << ' ';
1776 0 : else if (bInitialSpace)
1777 0 : rSink << ' ';
1778 0 : rSink << '<';
1779 0 : bInitialSpace = false;
1780 0 : eBrackets = BRACKETS_INSIDE;
1781 : }
1782 :
1783 : // Write this specials:
1784 0 : if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
1785 0 : >= rSink.getLineLengthLimit())
1786 0 : rSink << INetMIMEOutputSink::endl << ' ';
1787 0 : else if (bInitialSpace)
1788 0 : rSink << ' ';
1789 0 : rSink << sal_Char(*pBodyPtr++);
1790 0 : bInitialSpace = false;
1791 0 : break;
1792 :
1793 : case '\x0D': // CR
1794 : // A <CRLF WSP> adds to accumulated space, a <CR> not
1795 : // followed by <LF WSP> starts 'junk':
1796 0 : if (startsWithLineFolding(pBodyPtr, pBodyEnd))
1797 : {
1798 0 : bInitialSpace = true;
1799 0 : pBodyPtr += 3;
1800 0 : break;
1801 : }
1802 : default:
1803 : {
1804 : // The next token is either one of <"." / "@" / atom /
1805 : // quoted-string / domain-literal>, or it's 'junk'; if it
1806 : // is not 'junk', it is either a 'phrase' (i.e., it may
1807 : // contain encoded-words) or a 'non-phrase' (i.e., it may
1808 : // not contain encoded-words):
1809 : enum Entity { ENTITY_JUNK, ENTITY_NON_PHRASE,
1810 : ENTITY_PHRASE };
1811 0 : Entity eEntity = ENTITY_JUNK;
1812 0 : switch (*pBodyPtr)
1813 : {
1814 : case '.':
1815 : case '@':
1816 : case '[':
1817 : // A token of <"." / "@" / domain-literal> always
1818 : // starts a 'non-phrase':
1819 0 : eEntity = ENTITY_NON_PHRASE;
1820 0 : break;
1821 :
1822 : default:
1823 0 : if (rtl::isAscii(*pBodyPtr)
1824 0 : && !isAtomChar(*pBodyPtr))
1825 : {
1826 0 : eEntity = ENTITY_JUNK;
1827 0 : break;
1828 : }
1829 : case '"':
1830 : // A token of <atom / quoted-string> can either be
1831 : // a 'phrase' or a 'non-phrase':
1832 0 : switch (eType)
1833 : {
1834 : case HEADER_FIELD_STRUCTURED:
1835 0 : eEntity = ENTITY_NON_PHRASE;
1836 0 : break;
1837 :
1838 : case HEADER_FIELD_PHRASE:
1839 0 : eEntity = ENTITY_PHRASE;
1840 0 : break;
1841 :
1842 : case HEADER_FIELD_MESSAGE_ID:
1843 : // A 'phrase' if and only if outside any
1844 : // bracketed block:
1845 : eEntity
1846 : = eBrackets == BRACKETS_OUTSIDE ?
1847 : ENTITY_PHRASE :
1848 0 : ENTITY_NON_PHRASE;
1849 0 : break;
1850 :
1851 : case HEADER_FIELD_ADDRESS:
1852 : {
1853 : // A 'non-phrase' if and only if, after
1854 : // skipping this token and any following
1855 : // <linear-white-space> and <comment>s,
1856 : // there is no token left, or the next
1857 : // token is any of <"." / "@" / ">" / ","
1858 : // / ";">, or the next token is <":"> and
1859 : // is within a bracketed block:
1860 0 : const sal_Unicode * pLookAhead = pBodyPtr;
1861 0 : if (*pLookAhead == '"')
1862 : {
1863 : pLookAhead
1864 : = skipQuotedString(pLookAhead,
1865 0 : pBodyEnd);
1866 0 : if (pLookAhead == pBodyPtr)
1867 0 : pLookAhead = pBodyEnd;
1868 : }
1869 : else
1870 0 : while (pLookAhead != pBodyEnd
1871 0 : && (isAtomChar(*pLookAhead)
1872 0 : || !rtl::isAscii(
1873 0 : *pLookAhead)))
1874 0 : ++pLookAhead;
1875 0 : while (pLookAhead != pBodyEnd)
1876 0 : switch (*pLookAhead)
1877 : {
1878 : case '\t':
1879 : case ' ':
1880 0 : ++pLookAhead;
1881 0 : break;
1882 :
1883 : case '(':
1884 : {
1885 : const sal_Unicode * pPast
1886 : = skipComment(pLookAhead,
1887 0 : pBodyEnd);
1888 : pLookAhead
1889 : = pPast == pLookAhead ?
1890 0 : pBodyEnd : pPast;
1891 0 : break;
1892 : }
1893 :
1894 : case ',':
1895 : case '.':
1896 : case ';':
1897 : case '>':
1898 : case '@':
1899 0 : eEntity = ENTITY_NON_PHRASE;
1900 0 : goto entity_determined;
1901 :
1902 : case ':':
1903 : eEntity
1904 : = eBrackets
1905 : == BRACKETS_OUTSIDE ?
1906 : ENTITY_PHRASE :
1907 0 : ENTITY_NON_PHRASE;
1908 0 : goto entity_determined;
1909 :
1910 : case '\x0D': // CR
1911 0 : if (startsWithLineFolding(
1912 : pLookAhead, pBodyEnd))
1913 : {
1914 0 : pLookAhead += 3;
1915 0 : break;
1916 : }
1917 : default:
1918 0 : eEntity = ENTITY_PHRASE;
1919 0 : goto entity_determined;
1920 : }
1921 0 : eEntity = ENTITY_NON_PHRASE;
1922 : entity_determined:
1923 0 : break;
1924 : }
1925 :
1926 : case HEADER_FIELD_TEXT:
1927 : OSL_ASSERT(false);
1928 0 : break;
1929 : }
1930 :
1931 : // In a 'non-phrase', a non-US-ASCII character
1932 : // cannot be part of an <atom>, but instead the
1933 : // whole entity is 'junk' rather than 'non-
1934 : // phrase':
1935 0 : if (eEntity == ENTITY_NON_PHRASE
1936 0 : && !rtl::isAscii(*pBodyPtr))
1937 0 : eEntity = ENTITY_JUNK;
1938 0 : break;
1939 : }
1940 :
1941 0 : switch (eEntity)
1942 : {
1943 : case ENTITY_JUNK:
1944 : {
1945 : // Write a pending '<' if necessary:
1946 0 : if (eBrackets == BRACKETS_OPENING)
1947 : {
1948 0 : if (rSink.getColumn()
1949 0 : + (bInitialSpace ? 1 : 0)
1950 0 : >= rSink.getLineLengthLimit())
1951 0 : rSink << INetMIMEOutputSink::endl << ' ';
1952 0 : else if (bInitialSpace)
1953 0 : rSink << ' ';
1954 0 : rSink << '<';
1955 0 : bInitialSpace = false;
1956 0 : eBrackets = BRACKETS_INSIDE;
1957 : }
1958 :
1959 : // Calculate the length of in- and output:
1960 0 : const sal_Unicode * pStart = pBodyPtr;
1961 0 : sal_Size nLength = 0;
1962 0 : bool bModify = false;
1963 0 : bool bEnd = false;
1964 0 : while (pBodyPtr != pBodyEnd && !bEnd)
1965 0 : switch (*pBodyPtr)
1966 : {
1967 : case '\x0D': // CR
1968 0 : if (startsWithLineFolding(pBodyPtr,
1969 : pBodyEnd))
1970 0 : bEnd = true;
1971 0 : else if (startsWithLineBreak(
1972 : pBodyPtr, pBodyEnd))
1973 : {
1974 0 : nLength += 3;
1975 0 : bModify = true;
1976 0 : pBodyPtr += 2;
1977 : }
1978 : else
1979 : {
1980 0 : ++nLength;
1981 0 : ++pBodyPtr;
1982 : }
1983 0 : break;
1984 :
1985 : case '\t':
1986 : case ' ':
1987 0 : bEnd = true;
1988 0 : break;
1989 :
1990 : default:
1991 0 : if (isVisible(*pBodyPtr))
1992 0 : bEnd = true;
1993 0 : else if (rtl::isAscii(*pBodyPtr))
1994 : {
1995 0 : ++nLength;
1996 0 : ++pBodyPtr;
1997 : }
1998 : else
1999 : {
2000 : nLength += getUTF8OctetCount(
2001 0 : *pBodyPtr++);
2002 0 : bModify = true;
2003 : }
2004 0 : break;
2005 : }
2006 :
2007 : // Write the output:
2008 0 : if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
2009 0 : + nLength
2010 0 : > rSink.getLineLengthLimit())
2011 0 : rSink << INetMIMEOutputSink::endl << ' ';
2012 0 : else if (bInitialSpace)
2013 0 : rSink << ' ';
2014 0 : bInitialSpace = false;
2015 0 : if (bModify)
2016 0 : while (pStart != pBodyPtr)
2017 0 : if (startsWithLineBreak(pStart, pBodyPtr))
2018 : {
2019 0 : rSink << "\x0D\\\x0A"; // CR, '\', LF
2020 0 : pStart += 2;
2021 : }
2022 : else
2023 0 : writeUTF8(rSink, *pStart++);
2024 : else
2025 0 : rSink.write(pStart, pBodyPtr);
2026 0 : break;
2027 : }
2028 :
2029 : case ENTITY_NON_PHRASE:
2030 : {
2031 : // Calculate the length of in- and output:
2032 0 : const sal_Unicode * pStart = pBodyPtr;
2033 0 : sal_Size nLength = 0;
2034 0 : bool bBracketedBlock = false;
2035 0 : bool bSymbol = *pStart != '.' && *pStart != '@';
2036 0 : bool bModify = false;
2037 0 : bool bEnd = false;
2038 0 : while (pBodyPtr != pBodyEnd && !bEnd)
2039 0 : switch (*pBodyPtr)
2040 : {
2041 : case '\t':
2042 : case ' ':
2043 : case '\x0D': // CR
2044 : {
2045 : const sal_Unicode * pLookAhead
2046 : = skipLinearWhiteSpace(pBodyPtr,
2047 0 : pBodyEnd);
2048 0 : if (pLookAhead < pBodyEnd
2049 0 : && (bSymbol ?
2050 0 : isAtomChar(*pLookAhead)
2051 0 : || *pLookAhead == '"'
2052 0 : || *pLookAhead == '[' :
2053 0 : *pLookAhead == '.'
2054 0 : || *pLookAhead == '@'
2055 0 : || (*pLookAhead == '>'
2056 0 : && eType
2057 0 : >= HEADER_FIELD_MESSAGE_ID
2058 0 : && eBrackets
2059 : == BRACKETS_OPENING)))
2060 : {
2061 0 : bModify = true;
2062 0 : pBodyPtr = pLookAhead;
2063 : }
2064 : else
2065 0 : bEnd = true;
2066 0 : break;
2067 : }
2068 :
2069 : case '"':
2070 0 : if (bSymbol)
2071 : {
2072 : pBodyPtr
2073 : = scanQuotedBlock(pBodyPtr,
2074 : pBodyEnd,
2075 : '"', '"',
2076 : nLength,
2077 0 : bModify);
2078 0 : bSymbol = false;
2079 : }
2080 : else
2081 0 : bEnd = true;
2082 0 : break;
2083 :
2084 : case '[':
2085 0 : if (bSymbol)
2086 : {
2087 : pBodyPtr
2088 : = scanQuotedBlock(pBodyPtr,
2089 : pBodyEnd,
2090 : '[', ']',
2091 : nLength,
2092 0 : bModify);
2093 0 : bSymbol = false;
2094 : }
2095 : else
2096 0 : bEnd = true;
2097 0 : break;
2098 :
2099 : case '.':
2100 : case '@':
2101 0 : if (bSymbol)
2102 0 : bEnd = true;
2103 : else
2104 : {
2105 0 : ++nLength;
2106 0 : bSymbol = true;
2107 0 : ++pBodyPtr;
2108 : }
2109 0 : break;
2110 :
2111 : case '>':
2112 0 : if (eBrackets == BRACKETS_OPENING
2113 0 : && eType
2114 0 : >= HEADER_FIELD_MESSAGE_ID)
2115 : {
2116 0 : ++nLength;
2117 0 : bBracketedBlock = true;
2118 0 : ++pBodyPtr;
2119 : }
2120 0 : bEnd = true;
2121 0 : break;
2122 :
2123 : default:
2124 0 : if (isAtomChar(*pBodyPtr) && bSymbol)
2125 : {
2126 0 : while (pBodyPtr != pBodyEnd
2127 0 : && isAtomChar(*pBodyPtr))
2128 : {
2129 0 : ++nLength;
2130 0 : ++pBodyPtr;
2131 : }
2132 0 : bSymbol = false;
2133 : }
2134 : else
2135 : {
2136 0 : if (!rtl::isAscii(*pBodyPtr))
2137 0 : bModify = true;
2138 0 : bEnd = true;
2139 : }
2140 0 : break;
2141 : }
2142 :
2143 : // Write a pending '<' if necessary:
2144 0 : if (eBrackets == BRACKETS_OPENING
2145 0 : && !bBracketedBlock)
2146 : {
2147 0 : if (rSink.getColumn()
2148 0 : + (bInitialSpace ? 1 : 0)
2149 0 : >= rSink.getLineLengthLimit())
2150 0 : rSink << INetMIMEOutputSink::endl << ' ';
2151 0 : else if (bInitialSpace)
2152 0 : rSink << ' ';
2153 0 : rSink << '<';
2154 0 : bInitialSpace = false;
2155 0 : eBrackets = BRACKETS_INSIDE;
2156 : }
2157 :
2158 : // Write the output:
2159 0 : if (rSink.getColumn() + (bInitialSpace ? 1 : 0)
2160 0 : + nLength
2161 0 : > rSink.getLineLengthLimit())
2162 0 : rSink << INetMIMEOutputSink::endl << ' ';
2163 0 : else if (bInitialSpace)
2164 0 : rSink << ' ';
2165 0 : bInitialSpace = false;
2166 0 : if (bBracketedBlock)
2167 : {
2168 0 : rSink << '<';
2169 0 : eBrackets = BRACKETS_OUTSIDE;
2170 : }
2171 0 : if (bModify)
2172 : {
2173 : enum Mode { MODE_PLAIN, MODE_QUOTED_STRING,
2174 : MODE_DOMAIN_LITERAL };
2175 0 : Mode eMode = MODE_PLAIN;
2176 0 : while (pStart != pBodyPtr)
2177 0 : switch (*pStart)
2178 : {
2179 : case '\x0D': // CR
2180 0 : if (startsWithLineFolding(
2181 : pStart, pBodyPtr))
2182 : {
2183 0 : if (eMode != MODE_PLAIN)
2184 : rSink << sal_Char(
2185 0 : pStart[2]);
2186 0 : pStart += 3;
2187 : }
2188 0 : else if (startsWithLineBreak(
2189 : pStart, pBodyPtr))
2190 : {
2191 0 : rSink << "\x0D\\\x0A";
2192 : // CR, '\', LF
2193 0 : pStart += 2;
2194 : }
2195 : else
2196 : {
2197 0 : rSink << '\x0D'; // CR
2198 0 : ++pStart;
2199 : }
2200 0 : break;
2201 :
2202 : case '\t':
2203 : case ' ':
2204 0 : if (eMode != MODE_PLAIN)
2205 0 : rSink << sal_Char(*pStart);
2206 0 : ++pStart;
2207 0 : break;
2208 :
2209 : case '"':
2210 0 : if (eMode == MODE_PLAIN)
2211 0 : eMode = MODE_QUOTED_STRING;
2212 0 : else if (eMode
2213 : == MODE_QUOTED_STRING)
2214 0 : eMode = MODE_PLAIN;
2215 0 : rSink << '"';
2216 0 : ++pStart;
2217 0 : break;
2218 :
2219 : case '[':
2220 0 : if (eMode == MODE_PLAIN)
2221 0 : eMode = MODE_DOMAIN_LITERAL;
2222 0 : rSink << '[';
2223 0 : ++pStart;
2224 0 : break;
2225 :
2226 : case ']':
2227 0 : if (eMode == MODE_DOMAIN_LITERAL)
2228 0 : eMode = MODE_PLAIN;
2229 0 : rSink << ']';
2230 0 : ++pStart;
2231 0 : break;
2232 :
2233 : case '\\':
2234 0 : rSink << '\\';
2235 0 : if (++pStart < pBodyPtr)
2236 0 : writeUTF8(rSink, *pStart++);
2237 0 : break;
2238 :
2239 : default:
2240 0 : writeUTF8(rSink, *pStart++);
2241 0 : break;
2242 : }
2243 : }
2244 : else
2245 0 : rSink.write(pStart, pBodyPtr);
2246 0 : break;
2247 : }
2248 :
2249 : case ENTITY_PHRASE:
2250 : {
2251 : // Write a pending '<' if necessary:
2252 0 : if (eBrackets == BRACKETS_OPENING)
2253 : {
2254 0 : if (rSink.getColumn()
2255 0 : + (bInitialSpace ? 1 : 0)
2256 0 : >= rSink.getLineLengthLimit())
2257 0 : rSink << INetMIMEOutputSink::endl << ' ';
2258 0 : else if (bInitialSpace)
2259 0 : rSink << ' ';
2260 0 : rSink << '<';
2261 0 : bInitialSpace = false;
2262 0 : eBrackets = BRACKETS_INSIDE;
2263 : }
2264 :
2265 : // Calculate the length of in- and output:
2266 0 : const sal_Unicode * pStart = pBodyPtr;
2267 0 : bool bQuotedString = false;
2268 0 : bool bEnd = false;
2269 0 : while (pBodyPtr != pBodyEnd && !bEnd)
2270 0 : switch (*pBodyPtr)
2271 : {
2272 : case '\t':
2273 : case ' ':
2274 : case '\x0D': // CR
2275 0 : if (bQuotedString)
2276 0 : ++pBodyPtr;
2277 : else
2278 : {
2279 : const sal_Unicode * pLookAhead
2280 : = skipLinearWhiteSpace(
2281 0 : pBodyPtr, pBodyEnd);
2282 0 : if (pLookAhead != pBodyEnd
2283 0 : && (isAtomChar(*pLookAhead)
2284 0 : || !rtl::isAscii(*pLookAhead)
2285 0 : || *pLookAhead == '"'))
2286 0 : pBodyPtr = pLookAhead;
2287 : else
2288 0 : bEnd = true;
2289 : }
2290 0 : break;
2291 :
2292 : case '"':
2293 0 : bQuotedString = !bQuotedString;
2294 0 : ++pBodyPtr;
2295 0 : break;
2296 :
2297 : case '\\':
2298 0 : if (bQuotedString)
2299 : {
2300 0 : if (++pBodyPtr != pBodyEnd)
2301 0 : ++pBodyPtr;
2302 : }
2303 : else
2304 0 : bEnd = true;
2305 0 : break;
2306 :
2307 : default:
2308 0 : if (bQuotedString
2309 0 : || isAtomChar(*pBodyPtr)
2310 0 : || !rtl::isAscii(*pBodyPtr))
2311 0 : ++pBodyPtr;
2312 : else
2313 0 : bEnd = true;
2314 0 : break;
2315 : }
2316 :
2317 : // Write the phrase, introducing encoded-words
2318 : // where necessary:
2319 : INetMIMEEncodedWordOutputSink
2320 : aOutput(
2321 : rSink,
2322 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE,
2323 : bInitialSpace ?
2324 : INetMIMEEncodedWordOutputSink::SPACE_ALWAYS :
2325 : INetMIMEEncodedWordOutputSink::SPACE_ENCODED,
2326 0 : ePreferredEncoding);
2327 0 : while (pStart != pBodyPtr)
2328 0 : switch (*pStart)
2329 : {
2330 : case '"':
2331 0 : ++pStart;
2332 0 : break;
2333 :
2334 : case '\\':
2335 0 : if (++pStart != pBodyPtr)
2336 0 : aOutput << *pStart++;
2337 0 : break;
2338 :
2339 : case '\x0D': // CR
2340 0 : pStart += 2;
2341 0 : aOutput << *pStart++;
2342 0 : break;
2343 :
2344 : default:
2345 0 : aOutput << *pStart++;
2346 0 : break;
2347 : }
2348 0 : bInitialSpace = aOutput.flush();
2349 0 : break;
2350 : }
2351 : }
2352 0 : break;
2353 : }
2354 : }
2355 : }
2356 0 : }
2357 :
2358 : // static
2359 0 : bool INetMIME::translateUTF8Char(const sal_Char *& rBegin,
2360 : const sal_Char * pEnd,
2361 : rtl_TextEncoding eEncoding,
2362 : sal_uInt32 & rCharacter)
2363 : {
2364 0 : if (rBegin == pEnd || static_cast< unsigned char >(*rBegin) < 0x80
2365 0 : || static_cast< unsigned char >(*rBegin) >= 0xFE)
2366 0 : return false;
2367 :
2368 : int nCount;
2369 : sal_uInt32 nMin;
2370 : sal_uInt32 nUCS4;
2371 0 : const sal_Char * p = rBegin;
2372 0 : if (static_cast< unsigned char >(*p) < 0xE0)
2373 : {
2374 0 : nCount = 1;
2375 0 : nMin = 0x80;
2376 0 : nUCS4 = static_cast< unsigned char >(*p) & 0x1F;
2377 : }
2378 0 : else if (static_cast< unsigned char >(*p) < 0xF0)
2379 : {
2380 0 : nCount = 2;
2381 0 : nMin = 0x800;
2382 0 : nUCS4 = static_cast< unsigned char >(*p) & 0xF;
2383 : }
2384 0 : else if (static_cast< unsigned char >(*p) < 0xF8)
2385 : {
2386 0 : nCount = 3;
2387 0 : nMin = 0x10000;
2388 0 : nUCS4 = static_cast< unsigned char >(*p) & 7;
2389 : }
2390 0 : else if (static_cast< unsigned char >(*p) < 0xFC)
2391 : {
2392 0 : nCount = 4;
2393 0 : nMin = 0x200000;
2394 0 : nUCS4 = static_cast< unsigned char >(*p) & 3;
2395 : }
2396 : else
2397 : {
2398 0 : nCount = 5;
2399 0 : nMin = 0x4000000;
2400 0 : nUCS4 = static_cast< unsigned char >(*p) & 1;
2401 : }
2402 0 : ++p;
2403 :
2404 0 : for (; nCount-- > 0; ++p)
2405 0 : if ((static_cast< unsigned char >(*p) & 0xC0) == 0x80)
2406 0 : nUCS4 = (nUCS4 << 6) | (static_cast< unsigned char >(*p) & 0x3F);
2407 : else
2408 0 : return false;
2409 :
2410 0 : if (nUCS4 < nMin || nUCS4 > 0x10FFFF)
2411 0 : return false;
2412 :
2413 0 : if (eEncoding >= RTL_TEXTENCODING_UCS4)
2414 0 : rCharacter = nUCS4;
2415 : else
2416 : {
2417 : sal_Unicode aUTF16[2];
2418 0 : const sal_Unicode * pUTF16End = putUTF32Character(aUTF16, nUCS4);
2419 : sal_Size nSize;
2420 : sal_Char * pBuffer = convertFromUnicode(aUTF16, pUTF16End, eEncoding,
2421 0 : nSize);
2422 0 : if (!pBuffer)
2423 0 : return false;
2424 : DBG_ASSERT(nSize == 1,
2425 : "INetMIME::translateUTF8Char(): Bad conversion");
2426 0 : rCharacter = *pBuffer;
2427 0 : delete[] pBuffer;
2428 : }
2429 0 : rBegin = p;
2430 0 : return true;
2431 : }
2432 :
2433 : // static
2434 6 : OUString INetMIME::decodeHeaderFieldBody(HeaderFieldType eType,
2435 : const OString& rBody)
2436 : {
2437 : // Due to a bug in INetCoreRFC822MessageStream::ConvertTo7Bit(), old
2438 : // versions of StarOffice send mails with header fields where encoded
2439 : // words can be preceded by '=', ',', '.', '"', or '(', and followed by
2440 : // '=', ',', '.', '"', ')', without any required white space in between.
2441 : // And there appear to exist some broken mailers that only encode single
2442 : // letters within words, like "Appel
2443 : // =?iso-8859-1?Q?=E0?=t=?iso-8859-1?Q?=E9?=moin", so it seems best to
2444 : // detect encoded words even when not propperly surrounded by white space.
2445 :
2446 : // Non US-ASCII characters in rBody are treated as ISO-8859-1.
2447 :
2448 : // encoded-word = "=?"
2449 : // 1*(%x21 / %x23-27 / %x2A-2B / %x2D / %30-39 / %x41-5A / %x5E-7E)
2450 : // ["*" 1*8ALPHA *("-" 1*8ALPHA)] "?"
2451 : // ("B?" *(4base64) (4base64 / 3base64 "=" / 2base64 "==")
2452 : // / "Q?" 1*(%x21-3C / %x3E / %x40-7E / "=" 2HEXDIG))
2453 : // "?="
2454 :
2455 : // base64 = ALPHA / DIGIT / "+" / "/"
2456 :
2457 6 : const sal_Char * pBegin = rBody.getStr();
2458 6 : const sal_Char * pEnd = pBegin + rBody.getLength();
2459 :
2460 6 : OUString sDecoded;
2461 6 : const sal_Char * pCopyBegin = pBegin;
2462 :
2463 : /* bool bStartEncodedWord = true; */
2464 6 : const sal_Char * pWSPBegin = pBegin;
2465 6 : bool bQuotedEncodedText = false;
2466 6 : sal_uInt32 nCommentLevel = 0;
2467 :
2468 18 : for (const sal_Char * p = pBegin; p != pEnd;)
2469 : {
2470 6 : OUString sEncodedText;
2471 6 : if (p != pEnd && *p == '=' /* && bStartEncodedWord */)
2472 : {
2473 6 : const sal_Char * q = p + 1;
2474 6 : bool bEncodedWord = q != pEnd && *q++ == '?';
2475 :
2476 6 : rtl_TextEncoding eCharsetEncoding = RTL_TEXTENCODING_DONTKNOW;
2477 6 : if (bEncodedWord)
2478 : {
2479 6 : const sal_Char * pCharsetBegin = q;
2480 6 : const sal_Char * pLanguageBegin = 0;
2481 6 : int nAlphaCount = 0;
2482 78 : for (bool bDone = false; !bDone;)
2483 66 : if (q == pEnd)
2484 : {
2485 0 : bEncodedWord = false;
2486 0 : bDone = true;
2487 : }
2488 : else
2489 : {
2490 66 : sal_Char cChar = *q++;
2491 66 : switch (cChar)
2492 : {
2493 : case '*':
2494 0 : pLanguageBegin = q - 1;
2495 0 : nAlphaCount = 0;
2496 0 : break;
2497 :
2498 : case '-':
2499 12 : if (pLanguageBegin != 0)
2500 : {
2501 0 : if (nAlphaCount == 0)
2502 0 : pLanguageBegin = 0;
2503 : else
2504 0 : nAlphaCount = 0;
2505 : }
2506 12 : break;
2507 :
2508 : case '?':
2509 6 : if (pCharsetBegin == q - 1)
2510 0 : bEncodedWord = false;
2511 : else
2512 : {
2513 : eCharsetEncoding
2514 : = getCharsetEncoding(
2515 : pCharsetBegin,
2516 : pLanguageBegin == 0
2517 0 : || nAlphaCount == 0 ?
2518 12 : q - 1 : pLanguageBegin);
2519 : bEncodedWord = isMIMECharsetEncoding(
2520 6 : eCharsetEncoding);
2521 : eCharsetEncoding
2522 6 : = translateFromMIME(eCharsetEncoding);
2523 : }
2524 6 : bDone = true;
2525 6 : break;
2526 :
2527 : default:
2528 48 : if (pLanguageBegin != 0
2529 48 : && (!rtl::isAsciiAlpha(cChar) || ++nAlphaCount > 8))
2530 0 : pLanguageBegin = 0;
2531 48 : break;
2532 : }
2533 : }
2534 : }
2535 :
2536 6 : bool bEncodingB = false;
2537 6 : if (bEncodedWord)
2538 : {
2539 6 : if (q == pEnd)
2540 0 : bEncodedWord = false;
2541 : else
2542 : {
2543 6 : switch (*q++)
2544 : {
2545 : case 'B':
2546 : case 'b':
2547 6 : bEncodingB = true;
2548 6 : break;
2549 :
2550 : case 'Q':
2551 : case 'q':
2552 0 : bEncodingB = false;
2553 0 : break;
2554 :
2555 : default:
2556 0 : bEncodedWord = false;
2557 0 : break;
2558 : }
2559 : }
2560 : }
2561 :
2562 6 : bEncodedWord = bEncodedWord && q != pEnd && *q++ == '?';
2563 :
2564 6 : OStringBuffer sText;
2565 6 : if (bEncodedWord)
2566 : {
2567 6 : if (bEncodingB)
2568 : {
2569 18 : for (bool bDone = false; !bDone;)
2570 : {
2571 6 : if (pEnd - q < 4)
2572 : {
2573 0 : bEncodedWord = false;
2574 0 : bDone = true;
2575 : }
2576 : else
2577 : {
2578 6 : bool bFinal = false;
2579 6 : int nCount = 3;
2580 6 : sal_uInt32 nValue = 0;
2581 30 : for (int nShift = 18; nShift >= 0; nShift -= 6)
2582 : {
2583 24 : int nWeight = getBase64Weight(*q++);
2584 24 : if (nWeight == -2)
2585 : {
2586 0 : bEncodedWord = false;
2587 0 : bDone = true;
2588 0 : break;
2589 : }
2590 24 : if (nWeight == -1)
2591 : {
2592 6 : if (!bFinal)
2593 : {
2594 4 : if (nShift >= 12)
2595 : {
2596 0 : bEncodedWord = false;
2597 0 : bDone = true;
2598 0 : break;
2599 : }
2600 4 : bFinal = true;
2601 4 : nCount = nShift == 6 ? 1 : 2;
2602 : }
2603 : }
2604 : else
2605 18 : nValue |= nWeight << nShift;
2606 : }
2607 6 : if (bEncodedWord)
2608 : {
2609 18 : for (int nShift = 16; nCount-- > 0; nShift -= 8)
2610 12 : sText.append(sal_Char(nValue >> nShift & 0xFF));
2611 6 : if (*q == '?')
2612 : {
2613 6 : ++q;
2614 6 : bDone = true;
2615 : }
2616 6 : if (bFinal && !bDone)
2617 : {
2618 0 : bEncodedWord = false;
2619 0 : bDone = true;
2620 : }
2621 : }
2622 : }
2623 : }
2624 : }
2625 : else
2626 : {
2627 0 : const sal_Char * pEncodedTextBegin = q;
2628 0 : const sal_Char * pEncodedTextCopyBegin = q;
2629 0 : for (bool bDone = false; !bDone;)
2630 0 : if (q == pEnd)
2631 : {
2632 0 : bEncodedWord = false;
2633 0 : bDone = true;
2634 : }
2635 : else
2636 : {
2637 0 : sal_uInt32 nChar = *q++;
2638 0 : switch (nChar)
2639 : {
2640 : case '=':
2641 : {
2642 0 : if (pEnd - q < 2)
2643 : {
2644 0 : bEncodedWord = false;
2645 0 : bDone = true;
2646 0 : break;
2647 : }
2648 0 : int nDigit1 = getHexWeight(q[0]);
2649 0 : int nDigit2 = getHexWeight(q[1]);
2650 0 : if (nDigit1 < 0 || nDigit2 < 0)
2651 : {
2652 0 : bEncodedWord = false;
2653 0 : bDone = true;
2654 0 : break;
2655 : }
2656 : sText.append(rBody.copy(
2657 0 : (pEncodedTextCopyBegin - pBegin),
2658 0 : (q - 1 - pEncodedTextCopyBegin)));
2659 0 : sText.append(sal_Char(nDigit1 << 4 | nDigit2));
2660 0 : q += 2;
2661 0 : pEncodedTextCopyBegin = q;
2662 0 : break;
2663 : }
2664 :
2665 : case '?':
2666 0 : if (q - pEncodedTextBegin > 1)
2667 : sText.append(rBody.copy(
2668 0 : (pEncodedTextCopyBegin - pBegin),
2669 0 : (q - 1 - pEncodedTextCopyBegin)));
2670 : else
2671 0 : bEncodedWord = false;
2672 0 : bDone = true;
2673 0 : break;
2674 :
2675 : case '_':
2676 : sText.append(rBody.copy(
2677 0 : (pEncodedTextCopyBegin - pBegin),
2678 0 : (q - 1 - pEncodedTextCopyBegin)));
2679 0 : sText.append(' ');
2680 0 : pEncodedTextCopyBegin = q;
2681 0 : break;
2682 :
2683 : default:
2684 0 : if (!isVisible(nChar))
2685 : {
2686 0 : bEncodedWord = false;
2687 0 : bDone = true;
2688 : }
2689 0 : break;
2690 : }
2691 : }
2692 : }
2693 : }
2694 :
2695 6 : bEncodedWord = bEncodedWord && q != pEnd && *q++ == '=';
2696 :
2697 6 : sal_Unicode * pUnicodeBuffer = 0;
2698 6 : sal_Size nUnicodeSize = 0;
2699 6 : if (bEncodedWord)
2700 : {
2701 : pUnicodeBuffer
2702 : = convertToUnicode(sText.getStr(),
2703 6 : sText.getStr() + sText.getLength(),
2704 12 : eCharsetEncoding, nUnicodeSize);
2705 6 : if (pUnicodeBuffer == 0)
2706 0 : bEncodedWord = false;
2707 : }
2708 :
2709 6 : if (bEncodedWord)
2710 : {
2711 6 : appendISO88591(sDecoded, pCopyBegin, pWSPBegin);
2712 6 : if (eType == HEADER_FIELD_TEXT)
2713 12 : sDecoded += OUString(
2714 : pUnicodeBuffer,
2715 6 : static_cast< sal_Int32 >(nUnicodeSize));
2716 0 : else if (nCommentLevel == 0)
2717 : {
2718 0 : sEncodedText = OUString(pUnicodeBuffer, nUnicodeSize);
2719 0 : if (!bQuotedEncodedText)
2720 : {
2721 0 : const sal_Unicode * pTextPtr = pUnicodeBuffer;
2722 : const sal_Unicode * pTextEnd = pTextPtr
2723 0 : + nUnicodeSize;
2724 0 : for (; pTextPtr != pTextEnd; ++pTextPtr)
2725 0 : if (!isEncodedWordTokenChar(*pTextPtr))
2726 : {
2727 0 : bQuotedEncodedText = true;
2728 0 : break;
2729 : }
2730 : }
2731 : }
2732 : else
2733 : {
2734 0 : const sal_Unicode * pTextPtr = pUnicodeBuffer;
2735 0 : const sal_Unicode * pTextEnd = pTextPtr + nUnicodeSize;
2736 0 : for (; pTextPtr != pTextEnd; ++pTextPtr)
2737 : {
2738 0 : switch (*pTextPtr)
2739 : {
2740 : case '(':
2741 : case ')':
2742 : case '\\':
2743 : case '\x0D':
2744 : case '=':
2745 0 : sDecoded += "\\";
2746 0 : break;
2747 : }
2748 0 : sDecoded += OUString(*pTextPtr);
2749 : }
2750 : }
2751 6 : delete[] pUnicodeBuffer;
2752 6 : p = q;
2753 6 : pCopyBegin = p;
2754 :
2755 6 : pWSPBegin = p;
2756 12 : while (p != pEnd && isWhiteSpace(*p))
2757 0 : ++p;
2758 : /* bStartEncodedWord = p != pWSPBegin; */
2759 6 : continue;
2760 0 : }
2761 : }
2762 :
2763 0 : if (!sEncodedText.isEmpty())
2764 : {
2765 0 : if (bQuotedEncodedText)
2766 : {
2767 0 : sDecoded += "\"";
2768 0 : const sal_Unicode * pTextPtr = sEncodedText.getStr();
2769 0 : const sal_Unicode * pTextEnd = pTextPtr + sEncodedText.getLength();
2770 0 : for (;pTextPtr != pTextEnd; ++pTextPtr)
2771 : {
2772 0 : switch (*pTextPtr)
2773 : {
2774 : case '"':
2775 : case '\\':
2776 : case '\x0D':
2777 0 : sDecoded += "\\";
2778 0 : break;
2779 : }
2780 0 : sDecoded += OUString(*pTextPtr);
2781 : }
2782 0 : sDecoded += "\"";
2783 : }
2784 : else
2785 0 : sDecoded += sEncodedText;
2786 0 : bQuotedEncodedText = false;
2787 : }
2788 :
2789 0 : if (p == pEnd)
2790 0 : break;
2791 :
2792 0 : switch (*p++)
2793 : {
2794 : case '"':
2795 0 : if (eType != HEADER_FIELD_TEXT && nCommentLevel == 0)
2796 : {
2797 : const sal_Char * pQuotedStringEnd
2798 0 : = skipQuotedString(p - 1, pEnd);
2799 0 : p = pQuotedStringEnd == p - 1 ? pEnd : pQuotedStringEnd;
2800 : }
2801 : /* bStartEncodedWord = true; */
2802 0 : break;
2803 :
2804 : case '(':
2805 0 : if (eType != HEADER_FIELD_TEXT)
2806 0 : ++nCommentLevel;
2807 : /* bStartEncodedWord = true; */
2808 0 : break;
2809 :
2810 : case ')':
2811 0 : if (nCommentLevel > 0)
2812 0 : --nCommentLevel;
2813 : /* bStartEncodedWord = false; */
2814 0 : break;
2815 :
2816 : default:
2817 : {
2818 0 : const sal_Char * pUTF8Begin = p - 1;
2819 0 : const sal_Char * pUTF8End = pUTF8Begin;
2820 0 : sal_uInt32 nCharacter = 0;
2821 0 : if (translateUTF8Char(pUTF8End, pEnd, RTL_TEXTENCODING_UCS4,
2822 : nCharacter))
2823 : {
2824 0 : appendISO88591(sDecoded, pCopyBegin, p - 1);
2825 : sal_Unicode aUTF16Buf[2];
2826 0 : sal_Int32 nUTF16Len = putUTF32Character(aUTF16Buf, nCharacter) - aUTF16Buf;
2827 0 : sDecoded += OUString(aUTF16Buf, nUTF16Len);
2828 0 : p = pUTF8End;
2829 0 : pCopyBegin = p;
2830 : }
2831 : /* bStartEncodedWord = false; */
2832 0 : break;
2833 : }
2834 : }
2835 0 : pWSPBegin = p;
2836 0 : }
2837 :
2838 6 : appendISO88591(sDecoded, pCopyBegin, pEnd);
2839 6 : return sDecoded;
2840 : }
2841 :
2842 : // INetMIMEOutputSink
2843 :
2844 : // virtual
2845 0 : sal_Size INetMIMEOutputSink::writeSequence(const sal_Char * pSequence)
2846 : {
2847 0 : sal_Size nLength = rtl_str_getLength(pSequence);
2848 0 : writeSequence(pSequence, pSequence + nLength);
2849 0 : return nLength;
2850 : }
2851 :
2852 : // virtual
2853 0 : void INetMIMEOutputSink::writeSequence(const sal_uInt32 * pBegin,
2854 : const sal_uInt32 * pEnd)
2855 : {
2856 : DBG_ASSERT(pBegin && pBegin <= pEnd,
2857 : "INetMIMEOutputSink::writeSequence(): Bad sequence");
2858 :
2859 0 : sal_Char * pBufferBegin = new sal_Char[pEnd - pBegin];
2860 0 : sal_Char * pBufferEnd = pBufferBegin;
2861 0 : while (pBegin != pEnd)
2862 : {
2863 : DBG_ASSERT(*pBegin < 256,
2864 : "INetMIMEOutputSink::writeSequence(): Bad octet");
2865 0 : *pBufferEnd++ = sal_Char(*pBegin++);
2866 : }
2867 0 : writeSequence(pBufferBegin, pBufferEnd);
2868 0 : delete[] pBufferBegin;
2869 0 : }
2870 :
2871 : // virtual
2872 0 : void INetMIMEOutputSink::writeSequence(const sal_Unicode * pBegin,
2873 : const sal_Unicode * pEnd)
2874 : {
2875 : assert(pBegin && pBegin <= pEnd &&
2876 : "INetMIMEOutputSink::writeSequence(): Bad sequence");
2877 :
2878 0 : sal_Char * pBufferBegin = new sal_Char[pEnd - pBegin];
2879 0 : sal_Char * pBufferEnd = pBufferBegin;
2880 0 : while (pBegin != pEnd)
2881 : {
2882 : DBG_ASSERT(*pBegin < 256,
2883 : "INetMIMEOutputSink::writeSequence(): Bad octet");
2884 0 : *pBufferEnd++ = sal_Char(*pBegin++);
2885 : }
2886 0 : writeSequence(pBufferBegin, pBufferEnd);
2887 0 : delete[] pBufferBegin;
2888 0 : }
2889 :
2890 : // virtual
2891 0 : ErrCode INetMIMEOutputSink::getError() const
2892 : {
2893 0 : return ERRCODE_NONE;
2894 : }
2895 :
2896 0 : void INetMIMEOutputSink::writeLineEnd()
2897 : {
2898 : static const sal_Char aCRLF[2] = { 0x0D, 0x0A };
2899 0 : writeSequence(aCRLF, aCRLF + 2);
2900 0 : m_nColumn = 0;
2901 0 : }
2902 :
2903 : // INetMIMEStringOutputSink
2904 :
2905 : // virtual
2906 0 : void INetMIMEStringOutputSink::writeSequence(const sal_Char * pBegin,
2907 : const sal_Char * pEnd)
2908 : {
2909 : OSL_ENSURE(pBegin && pBegin <= pEnd,
2910 : "INetMIMEStringOutputSink::writeSequence(): Bad sequence");
2911 :
2912 0 : m_aBuffer.append(pBegin, pEnd - pBegin);
2913 0 : }
2914 :
2915 : // virtual
2916 0 : ErrCode INetMIMEStringOutputSink::getError() const
2917 : {
2918 0 : return ERRCODE_NONE;
2919 : }
2920 :
2921 : // INetMIMEEncodedWordOutputSink
2922 :
2923 : static const sal_Char aEscape[128]
2924 : = { INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x00
2925 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x01
2926 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x02
2927 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x03
2928 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x04
2929 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x05
2930 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x06
2931 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x07
2932 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x08
2933 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x09
2934 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x0A
2935 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x0B
2936 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x0C
2937 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x0D
2938 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x0E
2939 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x0F
2940 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x10
2941 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x11
2942 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x12
2943 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x13
2944 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x14
2945 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x15
2946 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x16
2947 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x17
2948 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x18
2949 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x19
2950 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x1A
2951 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x1B
2952 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x1C
2953 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x1D
2954 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x1E
2955 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // 0x1F
2956 : 0, // ' '
2957 : 0, // '!'
2958 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '"'
2959 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '#'
2960 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '$'
2961 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '%'
2962 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '&'
2963 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '''
2964 : INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '('
2965 : INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // ')'
2966 : 0, // '*'
2967 : 0, // '+'
2968 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // ','
2969 : 0, // '-'
2970 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '.'
2971 : 0, // '/'
2972 : 0, // '0'
2973 : 0, // '1'
2974 : 0, // '2'
2975 : 0, // '3'
2976 : 0, // '4'
2977 : 0, // '5'
2978 : 0, // '6'
2979 : 0, // '7'
2980 : 0, // '8'
2981 : 0, // '9'
2982 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // ':'
2983 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // ';'
2984 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '<'
2985 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '='
2986 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '>'
2987 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '?'
2988 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '@'
2989 : 0, // 'A'
2990 : 0, // 'B'
2991 : 0, // 'C'
2992 : 0, // 'D'
2993 : 0, // 'E'
2994 : 0, // 'F'
2995 : 0, // 'G'
2996 : 0, // 'H'
2997 : 0, // 'I'
2998 : 0, // 'J'
2999 : 0, // 'K'
3000 : 0, // 'L'
3001 : 0, // 'M'
3002 : 0, // 'N'
3003 : 0, // 'O'
3004 : 0, // 'P'
3005 : 0, // 'Q'
3006 : 0, // 'R'
3007 : 0, // 'S'
3008 : 0, // 'T'
3009 : 0, // 'U'
3010 : 0, // 'V'
3011 : 0, // 'W'
3012 : 0, // 'X'
3013 : 0, // 'Y'
3014 : 0, // 'Z'
3015 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '['
3016 : INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '\'
3017 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // ']'
3018 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '^'
3019 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '_'
3020 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '`'
3021 : 0, // 'a'
3022 : 0, // 'b'
3023 : 0, // 'c'
3024 : 0, // 'd'
3025 : 0, // 'e'
3026 : 0, // 'f'
3027 : 0, // 'g'
3028 : 0, // 'h'
3029 : 0, // 'i'
3030 : 0, // 'j'
3031 : 0, // 'k'
3032 : 0, // 'l'
3033 : 0, // 'm'
3034 : 0, // 'n'
3035 : 0, // 'o'
3036 : 0, // 'p'
3037 : 0, // 'q'
3038 : 0, // 'r'
3039 : 0, // 's'
3040 : 0, // 't'
3041 : 0, // 'u'
3042 : 0, // 'v'
3043 : 0, // 'w'
3044 : 0, // 'x'
3045 : 0, // 'y'
3046 : 0, // 'z'
3047 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '{'
3048 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '|'
3049 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '}'
3050 : INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE, // '~'
3051 : INetMIMEEncodedWordOutputSink::CONTEXT_TEXT | INetMIMEEncodedWordOutputSink::CONTEXT_COMMENT | INetMIMEEncodedWordOutputSink::CONTEXT_PHRASE }; // DEL
3052 :
3053 : inline bool
3054 0 : INetMIMEEncodedWordOutputSink::needsEncodedWordEscape(sal_uInt32 nChar) const
3055 : {
3056 0 : return !rtl::isAscii(nChar) || aEscape[nChar] & m_eContext;
3057 : }
3058 :
3059 0 : void INetMIMEEncodedWordOutputSink::finish(bool bWriteTrailer)
3060 : {
3061 0 : if (m_eInitialSpace == SPACE_ALWAYS && m_nExtraSpaces == 0)
3062 0 : m_nExtraSpaces = 1;
3063 :
3064 0 : if (m_eEncodedWordState == STATE_SECOND_EQUALS)
3065 : {
3066 : // If the text is already an encoded word, copy it verbatim:
3067 0 : sal_uInt32 nSize = m_pBufferEnd - m_pBuffer;
3068 0 : switch (m_ePrevCoding)
3069 : {
3070 : case CODING_QUOTED:
3071 0 : m_rSink << '"';
3072 : case CODING_NONE:
3073 0 : if (m_eInitialSpace == SPACE_ENCODED && m_nExtraSpaces == 0)
3074 0 : m_nExtraSpaces = 1;
3075 0 : for (; m_nExtraSpaces > 1; --m_nExtraSpaces)
3076 : {
3077 0 : if (m_rSink.getColumn() >= m_rSink.getLineLengthLimit())
3078 0 : m_rSink << INetMIMEOutputSink::endl;
3079 0 : m_rSink << ' ';
3080 : }
3081 0 : if (m_nExtraSpaces == 1)
3082 : {
3083 0 : if (m_rSink.getColumn() + nSize
3084 0 : >= m_rSink.getLineLengthLimit())
3085 0 : m_rSink << INetMIMEOutputSink::endl;
3086 0 : m_rSink << ' ';
3087 : }
3088 0 : break;
3089 :
3090 : case CODING_ENCODED:
3091 : {
3092 : const sal_Char * pCharsetName
3093 0 : = INetMIME::getCharsetName(m_ePrevMIMEEncoding);
3094 0 : while (m_nExtraSpaces-- > 0)
3095 : {
3096 0 : if (m_rSink.getColumn()
3097 0 : > m_rSink.getLineLengthLimit() - 3)
3098 0 : m_rSink << "?=" << INetMIMEOutputSink::endl << " =?"
3099 0 : << pCharsetName << "?Q?";
3100 0 : m_rSink << '_';
3101 : }
3102 0 : m_rSink << "?=";
3103 : }
3104 : //fall-through
3105 : case CODING_ENCODED_TERMINATED:
3106 0 : if (m_rSink.getColumn() + nSize
3107 0 : > m_rSink.getLineLengthLimit() - 1)
3108 0 : m_rSink << INetMIMEOutputSink::endl;
3109 0 : m_rSink << ' ';
3110 0 : break;
3111 : }
3112 0 : m_rSink.write(m_pBuffer, m_pBufferEnd);
3113 0 : m_eCoding = CODING_ENCODED_TERMINATED;
3114 : }
3115 : else
3116 : {
3117 : // If the text itself is too long to fit into a single line, make it
3118 : // into multiple encoded words:
3119 0 : switch (m_eCoding)
3120 : {
3121 : case CODING_NONE:
3122 0 : if (m_nExtraSpaces == 0)
3123 : {
3124 : DBG_ASSERT(m_ePrevCoding == CODING_NONE
3125 : || m_pBuffer == m_pBufferEnd,
3126 : "INetMIMEEncodedWordOutputSink::finish():"
3127 : " Bad state");
3128 0 : if (m_rSink.getColumn() + (m_pBufferEnd - m_pBuffer)
3129 0 : > m_rSink.getLineLengthLimit())
3130 0 : m_eCoding = CODING_ENCODED;
3131 : }
3132 : else
3133 : {
3134 : OSL_ASSERT(m_pBufferEnd >= m_pBuffer);
3135 0 : if (static_cast< std::size_t >(m_pBufferEnd - m_pBuffer)
3136 0 : > m_rSink.getLineLengthLimit() - 1)
3137 : {
3138 0 : m_eCoding = CODING_ENCODED;
3139 : }
3140 : }
3141 0 : break;
3142 :
3143 : case CODING_QUOTED:
3144 0 : if (m_nExtraSpaces == 0)
3145 : {
3146 : DBG_ASSERT(m_ePrevCoding == CODING_NONE,
3147 : "INetMIMEEncodedWordOutputSink::finish():"
3148 : " Bad state");
3149 0 : if (m_rSink.getColumn() + (m_pBufferEnd - m_pBuffer)
3150 0 : + m_nQuotedEscaped
3151 0 : > m_rSink.getLineLengthLimit() - 2)
3152 0 : m_eCoding = CODING_ENCODED;
3153 : }
3154 0 : else if ((m_pBufferEnd - m_pBuffer) + m_nQuotedEscaped
3155 0 : > m_rSink.getLineLengthLimit() - 3)
3156 0 : m_eCoding = CODING_ENCODED;
3157 0 : break;
3158 :
3159 : default:
3160 0 : break;
3161 : }
3162 :
3163 0 : switch (m_eCoding)
3164 : {
3165 : case CODING_NONE:
3166 0 : switch (m_ePrevCoding)
3167 : {
3168 : case CODING_QUOTED:
3169 0 : if (m_rSink.getColumn() + m_nExtraSpaces
3170 0 : + (m_pBufferEnd - m_pBuffer)
3171 0 : < m_rSink.getLineLengthLimit())
3172 0 : m_eCoding = CODING_QUOTED;
3173 : else
3174 0 : m_rSink << '"';
3175 0 : break;
3176 :
3177 : case CODING_ENCODED:
3178 0 : m_rSink << "?=";
3179 0 : break;
3180 :
3181 : default:
3182 0 : break;
3183 : }
3184 0 : for (; m_nExtraSpaces > 1; --m_nExtraSpaces)
3185 : {
3186 0 : if (m_rSink.getColumn() >= m_rSink.getLineLengthLimit())
3187 0 : m_rSink << INetMIMEOutputSink::endl;
3188 0 : m_rSink << ' ';
3189 : }
3190 0 : if (m_nExtraSpaces == 1)
3191 : {
3192 0 : if (m_rSink.getColumn() + (m_pBufferEnd - m_pBuffer)
3193 0 : >= m_rSink.getLineLengthLimit())
3194 0 : m_rSink << INetMIMEOutputSink::endl;
3195 0 : m_rSink << ' ';
3196 : }
3197 0 : m_rSink.write(m_pBuffer, m_pBufferEnd);
3198 0 : if (m_eCoding == CODING_QUOTED && bWriteTrailer)
3199 : {
3200 0 : m_rSink << '"';
3201 0 : m_eCoding = CODING_NONE;
3202 : }
3203 0 : break;
3204 :
3205 : case CODING_QUOTED:
3206 : {
3207 0 : bool bInsertLeadingQuote = true;
3208 0 : sal_uInt32 nSize = (m_pBufferEnd - m_pBuffer)
3209 0 : + m_nQuotedEscaped + 2;
3210 0 : switch (m_ePrevCoding)
3211 : {
3212 : case CODING_QUOTED:
3213 0 : if (m_rSink.getColumn() + m_nExtraSpaces + nSize - 1
3214 0 : < m_rSink.getLineLengthLimit())
3215 : {
3216 0 : bInsertLeadingQuote = false;
3217 0 : --nSize;
3218 : }
3219 : else
3220 0 : m_rSink << '"';
3221 0 : break;
3222 :
3223 : case CODING_ENCODED:
3224 0 : m_rSink << "?=";
3225 0 : break;
3226 :
3227 : default:
3228 0 : break;
3229 : }
3230 0 : for (; m_nExtraSpaces > 1; --m_nExtraSpaces)
3231 : {
3232 0 : if (m_rSink.getColumn() >= m_rSink.getLineLengthLimit())
3233 0 : m_rSink << INetMIMEOutputSink::endl;
3234 0 : m_rSink << ' ';
3235 : }
3236 0 : if (m_nExtraSpaces == 1)
3237 : {
3238 0 : if (m_rSink.getColumn() + nSize
3239 0 : >= m_rSink.getLineLengthLimit())
3240 0 : m_rSink << INetMIMEOutputSink::endl;
3241 0 : m_rSink << ' ';
3242 : }
3243 0 : if (bInsertLeadingQuote)
3244 0 : m_rSink << '"';
3245 0 : for (const sal_Unicode * p = m_pBuffer; p != m_pBufferEnd;
3246 : ++p)
3247 : {
3248 0 : if (INetMIME::needsQuotedStringEscape(*p))
3249 0 : m_rSink << '\\';
3250 0 : m_rSink << sal_Char(*p);
3251 : }
3252 0 : if (bWriteTrailer)
3253 : {
3254 0 : m_rSink << '"';
3255 0 : m_eCoding = CODING_NONE;
3256 : }
3257 0 : break;
3258 : }
3259 :
3260 : case CODING_ENCODED:
3261 : {
3262 : rtl_TextEncoding eCharsetEncoding
3263 : = m_pEncodingList->
3264 0 : getPreferredEncoding(RTL_TEXTENCODING_UTF8);
3265 : rtl_TextEncoding eMIMEEncoding
3266 0 : = INetMIME::translateToMIME(eCharsetEncoding);
3267 :
3268 : // The non UTF-8 code will only work for stateless single byte
3269 : // character encodings (see also below):
3270 0 : sal_Char * pTargetBuffer = NULL;
3271 0 : sal_Size nTargetSize = 0;
3272 : sal_uInt32 nSize;
3273 0 : if (eMIMEEncoding == RTL_TEXTENCODING_UTF8)
3274 : {
3275 0 : nSize = 0;
3276 0 : for (sal_Unicode const * p = m_pBuffer;
3277 0 : p != m_pBufferEnd;)
3278 : {
3279 : sal_uInt32 nUTF32
3280 0 : = INetMIME::getUTF32Character(p, m_pBufferEnd);
3281 0 : nSize += needsEncodedWordEscape(nUTF32) ?
3282 0 : 3 * INetMIME::getUTF8OctetCount(nUTF32) :
3283 0 : 1;
3284 : // only US-ASCII characters (that are converted to
3285 : // a single byte by UTF-8) need no encoded word
3286 : // escapes...
3287 : }
3288 : }
3289 : else
3290 : {
3291 : rtl_UnicodeToTextConverter hConverter
3292 0 : = rtl_createUnicodeToTextConverter(eCharsetEncoding);
3293 : rtl_UnicodeToTextContext hContext
3294 0 : = rtl_createUnicodeToTextContext(hConverter);
3295 0 : for (sal_Size nBufferSize = m_pBufferEnd - m_pBuffer;;
3296 0 : nBufferSize += nBufferSize / 3 + 1)
3297 : {
3298 0 : pTargetBuffer = new sal_Char[nBufferSize];
3299 : sal_uInt32 nInfo;
3300 : sal_Size nSrcCvtBytes;
3301 : nTargetSize
3302 : = rtl_convertUnicodeToText(
3303 : hConverter, hContext, m_pBuffer,
3304 0 : m_pBufferEnd - m_pBuffer, pTargetBuffer,
3305 : nBufferSize,
3306 : RTL_UNICODETOTEXT_FLAGS_UNDEFINED_IGNORE
3307 : | RTL_UNICODETOTEXT_FLAGS_INVALID_IGNORE,
3308 0 : &nInfo, &nSrcCvtBytes);
3309 0 : if (!(nInfo
3310 0 : & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL))
3311 0 : break;
3312 0 : delete[] pTargetBuffer;
3313 0 : pTargetBuffer = NULL;
3314 0 : rtl_resetUnicodeToTextContext(hConverter, hContext);
3315 0 : }
3316 0 : rtl_destroyUnicodeToTextContext(hConverter, hContext);
3317 0 : rtl_destroyUnicodeToTextConverter(hConverter);
3318 :
3319 0 : nSize = nTargetSize;
3320 0 : for (sal_Size k = 0; k < nTargetSize; ++k)
3321 0 : if (needsEncodedWordEscape(static_cast<unsigned char>(
3322 0 : pTargetBuffer[k])))
3323 0 : nSize += 2;
3324 : }
3325 :
3326 : const sal_Char * pCharsetName
3327 0 : = INetMIME::getCharsetName(eMIMEEncoding);
3328 0 : sal_uInt32 nWrapperSize = rtl_str_getLength(pCharsetName) + 7;
3329 : // '=?', '?Q?', '?='
3330 :
3331 0 : switch (m_ePrevCoding)
3332 : {
3333 : case CODING_QUOTED:
3334 0 : m_rSink << '"';
3335 : case CODING_NONE:
3336 0 : if (m_eInitialSpace == SPACE_ENCODED
3337 0 : && m_nExtraSpaces == 0)
3338 0 : m_nExtraSpaces = 1;
3339 0 : nSize += nWrapperSize;
3340 0 : for (; m_nExtraSpaces > 1; --m_nExtraSpaces)
3341 : {
3342 0 : if (m_rSink.getColumn() >= m_rSink.getLineLengthLimit())
3343 0 : m_rSink << INetMIMEOutputSink::endl;
3344 0 : m_rSink << ' ';
3345 : }
3346 0 : if (m_nExtraSpaces == 1)
3347 : {
3348 0 : if (m_rSink.getColumn() + nSize >= m_rSink.getLineLengthLimit())
3349 0 : m_rSink << INetMIMEOutputSink::endl;
3350 0 : m_rSink << ' ';
3351 : }
3352 0 : m_rSink << "=?" << pCharsetName << "?Q?";
3353 0 : break;
3354 :
3355 : case CODING_ENCODED:
3356 0 : if (m_ePrevMIMEEncoding != eMIMEEncoding
3357 0 : || m_rSink.getColumn() + m_nExtraSpaces + nSize
3358 0 : > m_rSink.getLineLengthLimit() - 2)
3359 : {
3360 0 : m_rSink << "?=";
3361 0 : if (m_rSink.getColumn() + nWrapperSize
3362 0 : + m_nExtraSpaces + nSize
3363 0 : > m_rSink.getLineLengthLimit() - 1)
3364 0 : m_rSink << INetMIMEOutputSink::endl;
3365 0 : m_rSink << " =?" << pCharsetName << "?Q?";
3366 : }
3367 0 : while (m_nExtraSpaces-- > 0)
3368 : {
3369 0 : if (m_rSink.getColumn()
3370 0 : > m_rSink.getLineLengthLimit() - 3)
3371 0 : m_rSink << "?=" << INetMIMEOutputSink::endl
3372 0 : << " =?" << pCharsetName << "?Q?";
3373 0 : m_rSink << '_';
3374 : }
3375 0 : break;
3376 :
3377 : case CODING_ENCODED_TERMINATED:
3378 0 : if (m_rSink.getColumn() + nWrapperSize
3379 0 : + m_nExtraSpaces + nSize
3380 0 : > m_rSink.getLineLengthLimit() - 1)
3381 0 : m_rSink << INetMIMEOutputSink::endl;
3382 0 : m_rSink << " =?" << pCharsetName << "?Q?";
3383 0 : while (m_nExtraSpaces-- > 0)
3384 : {
3385 0 : if (m_rSink.getColumn()
3386 0 : > m_rSink.getLineLengthLimit() - 3)
3387 0 : m_rSink << "?=" << INetMIMEOutputSink::endl
3388 0 : << " =?" << pCharsetName << "?Q?";
3389 0 : m_rSink << '_';
3390 : }
3391 0 : break;
3392 : }
3393 :
3394 : // The non UTF-8 code will only work for stateless single byte
3395 : // character encodings (see also above):
3396 0 : if (eMIMEEncoding == RTL_TEXTENCODING_UTF8)
3397 : {
3398 0 : bool bInitial = true;
3399 0 : for (sal_Unicode const * p = m_pBuffer;
3400 0 : p != m_pBufferEnd;)
3401 : {
3402 : sal_uInt32 nUTF32
3403 0 : = INetMIME::getUTF32Character(p, m_pBufferEnd);
3404 0 : bool bEscape = needsEncodedWordEscape(nUTF32);
3405 : sal_uInt32 nWidth
3406 : = bEscape ?
3407 0 : 3 * INetMIME::getUTF8OctetCount(nUTF32) : 1;
3408 : // only US-ASCII characters (that are converted to
3409 : // a single byte by UTF-8) need no encoded word
3410 : // escapes...
3411 0 : if (!bInitial
3412 0 : && m_rSink.getColumn() + nWidth + 2
3413 0 : > m_rSink.getLineLengthLimit())
3414 0 : m_rSink << "?=" << INetMIMEOutputSink::endl
3415 0 : << " =?" << pCharsetName << "?Q?";
3416 0 : if (bEscape)
3417 : {
3418 : DBG_ASSERT(
3419 : nUTF32 < 0x10FFFF,
3420 : "INetMIMEEncodedWordOutputSink::finish():"
3421 : " Bad char");
3422 0 : if (nUTF32 < 0x80)
3423 : INetMIME::writeEscapeSequence(m_rSink,
3424 0 : nUTF32);
3425 0 : else if (nUTF32 < 0x800)
3426 : {
3427 : INetMIME::writeEscapeSequence(m_rSink,
3428 0 : (nUTF32 >> 6)
3429 0 : | 0xC0);
3430 : INetMIME::writeEscapeSequence(m_rSink,
3431 0 : (nUTF32 & 0x3F)
3432 0 : | 0x80);
3433 : }
3434 0 : else if (nUTF32 < 0x10000)
3435 : {
3436 : INetMIME::writeEscapeSequence(m_rSink,
3437 0 : (nUTF32 >> 12)
3438 0 : | 0xE0);
3439 : INetMIME::writeEscapeSequence(m_rSink,
3440 0 : ((nUTF32 >> 6)
3441 0 : & 0x3F)
3442 0 : | 0x80);
3443 : INetMIME::writeEscapeSequence(m_rSink,
3444 0 : (nUTF32 & 0x3F)
3445 0 : | 0x80);
3446 : }
3447 : else
3448 : {
3449 : INetMIME::writeEscapeSequence(m_rSink,
3450 0 : (nUTF32 >> 18)
3451 0 : | 0xF0);
3452 : INetMIME::writeEscapeSequence(m_rSink,
3453 0 : ((nUTF32 >> 12)
3454 0 : & 0x3F)
3455 0 : | 0x80);
3456 : INetMIME::writeEscapeSequence(m_rSink,
3457 0 : ((nUTF32 >> 6)
3458 0 : & 0x3F)
3459 0 : | 0x80);
3460 : INetMIME::writeEscapeSequence(m_rSink,
3461 0 : (nUTF32 & 0x3F)
3462 0 : | 0x80);
3463 : }
3464 : }
3465 : else
3466 0 : m_rSink << sal_Char(nUTF32);
3467 0 : bInitial = false;
3468 : }
3469 : }
3470 : else
3471 : {
3472 0 : for (sal_Size k = 0; k < nTargetSize; ++k)
3473 : {
3474 0 : sal_uInt32 nUCS4 = static_cast<unsigned char>(pTargetBuffer[k]);
3475 0 : bool bEscape = needsEncodedWordEscape(nUCS4);
3476 0 : if (k > 0
3477 0 : && m_rSink.getColumn() + (bEscape ? 5 : 3)
3478 0 : > m_rSink.getLineLengthLimit())
3479 0 : m_rSink << "?=" << INetMIMEOutputSink::endl
3480 0 : << " =?" << pCharsetName << "?Q?";
3481 0 : if (bEscape)
3482 0 : INetMIME::writeEscapeSequence(m_rSink, nUCS4);
3483 : else
3484 0 : m_rSink << sal_Char(nUCS4);
3485 : }
3486 0 : delete[] pTargetBuffer;
3487 : }
3488 :
3489 0 : if (bWriteTrailer)
3490 : {
3491 0 : m_rSink << "?=";
3492 0 : m_eCoding = CODING_ENCODED_TERMINATED;
3493 : }
3494 :
3495 0 : m_ePrevMIMEEncoding = eMIMEEncoding;
3496 0 : break;
3497 : }
3498 :
3499 : default:
3500 : OSL_ASSERT(false);
3501 0 : break;
3502 : }
3503 : }
3504 :
3505 0 : m_eInitialSpace = SPACE_NO;
3506 0 : m_nExtraSpaces = 0;
3507 0 : m_pEncodingList->reset();
3508 0 : m_pBufferEnd = m_pBuffer;
3509 0 : m_ePrevCoding = m_eCoding;
3510 0 : m_eCoding = CODING_NONE;
3511 0 : m_nQuotedEscaped = 0;
3512 0 : m_eEncodedWordState = STATE_INITIAL;
3513 0 : }
3514 :
3515 0 : INetMIMEEncodedWordOutputSink::~INetMIMEEncodedWordOutputSink()
3516 : {
3517 0 : rtl_freeMemory(m_pBuffer);
3518 0 : delete m_pEncodingList;
3519 0 : }
3520 :
3521 : INetMIMEEncodedWordOutputSink &
3522 0 : INetMIMEEncodedWordOutputSink::operator <<(sal_uInt32 nChar)
3523 : {
3524 0 : if (nChar == ' ')
3525 : {
3526 0 : if (m_pBufferEnd != m_pBuffer)
3527 0 : finish(false);
3528 0 : ++m_nExtraSpaces;
3529 : }
3530 : else
3531 : {
3532 : // Check for an already encoded word:
3533 0 : switch (m_eEncodedWordState)
3534 : {
3535 : case STATE_INITIAL:
3536 0 : if (nChar == '=')
3537 0 : m_eEncodedWordState = STATE_FIRST_EQUALS;
3538 : else
3539 0 : m_eEncodedWordState = STATE_BAD;
3540 0 : break;
3541 :
3542 : case STATE_FIRST_EQUALS:
3543 0 : if (nChar == '?')
3544 0 : m_eEncodedWordState = STATE_FIRST_EQUALS;
3545 : else
3546 0 : m_eEncodedWordState = STATE_BAD;
3547 0 : break;
3548 :
3549 : case STATE_FIRST_QUESTION:
3550 0 : if (INetMIME::isEncodedWordTokenChar(nChar))
3551 0 : m_eEncodedWordState = STATE_CHARSET;
3552 : else
3553 0 : m_eEncodedWordState = STATE_BAD;
3554 0 : break;
3555 :
3556 : case STATE_CHARSET:
3557 0 : if (nChar == '?')
3558 0 : m_eEncodedWordState = STATE_SECOND_QUESTION;
3559 0 : else if (!INetMIME::isEncodedWordTokenChar(nChar))
3560 0 : m_eEncodedWordState = STATE_BAD;
3561 0 : break;
3562 :
3563 : case STATE_SECOND_QUESTION:
3564 0 : if (nChar == 'B' || nChar == 'Q'
3565 0 : || nChar == 'b' || nChar == 'q')
3566 0 : m_eEncodedWordState = STATE_ENCODING;
3567 : else
3568 0 : m_eEncodedWordState = STATE_BAD;
3569 0 : break;
3570 :
3571 : case STATE_ENCODING:
3572 0 : if (nChar == '?')
3573 0 : m_eEncodedWordState = STATE_THIRD_QUESTION;
3574 : else
3575 0 : m_eEncodedWordState = STATE_BAD;
3576 0 : break;
3577 :
3578 : case STATE_THIRD_QUESTION:
3579 0 : if (INetMIME::isVisible(nChar) && nChar != '?')
3580 0 : m_eEncodedWordState = STATE_ENCODED_TEXT;
3581 : else
3582 0 : m_eEncodedWordState = STATE_BAD;
3583 0 : break;
3584 :
3585 : case STATE_ENCODED_TEXT:
3586 0 : if (nChar == '?')
3587 0 : m_eEncodedWordState = STATE_FOURTH_QUESTION;
3588 0 : else if (!INetMIME::isVisible(nChar))
3589 0 : m_eEncodedWordState = STATE_BAD;
3590 0 : break;
3591 :
3592 : case STATE_FOURTH_QUESTION:
3593 0 : if (nChar == '=')
3594 0 : m_eEncodedWordState = STATE_SECOND_EQUALS;
3595 : else
3596 0 : m_eEncodedWordState = STATE_BAD;
3597 0 : break;
3598 :
3599 : case STATE_SECOND_EQUALS:
3600 0 : m_eEncodedWordState = STATE_BAD;
3601 0 : break;
3602 :
3603 : case STATE_BAD:
3604 0 : break;
3605 : }
3606 :
3607 : // Update encoding:
3608 0 : m_pEncodingList->includes(nChar);
3609 :
3610 : // Update coding:
3611 : enum { TENQ = 1, // CONTEXT_TEXT, CODING_ENCODED
3612 : CENQ = 2, // CONTEXT_COMMENT, CODING_ENCODED
3613 : PQTD = 4, // CONTEXT_PHRASE, CODING_QUOTED
3614 : PENQ = 8 }; // CONTEXT_PHRASE, CODING_ENCODED
3615 : static const sal_Char aMinimal[128]
3616 : = { TENQ | CENQ | PENQ, // 0x00
3617 : TENQ | CENQ | PENQ, // 0x01
3618 : TENQ | CENQ | PENQ, // 0x02
3619 : TENQ | CENQ | PENQ, // 0x03
3620 : TENQ | CENQ | PENQ, // 0x04
3621 : TENQ | CENQ | PENQ, // 0x05
3622 : TENQ | CENQ | PENQ, // 0x06
3623 : TENQ | CENQ | PENQ, // 0x07
3624 : TENQ | CENQ | PENQ, // 0x08
3625 : TENQ | CENQ | PENQ, // 0x09
3626 : TENQ | CENQ | PENQ, // 0x0A
3627 : TENQ | CENQ | PENQ, // 0x0B
3628 : TENQ | CENQ | PENQ, // 0x0C
3629 : TENQ | CENQ | PENQ, // 0x0D
3630 : TENQ | CENQ | PENQ, // 0x0E
3631 : TENQ | CENQ | PENQ, // 0x0F
3632 : TENQ | CENQ | PENQ, // 0x10
3633 : TENQ | CENQ | PENQ, // 0x11
3634 : TENQ | CENQ | PENQ, // 0x12
3635 : TENQ | CENQ | PENQ, // 0x13
3636 : TENQ | CENQ | PENQ, // 0x14
3637 : TENQ | CENQ | PENQ, // 0x15
3638 : TENQ | CENQ | PENQ, // 0x16
3639 : TENQ | CENQ | PENQ, // 0x17
3640 : TENQ | CENQ | PENQ, // 0x18
3641 : TENQ | CENQ | PENQ, // 0x19
3642 : TENQ | CENQ | PENQ, // 0x1A
3643 : TENQ | CENQ | PENQ, // 0x1B
3644 : TENQ | CENQ | PENQ, // 0x1C
3645 : TENQ | CENQ | PENQ, // 0x1D
3646 : TENQ | CENQ | PENQ, // 0x1E
3647 : TENQ | CENQ | PENQ, // 0x1F
3648 : 0, // ' '
3649 : 0, // '!'
3650 : PQTD , // '"'
3651 : 0, // '#'
3652 : 0, // '$'
3653 : 0, // '%'
3654 : 0, // '&'
3655 : 0, // '''
3656 : CENQ | PQTD , // '('
3657 : CENQ | PQTD , // ')'
3658 : 0, // '*'
3659 : 0, // '+'
3660 : PQTD , // ','
3661 : 0, // '-'
3662 : PQTD , // '.'
3663 : 0, // '/'
3664 : 0, // '0'
3665 : 0, // '1'
3666 : 0, // '2'
3667 : 0, // '3'
3668 : 0, // '4'
3669 : 0, // '5'
3670 : 0, // '6'
3671 : 0, // '7'
3672 : 0, // '8'
3673 : 0, // '9'
3674 : PQTD , // ':'
3675 : PQTD , // ';'
3676 : PQTD , // '<'
3677 : 0, // '='
3678 : PQTD , // '>'
3679 : 0, // '?'
3680 : PQTD , // '@'
3681 : 0, // 'A'
3682 : 0, // 'B'
3683 : 0, // 'C'
3684 : 0, // 'D'
3685 : 0, // 'E'
3686 : 0, // 'F'
3687 : 0, // 'G'
3688 : 0, // 'H'
3689 : 0, // 'I'
3690 : 0, // 'J'
3691 : 0, // 'K'
3692 : 0, // 'L'
3693 : 0, // 'M'
3694 : 0, // 'N'
3695 : 0, // 'O'
3696 : 0, // 'P'
3697 : 0, // 'Q'
3698 : 0, // 'R'
3699 : 0, // 'S'
3700 : 0, // 'T'
3701 : 0, // 'U'
3702 : 0, // 'V'
3703 : 0, // 'W'
3704 : 0, // 'X'
3705 : 0, // 'Y'
3706 : 0, // 'Z'
3707 : PQTD , // '['
3708 : CENQ | PQTD , // '\'
3709 : PQTD , // ']'
3710 : 0, // '^'
3711 : 0, // '_'
3712 : 0, // '`'
3713 : 0, // 'a'
3714 : 0, // 'b'
3715 : 0, // 'c'
3716 : 0, // 'd'
3717 : 0, // 'e'
3718 : 0, // 'f'
3719 : 0, // 'g'
3720 : 0, // 'h'
3721 : 0, // 'i'
3722 : 0, // 'j'
3723 : 0, // 'k'
3724 : 0, // 'l'
3725 : 0, // 'm'
3726 : 0, // 'n'
3727 : 0, // 'o'
3728 : 0, // 'p'
3729 : 0, // 'q'
3730 : 0, // 'r'
3731 : 0, // 's'
3732 : 0, // 't'
3733 : 0, // 'u'
3734 : 0, // 'v'
3735 : 0, // 'w'
3736 : 0, // 'x'
3737 : 0, // 'y'
3738 : 0, // 'z'
3739 : 0, // '{'
3740 : 0, // '|'
3741 : 0, // '}'
3742 : 0, // '~'
3743 : TENQ | CENQ | PENQ }; // DEL
3744 0 : Coding eNewCoding = !rtl::isAscii(nChar) ? CODING_ENCODED :
3745 0 : m_eContext == CONTEXT_PHRASE ?
3746 0 : Coding(aMinimal[nChar] >> 2) :
3747 0 : aMinimal[nChar] & m_eContext ? CODING_ENCODED :
3748 0 : CODING_NONE;
3749 0 : if (eNewCoding > m_eCoding)
3750 0 : m_eCoding = eNewCoding;
3751 0 : if (m_eCoding == CODING_QUOTED
3752 0 : && INetMIME::needsQuotedStringEscape(nChar))
3753 0 : ++m_nQuotedEscaped;
3754 :
3755 : // Append to buffer:
3756 0 : if (sal_uInt32(m_pBufferEnd - m_pBuffer) == m_nBufferSize)
3757 : {
3758 : m_pBuffer
3759 : = static_cast< sal_Unicode * >(
3760 : rtl_reallocateMemory(m_pBuffer,
3761 0 : (m_nBufferSize + BUFFER_SIZE)
3762 0 : * sizeof (sal_Unicode)));
3763 0 : m_pBufferEnd = m_pBuffer + m_nBufferSize;
3764 0 : m_nBufferSize += BUFFER_SIZE;
3765 : }
3766 0 : *m_pBufferEnd++ = sal_Unicode(nChar);
3767 : }
3768 0 : return *this;
3769 : }
3770 :
3771 : // INetContentTypeParameterList
3772 :
3773 34 : void INetContentTypeParameterList::Clear()
3774 : {
3775 34 : maEntries.clear();
3776 34 : }
3777 :
3778 : const INetContentTypeParameter *
3779 26 : INetContentTypeParameterList::find(const OString& rAttribute) const
3780 : {
3781 26 : boost::ptr_vector<INetContentTypeParameter>::const_iterator iter;
3782 30 : for (iter = maEntries.begin(); iter != maEntries.end(); ++iter)
3783 : {
3784 22 : if (iter->m_sAttribute.equalsIgnoreAsciiCase(rAttribute))
3785 18 : return &(*iter);
3786 : }
3787 :
3788 8 : return NULL;
3789 : }
3790 :
3791 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|