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