xref: /trunk/main/tools/source/inet/inetmsg.cxx (revision 89b56da7)
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 ()__anonb6e06d850111::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 ()__anonb6e06d850211::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