1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_tools.hxx"
26 #include <sal/types.h>
27 #include <tools/datetime.hxx>
28 #ifndef _TOOLS_INETMIME_HXX
29 #include <tools/inetmime.hxx>
30 #endif
31 #include <tools/inetmsg.hxx>
32 #include <tools/inetstrm.hxx>
33 #include <rtl/instance.hxx>
34
35 #include <stdio.h>
36
37 //=======================================================================
38
ascii_isDigit(sal_Unicode ch)39 inline sal_Bool ascii_isDigit( sal_Unicode ch )
40 {
41 return ((ch >= 0x0030) && (ch <= 0x0039));
42 }
43
ascii_isLetter(sal_Unicode ch)44 inline sal_Bool ascii_isLetter( sal_Unicode ch )
45 {
46 return (( (ch >= 0x0041) && (ch <= 0x005A)) || ((ch >= 0x0061) && (ch <= 0x007A)));
47 }
48
ascii_toLowerCase(sal_Unicode ch)49 inline sal_Unicode ascii_toLowerCase( sal_Unicode ch )
50 {
51 if ( (ch >= 0x0041) && (ch <= 0x005A) )
52 return ch + 0x20;
53 else
54 return ch;
55 }
56
57 /*=======================================================================
58 *
59 * INetMessage Implementation.
60 *
61 *=====================================================================*/
62 #define CONSTASCII_STRINGPARAM(a) (a), RTL_TEXTENCODING_ASCII_US
63 #define HEADERFIELD INetMessageHeader
64
65 /*
66 * ~INetMessage.
67 */
~INetMessage(void)68 INetMessage::~INetMessage (void)
69 {
70 ListCleanup_Impl();
71 }
72
73 /*
74 * ListCleanup_Impl.
75 */
ListCleanup_Impl(void)76 void INetMessage::ListCleanup_Impl (void)
77 {
78 // Cleanup.
79 sal_uIntPtr i, n = m_aHeaderList.Count();
80 for (i = 0; i < n; i++)
81 delete ((HEADERFIELD*)(m_aHeaderList.GetObject(i)));
82 m_aHeaderList.Clear();
83 }
84
85 /*
86 * ListCopy.
87 */
ListCopy(const INetMessage & rMsg)88 void INetMessage::ListCopy (const INetMessage &rMsg)
89 {
90 if (!(this == &rMsg))
91 {
92 // Cleanup.
93 ListCleanup_Impl();
94
95 // Copy.
96 sal_uIntPtr i, n = rMsg.GetHeaderCount();
97 for (i = 0; i < n; i++)
98 {
99 HEADERFIELD *p = (HEADERFIELD*)(rMsg.m_aHeaderList.GetObject(i));
100 m_aHeaderList.Insert (new HEADERFIELD(*p), LIST_APPEND);
101 }
102 }
103 }
104
105 /*
106 * SetHeaderField_Impl.
107 */
SetHeaderField_Impl(INetMIME::HeaderFieldType eType,const ByteString & rName,const UniString & rValue,sal_uIntPtr & rnIndex)108 void INetMessage::SetHeaderField_Impl (
109 INetMIME::HeaderFieldType eType,
110 const ByteString &rName,
111 const UniString &rValue,
112 sal_uIntPtr &rnIndex)
113 {
114 INetMIMEStringOutputSink aSink (0, STRING_MAXLEN);
115 INetMIME::writeHeaderFieldBody (
116 aSink, eType, rValue, gsl_getSystemTextEncoding(), false);
117 SetHeaderField_Impl (
118 INetMessageHeader (rName, aSink.takeBuffer()), rnIndex);
119 }
120
121 /*
122 * SetHeaderField.
123 */
SetHeaderField(const UniString & rName,const UniString & rValue,sal_uIntPtr nIndex)124 sal_uIntPtr INetMessage::SetHeaderField (
125 const UniString& rName, const UniString& rValue, sal_uIntPtr nIndex)
126 {
127 sal_uIntPtr nResult = nIndex;
128 SetHeaderField_Impl (
129 INetMIME::HEADER_FIELD_TEXT,
130 ByteString (rName, RTL_TEXTENCODING_ASCII_US), rValue,
131 nResult);
132 return nResult;
133 }
134
135 /*
136 * SetHeaderField.
137 */
SetHeaderField(const INetMessageHeader & rHeader,sal_uIntPtr nIndex)138 sal_uIntPtr INetMessage::SetHeaderField (
139 const INetMessageHeader &rHeader, sal_uIntPtr nIndex)
140 {
141 sal_uIntPtr nResult = nIndex;
142 SetHeaderField_Impl (rHeader, nResult);
143 return nResult;
144 }
145
146
147 /*
148 * operator<<
149 */
operator <<(SvStream & rStrm) const150 SvStream& INetMessage::operator<< (SvStream& rStrm) const
151 {
152 rStrm << static_cast<sal_uInt32>(m_nDocSize);
153 rStrm.WriteByteString (m_aDocName, RTL_TEXTENCODING_UTF8);
154
155 sal_uIntPtr i, n = m_aHeaderList.Count();
156 rStrm << static_cast<sal_uInt32>(n);
157
158 for (i = 0; i < n; i++)
159 rStrm << *((HEADERFIELD *)(m_aHeaderList.GetObject(i)));
160
161 return rStrm;
162 }
163
164 /*
165 * operator>>
166 */
operator >>(SvStream & rStrm)167 SvStream& INetMessage::operator>> (SvStream& rStrm)
168 {
169 // Cleanup.
170 m_nDocSize = 0;
171 m_xDocLB.Clear();
172 ListCleanup_Impl();
173
174 sal_uInt32 nTemp;
175
176 // Copy.
177 rStrm >> nTemp;
178 m_nDocSize = nTemp;
179 rStrm.ReadByteString (m_aDocName, RTL_TEXTENCODING_UTF8);
180
181 sal_uIntPtr i, n = 0;
182 rStrm >> nTemp;
183 n = nTemp;
184
185 for (i = 0; i < n; i++)
186 {
187 HEADERFIELD *p = new HEADERFIELD();
188 rStrm >> *p;
189 m_aHeaderList.Insert (p, LIST_APPEND);
190 }
191
192 // Done.
193 return rStrm;
194 }
195
196 /*=======================================================================
197 *
198 * INetMessageHeaderIterator Implementation.
199 *
200 *=====================================================================*/
INetMessageHeaderIterator(const INetMessage & rMsg,const UniString & rHdrName)201 INetMessageHeaderIterator::INetMessageHeaderIterator (
202 const INetMessage& rMsg, const UniString& rHdrName)
203 {
204 sal_uIntPtr i, n = rMsg.GetHeaderCount();
205 for (i = 0; i < n; i++)
206 {
207 if (rHdrName.CompareIgnoreCaseToAscii (rMsg.GetHeaderName(i)) == 0)
208 {
209 UniString *pValue = new UniString (rMsg.GetHeaderValue(i));
210 aValueList.Insert (pValue, LIST_APPEND);
211 }
212 }
213 nValueCount = aValueList.Count();
214 }
215
~INetMessageHeaderIterator(void)216 INetMessageHeaderIterator::~INetMessageHeaderIterator (void)
217 {
218 sal_uIntPtr i, n = aValueList.Count();
219 for (i = 0; i < n; i++)
220 delete ((UniString*)(aValueList.GetObject(i)));
221 aValueList.Clear();
222 }
223
224 /*=======================================================================
225 *
226 * INetRFC822Message Implementation.
227 *
228 *=====================================================================*/
229 /*
230 * ImplINetRFC822MessageHeaderData.
231 */
232 namespace
233 {
234 struct ImplINetRFC822MessageHeaderDataImpl
235 {
operator ()__anonfd4a8d360111::ImplINetRFC822MessageHeaderDataImpl236 const ByteString* operator()()
237 {
238 static const ByteString _ImplINetRFC822MessageHeaderData[] =
239 {
240 ByteString ("BCC"),
241 ByteString ("CC"),
242 ByteString ("Comments"),
243 ByteString ("Date"),
244 ByteString ("From"),
245 ByteString ("In-Reply-To"),
246 ByteString ("Keywords"),
247 ByteString ("Message-ID"),
248 ByteString ("References"),
249 ByteString ("Reply-To"),
250 ByteString ("Return-Path"),
251 ByteString ("Subject"),
252 ByteString ("Sender"),
253 ByteString ("To"),
254 ByteString ("X-Mailer"),
255 ByteString ("Return-Receipt-To")
256 };
257 return &_ImplINetRFC822MessageHeaderData[0];
258 }
259 };
260
261 struct ImplINetRFC822MessageHeaderData
262 : public rtl::StaticAggregate< const ByteString, ImplINetRFC822MessageHeaderDataImpl > {};
263 }
264
265 #define HDR(n) ImplINetRFC822MessageHeaderData::get()[(n)]
266
267 /*
268 * _ImplINetRFC822MessageHeaderState.
269 */
270 enum _ImplINetRFC822MessageHeaderState
271 {
272 INETMSG_RFC822_BEGIN,
273 INETMSG_RFC822_CHECK,
274 INETMSG_RFC822_OK,
275 INETMSG_RFC822_JUNK,
276
277 INETMSG_RFC822_TOKEN_RE,
278 INETMSG_RFC822_TOKEN_RETURNMINUS,
279 INETMSG_RFC822_TOKEN_XMINUS,
280 INETMSG_RFC822_LETTER_C,
281 INETMSG_RFC822_LETTER_S
282 };
283
284 /*
285 * INetRFC822Message.
286 */
INetRFC822Message(void)287 INetRFC822Message::INetRFC822Message (void)
288 : INetMessage()
289 {
290 for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++)
291 m_nIndex[i] = LIST_ENTRY_NOTFOUND;
292 }
293
INetRFC822Message(const INetRFC822Message & rMsg)294 INetRFC822Message::INetRFC822Message (const INetRFC822Message& rMsg)
295 : INetMessage (rMsg)
296 {
297 for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++)
298 m_nIndex[i] = rMsg.m_nIndex[i];
299 }
300
301 /*
302 * operator=
303 */
operator =(const INetRFC822Message & rMsg)304 INetRFC822Message& INetRFC822Message::operator= (const INetRFC822Message& rMsg)
305 {
306 if (this != &rMsg)
307 {
308 INetMessage::operator= (rMsg);
309
310 for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++)
311 m_nIndex[i] = rMsg.m_nIndex[i];
312 }
313 return *this;
314 }
315
316 /*
317 * ~INetRFC822Message.
318 */
~INetRFC822Message(void)319 INetRFC822Message::~INetRFC822Message (void)
320 {
321 }
322
323 /*
324 * <Generate|Parse>DateField and local helper functions.
325 *
326 * GenerateDateField.
327 * Generates a String from Date and Time objects in format:
328 * Wkd, 00 Mon 0000 00:00:00 [GMT] (rfc822, rfc1123)
329 *
330 * ParseDateField.
331 * Parses a String in (implied) GMT format into class Date and Time objects.
332 * Four formats are accepted:
333 *
334 * [Wkd,] 1*2DIGIT Mon 2*4DIGIT 00:00:00 [GMT] (rfc1123)
335 * [Wkd,] 00 Mon 0000 00:00:00 [GMT]) (rfc822, rfc1123)
336 * Weekday, 00-Mon-00 00:00:00 [GMT] (rfc850, rfc1036)
337 * Wkd Mon 00 00:00:00 0000 [GMT] (ctime)
338 * 1*DIGIT (delta seconds)
339 *
340 */
341
342 // Months and Weekdays.
343 static const sal_Char *months[12] =
344 {
345 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
346 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
347 };
348
349 static const sal_Char *wkdays[7] =
350 {
351 "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
352 };
353
354 /*
355 * GenerateDateField.
356 */
GenerateDateField(const DateTime & rDateTime,UniString & rDateFieldW)357 sal_Bool INetRFC822Message::GenerateDateField (
358 const DateTime& rDateTime, UniString& rDateFieldW)
359 {
360 // Check arguments.
361 if (!rDateTime.IsValid() ||
362 (rDateTime.GetSec() > 59) ||
363 (rDateTime.GetMin() > 59) ||
364 (rDateTime.GetHour() > 23) ) return sal_False;
365
366 // Prepare output string.
367 ByteString rDateField;
368
369 // Insert Date.
370 rDateField += wkdays[(sal_uInt16)(rDateTime.GetDayOfWeek())];
371 rDateField += ", ";
372
373 sal_uInt16 nNum = rDateTime.GetDay();
374 if (nNum < 10) rDateField += '0';
375 rDateField += ByteString::CreateFromInt32(nNum);
376 rDateField += ' ';
377
378 rDateField += months[(sal_uInt16)(rDateTime.GetMonth() - 1)];
379 rDateField += ' ';
380
381 rDateField += ByteString::CreateFromInt32(rDateTime.GetYear());
382 rDateField += ' ';
383
384 // Insert Time.
385 nNum = rDateTime.GetHour();
386 if (nNum < 10) rDateField += '0';
387 rDateField += ByteString::CreateFromInt32(nNum);
388 rDateField += ':';
389
390 nNum = rDateTime.GetMin();
391 if (nNum < 10) rDateField += '0';
392 rDateField += ByteString::CreateFromInt32(nNum);
393 rDateField += ':';
394
395 nNum = rDateTime.GetSec();
396 if (nNum < 10) rDateField += '0';
397 rDateField += ByteString::CreateFromInt32(nNum);
398 rDateField += " GMT";
399
400 // Done.
401 rDateFieldW = UniString (rDateField, RTL_TEXTENCODING_ASCII_US);
402 return sal_True;
403 }
404
405 /*
406 * ParseDateField and local helper functions.
407 */
ParseNumber(const ByteString & rStr,sal_uInt16 & nIndex)408 static sal_uInt16 ParseNumber (const ByteString& rStr, sal_uInt16& nIndex)
409 {
410 sal_uInt16 n = nIndex;
411 while ((n < rStr.Len()) && ascii_isDigit(rStr.GetChar(n))) n++;
412
413 ByteString aNum (rStr.Copy (nIndex, (n - nIndex)));
414 nIndex = n;
415
416 return (sal_uInt16)(aNum.ToInt32());
417 }
418
ParseMonth(const ByteString & rStr,sal_uInt16 & nIndex)419 static sal_uInt16 ParseMonth (const ByteString& rStr, sal_uInt16& nIndex)
420 {
421 sal_uInt16 n = nIndex;
422 while ((n < rStr.Len()) && ascii_isLetter(rStr.GetChar(n))) n++;
423
424 ByteString aMonth (rStr.Copy (nIndex, 3));
425 nIndex = n;
426
427 sal_uInt16 i;
428 for (i = 0; i < 12; i++)
429 if (aMonth.CompareIgnoreCaseToAscii (months[i]) == 0) break;
430 return (i + 1);
431 }
432
ParseDateField(const UniString & rDateFieldW,DateTime & rDateTime)433 sal_Bool INetRFC822Message::ParseDateField (
434 const UniString& rDateFieldW, DateTime& rDateTime)
435 {
436 ByteString rDateField (rDateFieldW, RTL_TEXTENCODING_ASCII_US);
437 if (rDateField.Len() == 0) return sal_False;
438
439 if (rDateField.Search (':') != STRING_NOTFOUND)
440 {
441 // Some DateTime format.
442 sal_uInt16 nIndex = 0;
443
444 // Skip over <Wkd> or <Weekday>, leading and trailing space.
445 while ((nIndex < rDateField.Len()) &&
446 (rDateField.GetChar(nIndex) == ' '))
447 nIndex++;
448
449 while (
450 (nIndex < rDateField.Len()) &&
451 (ascii_isLetter (rDateField.GetChar(nIndex)) ||
452 (rDateField.GetChar(nIndex) == ',') ))
453 nIndex++;
454
455 while ((nIndex < rDateField.Len()) &&
456 (rDateField.GetChar(nIndex) == ' '))
457 nIndex++;
458
459 if (ascii_isLetter (rDateField.GetChar(nIndex)))
460 {
461 // Format: ctime().
462 if ((rDateField.Len() - nIndex) < 20) return sal_False;
463
464 rDateTime.SetMonth (ParseMonth (rDateField, nIndex)); nIndex++;
465 rDateTime.SetDay (ParseNumber (rDateField, nIndex)); nIndex++;
466
467 rDateTime.SetHour (ParseNumber (rDateField, nIndex)); nIndex++;
468 rDateTime.SetMin (ParseNumber (rDateField, nIndex)); nIndex++;
469 rDateTime.SetSec (ParseNumber (rDateField, nIndex)); nIndex++;
470 rDateTime.Set100Sec (0);
471
472 sal_uInt16 nYear = ParseNumber (rDateField, nIndex);
473 if (nYear < 100) nYear += 1900;
474 rDateTime.SetYear (nYear);
475 }
476 else
477 {
478 // Format: RFC1036 or RFC1123.
479 if ((rDateField.Len() - nIndex) < 17) return sal_False;
480
481 rDateTime.SetDay (ParseNumber (rDateField, nIndex)); nIndex++;
482 rDateTime.SetMonth (ParseMonth (rDateField, nIndex)); nIndex++;
483
484 sal_uInt16 nYear = ParseNumber (rDateField, nIndex); nIndex++;
485 if (nYear < 100) nYear += 1900;
486 rDateTime.SetYear (nYear);
487
488 rDateTime.SetHour (ParseNumber (rDateField, nIndex)); nIndex++;
489 rDateTime.SetMin (ParseNumber (rDateField, nIndex)); nIndex++;
490 rDateTime.SetSec (ParseNumber (rDateField, nIndex)); nIndex++;
491 rDateTime.Set100Sec (0);
492
493 if ((rDateField.GetChar(nIndex) == '+') ||
494 (rDateField.GetChar(nIndex) == '-') )
495 {
496 // Offset from GMT: "(+|-)HHMM".
497 sal_Bool bEast = (rDateField.GetChar(nIndex++) == '+');
498 sal_uInt16 nOffset = ParseNumber (rDateField, nIndex);
499 if (nOffset > 0)
500 {
501 Time aDiff;
502 aDiff.SetHour (nOffset / 100);
503 aDiff.SetMin (nOffset % 100);
504 aDiff.SetSec (0);
505 aDiff.Set100Sec (0);
506
507 if (bEast)
508 rDateTime -= aDiff;
509 else
510 rDateTime += aDiff;
511 }
512 }
513 }
514 }
515 else if (rDateField.IsNumericAscii())
516 {
517 // Format: delta seconds.
518 Time aDelta (0);
519 aDelta.SetTime (rDateField.ToInt32() * 100);
520
521 DateTime aNow;
522 aNow += aDelta;
523 aNow.ConvertToUTC();
524
525 rDateTime.SetDate (aNow.GetDate());
526 rDateTime.SetTime (aNow.GetTime());
527 }
528 else
529 {
530 // Junk.
531 return sal_False;
532 }
533
534 return (rDateTime.IsValid() &&
535 !((rDateTime.GetSec() > 59) ||
536 (rDateTime.GetMin() > 59) ||
537 (rDateTime.GetHour() > 23) ));
538 }
539
540 /*
541 * SetHeaderField.
542 * (Header Field Parser).
543 */
SetHeaderField(const INetMessageHeader & rHeader,sal_uIntPtr nNewIndex)544 sal_uIntPtr INetRFC822Message::SetHeaderField (
545 const INetMessageHeader &rHeader, sal_uIntPtr nNewIndex)
546 {
547 ByteString aName (rHeader.GetName());
548 const sal_Char *pData = aName.GetBuffer();
549 const sal_Char *pStop = pData + aName.Len() + 1;
550 const sal_Char *check = "";
551
552 sal_uIntPtr nIdx = LIST_APPEND;
553 int eState = INETMSG_RFC822_BEGIN;
554 int eOkState = INETMSG_RFC822_OK;
555
556 while (pData < pStop)
557 {
558 switch (eState)
559 {
560 case INETMSG_RFC822_BEGIN:
561 eState = INETMSG_RFC822_CHECK;
562 eOkState = INETMSG_RFC822_OK;
563
564 switch (ascii_toLowerCase (*pData))
565 {
566 case 'b':
567 check = "cc";
568 nIdx = INETMSG_RFC822_BCC;
569 break;
570
571 case 'c':
572 eState = INETMSG_RFC822_LETTER_C;
573 break;
574
575 case 'd':
576 check = "ate";
577 nIdx = INETMSG_RFC822_DATE;
578 break;
579
580 case 'f':
581 check = "rom";
582 nIdx = INETMSG_RFC822_FROM;
583 break;
584
585 case 'i':
586 check = "n-reply-to";
587 nIdx = INETMSG_RFC822_IN_REPLY_TO;
588 break;
589
590 case 'k':
591 check = "eywords";
592 nIdx = INETMSG_RFC822_KEYWORDS;
593 break;
594
595 case 'm':
596 check = "essage-id";
597 nIdx = INETMSG_RFC822_MESSAGE_ID;
598 break;
599
600 case 'r':
601 check = "e";
602 eOkState = INETMSG_RFC822_TOKEN_RE;
603 break;
604
605 case 's':
606 eState = INETMSG_RFC822_LETTER_S;
607 break;
608
609 case 't':
610 check = "o";
611 nIdx = INETMSG_RFC822_TO;
612 break;
613
614 case 'x':
615 check = "-";
616 eOkState = INETMSG_RFC822_TOKEN_XMINUS;
617 break;
618
619 default:
620 eState = INETMSG_RFC822_JUNK;
621 break;
622 }
623 pData++;
624 break;
625
626 case INETMSG_RFC822_TOKEN_RE:
627 eState = INETMSG_RFC822_CHECK;
628 eOkState = INETMSG_RFC822_OK;
629
630 switch (ascii_toLowerCase (*pData))
631 {
632 case 'f':
633 check = "erences";
634 nIdx = INETMSG_RFC822_REFERENCES;
635 break;
636
637 case 'p':
638 check = "ly-to";
639 nIdx = INETMSG_RFC822_REPLY_TO;
640 break;
641
642 case 't':
643 check = "urn-";
644 eOkState = INETMSG_RFC822_TOKEN_RETURNMINUS;
645 break;
646
647 default:
648 eState = INETMSG_RFC822_JUNK;
649 break;
650 }
651 pData++;
652 break;
653
654 case INETMSG_RFC822_TOKEN_RETURNMINUS:
655 eState = INETMSG_RFC822_CHECK;
656 eOkState = INETMSG_RFC822_OK;
657
658 switch (ascii_toLowerCase (*pData))
659 {
660 case 'p':
661 check = "ath";
662 nIdx = INETMSG_RFC822_RETURN_PATH;
663 break;
664
665 case 'r':
666 check = "eceipt-to";
667 nIdx = INETMSG_RFC822_RETURN_RECEIPT_TO;
668 break;
669
670 default:
671 eState = INETMSG_RFC822_JUNK;
672 break;
673 }
674 pData++;
675 break;
676
677 case INETMSG_RFC822_TOKEN_XMINUS:
678 eState = INETMSG_RFC822_CHECK;
679 eOkState = INETMSG_RFC822_OK;
680
681 switch (ascii_toLowerCase (*pData))
682 {
683 case 'm':
684 check = "ailer";
685 nIdx = INETMSG_RFC822_X_MAILER;
686 break;
687
688 #if 0 /* NYI */
689 case 'p':
690 check = "riority";
691 eOkState = INETMSG_RFC822_X_PRIORITY;
692 break;
693 #endif /* NYI */
694
695 default:
696 eState = INETMSG_RFC822_JUNK;
697 break;
698 }
699 pData++;
700 break;
701
702 case INETMSG_RFC822_LETTER_C:
703 eState = INETMSG_RFC822_CHECK;
704 eOkState = INETMSG_RFC822_OK;
705
706 switch (ascii_toLowerCase (*pData))
707 {
708 case 'c':
709 check = "";
710 nIdx = INETMSG_RFC822_CC;
711 break;
712
713 case 'o':
714 check = "mments";
715 nIdx = INETMSG_RFC822_COMMENTS;
716 break;
717
718 default:
719 eState = INETMSG_RFC822_JUNK;
720 break;
721 }
722 pData++;
723 break;
724
725 case INETMSG_RFC822_LETTER_S:
726 eState = INETMSG_RFC822_CHECK;
727 eOkState = INETMSG_RFC822_OK;
728
729 switch (ascii_toLowerCase (*pData))
730 {
731 case 'e':
732 check = "nder";
733 nIdx = INETMSG_RFC822_SENDER;
734 break;
735
736 case 'u':
737 check = "bject";
738 nIdx = INETMSG_RFC822_SUBJECT;
739 break;
740
741 default:
742 eState = INETMSG_RFC822_JUNK;
743 break;
744 }
745 pData++;
746 break;
747
748 case INETMSG_RFC822_CHECK:
749 if (*check)
750 {
751 while (*pData && *check &&
752 (ascii_toLowerCase (*pData) == *check))
753 {
754 pData++;
755 check++;
756 }
757 }
758 else
759 {
760 check = pData;
761 }
762 eState = (*check == '\0') ? eOkState : INETMSG_RFC822_JUNK;
763 break;
764
765 case INETMSG_RFC822_OK:
766 pData = pStop;
767 SetHeaderField_Impl (
768 HEADERFIELD (HDR(nIdx), rHeader.GetValue()),
769 m_nIndex[nIdx]);
770 nNewIndex = m_nIndex[nIdx];
771 break;
772
773 default: // INETMSG_RFC822_JUNK
774 pData = pStop;
775 nNewIndex = INetMessage::SetHeaderField (rHeader, nNewIndex);
776 break;
777 }
778 }
779 return nNewIndex;
780 }
781
782 /*
783 * Specific Set-Methods.
784 */
SetBCC(const UniString & rBCC)785 void INetRFC822Message::SetBCC (const UniString& rBCC)
786 {
787 SetHeaderField_Impl (
788 INetMIME::HEADER_FIELD_ADDRESS,
789 HDR(INETMSG_RFC822_BCC), rBCC,
790 m_nIndex[INETMSG_RFC822_BCC]);
791 }
792
SetCC(const UniString & rCC)793 void INetRFC822Message::SetCC (const UniString& rCC)
794 {
795 SetHeaderField_Impl (
796 INetMIME::HEADER_FIELD_ADDRESS,
797 HDR(INETMSG_RFC822_CC), rCC,
798 m_nIndex[INETMSG_RFC822_CC]);
799 }
800
SetComments(const UniString & rComments)801 void INetRFC822Message::SetComments (const UniString& rComments)
802 {
803 SetHeaderField_Impl (
804 INetMIME::HEADER_FIELD_TEXT,
805 HDR(INETMSG_RFC822_COMMENTS), rComments,
806 m_nIndex[INETMSG_RFC822_COMMENTS]);
807 }
808
SetDate(const UniString & rDate)809 void INetRFC822Message::SetDate (const UniString& rDate)
810 {
811 SetHeaderField_Impl (
812 INetMIME::HEADER_FIELD_STRUCTURED,
813 HDR(INETMSG_RFC822_DATE), rDate,
814 m_nIndex[INETMSG_RFC822_DATE]);
815 }
816
SetFrom(const UniString & rFrom)817 void INetRFC822Message::SetFrom (const UniString& rFrom)
818 {
819 SetHeaderField_Impl (
820 INetMIME::HEADER_FIELD_ADDRESS,
821 HDR(INETMSG_RFC822_FROM), rFrom,
822 m_nIndex[INETMSG_RFC822_FROM]);
823 }
824
SetInReplyTo(const UniString & rInReplyTo)825 void INetRFC822Message::SetInReplyTo (const UniString& rInReplyTo)
826 {
827 SetHeaderField_Impl (
828 INetMIME::HEADER_FIELD_ADDRESS, // ??? MESSAGE_ID ???
829 HDR(INETMSG_RFC822_IN_REPLY_TO), rInReplyTo,
830 m_nIndex[INETMSG_RFC822_IN_REPLY_TO]);
831 }
832
SetKeywords(const UniString & rKeywords)833 void INetRFC822Message::SetKeywords (const UniString& rKeywords)
834 {
835 SetHeaderField_Impl (
836 INetMIME::HEADER_FIELD_PHRASE,
837 HDR(INETMSG_RFC822_KEYWORDS), rKeywords,
838 m_nIndex[INETMSG_RFC822_KEYWORDS]);
839 }
840
SetMessageID(const UniString & rMessageID)841 void INetRFC822Message::SetMessageID (const UniString& rMessageID)
842 {
843 SetHeaderField_Impl (
844 INetMIME::HEADER_FIELD_MESSAGE_ID,
845 HDR(INETMSG_RFC822_MESSAGE_ID), rMessageID,
846 m_nIndex[INETMSG_RFC822_MESSAGE_ID]);
847 }
848
SetReferences(const UniString & rReferences)849 void INetRFC822Message::SetReferences (const UniString& rReferences)
850 {
851 SetHeaderField_Impl (
852 INetMIME::HEADER_FIELD_MESSAGE_ID,
853 HDR(INETMSG_RFC822_REFERENCES), rReferences,
854 m_nIndex[INETMSG_RFC822_REFERENCES]);
855 }
856
SetReplyTo(const UniString & rReplyTo)857 void INetRFC822Message::SetReplyTo (const UniString& rReplyTo)
858 {
859 SetHeaderField_Impl (
860 INetMIME::HEADER_FIELD_ADDRESS,
861 HDR(INETMSG_RFC822_REPLY_TO), rReplyTo,
862 m_nIndex[INETMSG_RFC822_REPLY_TO]);
863 }
864
SetReturnPath(const UniString & rReturnPath)865 void INetRFC822Message::SetReturnPath (const UniString& rReturnPath)
866 {
867 SetHeaderField_Impl (
868 INetMIME::HEADER_FIELD_ADDRESS,
869 HDR(INETMSG_RFC822_RETURN_PATH), rReturnPath,
870 m_nIndex[INETMSG_RFC822_RETURN_PATH]);
871 }
872
SetReturnReceiptTo(const UniString & rValue)873 void INetRFC822Message::SetReturnReceiptTo (const UniString& rValue)
874 {
875 SetHeaderField_Impl (
876 INetMIME::HEADER_FIELD_ADDRESS,
877 HDR(INETMSG_RFC822_RETURN_RECEIPT_TO), rValue,
878 m_nIndex[INETMSG_RFC822_RETURN_RECEIPT_TO]);
879 }
880
SetSender(const UniString & rSender)881 void INetRFC822Message::SetSender (const UniString& rSender)
882 {
883 SetHeaderField_Impl (
884 INetMIME::HEADER_FIELD_ADDRESS,
885 HDR(INETMSG_RFC822_SENDER), rSender,
886 m_nIndex[INETMSG_RFC822_SENDER]);
887 }
888
SetSubject(const UniString & rSubject)889 void INetRFC822Message::SetSubject (const UniString& rSubject)
890 {
891 SetHeaderField_Impl (
892 INetMIME::HEADER_FIELD_TEXT,
893 HDR(INETMSG_RFC822_SUBJECT), rSubject,
894 m_nIndex[INETMSG_RFC822_SUBJECT]);
895 }
896
SetTo(const UniString & rTo)897 void INetRFC822Message::SetTo (const UniString& rTo)
898 {
899 SetHeaderField_Impl (
900 INetMIME::HEADER_FIELD_ADDRESS,
901 HDR(INETMSG_RFC822_TO), rTo,
902 m_nIndex[INETMSG_RFC822_TO]);
903 }
904
SetXMailer(const UniString & rXMailer)905 void INetRFC822Message::SetXMailer (const UniString& rXMailer)
906 {
907 SetHeaderField_Impl (
908 INetMIME::HEADER_FIELD_TEXT,
909 HDR(INETMSG_RFC822_X_MAILER), rXMailer,
910 m_nIndex[INETMSG_RFC822_X_MAILER]);
911 }
912
913 /*
914 * operator<<
915 */
operator <<(SvStream & rStrm) const916 SvStream& INetRFC822Message::operator<< (SvStream& rStrm) const
917 {
918 INetMessage::operator<< (rStrm);
919
920 for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++)
921 rStrm << static_cast<sal_uInt32>(m_nIndex[i]);
922
923 return rStrm;
924 }
925
926 /*
927 * operator>>
928 */
operator >>(SvStream & rStrm)929 SvStream& INetRFC822Message::operator>> (SvStream& rStrm)
930 {
931 INetMessage::operator>> (rStrm);
932
933 sal_uInt32 nTemp;
934 for (sal_uInt16 i = 0; i < INETMSG_RFC822_NUMHDR; i++)
935 {
936 rStrm >> nTemp;
937 m_nIndex[i] = nTemp;
938 }
939
940 return rStrm;
941 }
942
943 /*=======================================================================
944 *
945 * INetMIMEMessage Implementation.
946 *
947 *=====================================================================*/
948 /*
949 * _ImplINetMIMEMessageHeaderData.
950 */
951 namespace
952 {
953 struct ImplINetMIMEMessageHeaderDataImpl
954 {
operator ()__anonfd4a8d360211::ImplINetMIMEMessageHeaderDataImpl955 const ByteString* operator()()
956 {
957 static const ByteString _ImplINetMIMEMessageHeaderData[] =
958 {
959 ByteString ("MIME-Version"),
960 ByteString ("Content-Description"),
961 ByteString ("Content-Disposition"),
962 ByteString ("Content-ID"),
963 ByteString ("Content-Type"),
964 ByteString ("Content-Transfer-Encoding")
965 };
966 return &_ImplINetMIMEMessageHeaderData[0];
967 }
968 };
969
970 struct ImplINetMIMEMessageHeaderData
971 : public rtl::StaticAggregate< const ByteString, ImplINetMIMEMessageHeaderDataImpl > {};
972 }
973
974 #define MIMEHDR(n) ImplINetMIMEMessageHeaderData::get()[(n)]
975
976 /*
977 * _ImplINetMIMEMessageHeaderState.
978 */
979 enum _ImplINetMIMEMessageHeaderState
980 {
981 INETMSG_MIME_BEGIN,
982 INETMSG_MIME_CHECK,
983 INETMSG_MIME_OK,
984 INETMSG_MIME_JUNK,
985
986 INETMSG_MIME_TOKEN_CONTENT,
987 INETMSG_MIME_TOKEN_CONTENT_D,
988 INETMSG_MIME_TOKEN_CONTENT_T
989 };
990
991 /*
992 * INetMIMEMessage.
993 */
INetMIMEMessage(void)994 INetMIMEMessage::INetMIMEMessage (void)
995 : INetRFC822Message (),
996 pParent (NULL),
997 nNumChildren (0),
998 bHeaderParsed (sal_False)
999 {
1000 for (sal_uInt16 i = 0; i < INETMSG_MIME_NUMHDR; i++)
1001 m_nIndex[i] = LIST_ENTRY_NOTFOUND;
1002 }
1003
INetMIMEMessage(const INetMIMEMessage & rMsg)1004 INetMIMEMessage::INetMIMEMessage (const INetMIMEMessage& rMsg)
1005 : INetRFC822Message (rMsg)
1006 {
1007 // Copy.
1008 CopyImp (rMsg);
1009 }
1010
1011 /*
1012 * operator=
1013 */
operator =(const INetMIMEMessage & rMsg)1014 INetMIMEMessage& INetMIMEMessage::operator= (
1015 const INetMIMEMessage& rMsg)
1016 {
1017 if (this != &rMsg)
1018 {
1019 // Assign base.
1020 INetRFC822Message::operator= (rMsg);
1021
1022 // Cleanup.
1023 CleanupImp();
1024
1025 // Copy.
1026 CopyImp (rMsg);
1027 }
1028 return *this;
1029 }
1030
1031 /*
1032 * ~INetMIMEMessage.
1033 */
~INetMIMEMessage(void)1034 INetMIMEMessage::~INetMIMEMessage (void)
1035 {
1036 // Cleanup.
1037 CleanupImp();
1038 }
1039
1040 /*
1041 * CleanupImp.
1042 */
CleanupImp(void)1043 void INetMIMEMessage::CleanupImp (void)
1044 {
1045 INetMIMEMessage *pChild = NULL;
1046 while ((pChild = (INetMIMEMessage *)(aChildren.Remove())) != NULL)
1047 if (pChild->pParent == this) delete pChild;
1048 }
1049
1050 /*
1051 * CopyImp.
1052 */
CopyImp(const INetMIMEMessage & rMsg)1053 void INetMIMEMessage::CopyImp (const INetMIMEMessage& rMsg)
1054 {
1055 bHeaderParsed = rMsg.bHeaderParsed;
1056
1057 sal_uInt16 i;
1058 for (i = 0; i < INETMSG_MIME_NUMHDR; i++)
1059 m_nIndex[i] = rMsg.m_nIndex[i];
1060
1061 m_aBoundary = rMsg.m_aBoundary;
1062 nNumChildren = rMsg.nNumChildren;
1063
1064 for (i = 0; i < rMsg.aChildren.Count(); i++)
1065 {
1066 INetMIMEMessage *pChild =
1067 (INetMIMEMessage *)(rMsg.aChildren.GetObject (i));
1068
1069 if (pChild->pParent == &rMsg)
1070 {
1071 pChild = pChild->CreateMessage (*pChild);
1072 pChild->pParent = this;
1073 }
1074 aChildren.Insert (pChild, LIST_APPEND);
1075 }
1076 }
1077
1078 /*
1079 * CreateMessage.
1080 */
CreateMessage(const INetMIMEMessage & rMsg) const1081 INetMIMEMessage *INetMIMEMessage::CreateMessage (
1082 const INetMIMEMessage& rMsg) const
1083 {
1084 return (new INetMIMEMessage (rMsg));
1085 }
1086
1087 /*
1088 * SetHeaderField.
1089 * (Header Field Parser).
1090 */
SetHeaderField(const INetMessageHeader & rHeader,sal_uIntPtr nNewIndex)1091 sal_uIntPtr INetMIMEMessage::SetHeaderField (
1092 const INetMessageHeader &rHeader, sal_uIntPtr nNewIndex)
1093 {
1094 ByteString aName (rHeader.GetName());
1095 const sal_Char *pData = aName.GetBuffer();
1096 const sal_Char *pStop = pData + aName.Len() + 1;
1097 const sal_Char *check = "";
1098
1099 sal_uIntPtr nIdx = LIST_APPEND;
1100 int eState = INETMSG_MIME_BEGIN;
1101 int eOkState = INETMSG_MIME_OK;
1102
1103 while (pData < pStop)
1104 {
1105 switch (eState)
1106 {
1107 case INETMSG_MIME_BEGIN:
1108 eState = INETMSG_MIME_CHECK;
1109 eOkState = INETMSG_MIME_OK;
1110
1111 switch (ascii_toLowerCase (*pData))
1112 {
1113 case 'c':
1114 check = "ontent-";
1115 eOkState = INETMSG_MIME_TOKEN_CONTENT;
1116 break;
1117
1118 case 'm':
1119 check = "ime-version";
1120 nIdx = INETMSG_MIME_VERSION;
1121 break;
1122
1123 default:
1124 eState = INETMSG_MIME_JUNK;
1125 break;
1126 }
1127 pData++;
1128 break;
1129
1130 case INETMSG_MIME_TOKEN_CONTENT:
1131 eState = INETMSG_MIME_CHECK;
1132 eOkState = INETMSG_MIME_OK;
1133
1134 switch (ascii_toLowerCase (*pData))
1135 {
1136 case 'd':
1137 eState = INETMSG_MIME_TOKEN_CONTENT_D;
1138 break;
1139
1140 case 'i':
1141 check = "d";
1142 nIdx = INETMSG_MIME_CONTENT_ID;
1143 break;
1144
1145 case 't':
1146 eState = INETMSG_MIME_TOKEN_CONTENT_T;
1147 break;
1148
1149 default:
1150 eState = INETMSG_MIME_JUNK;
1151 break;
1152 }
1153 pData++;
1154 break;
1155
1156 case INETMSG_MIME_TOKEN_CONTENT_D:
1157 eState = INETMSG_MIME_CHECK;
1158 eOkState = INETMSG_MIME_OK;
1159
1160 switch (ascii_toLowerCase (*pData))
1161 {
1162 case 'e':
1163 check = "scription";
1164 nIdx = INETMSG_MIME_CONTENT_DESCRIPTION;
1165 break;
1166
1167 case 'i':
1168 check = "sposition";
1169 nIdx = INETMSG_MIME_CONTENT_DISPOSITION;
1170 break;
1171
1172 default:
1173 eState = INETMSG_MIME_JUNK;
1174 break;
1175 }
1176 pData++;
1177 break;
1178
1179 case INETMSG_MIME_TOKEN_CONTENT_T:
1180 eState = INETMSG_MIME_CHECK;
1181 eOkState = INETMSG_MIME_OK;
1182
1183 switch (ascii_toLowerCase (*pData))
1184 {
1185 case 'r':
1186 check = "ansfer-encoding";
1187 nIdx = INETMSG_MIME_CONTENT_TRANSFER_ENCODING;
1188 break;
1189
1190 case 'y':
1191 check = "pe";
1192 nIdx = INETMSG_MIME_CONTENT_TYPE;
1193 break;
1194
1195 default:
1196 eState = INETMSG_MIME_JUNK;
1197 break;
1198 }
1199 pData++;
1200 break;
1201
1202 case INETMSG_MIME_CHECK:
1203 if (*check)
1204 {
1205 while (*pData && *check &&
1206 (ascii_toLowerCase (*pData) == *check))
1207 {
1208 pData++;
1209 check++;
1210 }
1211 }
1212 else
1213 {
1214 check = pData;
1215 }
1216 eState = (*check == '\0') ? eOkState : INETMSG_MIME_JUNK;
1217 break;
1218
1219 case INETMSG_MIME_OK:
1220 pData = pStop;
1221 SetHeaderField_Impl (
1222 HEADERFIELD (MIMEHDR(nIdx), rHeader.GetValue()),
1223 m_nIndex[nIdx]);
1224 nNewIndex = m_nIndex[nIdx];
1225 break;
1226
1227 default: // INETMSG_MIME_JUNK
1228 pData = pStop;
1229 nNewIndex = INetRFC822Message::SetHeaderField (
1230 rHeader, nNewIndex);
1231 break;
1232 }
1233 }
1234 return nNewIndex;
1235 }
1236
1237 /*
1238 * Specific Set-Methods.
1239 */
SetMIMEVersion(const UniString & rVersion)1240 void INetMIMEMessage::SetMIMEVersion (const UniString& rVersion)
1241 {
1242 SetHeaderField_Impl (
1243 INetMIME::HEADER_FIELD_TEXT,
1244 MIMEHDR(INETMSG_MIME_VERSION), rVersion,
1245 m_nIndex[INETMSG_MIME_VERSION]);
1246 }
1247
SetContentDescription(const String & rDescription)1248 void INetMIMEMessage::SetContentDescription (const String& rDescription)
1249 {
1250 SetHeaderField_Impl (
1251 INetMIME::HEADER_FIELD_TEXT,
1252 MIMEHDR(INETMSG_MIME_CONTENT_DESCRIPTION), rDescription,
1253 m_nIndex[INETMSG_MIME_CONTENT_DESCRIPTION]);
1254 }
1255
SetContentDisposition(const String & rDisposition)1256 void INetMIMEMessage::SetContentDisposition (const String& rDisposition)
1257 {
1258 SetHeaderField_Impl (
1259 INetMIME::HEADER_FIELD_TEXT,
1260 MIMEHDR(INETMSG_MIME_CONTENT_DISPOSITION), rDisposition,
1261 m_nIndex[INETMSG_MIME_CONTENT_DISPOSITION]);
1262 }
1263
SetContentID(const String & rID)1264 void INetMIMEMessage::SetContentID (const String& rID)
1265 {
1266 SetHeaderField_Impl (
1267 INetMIME::HEADER_FIELD_TEXT,
1268 MIMEHDR(INETMSG_MIME_CONTENT_ID), rID,
1269 m_nIndex[INETMSG_MIME_CONTENT_ID]);
1270 }
1271
SetContentType(const String & rType)1272 void INetMIMEMessage::SetContentType (const String& rType)
1273 {
1274 SetHeaderField_Impl (
1275 INetMIME::HEADER_FIELD_TEXT,
1276 MIMEHDR(INETMSG_MIME_CONTENT_TYPE), rType,
1277 m_nIndex[INETMSG_MIME_CONTENT_TYPE]);
1278 }
1279
SetContentTransferEncoding(const String & rEncoding)1280 void INetMIMEMessage::SetContentTransferEncoding (
1281 const String& rEncoding)
1282 {
1283 SetHeaderField_Impl (
1284 INetMIME::HEADER_FIELD_TEXT,
1285 MIMEHDR(INETMSG_MIME_CONTENT_TRANSFER_ENCODING), rEncoding,
1286 m_nIndex[INETMSG_MIME_CONTENT_TRANSFER_ENCODING]);
1287 }
1288
1289 /*
1290 * GetDefaultContentType.
1291 */
GetDefaultContentType(String & rContentType)1292 void INetMIMEMessage::GetDefaultContentType (String& rContentType)
1293 {
1294 String aDefaultCT (
1295 "text/plain; charset=us-ascii", RTL_TEXTENCODING_ASCII_US);
1296 if (pParent == NULL)
1297 {
1298 rContentType = aDefaultCT;
1299 }
1300 else
1301 {
1302 String aParentCT (pParent->GetContentType());
1303 if (aParentCT.Len() == 0)
1304 pParent->GetDefaultContentType (aParentCT);
1305
1306 if (aParentCT.CompareIgnoreCaseToAscii ("message/", 8) == 0)
1307 {
1308 rContentType = aDefaultCT;
1309 }
1310 else if (aParentCT.CompareIgnoreCaseToAscii ("multipart/", 10) == 0)
1311 {
1312 if (aParentCT.CompareIgnoreCaseToAscii ("multipart/digest") == 0)
1313 rContentType.AssignAscii ("message/rfc822");
1314 else
1315 rContentType = aDefaultCT;
1316 }
1317 else
1318 {
1319 rContentType = aDefaultCT;
1320 }
1321 }
1322 }
1323
1324 /*
1325 * EnableAttachChild.
1326 */
EnableAttachChild(INetMessageContainerType eType)1327 sal_Bool INetMIMEMessage::EnableAttachChild (INetMessageContainerType eType)
1328 {
1329 // Check context.
1330 if (IsContainer())
1331 return sal_False;
1332
1333 // Setup Content-Type header field.
1334 ByteString aContentType;
1335 switch (eType)
1336 {
1337 case INETMSG_MESSAGE_RFC822:
1338 aContentType = "message/rfc822";
1339 break;
1340
1341 case INETMSG_MULTIPART_ALTERNATIVE:
1342 aContentType = "multipart/alternative";
1343 break;
1344
1345 case INETMSG_MULTIPART_DIGEST:
1346 aContentType = "multipart/digest";
1347 break;
1348
1349 case INETMSG_MULTIPART_PARALLEL:
1350 aContentType = "multipart/parallel";
1351 break;
1352
1353 case INETMSG_MULTIPART_RELATED:
1354 aContentType = "multipart/related";
1355 break;
1356
1357 case INETMSG_MULTIPART_FORM_DATA:
1358 aContentType = "multipart/form-data";
1359 break;
1360
1361 default:
1362 aContentType = "multipart/mixed";
1363 break;
1364 }
1365
1366 // Setup boundary for multipart types.
1367 if (aContentType.CompareIgnoreCaseToAscii ("multipart/", 10) == 0)
1368 {
1369 // Generate a unique boundary from current time.
1370 sal_Char sTail[16 + 1];
1371 Time aCurTime;
1372 sal_uInt64 nThis = reinterpret_cast< sal_uIntPtr >( this ); // we can be on a 64bit architecture
1373 nThis = ( ( nThis >> 32 ) ^ nThis ) & SAL_MAX_UINT32;
1374 sprintf (sTail, "%08X%08X",
1375 static_cast< unsigned int >(aCurTime.GetTime()),
1376 static_cast< unsigned int >(nThis));
1377 m_aBoundary = "------------_4D48";
1378 m_aBoundary += sTail;
1379
1380 // Append boundary as ContentType parameter.
1381 aContentType += "; boundary=";
1382 aContentType += m_aBoundary;
1383 }
1384
1385 // Set header fields.
1386 SetMIMEVersion (String (CONSTASCII_STRINGPARAM("1.0")));
1387 SetContentType (String (aContentType, RTL_TEXTENCODING_ASCII_US));
1388 SetContentTransferEncoding (String (CONSTASCII_STRINGPARAM("7bit")));
1389
1390 // Done.
1391 return sal_True;
1392 }
1393
1394 /*
1395 * AttachChild.
1396 */
AttachChild(INetMIMEMessage & rChildMsg,sal_Bool bOwner)1397 sal_Bool INetMIMEMessage::AttachChild (
1398 INetMIMEMessage& rChildMsg, sal_Bool bOwner)
1399 {
1400 if (IsContainer() /*&& rChildMsg.GetContentType().Len() */)
1401 {
1402 if (bOwner) rChildMsg.pParent = this;
1403 aChildren.Insert (&rChildMsg, LIST_APPEND);
1404 nNumChildren = aChildren.Count();
1405
1406 return sal_True;
1407 }
1408 return sal_False;
1409 }
1410
1411 /*
1412 * DetachChild.
1413 */
DetachChild(sal_uIntPtr nIndex,INetMIMEMessage & rChildMsg) const1414 sal_Bool INetMIMEMessage::DetachChild (
1415 sal_uIntPtr nIndex, INetMIMEMessage& rChildMsg) const
1416 {
1417 if (IsContainer())
1418 {
1419 // Check document stream.
1420 if (GetDocumentLB() == NULL) return sal_False;
1421 SvStream *pDocStrm = new SvStream (GetDocumentLB());
1422
1423 // Initialize message buffer.
1424 char pMsgBuffer[1024];
1425 char *pMsgRead, *pMsgWrite;
1426 pMsgRead = pMsgWrite = pMsgBuffer;
1427
1428 // Initialize message parser stream.
1429 INetMIMEMessageStream *pMsgStrm = NULL;
1430
1431 // Check for "multipart/uvw" or "message/xyz".
1432 if (IsMultipart())
1433 {
1434 // Multipart message body. Initialize multipart delimiters.
1435 ByteString aDelim ("--");
1436 aDelim += GetMultipartBoundary();
1437 ByteString aClose = aDelim;
1438 aClose += "--";
1439
1440 // Initialize line buffer.
1441 SvMemoryStream aLineBuf;
1442
1443 // Initialize control variables.
1444 INetMessageStreamState eState = INETMSG_EOL_SCR;
1445 int nCurIndex = -1;
1446
1447 // Go!
1448 while (nCurIndex < (int)(nIndex + 1))
1449 {
1450 if ((pMsgRead - pMsgWrite) > 0)
1451 {
1452 // Bytes still in buffer.
1453 if (eState == INETMSG_EOL_FCR)
1454 {
1455 // Check for 2nd line break character.
1456 if ((*pMsgWrite == '\r') || (*pMsgWrite == '\n'))
1457 aLineBuf << *pMsgWrite++;
1458
1459 // Check current index.
1460 if (nCurIndex == (int)nIndex)
1461 {
1462 // Found requested part.
1463 if (pMsgStrm == NULL)
1464 {
1465 // Create message parser stream.
1466 pMsgStrm = new INetMIMEMessageStream;
1467 pMsgStrm->SetTargetMessage (&rChildMsg);
1468 }
1469
1470 // Put message down-stream.
1471 int status = pMsgStrm->Write (
1472 (const sal_Char *) aLineBuf.GetData(), aLineBuf.Tell());
1473 if (status != INETSTREAM_STATUS_OK)
1474 {
1475 // Cleanup.
1476 delete pDocStrm;
1477 delete pMsgStrm;
1478
1479 // Finish.
1480 return (!(status == INETSTREAM_STATUS_OK));
1481 }
1482 }
1483
1484 // Reset to <Begin-of-Line>.
1485 aLineBuf.Seek (STREAM_SEEK_TO_BEGIN);
1486 eState = INETMSG_EOL_SCR;
1487 }
1488 else if ((*pMsgWrite == '\r') || (*pMsgWrite == '\n'))
1489 {
1490 /*
1491 * Found any line break character.
1492 * Compare buffered line with part/close delimiter.
1493 * Increment current part index upon match.
1494 */
1495 sal_uInt16 nLen = (sal_uInt16)(aLineBuf.Tell() & 0xffff);
1496 if (nLen == aDelim.Len())
1497 {
1498 if (aDelim.CompareTo ((const sal_Char *) aLineBuf.GetData(), nLen)
1499 == COMPARE_EQUAL) nCurIndex++;
1500 }
1501 else if (nLen == aClose.Len())
1502 {
1503 if (aClose.CompareTo ((const sal_Char *) aLineBuf.GetData(), nLen)
1504 == COMPARE_EQUAL) nCurIndex++;
1505 }
1506 aLineBuf << *pMsgWrite++;
1507 eState = INETMSG_EOL_FCR;
1508 }
1509 else
1510 {
1511 // Insert into line buffer.
1512 aLineBuf << *pMsgWrite;
1513 }
1514 }
1515 else
1516 {
1517 // Buffer empty. Reset to <Begin-of-Buffer>.
1518 pMsgRead = pMsgWrite = pMsgBuffer;
1519
1520 // Read document stream.
1521 sal_uIntPtr nRead = pDocStrm->Read (
1522 pMsgBuffer, sizeof (pMsgBuffer));
1523 if (nRead > 0)
1524 {
1525 // Set read pointer.
1526 pMsgRead += nRead;
1527 }
1528 else
1529 {
1530 // Premature end.
1531 if (pMsgStrm)
1532 {
1533 // Assume end of requested part.
1534 nCurIndex++;
1535 }
1536 else
1537 {
1538 // Requested part not found.
1539 delete pDocStrm;
1540 return sal_False;
1541 }
1542 }
1543 }
1544 } // while (nCurIndex < (nIndex + 1))
1545 }
1546 else
1547 {
1548 // Encapsulated message body. Create message parser stream.
1549 pMsgStrm = new INetMIMEMessageStream;
1550 pMsgStrm->SetTargetMessage (&rChildMsg);
1551
1552 // Initialize control variables.
1553 INetMessageStreamState eState = INETMSG_EOL_BEGIN;
1554
1555 // Go.
1556 while (eState == INETMSG_EOL_BEGIN)
1557 {
1558 if ((pMsgRead - pMsgWrite) > 0)
1559 {
1560 // Bytes still in buffer. Put message down-stream.
1561 int status = pMsgStrm->Write (
1562 pMsgBuffer, (pMsgRead - pMsgWrite));
1563 if (status != INETSTREAM_STATUS_OK)
1564 {
1565 // Cleanup.
1566 delete pDocStrm;
1567 delete pMsgStrm;
1568
1569 // Finish.
1570 return (!(status == INETSTREAM_STATUS_ERROR));
1571 }
1572 pMsgWrite = pMsgBuffer + (pMsgRead - pMsgWrite);
1573 }
1574 else
1575 {
1576 // Buffer empty. Reset to <Begin-of-Buffer>.
1577 pMsgRead = pMsgWrite = pMsgBuffer;
1578
1579 // Read document stream.
1580 sal_uIntPtr nRead = pDocStrm->Read (
1581 pMsgBuffer, sizeof (pMsgBuffer));
1582 if (nRead > 0)
1583 {
1584 // Set read pointer.
1585 pMsgRead += nRead;
1586 }
1587 else
1588 {
1589 // Mark we're done.
1590 eState = INETMSG_EOL_DONE;
1591 }
1592 }
1593 } // while (eState == INETMSG_EOL_BEGIN)
1594 }
1595
1596 // Done.
1597 if (pDocStrm) delete pDocStrm;
1598 if (pMsgStrm) delete pMsgStrm;
1599 return sal_True;
1600 }
1601 return sal_False;
1602 }
1603
1604 /*
1605 * operator<<
1606 */
operator <<(SvStream & rStrm) const1607 SvStream& INetMIMEMessage::operator<< (SvStream& rStrm) const
1608 {
1609 INetRFC822Message::operator<< (rStrm);
1610
1611 for (sal_uInt16 i = 0; i < INETMSG_MIME_NUMHDR; i++)
1612 rStrm << static_cast<sal_uInt32>(m_nIndex[i]);
1613
1614 #ifdef ENABLE_BYTESTRING_STREAM_OPERATORS
1615 rStrm << m_aBoundary;
1616 #else
1617 rStrm.WriteByteString (m_aBoundary);
1618 #endif
1619 rStrm << static_cast<sal_uInt32>(nNumChildren);
1620
1621 return rStrm;
1622 }
1623
1624 /*
1625 * operator>>
1626 */
operator >>(SvStream & rStrm)1627 SvStream& INetMIMEMessage::operator>> (SvStream& rStrm)
1628 {
1629 INetRFC822Message::operator>> (rStrm);
1630
1631 sal_uInt32 nTemp;
1632 for (sal_uInt16 i = 0; i < INETMSG_MIME_NUMHDR; i++)
1633 {
1634 rStrm >> nTemp;
1635 m_nIndex[i] = nTemp;
1636 }
1637
1638 #ifdef ENABLE_BYTESTRING_STREAM_OPERATORS
1639 rStrm >> m_aBoundary;
1640 #else
1641 rStrm.ReadByteString (m_aBoundary);
1642 #endif
1643 rStrm >> nTemp;
1644 nNumChildren = nTemp;
1645
1646 return rStrm;
1647 }
1648
1649
1650