LCOV - code coverage report
Current view: top level - libreoffice/tools/source/inet - inetmsg.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 494 0.0 %
Date: 2012-12-27 Functions: 0 44 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10