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