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

Generated by: LCOV version 1.11