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 : :
20 : : #include <sal/types.h>
21 : : #include <tools/datetime.hxx>
22 : : #include <tools/inetmime.hxx>
23 : : #include <tools/inetmsg.hxx>
24 : : #include <tools/inetstrm.hxx>
25 : : #include <tools/contnr.hxx>
26 : : #include <rtl/instance.hxx>
27 : : #include <rtl/strbuf.hxx>
28 : : #include <comphelper/string.hxx>
29 : :
30 : : #include <stdio.h>
31 : :
32 : 0 : inline sal_Bool ascii_isDigit( sal_Unicode ch )
33 : : {
34 [ # # ][ # # ]: 0 : return ((ch >= 0x0030) && (ch <= 0x0039));
35 : : }
36 : :
37 : 0 : inline sal_Bool ascii_isLetter( sal_Unicode ch )
38 : : {
39 [ # # ][ # # ]: 0 : return (( (ch >= 0x0041) && (ch <= 0x005A)) || ((ch >= 0x0061) && (ch <= 0x007A)));
[ # # ][ # # ]
40 : : }
41 : :
42 : 0 : inline sal_Unicode ascii_toLowerCase( sal_Unicode ch )
43 : : {
44 [ # # ][ # # ]: 0 : if ( (ch >= 0x0041) && (ch <= 0x005A) )
45 : 0 : return ch + 0x20;
46 : : else
47 : 0 : return ch;
48 : : }
49 : :
50 : : #define CONSTASCII_STRINGPARAM(a) (a), RTL_TEXTENCODING_ASCII_US
51 : :
52 [ # # ]: 0 : INetMessage::~INetMessage()
53 : : {
54 [ # # ]: 0 : ListCleanup_Impl();
55 [ # # ]: 0 : }
56 : :
57 : 0 : void INetMessage::ListCleanup_Impl()
58 : : {
59 : : // Cleanup.
60 : 0 : sal_uIntPtr i, n = m_aHeaderList.size();
61 [ # # ]: 0 : for (i = 0; i < n; i++)
62 [ # # ]: 0 : delete m_aHeaderList[ i ];
63 : 0 : m_aHeaderList.clear();
64 : 0 : }
65 : :
66 : 0 : void INetMessage::ListCopy (const INetMessage &rMsg)
67 : : {
68 [ # # ]: 0 : if (!(this == &rMsg))
69 : : {
70 : : // Cleanup.
71 : 0 : ListCleanup_Impl();
72 : :
73 : : // Copy.
74 : 0 : sal_uIntPtr i, n = rMsg.GetHeaderCount();
75 [ # # ]: 0 : for (i = 0; i < n; i++)
76 : : {
77 : 0 : INetMessageHeader *p = rMsg.m_aHeaderList[ i ];
78 [ # # ]: 0 : m_aHeaderList.push_back( new INetMessageHeader(*p) );
79 : : }
80 : : }
81 : 0 : }
82 : :
83 : 0 : void INetMessage::SetHeaderField_Impl (
84 : : INetMIME::HeaderFieldType eType,
85 : : const rtl::OString &rName,
86 : : const rtl::OUString &rValue,
87 : : sal_uIntPtr &rnIndex)
88 : : {
89 : 0 : INetMIMEStringOutputSink aSink (0, STRING_MAXLEN);
90 : : INetMIME::writeHeaderFieldBody (
91 [ # # ][ # # ]: 0 : aSink, eType, rValue, osl_getThreadTextEncoding(), false);
92 : : SetHeaderField_Impl (
93 [ # # ]: 0 : INetMessageHeader (rName, aSink.takeBuffer()), rnIndex);
94 : 0 : }
95 : :
96 : 0 : sal_uIntPtr INetMessage::SetHeaderField (
97 : : const INetMessageHeader &rHeader, sal_uIntPtr nIndex)
98 : : {
99 : 0 : sal_uIntPtr nResult = nIndex;
100 [ # # ]: 0 : SetHeaderField_Impl (rHeader, nResult);
101 : 0 : return nResult;
102 : : }
103 : :
104 : 0 : SvStream& INetMessage::operator<< (SvStream& rStrm) const
105 : : {
106 : 0 : rStrm << static_cast<sal_uInt32>(m_nDocSize);
107 : 0 : write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(rStrm, m_aDocName, RTL_TEXTENCODING_UTF8);
108 : :
109 : 0 : sal_uIntPtr i, n = m_aHeaderList.size();
110 : 0 : rStrm << static_cast<sal_uInt32>(n);
111 : :
112 [ # # ]: 0 : for (i = 0; i < n; i++)
113 : 0 : rStrm << *( m_aHeaderList[ i ] );
114 : :
115 : 0 : return rStrm;
116 : : }
117 : :
118 : 0 : SvStream& INetMessage::operator>> (SvStream& rStrm)
119 : : {
120 : : // Cleanup.
121 : 0 : m_nDocSize = 0;
122 [ # # ]: 0 : m_xDocLB.Clear();
123 [ # # ]: 0 : ListCleanup_Impl();
124 : :
125 : : sal_uInt32 nTemp;
126 : :
127 : : // Copy.
128 [ # # ]: 0 : rStrm >> nTemp;
129 : 0 : m_nDocSize = nTemp;
130 [ # # ]: 0 : m_aDocName = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(rStrm, RTL_TEXTENCODING_UTF8);
131 : :
132 : 0 : sal_uIntPtr i, n = 0;
133 [ # # ]: 0 : rStrm >> nTemp;
134 : 0 : n = nTemp;
135 : :
136 [ # # ]: 0 : for (i = 0; i < n; i++)
137 : : {
138 [ # # ]: 0 : INetMessageHeader *p = new INetMessageHeader();
139 [ # # ]: 0 : rStrm >> *p;
140 [ # # ]: 0 : m_aHeaderList.push_back( p );
141 : : }
142 : :
143 : : // Done.
144 : 0 : return rStrm;
145 : : }
146 : :
147 : : namespace
148 : : {
149 : : struct ImplINetRFC822MessageHeaderDataImpl
150 : : {
151 : 0 : const rtl::OString* operator()()
152 : : {
153 : : static const rtl::OString _ImplINetRFC822MessageHeaderData[] =
154 : : {
155 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("BCC")),
156 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("CC")),
157 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Comments")),
158 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Date")),
159 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("From")),
160 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("In-Reply-To")),
161 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Keywords")),
162 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Message-ID")),
163 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("References")),
164 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Reply-To")),
165 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Return-Path")),
166 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Subject")),
167 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Sender")),
168 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("To")),
169 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("X-Mailer")),
170 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Return-Receipt-To"))
171 [ # # ][ # # ]: 0 : };
[ # # ]
172 : 0 : return &_ImplINetRFC822MessageHeaderData[0];
173 : : }
174 : : };
175 : :
176 : : struct ImplINetRFC822MessageHeaderData
177 : : : public rtl::StaticAggregate< const rtl::OString, ImplINetRFC822MessageHeaderDataImpl > {};
178 : : }
179 : :
180 : : #define HDR(n) ImplINetRFC822MessageHeaderData::get()[(n)]
181 : :
182 : : enum _ImplINetRFC822MessageHeaderState
183 : : {
184 : : INETMSG_RFC822_BEGIN,
185 : : INETMSG_RFC822_CHECK,
186 : : INETMSG_RFC822_OK,
187 : : INETMSG_RFC822_JUNK,
188 : :
189 : : INETMSG_RFC822_TOKEN_RE,
190 : : INETMSG_RFC822_TOKEN_RETURNMINUS,
191 : : INETMSG_RFC822_TOKEN_XMINUS,
192 : : INETMSG_RFC822_LETTER_C,
193 : : INETMSG_RFC822_LETTER_S
194 : : };
195 : :
196 : 0 : INetRFC822Message::INetRFC822Message()
197 : 0 : : INetMessage()
198 : : {
199 [ # # ]: 0 : for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++)
200 : 0 : m_nIndex[i] = CONTAINER_ENTRY_NOTFOUND;
201 : 0 : }
202 : :
203 : 0 : INetRFC822Message::INetRFC822Message (const INetRFC822Message& rMsg)
204 : 0 : : INetMessage (rMsg)
205 : : {
206 [ # # ]: 0 : for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++)
207 : 0 : m_nIndex[i] = rMsg.m_nIndex[i];
208 : 0 : }
209 : :
210 : 0 : INetRFC822Message& INetRFC822Message::operator= (const INetRFC822Message& rMsg)
211 : : {
212 [ # # ]: 0 : if (this != &rMsg)
213 : : {
214 : 0 : INetMessage::operator= (rMsg);
215 : :
216 [ # # ]: 0 : for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++)
217 : 0 : m_nIndex[i] = rMsg.m_nIndex[i];
218 : : }
219 : 0 : return *this;
220 : : }
221 : :
222 : 0 : INetRFC822Message::~INetRFC822Message()
223 : : {
224 [ # # ]: 0 : }
225 : :
226 : : /* ParseDateField and local helper functions.
227 : : *
228 : : * Parses a String in (implied) GMT format into class Date and Time objects.
229 : : * Four formats are accepted:
230 : : *
231 : : * [Wkd,] 1*2DIGIT Mon 2*4DIGIT 00:00:00 [GMT] (rfc1123)
232 : : * [Wkd,] 00 Mon 0000 00:00:00 [GMT]) (rfc822, rfc1123)
233 : : * Weekday, 00-Mon-00 00:00:00 [GMT] (rfc850, rfc1036)
234 : : * Wkd Mon 00 00:00:00 0000 [GMT] (ctime)
235 : : * 1*DIGIT (delta seconds)
236 : : */
237 : :
238 : : static const sal_Char *months[12] =
239 : : {
240 : : "Jan", "Feb", "Mar", "Apr", "May", "Jun",
241 : : "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
242 : : };
243 : :
244 : 0 : static sal_uInt16 ParseNumber(const rtl::OString& rStr, sal_uInt16& nIndex)
245 : : {
246 : 0 : sal_uInt16 n = nIndex;
247 [ # # ][ # # ]: 0 : while ((n < rStr.getLength()) && ascii_isDigit(rStr[n])) n++;
[ # # ]
248 : :
249 : 0 : rtl::OString aNum(rStr.copy(nIndex, (n - nIndex)));
250 : 0 : nIndex = n;
251 : :
252 : 0 : return (sal_uInt16)(aNum.toInt32());
253 : : }
254 : :
255 : 0 : static sal_uInt16 ParseMonth(const rtl::OString& rStr, sal_uInt16& nIndex)
256 : : {
257 : 0 : sal_uInt16 n = nIndex;
258 [ # # ][ # # ]: 0 : while ((n < rStr.getLength()) && ascii_isLetter(rStr[n])) n++;
[ # # ]
259 : :
260 : 0 : rtl::OString aMonth(rStr.copy(nIndex, 3));
261 : 0 : nIndex = n;
262 : :
263 : : sal_uInt16 i;
264 [ # # ]: 0 : for (i = 0; i < 12; i++)
265 [ # # ]: 0 : if (aMonth.equalsIgnoreAsciiCase(months[i])) break;
266 : 0 : return (i + 1);
267 : : }
268 : :
269 : 0 : sal_Bool INetRFC822Message::ParseDateField (
270 : : const rtl::OUString& rDateFieldW, DateTime& rDateTime)
271 : : {
272 : : rtl::OString aDateField(rtl::OUStringToOString(rDateFieldW,
273 [ # # ]: 0 : RTL_TEXTENCODING_ASCII_US));
274 : :
275 [ # # ]: 0 : if (aDateField.isEmpty()) return sal_False;
276 : :
277 [ # # ]: 0 : if (aDateField.indexOf(':') != -1)
278 : : {
279 : : // Some DateTime format.
280 : 0 : sal_uInt16 nIndex = 0;
281 : :
282 : : // Skip over <Wkd> or <Weekday>, leading and trailing space.
283 [ # # # # ]: 0 : while ((nIndex < aDateField.getLength()) &&
[ # # ]
284 : 0 : (aDateField[nIndex] == ' '))
285 : 0 : nIndex++;
286 : :
287 [ # # # # : 0 : while (
# # ][ # # ]
288 : 0 : (nIndex < aDateField.getLength()) &&
289 : 0 : (ascii_isLetter (aDateField[nIndex]) ||
290 : 0 : (aDateField[nIndex] == ',') ))
291 : 0 : nIndex++;
292 : :
293 [ # # # # ]: 0 : while ((nIndex < aDateField.getLength()) &&
[ # # ]
294 : 0 : (aDateField[nIndex] == ' '))
295 : 0 : nIndex++;
296 : :
297 [ # # ]: 0 : if (ascii_isLetter (aDateField[nIndex]))
298 : : {
299 : : // Format: ctime().
300 [ # # ]: 0 : if ((aDateField.getLength() - nIndex) < 20) return sal_False;
301 : :
302 [ # # ][ # # ]: 0 : rDateTime.SetMonth (ParseMonth (aDateField, nIndex)); nIndex++;
303 [ # # ]: 0 : rDateTime.SetDay (ParseNumber (aDateField, nIndex)); nIndex++;
304 : :
305 [ # # ]: 0 : rDateTime.SetHour (ParseNumber (aDateField, nIndex)); nIndex++;
306 [ # # ]: 0 : rDateTime.SetMin (ParseNumber (aDateField, nIndex)); nIndex++;
307 [ # # ]: 0 : rDateTime.SetSec (ParseNumber (aDateField, nIndex)); nIndex++;
308 [ # # ]: 0 : rDateTime.Set100Sec (0);
309 : :
310 : 0 : sal_uInt16 nYear = ParseNumber (aDateField, nIndex);
311 [ # # ]: 0 : if (nYear < 100) nYear += 1900;
312 [ # # ]: 0 : rDateTime.SetYear (nYear);
313 : : }
314 : : else
315 : : {
316 : : // Format: RFC1036 or RFC1123.
317 [ # # ]: 0 : if ((aDateField.getLength() - nIndex) < 17) return sal_False;
318 : :
319 [ # # ]: 0 : rDateTime.SetDay (ParseNumber (aDateField, nIndex)); nIndex++;
320 [ # # ][ # # ]: 0 : rDateTime.SetMonth (ParseMonth (aDateField, nIndex)); nIndex++;
321 : :
322 : 0 : sal_uInt16 nYear = ParseNumber (aDateField, nIndex); nIndex++;
323 [ # # ]: 0 : if (nYear < 100) nYear += 1900;
324 [ # # ]: 0 : rDateTime.SetYear (nYear);
325 : :
326 [ # # ]: 0 : rDateTime.SetHour (ParseNumber (aDateField, nIndex)); nIndex++;
327 [ # # ]: 0 : rDateTime.SetMin (ParseNumber (aDateField, nIndex)); nIndex++;
328 [ # # ]: 0 : rDateTime.SetSec (ParseNumber (aDateField, nIndex)); nIndex++;
329 [ # # ]: 0 : rDateTime.Set100Sec (0);
330 : :
331 [ # # # # ]: 0 : if ((aDateField[nIndex] == '+') ||
[ # # ]
332 : 0 : (aDateField[nIndex] == '-') )
333 : : {
334 : : // Offset from GMT: "(+|-)HHMM".
335 : 0 : sal_Bool bEast = (aDateField[nIndex++] == '+');
336 : 0 : sal_uInt16 nOffset = ParseNumber (aDateField, nIndex);
337 [ # # ]: 0 : if (nOffset > 0)
338 : : {
339 : 0 : Time aDiff( Time::EMPTY );
340 [ # # ]: 0 : aDiff.SetHour (nOffset / 100);
341 [ # # ]: 0 : aDiff.SetMin (nOffset % 100);
342 [ # # ]: 0 : aDiff.SetSec (0);
343 [ # # ]: 0 : aDiff.Set100Sec (0);
344 : :
345 [ # # ]: 0 : if (bEast)
346 [ # # ]: 0 : rDateTime -= aDiff;
347 : : else
348 [ # # ]: 0 : rDateTime += aDiff;
349 : : }
350 : : }
351 : : }
352 : : }
353 [ # # ][ # # ]: 0 : else if (comphelper::string::isdigitAsciiString(aDateField))
354 : : {
355 : : // Format: delta seconds.
356 : 0 : Time aDelta (0);
357 : 0 : aDelta.SetTime (aDateField.toInt32() * 100);
358 : :
359 [ # # ]: 0 : DateTime aNow( DateTime::SYSTEM );
360 [ # # ]: 0 : aNow += aDelta;
361 [ # # ]: 0 : aNow.ConvertToUTC();
362 : :
363 : 0 : rDateTime.SetDate (aNow.GetDate());
364 : 0 : rDateTime.SetTime (aNow.GetTime());
365 : : }
366 : : else
367 : : {
368 : : // Junk.
369 : 0 : return sal_False;
370 : : }
371 : :
372 [ # # ]: 0 : return (rDateTime.IsValidAndGregorian() &&
373 : 0 : !((rDateTime.GetSec() > 59) ||
374 : 0 : (rDateTime.GetMin() > 59) ||
375 [ # # # # : 0 : (rDateTime.GetHour() > 23) ));
# # ][ # # ]
376 : : }
377 : :
378 : : // Header Field Parser
379 : 0 : sal_uIntPtr INetRFC822Message::SetHeaderField (
380 : : const INetMessageHeader &rHeader, sal_uIntPtr nNewIndex)
381 : : {
382 : 0 : rtl::OString aName (rHeader.GetName());
383 : 0 : const sal_Char *pData = aName.getStr();
384 : 0 : const sal_Char *pStop = pData + aName.getLength() + 1;
385 : 0 : const sal_Char *check = "";
386 : :
387 : 0 : sal_uIntPtr nIdx = LIST_APPEND;
388 : 0 : int eState = INETMSG_RFC822_BEGIN;
389 : 0 : int eOkState = INETMSG_RFC822_OK;
390 : :
391 [ # # ]: 0 : while (pData < pStop)
392 : : {
393 [ # # # # : 0 : switch (eState)
# # # #
# ]
394 : : {
395 : : case INETMSG_RFC822_BEGIN:
396 : 0 : eState = INETMSG_RFC822_CHECK;
397 : 0 : eOkState = INETMSG_RFC822_OK;
398 : :
399 [ # # # # : 0 : switch (ascii_toLowerCase (*pData))
# # # # #
# # # ]
400 : : {
401 : : case 'b':
402 : 0 : check = "cc";
403 : 0 : nIdx = INETMSG_RFC822_BCC;
404 : 0 : break;
405 : :
406 : : case 'c':
407 : 0 : eState = INETMSG_RFC822_LETTER_C;
408 : 0 : break;
409 : :
410 : : case 'd':
411 : 0 : check = "ate";
412 : 0 : nIdx = INETMSG_RFC822_DATE;
413 : 0 : break;
414 : :
415 : : case 'f':
416 : 0 : check = "rom";
417 : 0 : nIdx = INETMSG_RFC822_FROM;
418 : 0 : break;
419 : :
420 : : case 'i':
421 : 0 : check = "n-reply-to";
422 : 0 : nIdx = INETMSG_RFC822_IN_REPLY_TO;
423 : 0 : break;
424 : :
425 : : case 'k':
426 : 0 : check = "eywords";
427 : 0 : nIdx = INETMSG_RFC822_KEYWORDS;
428 : 0 : break;
429 : :
430 : : case 'm':
431 : 0 : check = "essage-id";
432 : 0 : nIdx = INETMSG_RFC822_MESSAGE_ID;
433 : 0 : break;
434 : :
435 : : case 'r':
436 : 0 : check = "e";
437 : 0 : eOkState = INETMSG_RFC822_TOKEN_RE;
438 : 0 : break;
439 : :
440 : : case 's':
441 : 0 : eState = INETMSG_RFC822_LETTER_S;
442 : 0 : break;
443 : :
444 : : case 't':
445 : 0 : check = "o";
446 : 0 : nIdx = INETMSG_RFC822_TO;
447 : 0 : break;
448 : :
449 : : case 'x':
450 : 0 : check = "-";
451 : 0 : eOkState = INETMSG_RFC822_TOKEN_XMINUS;
452 : 0 : break;
453 : :
454 : : default:
455 : 0 : eState = INETMSG_RFC822_JUNK;
456 : 0 : break;
457 : : }
458 : 0 : pData++;
459 : 0 : break;
460 : :
461 : : case INETMSG_RFC822_TOKEN_RE:
462 : 0 : eState = INETMSG_RFC822_CHECK;
463 : 0 : eOkState = INETMSG_RFC822_OK;
464 : :
465 [ # # # # ]: 0 : switch (ascii_toLowerCase (*pData))
466 : : {
467 : : case 'f':
468 : 0 : check = "erences";
469 : 0 : nIdx = INETMSG_RFC822_REFERENCES;
470 : 0 : break;
471 : :
472 : : case 'p':
473 : 0 : check = "ly-to";
474 : 0 : nIdx = INETMSG_RFC822_REPLY_TO;
475 : 0 : break;
476 : :
477 : : case 't':
478 : 0 : check = "urn-";
479 : 0 : eOkState = INETMSG_RFC822_TOKEN_RETURNMINUS;
480 : 0 : break;
481 : :
482 : : default:
483 : 0 : eState = INETMSG_RFC822_JUNK;
484 : 0 : break;
485 : : }
486 : 0 : pData++;
487 : 0 : break;
488 : :
489 : : case INETMSG_RFC822_TOKEN_RETURNMINUS:
490 : 0 : eState = INETMSG_RFC822_CHECK;
491 : 0 : eOkState = INETMSG_RFC822_OK;
492 : :
493 [ # # # ]: 0 : switch (ascii_toLowerCase (*pData))
494 : : {
495 : : case 'p':
496 : 0 : check = "ath";
497 : 0 : nIdx = INETMSG_RFC822_RETURN_PATH;
498 : 0 : break;
499 : :
500 : : case 'r':
501 : 0 : check = "eceipt-to";
502 : 0 : nIdx = INETMSG_RFC822_RETURN_RECEIPT_TO;
503 : 0 : break;
504 : :
505 : : default:
506 : 0 : eState = INETMSG_RFC822_JUNK;
507 : 0 : break;
508 : : }
509 : 0 : pData++;
510 : 0 : break;
511 : :
512 : : case INETMSG_RFC822_TOKEN_XMINUS:
513 : 0 : eState = INETMSG_RFC822_CHECK;
514 : 0 : eOkState = INETMSG_RFC822_OK;
515 : :
516 [ # # ]: 0 : switch (ascii_toLowerCase (*pData))
517 : : {
518 : : case 'm':
519 : 0 : check = "ailer";
520 : 0 : nIdx = INETMSG_RFC822_X_MAILER;
521 : 0 : break;
522 : :
523 : : default:
524 : 0 : eState = INETMSG_RFC822_JUNK;
525 : 0 : break;
526 : : }
527 : 0 : pData++;
528 : 0 : break;
529 : :
530 : : case INETMSG_RFC822_LETTER_C:
531 : 0 : eState = INETMSG_RFC822_CHECK;
532 : 0 : eOkState = INETMSG_RFC822_OK;
533 : :
534 [ # # # ]: 0 : switch (ascii_toLowerCase (*pData))
535 : : {
536 : : case 'c':
537 : 0 : check = "";
538 : 0 : nIdx = INETMSG_RFC822_CC;
539 : 0 : break;
540 : :
541 : : case 'o':
542 : 0 : check = "mments";
543 : 0 : nIdx = INETMSG_RFC822_COMMENTS;
544 : 0 : break;
545 : :
546 : : default:
547 : 0 : eState = INETMSG_RFC822_JUNK;
548 : 0 : break;
549 : : }
550 : 0 : pData++;
551 : 0 : break;
552 : :
553 : : case INETMSG_RFC822_LETTER_S:
554 : 0 : eState = INETMSG_RFC822_CHECK;
555 : 0 : eOkState = INETMSG_RFC822_OK;
556 : :
557 [ # # # ]: 0 : switch (ascii_toLowerCase (*pData))
558 : : {
559 : : case 'e':
560 : 0 : check = "nder";
561 : 0 : nIdx = INETMSG_RFC822_SENDER;
562 : 0 : break;
563 : :
564 : : case 'u':
565 : 0 : check = "bject";
566 : 0 : nIdx = INETMSG_RFC822_SUBJECT;
567 : 0 : break;
568 : :
569 : : default:
570 : 0 : eState = INETMSG_RFC822_JUNK;
571 : 0 : break;
572 : : }
573 : 0 : pData++;
574 : 0 : break;
575 : :
576 : : case INETMSG_RFC822_CHECK:
577 [ # # ]: 0 : if (*check)
578 : : {
579 [ # # ]: 0 : while (*pData && *check &&
[ # # # # ]
[ # # ]
580 : 0 : (ascii_toLowerCase (*pData) == *check))
581 : : {
582 : 0 : pData++;
583 : 0 : check++;
584 : : }
585 : : }
586 : : else
587 : : {
588 : 0 : check = pData;
589 : : }
590 [ # # ]: 0 : eState = (*check == '\0') ? eOkState : INETMSG_RFC822_JUNK;
591 : 0 : break;
592 : :
593 : : case INETMSG_RFC822_OK:
594 : 0 : pData = pStop;
595 : : SetHeaderField_Impl (
596 [ # # ]: 0 : INetMessageHeader (HDR(nIdx), rHeader.GetValue()),
597 [ # # ]: 0 : m_nIndex[nIdx]);
598 : 0 : nNewIndex = m_nIndex[nIdx];
599 : 0 : break;
600 : :
601 : : default: // INETMSG_RFC822_JUNK
602 : 0 : pData = pStop;
603 [ # # ]: 0 : nNewIndex = INetMessage::SetHeaderField (rHeader, nNewIndex);
604 : 0 : break;
605 : : }
606 : : }
607 : 0 : return nNewIndex;
608 : : }
609 : :
610 : 0 : SvStream& INetRFC822Message::operator<< (SvStream& rStrm) const
611 : : {
612 : 0 : INetMessage::operator<< (rStrm);
613 : :
614 [ # # ]: 0 : for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++)
615 : 0 : rStrm << static_cast<sal_uInt32>(m_nIndex[i]);
616 : :
617 : 0 : return rStrm;
618 : : }
619 : :
620 : 0 : SvStream& INetRFC822Message::operator>> (SvStream& rStrm)
621 : : {
622 [ # # ]: 0 : INetMessage::operator>> (rStrm);
623 : :
624 : : sal_uInt32 nTemp;
625 [ # # ]: 0 : for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++)
626 : : {
627 [ # # ]: 0 : rStrm >> nTemp;
628 : 0 : m_nIndex[i] = nTemp;
629 : : }
630 : :
631 : 0 : return rStrm;
632 : : }
633 : :
634 : : namespace
635 : : {
636 : : struct ImplINetMIMEMessageHeaderDataImpl
637 : : {
638 : 0 : const rtl::OString* operator()()
639 : : {
640 : : static const rtl::OString _ImplINetMIMEMessageHeaderData[] =
641 : : {
642 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("MIME-Version")),
643 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Content-Description")),
644 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Content-Disposition")),
645 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Content-ID")),
646 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Content-Type")),
647 : : rtl::OString(RTL_CONSTASCII_STRINGPARAM("Content-Transfer-Encoding"))
648 [ # # ][ # # ]: 0 : };
[ # # ]
649 : 0 : return &_ImplINetMIMEMessageHeaderData[0];
650 : : }
651 : : };
652 : :
653 : : struct ImplINetMIMEMessageHeaderData
654 : : : public rtl::StaticAggregate< const rtl::OString, ImplINetMIMEMessageHeaderDataImpl > {};
655 : : }
656 : :
657 : : #define MIMEHDR(n) ImplINetMIMEMessageHeaderData::get()[(n)]
658 : :
659 : : enum _ImplINetMIMEMessageHeaderState
660 : : {
661 : : INETMSG_MIME_BEGIN,
662 : : INETMSG_MIME_CHECK,
663 : : INETMSG_MIME_OK,
664 : : INETMSG_MIME_JUNK,
665 : :
666 : : INETMSG_MIME_TOKEN_CONTENT,
667 : : INETMSG_MIME_TOKEN_CONTENT_D,
668 : : INETMSG_MIME_TOKEN_CONTENT_T
669 : : };
670 : :
671 : 0 : INetMIMEMessage::INetMIMEMessage()
672 : : : INetRFC822Message (),
673 : : pParent (NULL),
674 [ # # ]: 0 : bHeaderParsed (sal_False)
675 : : {
676 [ # # ]: 0 : for (sal_uInt16 i = 0; i < INETMSG_MIME_NUMHDR; i++)
677 : 0 : m_nIndex[i] = CONTAINER_ENTRY_NOTFOUND;
678 : 0 : }
679 : :
680 : 0 : INetMIMEMessage::INetMIMEMessage (const INetMIMEMessage& rMsg)
681 [ # # ]: 0 : : INetRFC822Message (rMsg)
682 : : {
683 [ # # ]: 0 : CopyImp (rMsg);
684 : 0 : }
685 : :
686 : 0 : INetMIMEMessage& INetMIMEMessage::operator= (
687 : : const INetMIMEMessage& rMsg)
688 : : {
689 [ # # ]: 0 : if (this != &rMsg)
690 : : {
691 : : // Assign base.
692 : 0 : INetRFC822Message::operator= (rMsg);
693 : :
694 : 0 : CleanupImp();
695 : 0 : CopyImp (rMsg);
696 : : }
697 : 0 : return *this;
698 : : }
699 : :
700 : 0 : INetMIMEMessage::~INetMIMEMessage()
701 : : {
702 [ # # ]: 0 : CleanupImp();
703 [ # # ]: 0 : }
704 : :
705 : 0 : void INetMIMEMessage::CleanupImp()
706 : : {
707 [ # # ]: 0 : for( size_t i = 0, n = aChildren.size(); i < n; ++i ) {
708 [ # # ]: 0 : delete aChildren[ i ];
709 : : }
710 : 0 : aChildren.clear();
711 : 0 : }
712 : :
713 : 0 : void INetMIMEMessage::CopyImp (const INetMIMEMessage& rMsg)
714 : : {
715 : 0 : bHeaderParsed = rMsg.bHeaderParsed;
716 : :
717 : : size_t i;
718 [ # # ]: 0 : for (i = 0; i < INETMSG_MIME_NUMHDR; i++)
719 : 0 : m_nIndex[i] = rMsg.m_nIndex[i];
720 : :
721 : 0 : m_aBoundary = rMsg.m_aBoundary;
722 : :
723 [ # # ]: 0 : for (i = 0; i < rMsg.aChildren.size(); i++)
724 : : {
725 [ # # ]: 0 : INetMIMEMessage *pChild = rMsg.aChildren[ i ];
726 : :
727 [ # # ]: 0 : if (pChild->pParent == &rMsg)
728 : : {
729 [ # # ]: 0 : pChild = pChild->CreateMessage (*pChild);
730 : 0 : pChild->pParent = this;
731 : : }
732 [ # # ]: 0 : aChildren.push_back( pChild );
733 : : }
734 : 0 : }
735 : :
736 : 0 : INetMIMEMessage *INetMIMEMessage::CreateMessage (
737 : : const INetMIMEMessage& rMsg) const
738 : : {
739 [ # # ]: 0 : return (new INetMIMEMessage (rMsg));
740 : : }
741 : :
742 : : // Header Field Parser
743 : 0 : sal_uIntPtr INetMIMEMessage::SetHeaderField (
744 : : const INetMessageHeader &rHeader, sal_uIntPtr nNewIndex)
745 : : {
746 : 0 : rtl::OString aName (rHeader.GetName());
747 : 0 : const sal_Char *pData = aName.getStr();
748 : 0 : const sal_Char *pStop = pData + aName.getLength() + 1;
749 : 0 : const sal_Char *check = "";
750 : :
751 : 0 : sal_uIntPtr nIdx = LIST_APPEND;
752 : 0 : int eState = INETMSG_MIME_BEGIN;
753 : 0 : int eOkState = INETMSG_MIME_OK;
754 : :
755 [ # # ]: 0 : while (pData < pStop)
756 : : {
757 [ # # # # : 0 : switch (eState)
# # # ]
758 : : {
759 : : case INETMSG_MIME_BEGIN:
760 : 0 : eState = INETMSG_MIME_CHECK;
761 : 0 : eOkState = INETMSG_MIME_OK;
762 : :
763 [ # # # ]: 0 : switch (ascii_toLowerCase (*pData))
764 : : {
765 : : case 'c':
766 : 0 : check = "ontent-";
767 : 0 : eOkState = INETMSG_MIME_TOKEN_CONTENT;
768 : 0 : break;
769 : :
770 : : case 'm':
771 : 0 : check = "ime-version";
772 : 0 : nIdx = INETMSG_MIME_VERSION;
773 : 0 : break;
774 : :
775 : : default:
776 : 0 : eState = INETMSG_MIME_JUNK;
777 : 0 : break;
778 : : }
779 : 0 : pData++;
780 : 0 : break;
781 : :
782 : : case INETMSG_MIME_TOKEN_CONTENT:
783 : 0 : eState = INETMSG_MIME_CHECK;
784 : 0 : eOkState = INETMSG_MIME_OK;
785 : :
786 [ # # # # ]: 0 : switch (ascii_toLowerCase (*pData))
787 : : {
788 : : case 'd':
789 : 0 : eState = INETMSG_MIME_TOKEN_CONTENT_D;
790 : 0 : break;
791 : :
792 : : case 'i':
793 : 0 : check = "d";
794 : 0 : nIdx = INETMSG_MIME_CONTENT_ID;
795 : 0 : break;
796 : :
797 : : case 't':
798 : 0 : eState = INETMSG_MIME_TOKEN_CONTENT_T;
799 : 0 : break;
800 : :
801 : : default:
802 : 0 : eState = INETMSG_MIME_JUNK;
803 : 0 : break;
804 : : }
805 : 0 : pData++;
806 : 0 : break;
807 : :
808 : : case INETMSG_MIME_TOKEN_CONTENT_D:
809 : 0 : eState = INETMSG_MIME_CHECK;
810 : 0 : eOkState = INETMSG_MIME_OK;
811 : :
812 [ # # # ]: 0 : switch (ascii_toLowerCase (*pData))
813 : : {
814 : : case 'e':
815 : 0 : check = "scription";
816 : 0 : nIdx = INETMSG_MIME_CONTENT_DESCRIPTION;
817 : 0 : break;
818 : :
819 : : case 'i':
820 : 0 : check = "sposition";
821 : 0 : nIdx = INETMSG_MIME_CONTENT_DISPOSITION;
822 : 0 : break;
823 : :
824 : : default:
825 : 0 : eState = INETMSG_MIME_JUNK;
826 : 0 : break;
827 : : }
828 : 0 : pData++;
829 : 0 : break;
830 : :
831 : : case INETMSG_MIME_TOKEN_CONTENT_T:
832 : 0 : eState = INETMSG_MIME_CHECK;
833 : 0 : eOkState = INETMSG_MIME_OK;
834 : :
835 [ # # # ]: 0 : switch (ascii_toLowerCase (*pData))
836 : : {
837 : : case 'r':
838 : 0 : check = "ansfer-encoding";
839 : 0 : nIdx = INETMSG_MIME_CONTENT_TRANSFER_ENCODING;
840 : 0 : break;
841 : :
842 : : case 'y':
843 : 0 : check = "pe";
844 : 0 : nIdx = INETMSG_MIME_CONTENT_TYPE;
845 : 0 : break;
846 : :
847 : : default:
848 : 0 : eState = INETMSG_MIME_JUNK;
849 : 0 : break;
850 : : }
851 : 0 : pData++;
852 : 0 : break;
853 : :
854 : : case INETMSG_MIME_CHECK:
855 [ # # ]: 0 : if (*check)
856 : : {
857 [ # # ]: 0 : while (*pData && *check &&
[ # # # # ]
[ # # ]
858 : 0 : (ascii_toLowerCase (*pData) == *check))
859 : : {
860 : 0 : pData++;
861 : 0 : check++;
862 : : }
863 : : }
864 : : else
865 : : {
866 : 0 : check = pData;
867 : : }
868 [ # # ]: 0 : eState = (*check == '\0') ? eOkState : INETMSG_MIME_JUNK;
869 : 0 : break;
870 : :
871 : : case INETMSG_MIME_OK:
872 : 0 : pData = pStop;
873 : : SetHeaderField_Impl (
874 [ # # ]: 0 : INetMessageHeader (MIMEHDR(nIdx), rHeader.GetValue()),
875 [ # # ]: 0 : m_nIndex[nIdx]);
876 : 0 : nNewIndex = m_nIndex[nIdx];
877 : 0 : break;
878 : :
879 : : default: // INETMSG_MIME_JUNK
880 : 0 : pData = pStop;
881 : : nNewIndex = INetRFC822Message::SetHeaderField (
882 [ # # ]: 0 : rHeader, nNewIndex);
883 : 0 : break;
884 : : }
885 : : }
886 : 0 : return nNewIndex;
887 : : }
888 : :
889 : 0 : void INetMIMEMessage::SetMIMEVersion (const UniString& rVersion)
890 : : {
891 : : SetHeaderField_Impl (
892 : : INetMIME::HEADER_FIELD_TEXT,
893 [ # # ]: 0 : MIMEHDR(INETMSG_MIME_VERSION), rVersion,
894 [ # # ]: 0 : m_nIndex[INETMSG_MIME_VERSION]);
895 : 0 : }
896 : :
897 : 0 : void INetMIMEMessage::SetContentDisposition (const String& rDisposition)
898 : : {
899 : : SetHeaderField_Impl (
900 : : INetMIME::HEADER_FIELD_TEXT,
901 [ # # ]: 0 : MIMEHDR(INETMSG_MIME_CONTENT_DISPOSITION), rDisposition,
902 [ # # ]: 0 : m_nIndex[INETMSG_MIME_CONTENT_DISPOSITION]);
903 : 0 : }
904 : :
905 : 0 : void INetMIMEMessage::SetContentType (const String& rType)
906 : : {
907 : : SetHeaderField_Impl (
908 : : INetMIME::HEADER_FIELD_TEXT,
909 [ # # ]: 0 : MIMEHDR(INETMSG_MIME_CONTENT_TYPE), rType,
910 [ # # ]: 0 : m_nIndex[INETMSG_MIME_CONTENT_TYPE]);
911 : 0 : }
912 : :
913 : 0 : void INetMIMEMessage::SetContentTransferEncoding (
914 : : const rtl::OUString& rEncoding)
915 : : {
916 : : SetHeaderField_Impl (
917 : : INetMIME::HEADER_FIELD_TEXT,
918 : 0 : MIMEHDR(INETMSG_MIME_CONTENT_TRANSFER_ENCODING), rEncoding,
919 : 0 : m_nIndex[INETMSG_MIME_CONTENT_TRANSFER_ENCODING]);
920 : 0 : }
921 : :
922 : 0 : rtl::OUString INetMIMEMessage::GetDefaultContentType()
923 : : {
924 [ # # ]: 0 : if (pParent != NULL)
925 : : {
926 [ # # ][ # # ]: 0 : rtl::OUString aParentCT (pParent->GetContentType());
[ # # ]
927 [ # # ]: 0 : if (aParentCT.isEmpty())
928 [ # # ]: 0 : aParentCT = pParent->GetDefaultContentType();
929 : :
930 [ # # ]: 0 : if (aParentCT.equalsIgnoreAsciiCase("multipart/digest"))
931 [ # # ]: 0 : return rtl::OUString("message/rfc822");
932 : : }
933 : 0 : return rtl::OUString("text/plain; charset=us-ascii");
934 : : }
935 : :
936 : 0 : sal_Bool INetMIMEMessage::EnableAttachChild (INetMessageContainerType eType)
937 : : {
938 : : // Check context.
939 [ # # ][ # # ]: 0 : if (IsContainer())
940 : 0 : return sal_False;
941 : :
942 : : // Setup Content-Type header field.
943 : 0 : rtl::OStringBuffer aContentType;
944 [ # # # # : 0 : switch (eType)
# # # ]
945 : : {
946 : : case INETMSG_MESSAGE_RFC822:
947 [ # # ]: 0 : aContentType.append(RTL_CONSTASCII_STRINGPARAM("message/rfc822"));
948 : 0 : break;
949 : :
950 : : case INETMSG_MULTIPART_ALTERNATIVE:
951 [ # # ]: 0 : aContentType.append(RTL_CONSTASCII_STRINGPARAM("multipart/alternative"));
952 : 0 : break;
953 : :
954 : : case INETMSG_MULTIPART_DIGEST:
955 [ # # ]: 0 : aContentType.append(RTL_CONSTASCII_STRINGPARAM("multipart/digest"));
956 : 0 : break;
957 : :
958 : : case INETMSG_MULTIPART_PARALLEL:
959 [ # # ]: 0 : aContentType.append(RTL_CONSTASCII_STRINGPARAM("multipart/parallel"));
960 : 0 : break;
961 : :
962 : : case INETMSG_MULTIPART_RELATED:
963 [ # # ]: 0 : aContentType.append(RTL_CONSTASCII_STRINGPARAM("multipart/related"));
964 : 0 : break;
965 : :
966 : : case INETMSG_MULTIPART_FORM_DATA:
967 [ # # ]: 0 : aContentType.append(RTL_CONSTASCII_STRINGPARAM("multipart/form-data"));
968 : 0 : break;
969 : :
970 : : default:
971 [ # # ]: 0 : aContentType.append(RTL_CONSTASCII_STRINGPARAM("multipart/mixed"));
972 : 0 : break;
973 : : }
974 : :
975 : : // Setup boundary for multipart types.
976 [ # # ]: 0 : if (aContentType.toString().equalsIgnoreAsciiCaseL(RTL_CONSTASCII_STRINGPARAM("multipart/")))
977 : : {
978 : : // Generate a unique boundary from current time.
979 : : sal_Char sTail[16 + 1];
980 [ # # ]: 0 : Time aCurTime( Time::SYSTEM );
981 : 0 : sal_uInt64 nThis = reinterpret_cast< sal_uIntPtr >( this ); // we can be on a 64bit architecture
982 : 0 : nThis = ( ( nThis >> 32 ) ^ nThis ) & SAL_MAX_UINT32;
983 : : sprintf (sTail, "%08X%08X",
984 : 0 : static_cast< unsigned int >(aCurTime.GetTime()),
985 : 0 : static_cast< unsigned int >(nThis));
986 : 0 : m_aBoundary = "------------_4D48";
987 : 0 : m_aBoundary += sTail;
988 : :
989 : : // Append boundary as ContentType parameter.
990 [ # # ]: 0 : aContentType.append(RTL_CONSTASCII_STRINGPARAM("; boundary="));
991 [ # # ]: 0 : aContentType.append(m_aBoundary);
992 : : }
993 : :
994 : : // Set header fields.
995 [ # # ][ # # ]: 0 : SetMIMEVersion (String (CONSTASCII_STRINGPARAM("1.0")));
[ # # ]
996 [ # # ][ # # ]: 0 : SetContentType (rtl::OStringToOUString(aContentType.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US));
[ # # ][ # # ]
997 [ # # ][ # # ]: 0 : SetContentTransferEncoding (String (CONSTASCII_STRINGPARAM("7bit")));
[ # # ][ # # ]
998 : :
999 : : // Done.
1000 : 0 : return sal_True;
1001 : : }
1002 : :
1003 : 0 : sal_Bool INetMIMEMessage::AttachChild (
1004 : : INetMIMEMessage& rChildMsg, sal_Bool bOwner)
1005 : : {
1006 [ # # ]: 0 : if (IsContainer() /*&& rChildMsg.GetContentType().Len() */)
1007 : : {
1008 [ # # ]: 0 : if (bOwner) rChildMsg.pParent = this;
1009 [ # # ]: 0 : aChildren.push_back( &rChildMsg );
1010 : :
1011 : 0 : return sal_True;
1012 : : }
1013 : 0 : return sal_False;
1014 : : }
1015 : :
1016 : 0 : SvStream& INetMIMEMessage::operator<< (SvStream& rStrm) const
1017 : : {
1018 : 0 : INetRFC822Message::operator<< (rStrm);
1019 : :
1020 [ # # ]: 0 : for (sal_uInt16 i = 0; i < INETMSG_MIME_NUMHDR; i++)
1021 : 0 : rStrm << static_cast<sal_uInt32>(m_nIndex[i]);
1022 : :
1023 : 0 : write_lenPrefixed_uInt8s_FromOString<sal_uInt16>(rStrm, m_aBoundary);
1024 : 0 : rStrm << static_cast<sal_uInt32>(aChildren.size());
1025 : :
1026 : 0 : return rStrm;
1027 : : }
1028 : :
1029 : 0 : SvStream& INetMIMEMessage::operator>> (SvStream& rStrm)
1030 : : {
1031 [ # # ]: 0 : INetRFC822Message::operator>> (rStrm);
1032 : :
1033 : : sal_uInt32 nTemp;
1034 [ # # ]: 0 : for (sal_uInt16 i = 0; i < INETMSG_MIME_NUMHDR; i++)
1035 : : {
1036 [ # # ]: 0 : rStrm >> nTemp;
1037 : 0 : m_nIndex[i] = nTemp;
1038 : : }
1039 : :
1040 [ # # ]: 0 : m_aBoundary = read_lenPrefixed_uInt8s_ToOString<sal_uInt16>(rStrm);
1041 : :
1042 [ # # ]: 0 : rStrm >> nTemp;
1043 : :
1044 : 0 : return rStrm;
1045 : : }
1046 : :
1047 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|