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

Generated by: LCOV version 1.10