1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: inetmsg.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
33 #include <sal/types.h>
34 #include <tools/datetime.hxx>
35 #ifndef _TOOLS_INETMIME_HXX
36 #include <tools/inetmime.hxx>
38 #include <tools/inetmsg.hxx>
39 #include <tools/inetstrm.hxx>
40 #include <rtl/instance.hxx>
44 //=======================================================================
46 inline sal_Bool
ascii_isDigit( sal_Unicode ch
)
48 return ((ch
>= 0x0030) && (ch
<= 0x0039));
51 inline sal_Bool
ascii_isLetter( sal_Unicode ch
)
53 return (( (ch
>= 0x0041) && (ch
<= 0x005A)) || ((ch
>= 0x0061) && (ch
<= 0x007A)));
56 inline sal_Unicode
ascii_toLowerCase( sal_Unicode ch
)
58 if ( (ch
>= 0x0041) && (ch
<= 0x005A) )
64 /*=======================================================================
66 * INetMessage Implementation.
68 *=====================================================================*/
69 #define CONSTASCII_STRINGPARAM(a) (a), RTL_TEXTENCODING_ASCII_US
70 #define HEADERFIELD INetMessageHeader
75 INetMessage::~INetMessage (void)
83 void INetMessage::ListCleanup_Impl (void)
86 ULONG i
, n
= m_aHeaderList
.Count();
87 for (i
= 0; i
< n
; i
++)
88 delete ((HEADERFIELD
*)(m_aHeaderList
.GetObject(i
)));
89 m_aHeaderList
.Clear();
95 void INetMessage::ListCopy (const INetMessage
&rMsg
)
103 ULONG i
, n
= rMsg
.GetHeaderCount();
104 for (i
= 0; i
< n
; i
++)
106 HEADERFIELD
*p
= (HEADERFIELD
*)(rMsg
.m_aHeaderList
.GetObject(i
));
107 m_aHeaderList
.Insert (new HEADERFIELD(*p
), LIST_APPEND
);
113 * SetHeaderField_Impl.
115 void INetMessage::SetHeaderField_Impl (
116 INetMIME::HeaderFieldType eType
,
117 const ByteString
&rName
,
118 const UniString
&rValue
,
121 INetMIMEStringOutputSink
aSink (0, STRING_MAXLEN
);
122 INetMIME::writeHeaderFieldBody (
123 aSink
, eType
, rValue
, gsl_getSystemTextEncoding(), false);
124 SetHeaderField_Impl (
125 INetMessageHeader (rName
, aSink
.takeBuffer()), rnIndex
);
131 ULONG
INetMessage::SetHeaderField (
132 const UniString
& rName
, const UniString
& rValue
, ULONG nIndex
)
134 ULONG nResult
= nIndex
;
135 SetHeaderField_Impl (
136 INetMIME::HEADER_FIELD_TEXT
,
137 ByteString (rName
, RTL_TEXTENCODING_ASCII_US
), rValue
,
145 ULONG
INetMessage::SetHeaderField (
146 const INetMessageHeader
&rHeader
, ULONG nIndex
)
148 ULONG nResult
= nIndex
;
149 SetHeaderField_Impl (rHeader
, nResult
);
157 SvStream
& INetMessage::operator<< (SvStream
& rStrm
) const
159 rStrm
<< static_cast<sal_uInt32
>(m_nDocSize
);
160 rStrm
.WriteByteString (m_aDocName
, RTL_TEXTENCODING_UTF8
);
162 ULONG i
, n
= m_aHeaderList
.Count();
163 rStrm
<< static_cast<sal_uInt32
>(n
);
165 for (i
= 0; i
< n
; i
++)
166 rStrm
<< *((HEADERFIELD
*)(m_aHeaderList
.GetObject(i
)));
174 SvStream
& INetMessage::operator>> (SvStream
& rStrm
)
186 rStrm
.ReadByteString (m_aDocName
, RTL_TEXTENCODING_UTF8
);
192 for (i
= 0; i
< n
; i
++)
194 HEADERFIELD
*p
= new HEADERFIELD();
196 m_aHeaderList
.Insert (p
, LIST_APPEND
);
203 /*=======================================================================
205 * INetMessageHeaderIterator Implementation.
207 *=====================================================================*/
208 INetMessageHeaderIterator::INetMessageHeaderIterator (
209 const INetMessage
& rMsg
, const UniString
& rHdrName
)
211 ULONG i
, n
= rMsg
.GetHeaderCount();
212 for (i
= 0; i
< n
; i
++)
214 if (rHdrName
.CompareIgnoreCaseToAscii (rMsg
.GetHeaderName(i
)) == 0)
216 UniString
*pValue
= new UniString (rMsg
.GetHeaderValue(i
));
217 aValueList
.Insert (pValue
, LIST_APPEND
);
220 nValueCount
= aValueList
.Count();
223 INetMessageHeaderIterator::~INetMessageHeaderIterator (void)
225 ULONG i
, n
= aValueList
.Count();
226 for (i
= 0; i
< n
; i
++)
227 delete ((UniString
*)(aValueList
.GetObject(i
)));
231 /*=======================================================================
233 * INetRFC822Message Implementation.
235 *=====================================================================*/
237 * ImplINetRFC822MessageHeaderData.
241 struct ImplINetRFC822MessageHeaderDataImpl
243 const ByteString
* operator()()
245 static const ByteString _ImplINetRFC822MessageHeaderData
[] =
249 ByteString ("Comments"),
252 ByteString ("In-Reply-To"),
253 ByteString ("Keywords"),
254 ByteString ("Message-ID"),
255 ByteString ("References"),
256 ByteString ("Reply-To"),
257 ByteString ("Return-Path"),
258 ByteString ("Subject"),
259 ByteString ("Sender"),
261 ByteString ("X-Mailer"),
262 ByteString ("Return-Receipt-To")
264 return &_ImplINetRFC822MessageHeaderData
[0];
268 struct ImplINetRFC822MessageHeaderData
269 : public rtl::StaticAggregate
< const ByteString
, ImplINetRFC822MessageHeaderDataImpl
> {};
272 #define HDR(n) ImplINetRFC822MessageHeaderData::get()[(n)]
275 * _ImplINetRFC822MessageHeaderState.
277 enum _ImplINetRFC822MessageHeaderState
279 INETMSG_RFC822_BEGIN
,
280 INETMSG_RFC822_CHECK
,
284 INETMSG_RFC822_TOKEN_RE
,
285 INETMSG_RFC822_TOKEN_RETURNMINUS
,
286 INETMSG_RFC822_TOKEN_XMINUS
,
287 INETMSG_RFC822_LETTER_C
,
288 INETMSG_RFC822_LETTER_S
294 INetRFC822Message::INetRFC822Message (void)
297 for (USHORT i
= 0; i
< INETMSG_RFC822_NUMHDR
; i
++)
298 m_nIndex
[i
] = LIST_ENTRY_NOTFOUND
;
301 INetRFC822Message::INetRFC822Message (const INetRFC822Message
& rMsg
)
304 for (USHORT i
= 0; i
< INETMSG_RFC822_NUMHDR
; i
++)
305 m_nIndex
[i
] = rMsg
.m_nIndex
[i
];
311 INetRFC822Message
& INetRFC822Message::operator= (const INetRFC822Message
& rMsg
)
315 INetMessage::operator= (rMsg
);
317 for (USHORT i
= 0; i
< INETMSG_RFC822_NUMHDR
; i
++)
318 m_nIndex
[i
] = rMsg
.m_nIndex
[i
];
324 * ~INetRFC822Message.
326 INetRFC822Message::~INetRFC822Message (void)
331 * <Generate|Parse>DateField and local helper functions.
334 * Generates a String from Date and Time objects in format:
335 * Wkd, 00 Mon 0000 00:00:00 [GMT] (rfc822, rfc1123)
338 * Parses a String in (implied) GMT format into class Date and Time objects.
339 * Four formats are accepted:
341 * [Wkd,] 1*2DIGIT Mon 2*4DIGIT 00:00:00 [GMT] (rfc1123)
342 * [Wkd,] 00 Mon 0000 00:00:00 [GMT]) (rfc822, rfc1123)
343 * Weekday, 00-Mon-00 00:00:00 [GMT] (rfc850, rfc1036)
344 * Wkd Mon 00 00:00:00 0000 [GMT] (ctime)
345 * 1*DIGIT (delta seconds)
349 // Months and Weekdays.
350 static const sal_Char
*months
[12] =
352 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
353 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
356 static const sal_Char
*wkdays
[7] =
358 "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
364 BOOL
INetRFC822Message::GenerateDateField (
365 const DateTime
& rDateTime
, UniString
& rDateFieldW
)
368 if (!rDateTime
.IsValid() ||
369 (rDateTime
.GetSec() > 59) ||
370 (rDateTime
.GetMin() > 59) ||
371 (rDateTime
.GetHour() > 23) ) return FALSE
;
373 // Prepare output string.
374 ByteString rDateField
;
377 rDateField
+= wkdays
[(USHORT
)(rDateTime
.GetDayOfWeek())];
380 USHORT nNum
= rDateTime
.GetDay();
381 if (nNum
< 10) rDateField
+= '0';
382 rDateField
+= ByteString::CreateFromInt32(nNum
);
385 rDateField
+= months
[(USHORT
)(rDateTime
.GetMonth() - 1)];
388 rDateField
+= ByteString::CreateFromInt32(rDateTime
.GetYear());
392 nNum
= rDateTime
.GetHour();
393 if (nNum
< 10) rDateField
+= '0';
394 rDateField
+= ByteString::CreateFromInt32(nNum
);
397 nNum
= rDateTime
.GetMin();
398 if (nNum
< 10) rDateField
+= '0';
399 rDateField
+= ByteString::CreateFromInt32(nNum
);
402 nNum
= rDateTime
.GetSec();
403 if (nNum
< 10) rDateField
+= '0';
404 rDateField
+= ByteString::CreateFromInt32(nNum
);
405 rDateField
+= " GMT";
408 rDateFieldW
= UniString (rDateField
, RTL_TEXTENCODING_ASCII_US
);
413 * ParseDateField and local helper functions.
415 static USHORT
ParseNumber (const ByteString
& rStr
, USHORT
& nIndex
)
418 while ((n
< rStr
.Len()) && ascii_isDigit(rStr
.GetChar(n
))) n
++;
420 ByteString
aNum (rStr
.Copy (nIndex
, (n
- nIndex
)));
423 return (USHORT
)(aNum
.ToInt32());
426 static USHORT
ParseMonth (const ByteString
& rStr
, USHORT
& nIndex
)
429 while ((n
< rStr
.Len()) && ascii_isLetter(rStr
.GetChar(n
))) n
++;
431 ByteString
aMonth (rStr
.Copy (nIndex
, 3));
435 for (i
= 0; i
< 12; i
++)
436 if (aMonth
.CompareIgnoreCaseToAscii (months
[i
]) == 0) break;
440 BOOL
INetRFC822Message::ParseDateField (
441 const UniString
& rDateFieldW
, DateTime
& rDateTime
)
443 ByteString
rDateField (rDateFieldW
, RTL_TEXTENCODING_ASCII_US
);
444 if (rDateField
.Len() == 0) return FALSE
;
446 if (rDateField
.Search (':') != STRING_NOTFOUND
)
448 // Some DateTime format.
451 // Skip over <Wkd> or <Weekday>, leading and trailing space.
452 while ((nIndex
< rDateField
.Len()) &&
453 (rDateField
.GetChar(nIndex
) == ' '))
457 (nIndex
< rDateField
.Len()) &&
458 (ascii_isLetter (rDateField
.GetChar(nIndex
)) ||
459 (rDateField
.GetChar(nIndex
) == ',') ))
462 while ((nIndex
< rDateField
.Len()) &&
463 (rDateField
.GetChar(nIndex
) == ' '))
466 if (ascii_isLetter (rDateField
.GetChar(nIndex
)))
469 if ((rDateField
.Len() - nIndex
) < 20) return FALSE
;
471 rDateTime
.SetMonth (ParseMonth (rDateField
, nIndex
)); nIndex
++;
472 rDateTime
.SetDay (ParseNumber (rDateField
, nIndex
)); nIndex
++;
474 rDateTime
.SetHour (ParseNumber (rDateField
, nIndex
)); nIndex
++;
475 rDateTime
.SetMin (ParseNumber (rDateField
, nIndex
)); nIndex
++;
476 rDateTime
.SetSec (ParseNumber (rDateField
, nIndex
)); nIndex
++;
477 rDateTime
.Set100Sec (0);
479 USHORT nYear
= ParseNumber (rDateField
, nIndex
);
480 if (nYear
< 100) nYear
+= 1900;
481 rDateTime
.SetYear (nYear
);
485 // Format: RFC1036 or RFC1123.
486 if ((rDateField
.Len() - nIndex
) < 17) return FALSE
;
488 rDateTime
.SetDay (ParseNumber (rDateField
, nIndex
)); nIndex
++;
489 rDateTime
.SetMonth (ParseMonth (rDateField
, nIndex
)); nIndex
++;
491 USHORT nYear
= ParseNumber (rDateField
, nIndex
); nIndex
++;
492 if (nYear
< 100) nYear
+= 1900;
493 rDateTime
.SetYear (nYear
);
495 rDateTime
.SetHour (ParseNumber (rDateField
, nIndex
)); nIndex
++;
496 rDateTime
.SetMin (ParseNumber (rDateField
, nIndex
)); nIndex
++;
497 rDateTime
.SetSec (ParseNumber (rDateField
, nIndex
)); nIndex
++;
498 rDateTime
.Set100Sec (0);
500 if ((rDateField
.GetChar(nIndex
) == '+') ||
501 (rDateField
.GetChar(nIndex
) == '-') )
503 // Offset from GMT: "(+|-)HHMM".
504 BOOL bEast
= (rDateField
.GetChar(nIndex
++) == '+');
505 USHORT nOffset
= ParseNumber (rDateField
, nIndex
);
509 aDiff
.SetHour (nOffset
/ 100);
510 aDiff
.SetMin (nOffset
% 100);
522 else if (rDateField
.IsNumericAscii())
524 // Format: delta seconds.
526 aDelta
.SetTime (rDateField
.ToInt32() * 100);
532 rDateTime
.SetDate (aNow
.GetDate());
533 rDateTime
.SetTime (aNow
.GetTime());
541 return (rDateTime
.IsValid() &&
542 !((rDateTime
.GetSec() > 59) ||
543 (rDateTime
.GetMin() > 59) ||
544 (rDateTime
.GetHour() > 23) ));
549 * (Header Field Parser).
551 ULONG
INetRFC822Message::SetHeaderField (
552 const INetMessageHeader
&rHeader
, ULONG nNewIndex
)
554 ByteString
aName (rHeader
.GetName());
555 const sal_Char
*pData
= aName
.GetBuffer();
556 const sal_Char
*pStop
= pData
+ aName
.Len() + 1;
557 const sal_Char
*check
= "";
559 ULONG nIdx
= LIST_APPEND
;
560 int eState
= INETMSG_RFC822_BEGIN
;
561 int eOkState
= INETMSG_RFC822_OK
;
563 while (pData
< pStop
)
567 case INETMSG_RFC822_BEGIN
:
568 eState
= INETMSG_RFC822_CHECK
;
569 eOkState
= INETMSG_RFC822_OK
;
571 switch (ascii_toLowerCase (*pData
))
575 nIdx
= INETMSG_RFC822_BCC
;
579 eState
= INETMSG_RFC822_LETTER_C
;
584 nIdx
= INETMSG_RFC822_DATE
;
589 nIdx
= INETMSG_RFC822_FROM
;
593 check
= "n-reply-to";
594 nIdx
= INETMSG_RFC822_IN_REPLY_TO
;
599 nIdx
= INETMSG_RFC822_KEYWORDS
;
604 nIdx
= INETMSG_RFC822_MESSAGE_ID
;
609 eOkState
= INETMSG_RFC822_TOKEN_RE
;
613 eState
= INETMSG_RFC822_LETTER_S
;
618 nIdx
= INETMSG_RFC822_TO
;
623 eOkState
= INETMSG_RFC822_TOKEN_XMINUS
;
627 eState
= INETMSG_RFC822_JUNK
;
633 case INETMSG_RFC822_TOKEN_RE
:
634 eState
= INETMSG_RFC822_CHECK
;
635 eOkState
= INETMSG_RFC822_OK
;
637 switch (ascii_toLowerCase (*pData
))
641 nIdx
= INETMSG_RFC822_REFERENCES
;
646 nIdx
= INETMSG_RFC822_REPLY_TO
;
651 eOkState
= INETMSG_RFC822_TOKEN_RETURNMINUS
;
655 eState
= INETMSG_RFC822_JUNK
;
661 case INETMSG_RFC822_TOKEN_RETURNMINUS
:
662 eState
= INETMSG_RFC822_CHECK
;
663 eOkState
= INETMSG_RFC822_OK
;
665 switch (ascii_toLowerCase (*pData
))
669 nIdx
= INETMSG_RFC822_RETURN_PATH
;
674 nIdx
= INETMSG_RFC822_RETURN_RECEIPT_TO
;
678 eState
= INETMSG_RFC822_JUNK
;
684 case INETMSG_RFC822_TOKEN_XMINUS
:
685 eState
= INETMSG_RFC822_CHECK
;
686 eOkState
= INETMSG_RFC822_OK
;
688 switch (ascii_toLowerCase (*pData
))
692 nIdx
= INETMSG_RFC822_X_MAILER
;
698 eOkState
= INETMSG_RFC822_X_PRIORITY
;
703 eState
= INETMSG_RFC822_JUNK
;
709 case INETMSG_RFC822_LETTER_C
:
710 eState
= INETMSG_RFC822_CHECK
;
711 eOkState
= INETMSG_RFC822_OK
;
713 switch (ascii_toLowerCase (*pData
))
717 nIdx
= INETMSG_RFC822_CC
;
722 nIdx
= INETMSG_RFC822_COMMENTS
;
726 eState
= INETMSG_RFC822_JUNK
;
732 case INETMSG_RFC822_LETTER_S
:
733 eState
= INETMSG_RFC822_CHECK
;
734 eOkState
= INETMSG_RFC822_OK
;
736 switch (ascii_toLowerCase (*pData
))
740 nIdx
= INETMSG_RFC822_SENDER
;
745 nIdx
= INETMSG_RFC822_SUBJECT
;
749 eState
= INETMSG_RFC822_JUNK
;
755 case INETMSG_RFC822_CHECK
:
758 while (*pData
&& *check
&&
759 (ascii_toLowerCase (*pData
) == *check
))
769 eState
= (*check
== '\0') ? eOkState
: INETMSG_RFC822_JUNK
;
772 case INETMSG_RFC822_OK
:
774 SetHeaderField_Impl (
775 HEADERFIELD (HDR(nIdx
), rHeader
.GetValue()),
777 nNewIndex
= m_nIndex
[nIdx
];
780 default: // INETMSG_RFC822_JUNK
782 nNewIndex
= INetMessage::SetHeaderField (rHeader
, nNewIndex
);
790 * Specific Set-Methods.
792 void INetRFC822Message::SetBCC (const UniString
& rBCC
)
794 SetHeaderField_Impl (
795 INetMIME::HEADER_FIELD_ADDRESS
,
796 HDR(INETMSG_RFC822_BCC
), rBCC
,
797 m_nIndex
[INETMSG_RFC822_BCC
]);
800 void INetRFC822Message::SetCC (const UniString
& rCC
)
802 SetHeaderField_Impl (
803 INetMIME::HEADER_FIELD_ADDRESS
,
804 HDR(INETMSG_RFC822_CC
), rCC
,
805 m_nIndex
[INETMSG_RFC822_CC
]);
808 void INetRFC822Message::SetComments (const UniString
& rComments
)
810 SetHeaderField_Impl (
811 INetMIME::HEADER_FIELD_TEXT
,
812 HDR(INETMSG_RFC822_COMMENTS
), rComments
,
813 m_nIndex
[INETMSG_RFC822_COMMENTS
]);
816 void INetRFC822Message::SetDate (const UniString
& rDate
)
818 SetHeaderField_Impl (
819 INetMIME::HEADER_FIELD_STRUCTURED
,
820 HDR(INETMSG_RFC822_DATE
), rDate
,
821 m_nIndex
[INETMSG_RFC822_DATE
]);
824 void INetRFC822Message::SetFrom (const UniString
& rFrom
)
826 SetHeaderField_Impl (
827 INetMIME::HEADER_FIELD_ADDRESS
,
828 HDR(INETMSG_RFC822_FROM
), rFrom
,
829 m_nIndex
[INETMSG_RFC822_FROM
]);
832 void INetRFC822Message::SetInReplyTo (const UniString
& rInReplyTo
)
834 SetHeaderField_Impl (
835 INetMIME::HEADER_FIELD_ADDRESS
, // ??? MESSAGE_ID ???
836 HDR(INETMSG_RFC822_IN_REPLY_TO
), rInReplyTo
,
837 m_nIndex
[INETMSG_RFC822_IN_REPLY_TO
]);
840 void INetRFC822Message::SetKeywords (const UniString
& rKeywords
)
842 SetHeaderField_Impl (
843 INetMIME::HEADER_FIELD_PHRASE
,
844 HDR(INETMSG_RFC822_KEYWORDS
), rKeywords
,
845 m_nIndex
[INETMSG_RFC822_KEYWORDS
]);
848 void INetRFC822Message::SetMessageID (const UniString
& rMessageID
)
850 SetHeaderField_Impl (
851 INetMIME::HEADER_FIELD_MESSAGE_ID
,
852 HDR(INETMSG_RFC822_MESSAGE_ID
), rMessageID
,
853 m_nIndex
[INETMSG_RFC822_MESSAGE_ID
]);
856 void INetRFC822Message::SetReferences (const UniString
& rReferences
)
858 SetHeaderField_Impl (
859 INetMIME::HEADER_FIELD_MESSAGE_ID
,
860 HDR(INETMSG_RFC822_REFERENCES
), rReferences
,
861 m_nIndex
[INETMSG_RFC822_REFERENCES
]);
864 void INetRFC822Message::SetReplyTo (const UniString
& rReplyTo
)
866 SetHeaderField_Impl (
867 INetMIME::HEADER_FIELD_ADDRESS
,
868 HDR(INETMSG_RFC822_REPLY_TO
), rReplyTo
,
869 m_nIndex
[INETMSG_RFC822_REPLY_TO
]);
872 void INetRFC822Message::SetReturnPath (const UniString
& rReturnPath
)
874 SetHeaderField_Impl (
875 INetMIME::HEADER_FIELD_ADDRESS
,
876 HDR(INETMSG_RFC822_RETURN_PATH
), rReturnPath
,
877 m_nIndex
[INETMSG_RFC822_RETURN_PATH
]);
880 void INetRFC822Message::SetReturnReceiptTo (const UniString
& rValue
)
882 SetHeaderField_Impl (
883 INetMIME::HEADER_FIELD_ADDRESS
,
884 HDR(INETMSG_RFC822_RETURN_RECEIPT_TO
), rValue
,
885 m_nIndex
[INETMSG_RFC822_RETURN_RECEIPT_TO
]);
888 void INetRFC822Message::SetSender (const UniString
& rSender
)
890 SetHeaderField_Impl (
891 INetMIME::HEADER_FIELD_ADDRESS
,
892 HDR(INETMSG_RFC822_SENDER
), rSender
,
893 m_nIndex
[INETMSG_RFC822_SENDER
]);
896 void INetRFC822Message::SetSubject (const UniString
& rSubject
)
898 SetHeaderField_Impl (
899 INetMIME::HEADER_FIELD_TEXT
,
900 HDR(INETMSG_RFC822_SUBJECT
), rSubject
,
901 m_nIndex
[INETMSG_RFC822_SUBJECT
]);
904 void INetRFC822Message::SetTo (const UniString
& rTo
)
906 SetHeaderField_Impl (
907 INetMIME::HEADER_FIELD_ADDRESS
,
908 HDR(INETMSG_RFC822_TO
), rTo
,
909 m_nIndex
[INETMSG_RFC822_TO
]);
912 void INetRFC822Message::SetXMailer (const UniString
& rXMailer
)
914 SetHeaderField_Impl (
915 INetMIME::HEADER_FIELD_TEXT
,
916 HDR(INETMSG_RFC822_X_MAILER
), rXMailer
,
917 m_nIndex
[INETMSG_RFC822_X_MAILER
]);
923 SvStream
& INetRFC822Message::operator<< (SvStream
& rStrm
) const
925 INetMessage::operator<< (rStrm
);
927 for (USHORT i
= 0; i
< INETMSG_RFC822_NUMHDR
; i
++)
928 rStrm
<< static_cast<sal_uInt32
>(m_nIndex
[i
]);
936 SvStream
& INetRFC822Message::operator>> (SvStream
& rStrm
)
938 INetMessage::operator>> (rStrm
);
941 for (USHORT i
= 0; i
< INETMSG_RFC822_NUMHDR
; i
++)
950 /*=======================================================================
952 * INetMIMEMessage Implementation.
954 *=====================================================================*/
956 * _ImplINetMIMEMessageHeaderData.
960 struct ImplINetMIMEMessageHeaderDataImpl
962 const ByteString
* operator()()
964 static const ByteString _ImplINetMIMEMessageHeaderData
[] =
966 ByteString ("MIME-Version"),
967 ByteString ("Content-Description"),
968 ByteString ("Content-Disposition"),
969 ByteString ("Content-ID"),
970 ByteString ("Content-Type"),
971 ByteString ("Content-Transfer-Encoding")
973 return &_ImplINetMIMEMessageHeaderData
[0];
977 struct ImplINetMIMEMessageHeaderData
978 : public rtl::StaticAggregate
< const ByteString
, ImplINetMIMEMessageHeaderDataImpl
> {};
981 #define MIMEHDR(n) ImplINetMIMEMessageHeaderData::get()[(n)]
984 * _ImplINetMIMEMessageHeaderState.
986 enum _ImplINetMIMEMessageHeaderState
993 INETMSG_MIME_TOKEN_CONTENT
,
994 INETMSG_MIME_TOKEN_CONTENT_D
,
995 INETMSG_MIME_TOKEN_CONTENT_T
1001 INetMIMEMessage::INetMIMEMessage (void)
1002 : INetRFC822Message (),
1005 bHeaderParsed (FALSE
)
1007 for (USHORT i
= 0; i
< INETMSG_MIME_NUMHDR
; i
++)
1008 m_nIndex
[i
] = LIST_ENTRY_NOTFOUND
;
1011 INetMIMEMessage::INetMIMEMessage (const INetMIMEMessage
& rMsg
)
1012 : INetRFC822Message (rMsg
)
1021 INetMIMEMessage
& INetMIMEMessage::operator= (
1022 const INetMIMEMessage
& rMsg
)
1027 INetRFC822Message::operator= (rMsg
);
1041 INetMIMEMessage::~INetMIMEMessage (void)
1050 void INetMIMEMessage::CleanupImp (void)
1052 INetMIMEMessage
*pChild
= NULL
;
1053 while ((pChild
= (INetMIMEMessage
*)(aChildren
.Remove())) != NULL
)
1054 if (pChild
->pParent
== this) delete pChild
;
1060 void INetMIMEMessage::CopyImp (const INetMIMEMessage
& rMsg
)
1062 bHeaderParsed
= rMsg
.bHeaderParsed
;
1065 for (i
= 0; i
< INETMSG_MIME_NUMHDR
; i
++)
1066 m_nIndex
[i
] = rMsg
.m_nIndex
[i
];
1068 m_aBoundary
= rMsg
.m_aBoundary
;
1069 nNumChildren
= rMsg
.nNumChildren
;
1071 for (i
= 0; i
< rMsg
.aChildren
.Count(); i
++)
1073 INetMIMEMessage
*pChild
=
1074 (INetMIMEMessage
*)(rMsg
.aChildren
.GetObject (i
));
1076 if (pChild
->pParent
== &rMsg
)
1078 pChild
= pChild
->CreateMessage (*pChild
);
1079 pChild
->pParent
= this;
1081 aChildren
.Insert (pChild
, LIST_APPEND
);
1088 INetMIMEMessage
*INetMIMEMessage::CreateMessage (
1089 const INetMIMEMessage
& rMsg
) const
1091 return (new INetMIMEMessage (rMsg
));
1096 * (Header Field Parser).
1098 ULONG
INetMIMEMessage::SetHeaderField (
1099 const INetMessageHeader
&rHeader
, ULONG nNewIndex
)
1101 ByteString
aName (rHeader
.GetName());
1102 const sal_Char
*pData
= aName
.GetBuffer();
1103 const sal_Char
*pStop
= pData
+ aName
.Len() + 1;
1104 const sal_Char
*check
= "";
1106 ULONG nIdx
= LIST_APPEND
;
1107 int eState
= INETMSG_MIME_BEGIN
;
1108 int eOkState
= INETMSG_MIME_OK
;
1110 while (pData
< pStop
)
1114 case INETMSG_MIME_BEGIN
:
1115 eState
= INETMSG_MIME_CHECK
;
1116 eOkState
= INETMSG_MIME_OK
;
1118 switch (ascii_toLowerCase (*pData
))
1122 eOkState
= INETMSG_MIME_TOKEN_CONTENT
;
1126 check
= "ime-version";
1127 nIdx
= INETMSG_MIME_VERSION
;
1131 eState
= INETMSG_MIME_JUNK
;
1137 case INETMSG_MIME_TOKEN_CONTENT
:
1138 eState
= INETMSG_MIME_CHECK
;
1139 eOkState
= INETMSG_MIME_OK
;
1141 switch (ascii_toLowerCase (*pData
))
1144 eState
= INETMSG_MIME_TOKEN_CONTENT_D
;
1149 nIdx
= INETMSG_MIME_CONTENT_ID
;
1153 eState
= INETMSG_MIME_TOKEN_CONTENT_T
;
1157 eState
= INETMSG_MIME_JUNK
;
1163 case INETMSG_MIME_TOKEN_CONTENT_D
:
1164 eState
= INETMSG_MIME_CHECK
;
1165 eOkState
= INETMSG_MIME_OK
;
1167 switch (ascii_toLowerCase (*pData
))
1170 check
= "scription";
1171 nIdx
= INETMSG_MIME_CONTENT_DESCRIPTION
;
1175 check
= "sposition";
1176 nIdx
= INETMSG_MIME_CONTENT_DISPOSITION
;
1180 eState
= INETMSG_MIME_JUNK
;
1186 case INETMSG_MIME_TOKEN_CONTENT_T
:
1187 eState
= INETMSG_MIME_CHECK
;
1188 eOkState
= INETMSG_MIME_OK
;
1190 switch (ascii_toLowerCase (*pData
))
1193 check
= "ansfer-encoding";
1194 nIdx
= INETMSG_MIME_CONTENT_TRANSFER_ENCODING
;
1199 nIdx
= INETMSG_MIME_CONTENT_TYPE
;
1203 eState
= INETMSG_MIME_JUNK
;
1209 case INETMSG_MIME_CHECK
:
1212 while (*pData
&& *check
&&
1213 (ascii_toLowerCase (*pData
) == *check
))
1223 eState
= (*check
== '\0') ? eOkState
: INETMSG_MIME_JUNK
;
1226 case INETMSG_MIME_OK
:
1228 SetHeaderField_Impl (
1229 HEADERFIELD (MIMEHDR(nIdx
), rHeader
.GetValue()),
1231 nNewIndex
= m_nIndex
[nIdx
];
1234 default: // INETMSG_MIME_JUNK
1236 nNewIndex
= INetRFC822Message::SetHeaderField (
1237 rHeader
, nNewIndex
);
1245 * Specific Set-Methods.
1247 void INetMIMEMessage::SetMIMEVersion (const UniString
& rVersion
)
1249 SetHeaderField_Impl (
1250 INetMIME::HEADER_FIELD_TEXT
,
1251 MIMEHDR(INETMSG_MIME_VERSION
), rVersion
,
1252 m_nIndex
[INETMSG_MIME_VERSION
]);
1255 void INetMIMEMessage::SetContentDescription (const String
& rDescription
)
1257 SetHeaderField_Impl (
1258 INetMIME::HEADER_FIELD_TEXT
,
1259 MIMEHDR(INETMSG_MIME_CONTENT_DESCRIPTION
), rDescription
,
1260 m_nIndex
[INETMSG_MIME_CONTENT_DESCRIPTION
]);
1263 void INetMIMEMessage::SetContentDisposition (const String
& rDisposition
)
1265 SetHeaderField_Impl (
1266 INetMIME::HEADER_FIELD_TEXT
,
1267 MIMEHDR(INETMSG_MIME_CONTENT_DISPOSITION
), rDisposition
,
1268 m_nIndex
[INETMSG_MIME_CONTENT_DISPOSITION
]);
1271 void INetMIMEMessage::SetContentID (const String
& rID
)
1273 SetHeaderField_Impl (
1274 INetMIME::HEADER_FIELD_TEXT
,
1275 MIMEHDR(INETMSG_MIME_CONTENT_ID
), rID
,
1276 m_nIndex
[INETMSG_MIME_CONTENT_ID
]);
1279 void INetMIMEMessage::SetContentType (const String
& rType
)
1281 SetHeaderField_Impl (
1282 INetMIME::HEADER_FIELD_TEXT
,
1283 MIMEHDR(INETMSG_MIME_CONTENT_TYPE
), rType
,
1284 m_nIndex
[INETMSG_MIME_CONTENT_TYPE
]);
1287 void INetMIMEMessage::SetContentTransferEncoding (
1288 const String
& rEncoding
)
1290 SetHeaderField_Impl (
1291 INetMIME::HEADER_FIELD_TEXT
,
1292 MIMEHDR(INETMSG_MIME_CONTENT_TRANSFER_ENCODING
), rEncoding
,
1293 m_nIndex
[INETMSG_MIME_CONTENT_TRANSFER_ENCODING
]);
1297 * GetDefaultContentType.
1299 void INetMIMEMessage::GetDefaultContentType (String
& rContentType
)
1302 "text/plain; charset=us-ascii", RTL_TEXTENCODING_ASCII_US
);
1303 if (pParent
== NULL
)
1305 rContentType
= aDefaultCT
;
1309 String
aParentCT (pParent
->GetContentType());
1310 if (aParentCT
.Len() == 0)
1311 pParent
->GetDefaultContentType (aParentCT
);
1313 if (aParentCT
.CompareIgnoreCaseToAscii ("message/", 8) == 0)
1315 rContentType
= aDefaultCT
;
1317 else if (aParentCT
.CompareIgnoreCaseToAscii ("multipart/", 10) == 0)
1319 if (aParentCT
.CompareIgnoreCaseToAscii ("multipart/digest") == 0)
1320 rContentType
.AssignAscii ("message/rfc822");
1322 rContentType
= aDefaultCT
;
1326 rContentType
= aDefaultCT
;
1332 * EnableAttachChild.
1334 BOOL
INetMIMEMessage::EnableAttachChild (INetMessageContainerType eType
)
1340 // Setup Content-Type header field.
1341 ByteString aContentType
;
1344 case INETMSG_MESSAGE_RFC822
:
1345 aContentType
= "message/rfc822";
1348 case INETMSG_MULTIPART_ALTERNATIVE
:
1349 aContentType
= "multipart/alternative";
1352 case INETMSG_MULTIPART_DIGEST
:
1353 aContentType
= "multipart/digest";
1356 case INETMSG_MULTIPART_PARALLEL
:
1357 aContentType
= "multipart/parallel";
1360 case INETMSG_MULTIPART_RELATED
:
1361 aContentType
= "multipart/related";
1364 case INETMSG_MULTIPART_FORM_DATA
:
1365 aContentType
= "multipart/form-data";
1369 aContentType
= "multipart/mixed";
1373 // Setup boundary for multipart types.
1374 if (aContentType
.CompareIgnoreCaseToAscii ("multipart/", 10) == 0)
1376 // Generate a unique boundary from current time.
1377 sal_Char sTail
[16 + 1];
1379 sal_uInt64 nThis
= reinterpret_cast< sal_uIntPtr
>( this ); // we can be on a 64bit architecture
1380 nThis
= ( ( nThis
>> 32 ) ^ nThis
) & SAL_MAX_UINT32
;
1381 sprintf (sTail
, "%08X%08X",
1382 static_cast< unsigned int >(aCurTime
.GetTime()),
1383 static_cast< unsigned int >(nThis
));
1384 m_aBoundary
= "------------_4D48";
1385 m_aBoundary
+= sTail
;
1387 // Append boundary as ContentType parameter.
1388 aContentType
+= "; boundary=";
1389 aContentType
+= m_aBoundary
;
1392 // Set header fields.
1393 SetMIMEVersion (String (CONSTASCII_STRINGPARAM("1.0")));
1394 SetContentType (String (aContentType
, RTL_TEXTENCODING_ASCII_US
));
1395 SetContentTransferEncoding (String (CONSTASCII_STRINGPARAM("7bit")));
1404 BOOL
INetMIMEMessage::AttachChild (
1405 INetMIMEMessage
& rChildMsg
, BOOL bOwner
)
1407 if (IsContainer() /*&& rChildMsg.GetContentType().Len() */)
1409 if (bOwner
) rChildMsg
.pParent
= this;
1410 aChildren
.Insert (&rChildMsg
, LIST_APPEND
);
1411 nNumChildren
= aChildren
.Count();
1421 BOOL
INetMIMEMessage::DetachChild (
1422 ULONG nIndex
, INetMIMEMessage
& rChildMsg
) const
1426 // Check document stream.
1427 if (GetDocumentLB() == NULL
) return FALSE
;
1428 SvStream
*pDocStrm
= new SvStream (GetDocumentLB());
1430 // Initialize message buffer.
1431 char pMsgBuffer
[1024];
1432 char *pMsgRead
, *pMsgWrite
;
1433 pMsgRead
= pMsgWrite
= pMsgBuffer
;
1435 // Initialize message parser stream.
1436 INetMIMEMessageStream
*pMsgStrm
= NULL
;
1438 // Check for "multipart/uvw" or "message/xyz".
1441 // Multipart message body. Initialize multipart delimiters.
1442 ByteString
aDelim ("--");
1443 aDelim
+= GetMultipartBoundary();
1444 ByteString aClose
= aDelim
;
1447 // Initialize line buffer.
1448 SvMemoryStream aLineBuf
;
1450 // Initialize control variables.
1451 INetMessageStreamState eState
= INETMSG_EOL_SCR
;
1455 while (nCurIndex
< (int)(nIndex
+ 1))
1457 if ((pMsgRead
- pMsgWrite
) > 0)
1459 // Bytes still in buffer.
1460 if (eState
== INETMSG_EOL_FCR
)
1462 // Check for 2nd line break character.
1463 if ((*pMsgWrite
== '\r') || (*pMsgWrite
== '\n'))
1464 aLineBuf
<< *pMsgWrite
++;
1466 // Check current index.
1467 if (nCurIndex
== (int)nIndex
)
1469 // Found requested part.
1470 if (pMsgStrm
== NULL
)
1472 // Create message parser stream.
1473 pMsgStrm
= new INetMIMEMessageStream
;
1474 pMsgStrm
->SetTargetMessage (&rChildMsg
);
1477 // Put message down-stream.
1478 int status
= pMsgStrm
->Write (
1479 (const sal_Char
*) aLineBuf
.GetData(), aLineBuf
.Tell());
1480 if (status
!= INETSTREAM_STATUS_OK
)
1487 return (!(status
== INETSTREAM_STATUS_OK
));
1491 // Reset to <Begin-of-Line>.
1492 aLineBuf
.Seek (STREAM_SEEK_TO_BEGIN
);
1493 eState
= INETMSG_EOL_SCR
;
1495 else if ((*pMsgWrite
== '\r') || (*pMsgWrite
== '\n'))
1498 * Found any line break character.
1499 * Compare buffered line with part/close delimiter.
1500 * Increment current part index upon match.
1502 USHORT nLen
= (USHORT
)(aLineBuf
.Tell() & 0xffff);
1503 if (nLen
== aDelim
.Len())
1505 if (aDelim
.CompareTo ((const sal_Char
*) aLineBuf
.GetData(), nLen
)
1506 == COMPARE_EQUAL
) nCurIndex
++;
1508 else if (nLen
== aClose
.Len())
1510 if (aClose
.CompareTo ((const sal_Char
*) aLineBuf
.GetData(), nLen
)
1511 == COMPARE_EQUAL
) nCurIndex
++;
1513 aLineBuf
<< *pMsgWrite
++;
1514 eState
= INETMSG_EOL_FCR
;
1518 // Insert into line buffer.
1519 aLineBuf
<< *pMsgWrite
;
1524 // Buffer empty. Reset to <Begin-of-Buffer>.
1525 pMsgRead
= pMsgWrite
= pMsgBuffer
;
1527 // Read document stream.
1528 ULONG nRead
= pDocStrm
->Read (
1529 pMsgBuffer
, sizeof (pMsgBuffer
));
1532 // Set read pointer.
1540 // Assume end of requested part.
1545 // Requested part not found.
1551 } // while (nCurIndex < (nIndex + 1))
1555 // Encapsulated message body. Create message parser stream.
1556 pMsgStrm
= new INetMIMEMessageStream
;
1557 pMsgStrm
->SetTargetMessage (&rChildMsg
);
1559 // Initialize control variables.
1560 INetMessageStreamState eState
= INETMSG_EOL_BEGIN
;
1563 while (eState
== INETMSG_EOL_BEGIN
)
1565 if ((pMsgRead
- pMsgWrite
) > 0)
1567 // Bytes still in buffer. Put message down-stream.
1568 int status
= pMsgStrm
->Write (
1569 pMsgBuffer
, (pMsgRead
- pMsgWrite
));
1570 if (status
!= INETSTREAM_STATUS_OK
)
1577 return (!(status
== INETSTREAM_STATUS_ERROR
));
1579 pMsgWrite
= pMsgBuffer
+ (pMsgRead
- pMsgWrite
);
1583 // Buffer empty. Reset to <Begin-of-Buffer>.
1584 pMsgRead
= pMsgWrite
= pMsgBuffer
;
1586 // Read document stream.
1587 ULONG nRead
= pDocStrm
->Read (
1588 pMsgBuffer
, sizeof (pMsgBuffer
));
1591 // Set read pointer.
1597 eState
= INETMSG_EOL_DONE
;
1600 } // while (eState == INETMSG_EOL_BEGIN)
1604 if (pDocStrm
) delete pDocStrm
;
1605 if (pMsgStrm
) delete pMsgStrm
;
1614 SvStream
& INetMIMEMessage::operator<< (SvStream
& rStrm
) const
1616 INetRFC822Message::operator<< (rStrm
);
1618 for (USHORT i
= 0; i
< INETMSG_MIME_NUMHDR
; i
++)
1619 rStrm
<< static_cast<sal_uInt32
>(m_nIndex
[i
]);
1621 #ifdef ENABLE_BYTESTRING_STREAM_OPERATORS
1622 rStrm
<< m_aBoundary
;
1624 rStrm
.WriteByteString (m_aBoundary
);
1626 rStrm
<< static_cast<sal_uInt32
>(nNumChildren
);
1634 SvStream
& INetMIMEMessage::operator>> (SvStream
& rStrm
)
1636 INetRFC822Message::operator>> (rStrm
);
1639 for (USHORT i
= 0; i
< INETMSG_MIME_NUMHDR
; i
++)
1642 m_nIndex
[i
] = nTemp
;
1645 #ifdef ENABLE_BYTESTRING_STREAM_OPERATORS
1646 rStrm
>> m_aBoundary
;
1648 rStrm
.ReadByteString (m_aBoundary
);
1651 nNumChildren
= nTemp
;