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 : #ifndef INCLUDED_TOOLS_INETMIME_HXX
20 : #define INCLUDED_TOOLS_INETMIME_HXX
21 :
22 : #include <boost/ptr_container/ptr_vector.hpp>
23 :
24 : #include <tools/toolsdllapi.h>
25 : #include <rtl/alloc.h>
26 : #include <rtl/character.hxx>
27 : #include <rtl/string.hxx>
28 : #include <rtl/strbuf.hxx>
29 : #include <rtl/ustring.hxx>
30 : #include <rtl/tencinfo.h>
31 : #include <tools/debug.hxx>
32 : #include <tools/errcode.hxx>
33 :
34 : class DateTime;
35 : class INetContentTypeParameterList;
36 : class INetMIMECharsetList_Impl;
37 : class INetMIMEOutputSink;
38 :
39 : class TOOLS_DLLPUBLIC INetMIME
40 : {
41 : public:
42 : enum { SOFT_LINE_LENGTH_LIMIT = 76,
43 : HARD_LINE_LENGTH_LIMIT = 998 };
44 :
45 : /** The various types of message header field bodies, with respect to
46 : encoding and decoding them.
47 :
48 : @descr At the moment, five different types of header fields suffice
49 : to describe how to encoded and decode any known message header field
50 : body, but need for more types may arise in the future as new header
51 : fields are introduced.
52 :
53 : @descr The following is an exhaustive list of all the header fields
54 : currently known to our implementation. For every header field, it
55 : includes a 'canonic' (with regard to capitalization) name, a grammar
56 : rule for the body (using RFC 822 and RFC 2234 conventions), a list of
57 : relevant sources of information, and the HeaderFieldType value to use
58 : with that header field. The list is based on RFC 2076 and draft-
59 : palme-mailext-headers-02.txt (see also <http://www.dsv.su.se/~jpalme/
60 : ietf/jp-ietf-home.html#anchor1003783>).
61 :
62 : Approved: address ;RFC 1036; HEADER_FIELD_ADDRESS
63 : bcc: #address ;RFCs 822, 2047; HEADER_FIELD_ADDRESS
64 : cc: 1#address ;RFCs 822, 2047; HEADER_FIELD_ADDRESS
65 : Comments: *text ;RFCs 822, RFC 2047; HEADER_FIELD_TEXT
66 : Content-Base: absoluteURI ;RFC 2110; HEADER_FIELD_TEXT
67 : Content-Description: *text ;RFC 2045, RFC 2047; HEADER_FIELD_TEXT
68 : Content-Disposition: disposition-type *(";" disposition-parm)
69 : ;RFC 1806; HEADER_FIELD_STRUCTURED
70 : Content-ID: msg-id ;RFC 2045, RFC 2047; HEADER_FIELD_MESSAGE_ID
71 : Content-Location: absoluteURI / relativeURI ;RFC 2110;
72 : HEADER_FIELD_TEXT
73 : Content-Transfer-Encoding: mechanism ;RFC 2045, RFC 2047;
74 : HEADER_FIELD_STRUCTURED
75 : Content-Type: type "/" subtype *(";" parameter) ;RFC 2045, RFC 2047;
76 : HEADER_FIELD_STRUCTURED
77 : Control: *text ;RFC 1036; HEADER_FIELD_TEXT
78 : Date: date-time ;RFC 822, RFC 1123, RFC 2047; HEADER_FIELD_STRUCTURED
79 : Distribution: 1#atom ;RFC 1036; HEADER_FIELD_STRUCTURED
80 : Encrypted: 1#2word ;RFC 822, RFC 2047; HEADER_FIELD_STRUCTURED
81 : Expires: date-time ;RFC 1036; HEADER_FIELD_STRUCTURED
82 : Followup-To: 1#(atom *("." atom)) ;RFC 1036; HEADER_FIELD_STRUCTURED
83 : From: mailbox / 1#mailbox ;RFC 822, RFC 2047; HEADER_FIELD_ADDRESS
84 : In-Reply-To: *(phrase / msg-id) ;RFC 822, RFC 2047;
85 : HEADER_FIELD_ADDRESS
86 : Keywords: #phrase ;RFC 822, RFC 2047; HEADER_FIELD_PHRASE
87 : MIME-Version: 1*DIGIT "." 1*DIGIT ;RFC 2045, RFC 2047;
88 : HEADER_FIELD_STRUCTURED
89 : Message-ID: msg-id ;RFC 822, RFC 2047; HEADER_FIELD_MESSAGE_ID
90 : Newsgroups: 1#(atom *("." atom)) ;RFC 1036, RFC 2047;
91 : HEADER_FIELD_STRUCTURED
92 : Organization: *text ;RFC 1036; HEADER_FIELD_TEXT
93 : Received: ["from" domain] ["by" domain] ["via" atom] *("with" atom)
94 : ["id" msg-id] ["for" addr-spec] ";" date-time ;RFC 822, RFC 1123,
95 : RFC 2047; HEADER_FIELD_STRUCTURED
96 : References: *(phrase / msg-id) ;RFC 822, RFC 2047;
97 : HEADER_FIELD_ADDRESS
98 : Reply-To: 1#address ;RFC 822, RFC 2047; HEADER_FIELD_ADDRESS
99 : Resent-Date: date-time ;RFC 822, RFC 1123, RFC 2047;
100 : HEADER_FIELD_STRUCTURED
101 : Resent-From: mailbox / 1#mailbox ;RFC 822, RFC 2047;
102 : HEADER_FIELD_ADDRESS
103 : Resent-Message-ID: msg-id ;RFC 822, RFC 2047; HEADER_FIELD_MESSAGE_ID
104 : Resent-Reply-To: 1#address ;RFC 822, RFC 2047; HEADER_FIELD_ADDRESS
105 : Resent-Sender: mailbox ;RFC 822, RFC 2047; HEADER_FIELD_ADDRESS
106 : Resent-To: 1#address ;RFC 822, RFC 2047; HEADER_FIELD_ADDRESS
107 : Resent-bcc: #address ;RFC 822, RFC 2047; HEADER_FIELD_ADDRESS
108 : Resent-cc: 1#address ;RFC 822, RFC 2047; HEADER_FIELD_ADDRESS
109 : Return-path: route-addr / ("<" ">") ;RFC 822, RFC 1123, RFC 2047;
110 : HEADER_FIELD_STRUCTURED
111 : Return-Receipt-To: address ;Not Internet standard;
112 : HEADER_FIELD_ADDRES
113 : Sender: mailbox ;RFC 822, RFC 2047; HEADER_FIELD_ADDRESS
114 : Subject: *text ;RFC 822, RFC 2047; HEADER_FIELD_TEXT
115 : Summary: *text ;RFC 1036; HEADER_FIELD_TEXT
116 : To: 1#address ;RFC 822, RFC 2047; HEADER_FIELD_ADDRESS
117 : X-CHAOS-Marked: "YES" / "NO" ;local; HEADER_FIELD_STRUCTURED
118 : X-CHAOS-Read: "YES" / "NO" ;local; HEADER_FIELD_STRUCTURED
119 : X-CHAOS-Recipients: #*("<" atom word ">") ;local;
120 : HEADER_FIELD_STRUCTURED
121 : X-CHAOS-Size: 1*DIGIT ;local; HEADER_FIELD_STRUCTURED
122 : X-Mailer: *text ;Not Internet standard; HEADER_FIELD_TEXT
123 : X-Mozilla-Status: 4HEXDIG ;Mozilla; HEADER_FIELD_STRUCTURED
124 : X-Newsreader: *text ;Not Internet standard; HEADER_FIELD_TEXT
125 : X-Priority: "1" / "2" / "3" / "4" / "5" ;Not Internet standard;
126 : HEADER_FIELD_STRUCTURED
127 : Xref: sub-domain
128 : 1*((atom / string) *("." (atom / string)) ":" msg-number)
129 : ;RFCs 1036, 2047, local; HEADER_FIELD_STRUCTURED
130 : */
131 : enum HeaderFieldType
132 : {
133 : HEADER_FIELD_TEXT,
134 : HEADER_FIELD_STRUCTURED,
135 : HEADER_FIELD_PHRASE,
136 : HEADER_FIELD_MESSAGE_ID,
137 : HEADER_FIELD_ADDRESS
138 : };
139 :
140 : /** Check for ISO 8859-1 character.
141 :
142 : @param nChar Some UCS-4 character.
143 :
144 : @return True if nChar is a ISO 8859-1 character (0x00--0xFF).
145 : */
146 : static inline bool isISO88591(sal_uInt32 nChar);
147 :
148 : /** Check for US-ASCII control character.
149 :
150 : @param nChar Some UCS-4 character.
151 :
152 : @return True if nChar is a US-ASCII control character (US-ASCII
153 : 0x00--0x1F or 0x7F).
154 : */
155 : static inline bool isControl(sal_uInt32 nChar);
156 :
157 : /** Check for US-ASCII white space character.
158 :
159 : @param nChar Some UCS-4 character.
160 :
161 : @return True if nChar is a US-ASCII white space character (US-ASCII
162 : 0x09 or 0x20).
163 : */
164 : static inline bool isWhiteSpace(sal_uInt32 nChar);
165 :
166 : /** Check for US-ASCII visible character.
167 :
168 : @param nChar Some UCS-4 character.
169 :
170 : @return True if nChar is a US-ASCII visible character (US-ASCII
171 : 0x21--0x7E).
172 : */
173 : static inline bool isVisible(sal_uInt32 nChar);
174 :
175 : /** Check for US-ASCII Base 64 digit character.
176 :
177 : @param nChar Some UCS-4 character.
178 :
179 : @return True if nChar is a US-ASCII Base 64 digit character (US-ASCII
180 : 'A'--'Z', 'a'--'z', '0'--'9', '+', or '/').
181 : */
182 : static inline bool isBase64Digit(sal_uInt32 nChar);
183 :
184 : /** Check whether some character is valid within an RFC 822 <atom>.
185 :
186 : @param nChar Some UCS-4 character.
187 :
188 : @return True if nChar is valid within an RFC 822 <atom> (US-ASCII
189 : 'A'--'Z', 'a'--'z', '0'--'9', '!', '#', '$', '%', '&', ''', '*', '+',
190 : '-', '/', '=', '?', '^', '_', '`', '{', '|', '}', or '~').
191 : */
192 : static bool isAtomChar(sal_uInt32 nChar);
193 :
194 : /** Check whether some character is valid within an RFC 2045 <token>.
195 :
196 : @param nChar Some UCS-4 character.
197 :
198 : @return True if nChar is valid within an RFC 2047 <token> (US-ASCII
199 : 'A'--'Z', 'a'--'z', '0'--'9', '!', '#', '$', '%', '&', ''', '*', '+',
200 : '-', '.', '^', '_', '`', '{', '|', '}', or '~').
201 : */
202 : static bool isTokenChar(sal_uInt32 nChar);
203 :
204 : /** Check whether some character is valid within an RFC 2047 <token>.
205 :
206 : @param nChar Some UCS-4 character.
207 :
208 : @return True if nChar is valid within an RFC 2047 <token> (US-ASCII
209 : 'A'--'Z', 'a'--'z', '0'--'9', '!', '#', '$', '%', '&', ''', '*', '+',
210 : '-', '^', '_', '`', '{', '|', '}', or '~').
211 : */
212 : static bool isEncodedWordTokenChar(sal_uInt32 nChar);
213 :
214 : /** Check whether some character is valid within an RFC 2060 <atom>.
215 :
216 : @param nChar Some UCS-4 character.
217 :
218 : @return True if nChar is valid within an RFC 2060 <atom> (US-ASCII
219 : 'A'--'Z', 'a'--'z', '0'--'9', '!', '#', '$', '&', ''', '+', ',', '-',
220 : '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', ']', '^', '_', '`',
221 : '|', '}', or '~').
222 : */
223 : static bool isIMAPAtomChar(sal_uInt32 nChar);
224 :
225 : /** Get the digit weight of a US-ASCII character.
226 :
227 : @param nChar Some UCS-4 character.
228 :
229 : @return If nChar is a US-ASCII (decimal) digit character (US-ASCII
230 : '0'--'9'), return the corresponding weight (0--9); otherwise,
231 : return -1.
232 : */
233 : static inline int getWeight(sal_uInt32 nChar);
234 :
235 : /** Get the hexadecimal digit weight of a US-ASCII character.
236 :
237 : @param nChar Some UCS-4 character.
238 :
239 : @return If nChar is a US-ASCII hexadecimal digit character (US-ASCII
240 : '0'--'9', 'A'--'F', or 'a'--'f'), return the corresponding weight
241 : (0--15); otherwise, return -1.
242 : */
243 : static inline int getHexWeight(sal_uInt32 nChar);
244 :
245 : /** Get the Base 64 digit weight of a US-ASCII character.
246 :
247 : @param nChar Some UCS-4 character.
248 :
249 : @return If nChar is a US-ASCII Base 64 digit character (US-ASCII
250 : 'A'--'F', or 'a'--'f', '0'--'9', '+', or '/'), return the
251 : corresponding weight (0--63); if nChar is the US-ASCII Base 64 padding
252 : character (US-ASCII '='), return -1; otherwise, return -2.
253 : */
254 : static inline int getBase64Weight(sal_uInt32 nChar);
255 :
256 : /** Get a hexadecimal digit encoded as US-ASCII.
257 :
258 : @param nWeight Must be in the range 0--15, inclusive.
259 :
260 : @return The canonic (i.e., upper case) hexadecimal digit
261 : corresponding to nWeight (US-ASCII '0'--'9' or 'A'--'F').
262 : */
263 : static sal_uInt32 getHexDigit(int nWeight);
264 :
265 : static inline bool isHighSurrogate(sal_uInt32 nUTF16);
266 :
267 : static inline bool isLowSurrogate(sal_uInt32 nUTF16);
268 :
269 : static inline sal_uInt32 toUTF32(sal_Unicode cHighSurrogate,
270 : sal_Unicode cLowSurrogate);
271 :
272 : /** Check two US-ASCII strings for equality, ignoring case.
273 :
274 : @param pBegin1 Points to the start of the first string, must not be
275 : null.
276 :
277 : @param pEnd1 Points past the end of the first string, must be >=
278 : pBegin1.
279 :
280 : @param pString2 Points to the start of the null terminated second
281 : string, must not be null.
282 :
283 : @return True if the two strings are equal, ignoring the case of US-
284 : ASCII alphabetic characters (US-ASCII 'A'--'Z' and 'a'--'z').
285 : */
286 : static bool equalIgnoreCase(const sal_Char * pBegin1,
287 : const sal_Char * pEnd1,
288 : const sal_Char * pString2);
289 :
290 : /** Check two US-ASCII strings for equality, ignoring case.
291 :
292 : @param pBegin1 Points to the start of the first string, must not be
293 : null.
294 :
295 : @param pEnd1 Points past the end of the first string, must be >=
296 : pBegin1.
297 :
298 : @param pString2 Points to the start of the null terminated second
299 : string, must not be null.
300 :
301 : @return True if the two strings are equal, ignoring the case of US-
302 : ASCII alphabetic characters (US-ASCII 'A'--'Z' and 'a'--'z').
303 : */
304 : static bool equalIgnoreCase(const sal_Unicode * pBegin1,
305 : const sal_Unicode * pEnd1,
306 : const sal_Char * pString2);
307 :
308 : static inline bool startsWithLineBreak(const sal_Char * pBegin,
309 : const sal_Char * pEnd);
310 :
311 : static inline bool startsWithLineBreak(const sal_Unicode * pBegin,
312 : const sal_Unicode * pEnd);
313 :
314 : static inline bool startsWithLineFolding(const sal_Char * pBegin,
315 : const sal_Char * pEnd);
316 :
317 : static inline bool startsWithLineFolding(const sal_Unicode * pBegin,
318 : const sal_Unicode * pEnd);
319 :
320 : static bool startsWithLinearWhiteSpace(const sal_Char * pBegin,
321 : const sal_Char * pEnd);
322 :
323 : static const sal_Unicode * skipLinearWhiteSpace(const sal_Unicode *
324 : pBegin,
325 : const sal_Unicode * pEnd);
326 :
327 : static const sal_Unicode * skipComment(const sal_Unicode * pBegin,
328 : const sal_Unicode * pEnd);
329 :
330 : static const sal_Unicode * skipLinearWhiteSpaceComment(const sal_Unicode *
331 : pBegin,
332 : const sal_Unicode *
333 : pEnd);
334 :
335 : static inline bool needsQuotedStringEscape(sal_uInt32 nChar);
336 :
337 : static const sal_Char * skipQuotedString(const sal_Char * pBegin,
338 : const sal_Char * pEnd);
339 :
340 : static const sal_Unicode * skipQuotedString(const sal_Unicode * pBegin,
341 : const sal_Unicode * pEnd);
342 :
343 : static bool scanUnsigned(const sal_Unicode *& rBegin,
344 : const sal_Unicode * pEnd, bool bLeadingZeroes,
345 : sal_uInt32 & rValue);
346 :
347 : static const sal_Unicode * scanQuotedBlock(const sal_Unicode * pBegin,
348 : const sal_Unicode * pEnd,
349 : sal_uInt32 nOpening,
350 : sal_uInt32 nClosing,
351 : sal_Size & rLength,
352 : bool & rModify);
353 :
354 : static sal_Unicode const * scanParameters(sal_Unicode const * pBegin,
355 : sal_Unicode const * pEnd,
356 : INetContentTypeParameterList *
357 : pParameters);
358 :
359 : /** Parse the body of an RFC 2045 Content-Type header field.
360 :
361 : @param pBegin The range (that must be valid) from non-null pBegin,
362 : inclusive. to non-null pEnd, exclusive, forms the body of the
363 : Content-Type header field. It must be of the form
364 :
365 : token "/" token *(";" token "=" (token / quoted-string))
366 :
367 : with intervening linear white space and comments (cf. RFCs 822, 2045).
368 : The RFC 2231 extension are supported. The encoding of rMediaType
369 : should be US-ASCII, but any Unicode values in the range U+0080..U+FFFF
370 : are interpretet 'as appropriate.'
371 :
372 : @param pType If not null, returns the type (the first of the above
373 : tokens), in US-ASCII encoding and converted to lower case.
374 :
375 : @param pSubType If not null, returns the sub-type (the second of the
376 : above tokens), in US-ASCII encoding and converted to lower case.
377 :
378 : @param pParameters If not null, returns the parameters as a list of
379 : INetContentTypeParameters (the attributes are in US-ASCII encoding and
380 : converted to lower case, the values are in Unicode encoding). If
381 : null, only the syntax of the parameters is checked, but they are not
382 : returned.
383 :
384 : @return Null if the syntax of the field body is incorrect (i.e., does
385 : not start with type and sub-type tokens). Otherwise, a pointer past the
386 : longest valid input prefix. If null is returned, none of the output
387 : parameters will be modified.
388 : */
389 : static sal_Unicode const * scanContentType(
390 : sal_Unicode const *pBegin, sal_Unicode const * pEnd,
391 : OUString * pType = 0, OUString * pSubType = 0,
392 : INetContentTypeParameterList * pParameters = 0);
393 :
394 : static inline rtl_TextEncoding translateToMIME(rtl_TextEncoding
395 : eEncoding);
396 :
397 : static inline rtl_TextEncoding translateFromMIME(rtl_TextEncoding
398 : eEncoding);
399 :
400 : static const sal_Char * getCharsetName(rtl_TextEncoding eEncoding);
401 :
402 : static rtl_TextEncoding getCharsetEncoding(const sal_Char * pBegin,
403 : const sal_Char * pEnd);
404 :
405 : static inline bool isMIMECharsetEncoding(rtl_TextEncoding eEncoding);
406 :
407 : static INetMIMECharsetList_Impl *
408 : createPreferredCharsetList(rtl_TextEncoding eEncoding);
409 :
410 : static sal_Unicode * convertToUnicode(const sal_Char * pBegin,
411 : const sal_Char * pEnd,
412 : rtl_TextEncoding eEncoding,
413 : sal_Size & rSize);
414 :
415 : static sal_Char * convertFromUnicode(const sal_Unicode * pBegin,
416 : const sal_Unicode * pEnd,
417 : rtl_TextEncoding eEncoding,
418 : sal_Size & rSize);
419 :
420 : /** Get the number of octets required to encode an UCS-4 character using
421 : UTF-8 encoding.
422 :
423 : @param nChar Some UCS-4 character.
424 :
425 : @return The number of octets required (in the range 1--6, inclusive).
426 : */
427 : static inline int getUTF8OctetCount(sal_uInt32 nChar);
428 :
429 : static inline void writeEscapeSequence(INetMIMEOutputSink & rSink,
430 : sal_uInt32 nChar);
431 :
432 : static void writeUTF8(INetMIMEOutputSink & rSink, sal_uInt32 nChar);
433 :
434 : static void writeHeaderFieldBody(INetMIMEOutputSink & rSink,
435 : HeaderFieldType eType,
436 : const OUString& rBody,
437 : rtl_TextEncoding ePreferredEncoding,
438 : bool bInitialSpace = true);
439 :
440 : static bool translateUTF8Char(const sal_Char *& rBegin,
441 : const sal_Char * pEnd,
442 : rtl_TextEncoding eEncoding,
443 : sal_uInt32 & rCharacter);
444 :
445 : static OUString decodeHeaderFieldBody(HeaderFieldType eType,
446 : const OString& rBody);
447 :
448 : /** Get the UTF-32 character at the head of a UTF-16 encoded string.
449 :
450 : @param rBegin Points to the start of the UTF-16 encoded string, must
451 : not be null. On exit, it points past the first UTF-32 character's
452 : encoding.
453 :
454 : @param pEnd Points past the end of the UTF-16 encoded string, must be
455 : strictly greater than rBegin.
456 :
457 : @return The UCS-4 character at the head of the UTF-16 encoded string.
458 : If the string does not start with the UTF-16 encoding of a UCS-32
459 : character, the first UTF-16 value is returned.
460 : */
461 : static inline sal_uInt32 getUTF32Character(const sal_Unicode *& rBegin,
462 : const sal_Unicode * pEnd);
463 :
464 : /** Put the UTF-16 encoding of a UTF-32 character into a buffer.
465 :
466 : @param pBuffer Points to a buffer, must not be null.
467 :
468 : @param nUTF32 An UTF-32 character, must be in the range 0..0x10FFFF.
469 :
470 : @return A pointer past the UTF-16 characters put into the buffer
471 : (i.e., pBuffer + 1 or pBuffer + 2).
472 : */
473 : static inline sal_Unicode * putUTF32Character(sal_Unicode * pBuffer,
474 : sal_uInt32 nUTF32);
475 : };
476 :
477 : // static
478 : inline bool INetMIME::isISO88591(sal_uInt32 nChar)
479 : {
480 : return nChar <= 0xFF;
481 : }
482 :
483 : // static
484 : inline bool INetMIME::isControl(sal_uInt32 nChar)
485 : {
486 : return nChar <= 0x1F || nChar == 0x7F;
487 : }
488 :
489 : // static
490 0 : inline bool INetMIME::isWhiteSpace(sal_uInt32 nChar)
491 : {
492 0 : return nChar == '\t' || nChar == ' ';
493 : }
494 :
495 : // static
496 2260 : inline bool INetMIME::isVisible(sal_uInt32 nChar)
497 : {
498 2260 : return nChar >= '!' && nChar <= '~';
499 : }
500 :
501 : // static
502 : inline bool INetMIME::isBase64Digit(sal_uInt32 nChar)
503 : {
504 : return rtl::isAsciiUpperCase(nChar) || rtl::isAsciiLowerCase(nChar) || rtl::isAsciiDigit(nChar)
505 : || nChar == '+' || nChar == '/';
506 : }
507 :
508 : // static
509 248 : inline int INetMIME::getWeight(sal_uInt32 nChar)
510 : {
511 248 : return rtl::isAsciiDigit(nChar) ? int(nChar - '0') : -1;
512 : }
513 :
514 : // static
515 122272 : inline int INetMIME::getHexWeight(sal_uInt32 nChar)
516 : {
517 184428 : return rtl::isAsciiDigit(nChar) ? int(nChar - '0') :
518 60116 : nChar >= 'A' && nChar <= 'F' ? int(nChar - 'A' + 10) :
519 244544 : nChar >= 'a' && nChar <= 'f' ? int(nChar - 'a' + 10) : -1;
520 : }
521 :
522 : // static
523 24 : inline int INetMIME::getBase64Weight(sal_uInt32 nChar)
524 : {
525 42 : return rtl::isAsciiUpperCase(nChar) ? int(nChar - 'A') :
526 6 : rtl::isAsciiLowerCase(nChar) ? int(nChar - 'a' + 26) :
527 6 : rtl::isAsciiDigit(nChar) ? int(nChar - '0' + 52) :
528 : nChar == '+' ? 62 :
529 : nChar == '/' ? 63 :
530 54 : nChar == '=' ? -1 : -2;
531 : }
532 :
533 : // static
534 1614 : inline bool INetMIME::isHighSurrogate(sal_uInt32 nUTF16)
535 : {
536 1614 : return nUTF16 >= 0xD800 && nUTF16 <= 0xDBFF;
537 : }
538 :
539 : // static
540 122 : inline bool INetMIME::isLowSurrogate(sal_uInt32 nUTF16)
541 : {
542 122 : return nUTF16 >= 0xDC00 && nUTF16 <= 0xDFFF;
543 : }
544 :
545 : // static
546 : inline sal_uInt32 INetMIME::toUTF32(sal_Unicode cHighSurrogate,
547 : sal_Unicode cLowSurrogate)
548 : {
549 : DBG_ASSERT(isHighSurrogate(cHighSurrogate)
550 : && isLowSurrogate(cLowSurrogate),
551 : "INetMIME::toUTF32(): Bad chars");
552 : return ((sal_uInt32(cHighSurrogate) & 0x3FF) << 10)
553 : | (sal_uInt32(cLowSurrogate) & 0x3FF);
554 : }
555 :
556 : // static
557 : inline bool INetMIME::startsWithLineBreak(const sal_Char * pBegin,
558 : const sal_Char * pEnd)
559 : {
560 : DBG_ASSERT(pBegin && pBegin <= pEnd,
561 : "INetMIME::startsWithLineBreak(): Bad sequence");
562 :
563 : return pEnd - pBegin >= 2 && pBegin[0] == 0x0D && pBegin[1] == 0x0A;
564 : // CR, LF
565 : }
566 :
567 : // static
568 0 : inline bool INetMIME::startsWithLineBreak(const sal_Unicode * pBegin,
569 : const sal_Unicode * pEnd)
570 : {
571 : DBG_ASSERT(pBegin && pBegin <= pEnd,
572 : "INetMIME::startsWithLineBreak(): Bad sequence");
573 :
574 0 : return pEnd - pBegin >= 2 && pBegin[0] == 0x0D && pBegin[1] == 0x0A;
575 : // CR, LF
576 : }
577 :
578 : // static
579 : inline bool INetMIME::startsWithLineFolding(const sal_Char * pBegin,
580 : const sal_Char * pEnd)
581 : {
582 : DBG_ASSERT(pBegin && pBegin <= pEnd,
583 : "INetMIME::startsWithLineFolding(): Bad sequence");
584 :
585 : return pEnd - pBegin >= 3 && pBegin[0] == 0x0D && pBegin[1] == 0x0A
586 : && isWhiteSpace(pBegin[2]); // CR, LF
587 : }
588 :
589 : // static
590 0 : inline bool INetMIME::startsWithLineFolding(const sal_Unicode * pBegin,
591 : const sal_Unicode * pEnd)
592 : {
593 : DBG_ASSERT(pBegin && pBegin <= pEnd,
594 : "INetMIME::startsWithLineFolding(): Bad sequence");
595 :
596 0 : return pEnd - pBegin >= 3 && pBegin[0] == 0x0D && pBegin[1] == 0x0A
597 0 : && isWhiteSpace(pBegin[2]); // CR, LF
598 : }
599 :
600 : // static
601 : inline bool INetMIME::startsWithLinearWhiteSpace(const sal_Char * pBegin,
602 : const sal_Char * pEnd)
603 : {
604 : DBG_ASSERT(pBegin && pBegin <= pEnd,
605 : "INetMIME::startsWithLinearWhiteSpace(): Bad sequence");
606 :
607 : return pBegin != pEnd
608 : && (isWhiteSpace(*pBegin) || startsWithLineFolding(pBegin, pEnd));
609 : }
610 :
611 : // static
612 0 : inline bool INetMIME::needsQuotedStringEscape(sal_uInt32 nChar)
613 : {
614 0 : return nChar == '"' || nChar == '\\';
615 : }
616 :
617 : // static
618 0 : inline rtl_TextEncoding INetMIME::translateToMIME(rtl_TextEncoding eEncoding)
619 : {
620 : #if defined WNT
621 : return eEncoding == RTL_TEXTENCODING_MS_1252 ?
622 : RTL_TEXTENCODING_ISO_8859_1 : eEncoding;
623 : #else // WNT
624 0 : return eEncoding;
625 : #endif // WNT
626 : }
627 :
628 : // static
629 6 : inline rtl_TextEncoding INetMIME::translateFromMIME(rtl_TextEncoding
630 : eEncoding)
631 : {
632 : #if defined WNT
633 : return eEncoding == RTL_TEXTENCODING_ISO_8859_1 ?
634 : RTL_TEXTENCODING_MS_1252 : eEncoding;
635 : #else
636 6 : return eEncoding;
637 : #endif
638 : }
639 :
640 : // static
641 6 : inline bool INetMIME::isMIMECharsetEncoding(rtl_TextEncoding eEncoding)
642 : {
643 6 : return ( rtl_isOctetTextEncoding(eEncoding) == sal_True );
644 : }
645 :
646 : // static
647 0 : inline int INetMIME::getUTF8OctetCount(sal_uInt32 nChar)
648 : {
649 : DBG_ASSERT(nChar < 0x80000000, "INetMIME::getUTF8OctetCount(): Bad char");
650 :
651 : return nChar < 0x80 ? 1 :
652 : nChar < 0x800 ? 2 :
653 : nChar <= 0x10000 ? 3 :
654 : nChar <= 0x200000 ? 4 :
655 0 : nChar <= 0x4000000 ? 5 : 6;
656 : }
657 :
658 : // static
659 62103815 : inline sal_uInt32 INetMIME::getUTF32Character(const sal_Unicode *& rBegin,
660 : const sal_Unicode * pEnd)
661 : {
662 : DBG_ASSERT(rBegin && rBegin < pEnd,
663 : "INetMIME::getUTF32Character(): Bad sequence");
664 62103815 : if (rBegin + 1 < pEnd && rBegin[0] >= 0xD800 && rBegin[0] <= 0xDBFF
665 0 : && rBegin[1] >= 0xDC00 && rBegin[1] <= 0xDFFF)
666 : {
667 0 : sal_uInt32 nUTF32 = sal_uInt32(*rBegin++ & 0x3FF) << 10;
668 0 : return (nUTF32 | (*rBegin++ & 0x3FF)) + 0x10000;
669 : }
670 : else
671 62103815 : return *rBegin++;
672 : }
673 :
674 : // static
675 0 : inline sal_Unicode * INetMIME::putUTF32Character(sal_Unicode * pBuffer,
676 : sal_uInt32 nUTF32)
677 : {
678 : DBG_ASSERT(nUTF32 <= 0x10FFFF, "INetMIME::putUTF32Character(): Bad char");
679 0 : if (nUTF32 < 0x10000)
680 0 : *pBuffer++ = sal_Unicode(nUTF32);
681 : else
682 : {
683 0 : nUTF32 -= 0x10000;
684 0 : *pBuffer++ = sal_Unicode(0xD800 | (nUTF32 >> 10));
685 0 : *pBuffer++ = sal_Unicode(0xDC00 | (nUTF32 & 0x3FF));
686 : }
687 0 : return pBuffer;
688 : }
689 :
690 : class INetMIMEOutputSink
691 : {
692 : public:
693 : static sal_uInt32 const NO_LINE_LENGTH_LIMIT = SAL_MAX_UINT32;
694 :
695 : private:
696 : sal_uInt32 m_nColumn;
697 : sal_uInt32 m_nLineLengthLimit;
698 :
699 : protected:
700 : /** Write a sequence of octets.
701 :
702 : @param pBegin Points to the start of the sequence, must not be null.
703 :
704 : @param pEnd Points past the end of the sequence, must be >= pBegin.
705 : */
706 : virtual void writeSequence(const sal_Char * pBegin,
707 : const sal_Char * pEnd) = 0;
708 :
709 : /** Write a null terminated sequence of octets (without the terminating
710 : null).
711 :
712 : @param pOctets A null terminated sequence of octets, must not be
713 : null.
714 :
715 : @return The length of pOctets (without the terminating null).
716 : */
717 : virtual sal_Size writeSequence(const sal_Char * pSequence);
718 :
719 : /** Write a sequence of octets.
720 :
721 : @descr The supplied sequence of UCS-4 characters is interpreted as a
722 : sequence of octets. It is an error if any of the elements of the
723 : sequence has a numerical value greater than 255.
724 :
725 : @param pBegin Points to the start of the sequence, must not be null.
726 :
727 : @param pEnd Points past the end of the sequence, must be >= pBegin.
728 : */
729 : virtual void writeSequence(const sal_uInt32 * pBegin,
730 : const sal_uInt32 * pEnd);
731 :
732 : /** Write a sequence of octets.
733 :
734 : @descr The supplied sequence of Unicode characters is interpreted as
735 : a sequence of octets. It is an error if any of the elements of the
736 : sequence has a numerical value greater than 255.
737 :
738 : @param pBegin Points to the start of the sequence, must not be null.
739 :
740 : @param pEnd Points past the end of the sequence, must be >= pBegin.
741 : */
742 : virtual void writeSequence(const sal_Unicode * pBegin,
743 : const sal_Unicode * pEnd);
744 :
745 : public:
746 0 : INetMIMEOutputSink(sal_uInt32 nTheColumn = 0,
747 : sal_uInt32 nTheLineLengthLimit
748 : = INetMIME::SOFT_LINE_LENGTH_LIMIT):
749 0 : m_nColumn(nTheColumn), m_nLineLengthLimit(nTheLineLengthLimit) {}
750 :
751 0 : virtual ~INetMIMEOutputSink() {}
752 :
753 : /** Get the current column.
754 :
755 : @return The current column (starting from zero).
756 : */
757 0 : sal_uInt32 getColumn() const { return m_nColumn; }
758 :
759 0 : sal_uInt32 getLineLengthLimit() const { return m_nLineLengthLimit; }
760 :
761 : void setLineLengthLimit(sal_uInt32 nTheLineLengthLimit)
762 : { m_nLineLengthLimit = nTheLineLengthLimit; }
763 :
764 : virtual ErrCode getError() const;
765 :
766 : /** Write a sequence of octets.
767 :
768 : @param pBegin Points to the start of the sequence, must not be null.
769 :
770 : @param pEnd Points past the end of the sequence, must be >= pBegin.
771 : */
772 : inline void write(const sal_Char * pBegin, const sal_Char * pEnd);
773 :
774 : /** Write a sequence of octets.
775 :
776 : @param pBegin Points to the start of the sequence, must not be null.
777 :
778 : @param nLength The length of the sequence.
779 : */
780 : void write(const sal_Char * pBegin, sal_Size nLength)
781 : { write(pBegin, pBegin + nLength); }
782 :
783 : /** Write a sequence of octets.
784 :
785 : @descr The supplied sequence of UCS-4 characters is interpreted as a
786 : sequence of octets. It is an error if any of the elements of the
787 : sequence has a numerical value greater than 255.
788 :
789 : @param pBegin Points to the start of the sequence, must not be null.
790 :
791 : @param pEnd Points past the end of the sequence, must be >= pBegin.
792 : */
793 : inline void write(const sal_uInt32 * pBegin, const sal_uInt32 * pEnd);
794 :
795 : /** Write a sequence of octets.
796 :
797 : @descr The supplied sequence of Unicode characters is interpreted as
798 : a sequence of octets. It is an error if any of the elements of the
799 : sequence has a numerical value greater than 255.
800 :
801 : @param pBegin Points to the start of the sequence, must not be null.
802 :
803 : @param pEnd Points past the end of the sequence, must be >= pBegin.
804 : */
805 : inline void write(const sal_Unicode * pBegin, const sal_Unicode * pEnd);
806 :
807 : /** Write a sequence of octets.
808 :
809 : @param rOctets A OString, interpreted as a sequence of octets.
810 :
811 : @param nBegin The offset of the first character to write.
812 :
813 : @param nEnd The offset past the last character to write.
814 : */
815 : void write(const OString& rOctets, sal_Int32 nBegin, sal_Int32 nEnd)
816 : {
817 : writeSequence(rOctets.getStr() + nBegin, rOctets.getStr() + nEnd);
818 : m_nColumn += nEnd - nBegin;
819 : }
820 :
821 : /** Write a single octet.
822 :
823 : @param nOctet Some octet.
824 :
825 : @return This instance.
826 : */
827 : inline INetMIMEOutputSink & operator <<(sal_Char nOctet);
828 :
829 : /** Write a null terminated sequence of octets (without the terminating
830 : null).
831 :
832 : @param pOctets A null terminated sequence of octets, must not be
833 : null.
834 :
835 : @return This instance.
836 : */
837 : inline INetMIMEOutputSink & operator <<(const sal_Char * pOctets);
838 :
839 : /** Write a sequence of octets.
840 :
841 : @param rOctets A OString, interpreted as a sequence of octets.
842 :
843 : @return This instance.
844 : */
845 : INetMIMEOutputSink & operator <<(const OString& rOctets)
846 : {
847 : writeSequence(rOctets.getStr(), rOctets.getStr() + rOctets.getLength());
848 : m_nColumn += rOctets.getLength();
849 : return *this;
850 : }
851 :
852 : /** Call a manipulator function.
853 :
854 : @param pManipulator A manipulator function.
855 :
856 : @return Whatever the manipulator function returns.
857 : */
858 : INetMIMEOutputSink &
859 0 : operator <<(INetMIMEOutputSink & (* pManipulator)(INetMIMEOutputSink &))
860 0 : { return pManipulator(*this); }
861 :
862 : /** Write a line end (CR LF).
863 : */
864 : void writeLineEnd();
865 :
866 : /** A manipulator function that writes a line end (CR LF).
867 :
868 : @param rSink Some sink.
869 :
870 : @return The sink rSink.
871 : */
872 : static inline INetMIMEOutputSink & endl(INetMIMEOutputSink & rSink);
873 : };
874 :
875 : inline void INetMIMEOutputSink::write(const sal_Char * pBegin,
876 : const sal_Char * pEnd)
877 : {
878 : writeSequence(pBegin, pEnd);
879 : m_nColumn += pEnd - pBegin;
880 : }
881 :
882 : inline void INetMIMEOutputSink::write(const sal_uInt32 * pBegin,
883 : const sal_uInt32 * pEnd)
884 : {
885 : writeSequence(pBegin, pEnd);
886 : m_nColumn += pEnd - pBegin;
887 : }
888 :
889 0 : inline void INetMIMEOutputSink::write(const sal_Unicode * pBegin,
890 : const sal_Unicode * pEnd)
891 : {
892 0 : writeSequence(pBegin, pEnd);
893 0 : m_nColumn += pEnd - pBegin;
894 0 : }
895 :
896 0 : inline INetMIMEOutputSink & INetMIMEOutputSink::operator <<(sal_Char nOctet)
897 : {
898 0 : writeSequence(&nOctet, &nOctet + 1);
899 0 : ++m_nColumn;
900 0 : return *this;
901 : }
902 :
903 0 : inline INetMIMEOutputSink & INetMIMEOutputSink::operator <<(const sal_Char *
904 : pOctets)
905 : {
906 0 : m_nColumn += writeSequence(pOctets);
907 0 : return *this;
908 : }
909 :
910 : // static
911 0 : inline INetMIMEOutputSink & INetMIMEOutputSink::endl(INetMIMEOutputSink &
912 : rSink)
913 : {
914 0 : rSink.writeLineEnd();
915 0 : return rSink;
916 : }
917 :
918 : // static
919 0 : inline void INetMIME::writeEscapeSequence(INetMIMEOutputSink & rSink,
920 : sal_uInt32 nChar)
921 : {
922 : DBG_ASSERT(nChar <= 0xFF, "INetMIME::writeEscapeSequence(): Bad char");
923 0 : rSink << '=' << sal_uInt8(getHexDigit(nChar >> 4))
924 0 : << sal_uInt8(getHexDigit(nChar & 15));
925 0 : }
926 :
927 0 : class INetMIMEStringOutputSink: public INetMIMEOutputSink
928 : {
929 : OStringBuffer m_aBuffer;
930 :
931 : using INetMIMEOutputSink::writeSequence;
932 :
933 : virtual void writeSequence(const sal_Char * pBegin,
934 : const sal_Char * pEnd) SAL_OVERRIDE;
935 :
936 : public:
937 0 : inline INetMIMEStringOutputSink(sal_uInt32 nColumn = 0,
938 : sal_uInt32 nLineLengthLimit
939 : = INetMIME::SOFT_LINE_LENGTH_LIMIT):
940 0 : INetMIMEOutputSink(nColumn, nLineLengthLimit) {}
941 :
942 : virtual ErrCode getError() const SAL_OVERRIDE;
943 :
944 0 : OString takeBuffer()
945 : {
946 0 : return m_aBuffer.makeStringAndClear();
947 : }
948 : };
949 :
950 : class INetMIMEEncodedWordOutputSink
951 : {
952 : public:
953 : enum Context { CONTEXT_TEXT = 1,
954 : CONTEXT_COMMENT = 2,
955 : CONTEXT_PHRASE = 4 };
956 :
957 : enum Space { SPACE_NO, SPACE_ENCODED, SPACE_ALWAYS };
958 :
959 : private:
960 : enum { BUFFER_SIZE = 256 };
961 :
962 : enum Coding { CODING_NONE, CODING_QUOTED, CODING_ENCODED,
963 : CODING_ENCODED_TERMINATED };
964 :
965 : enum EncodedWordState { STATE_INITIAL, STATE_FIRST_EQUALS,
966 : STATE_FIRST_QUESTION, STATE_CHARSET,
967 : STATE_SECOND_QUESTION, STATE_ENCODING,
968 : STATE_THIRD_QUESTION, STATE_ENCODED_TEXT,
969 : STATE_FOURTH_QUESTION, STATE_SECOND_EQUALS,
970 : STATE_BAD };
971 :
972 : INetMIMEOutputSink & m_rSink;
973 : Context m_eContext;
974 : Space m_eInitialSpace;
975 : sal_uInt32 m_nExtraSpaces;
976 : INetMIMECharsetList_Impl * m_pEncodingList;
977 : sal_Unicode * m_pBuffer;
978 : sal_uInt32 m_nBufferSize;
979 : sal_Unicode * m_pBufferEnd;
980 : Coding m_ePrevCoding;
981 : rtl_TextEncoding m_ePrevMIMEEncoding;
982 : Coding m_eCoding;
983 : sal_uInt32 m_nQuotedEscaped;
984 : EncodedWordState m_eEncodedWordState;
985 :
986 : inline bool needsEncodedWordEscape(sal_uInt32 nChar) const;
987 :
988 : void finish(bool bWriteTrailer);
989 :
990 : public:
991 : inline INetMIMEEncodedWordOutputSink(INetMIMEOutputSink & rTheSink,
992 : Context eTheContext,
993 : Space eTheInitialSpace,
994 : rtl_TextEncoding ePreferredEncoding);
995 :
996 : ~INetMIMEEncodedWordOutputSink();
997 :
998 : INetMIMEEncodedWordOutputSink & operator <<(sal_uInt32 nChar);
999 :
1000 : inline void write(const sal_Char * pBegin, const sal_Char * pEnd);
1001 :
1002 : inline void write(const sal_Unicode * pBegin, const sal_Unicode * pEnd);
1003 :
1004 : inline bool flush();
1005 : };
1006 :
1007 0 : inline INetMIMEEncodedWordOutputSink::INetMIMEEncodedWordOutputSink(
1008 : INetMIMEOutputSink & rTheSink, Context eTheContext,
1009 : Space eTheInitialSpace, rtl_TextEncoding ePreferredEncoding):
1010 : m_rSink(rTheSink),
1011 : m_eContext(eTheContext),
1012 : m_eInitialSpace(eTheInitialSpace),
1013 : m_nExtraSpaces(0),
1014 0 : m_pEncodingList(INetMIME::createPreferredCharsetList(ePreferredEncoding)),
1015 : m_ePrevCoding(CODING_NONE),
1016 : m_ePrevMIMEEncoding(RTL_TEXTENCODING_DONTKNOW),
1017 : m_eCoding(CODING_NONE),
1018 : m_nQuotedEscaped(0),
1019 0 : m_eEncodedWordState(STATE_INITIAL)
1020 : {
1021 0 : m_nBufferSize = BUFFER_SIZE;
1022 : m_pBuffer = static_cast< sal_Unicode * >(rtl_allocateMemory(
1023 : m_nBufferSize
1024 0 : * sizeof (sal_Unicode)));
1025 0 : m_pBufferEnd = m_pBuffer;
1026 0 : }
1027 :
1028 : inline void INetMIMEEncodedWordOutputSink::write(const sal_Char * pBegin,
1029 : const sal_Char * pEnd)
1030 : {
1031 : DBG_ASSERT(pBegin && pBegin <= pEnd,
1032 : "INetMIMEEncodedWordOutputSink::write(): Bad sequence");
1033 :
1034 : while (pBegin != pEnd)
1035 : operator <<(*pBegin++);
1036 : }
1037 :
1038 0 : inline void INetMIMEEncodedWordOutputSink::write(const sal_Unicode * pBegin,
1039 : const sal_Unicode * pEnd)
1040 : {
1041 : DBG_ASSERT(pBegin && pBegin <= pEnd,
1042 : "INetMIMEEncodedWordOutputSink::write(): Bad sequence");
1043 :
1044 0 : while (pBegin != pEnd)
1045 0 : operator <<(*pBegin++);
1046 0 : }
1047 :
1048 0 : inline bool INetMIMEEncodedWordOutputSink::flush()
1049 : {
1050 0 : finish(true);
1051 0 : return m_ePrevCoding != CODING_NONE;
1052 : }
1053 :
1054 66 : struct INetContentTypeParameter
1055 : {
1056 : /** The name of the attribute, in US-ASCII encoding and converted to lower
1057 : case. If a parameter value is split as described in RFC 2231, there
1058 : will only be one item for the complete parameter, with the attribute
1059 : name lacking any section suffix.
1060 : */
1061 : const OString m_sAttribute;
1062 :
1063 : /** The optional character set specification (see RFC 2231), in US-ASCII
1064 : encoding and converted to lower case.
1065 : */
1066 : const OString m_sCharset;
1067 :
1068 : /** The optional language specification (see RFC 2231), in US-ASCII
1069 : encoding and converted to lower case.
1070 : */
1071 : const OString m_sLanguage;
1072 :
1073 : /** The attribute value. If the value is a quoted-string, it is
1074 : 'unpacked.' If a character set is specified, and the value can be
1075 : converted to Unicode, this is done. Also, if no character set is
1076 : specified, it is first tried to convert the value from UTF-8 encoding
1077 : to Unicode, and if that doesn't work (because the value is not in
1078 : UTF-8 encoding), it is converted from ISO-8859-1 encoding to Unicode
1079 : (which will always work). But if a character set is specified and the
1080 : value cannot be converted from that character set to Unicode, special
1081 : action is taken to produce a value that can possibly be transformed
1082 : back into its original form: Any 8-bit character from a non-encoded
1083 : part of the original value is directly converted to Unicode
1084 : (effectively handling it as if it was ISO-8859-1 encoded), and any
1085 : 8-bit character from an encoded part of the original value is mapped
1086 : to the range U+F800..U+F8FF at the top of the Corporate Use Subarea
1087 : within Unicode's Private Use Area (effectively adding 0xF800 to the
1088 : character's numeric value).
1089 : */
1090 : const OUString m_sValue;
1091 :
1092 : /** This is true if the value is successfully converted to Unicode, and
1093 : false if the value is a special mixture of ISO-LATIN-1 characters and
1094 : characters from Unicode's Private Use Area.
1095 : */
1096 : const bool m_bConverted;
1097 :
1098 22 : INetContentTypeParameter(const OString& rTheAttribute,
1099 : const OString& rTheCharset, const OString& rTheLanguage,
1100 : const OUString& rTheValue, bool bTheConverted)
1101 : : m_sAttribute(rTheAttribute)
1102 : , m_sCharset(rTheCharset)
1103 : , m_sLanguage(rTheLanguage)
1104 : , m_sValue(rTheValue)
1105 22 : , m_bConverted(bTheConverted)
1106 : {
1107 22 : }
1108 : };
1109 :
1110 186 : class TOOLS_DLLPUBLIC INetContentTypeParameterList
1111 : {
1112 : public:
1113 :
1114 : void Clear();
1115 :
1116 : void Insert(INetContentTypeParameter * pParameter, sal_uIntPtr nIndex)
1117 : {
1118 : maEntries.insert(maEntries.begin()+nIndex,pParameter);
1119 : }
1120 :
1121 22 : void Append(INetContentTypeParameter *pParameter)
1122 : {
1123 22 : maEntries.push_back(pParameter);
1124 22 : }
1125 :
1126 : inline const INetContentTypeParameter * GetObject(sal_uIntPtr nIndex) const
1127 : {
1128 : return &(maEntries[nIndex]);
1129 : }
1130 :
1131 : const INetContentTypeParameter * find(const OString& rAttribute) const;
1132 :
1133 : private:
1134 :
1135 : boost::ptr_vector<INetContentTypeParameter> maEntries;
1136 : };
1137 :
1138 : #endif
1139 :
1140 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|