meetingrequest/mrversit2/src/cesmricalcontentlinereader.cpp
changeset 0 8466d47a6819
equal deleted inserted replaced
-1:000000000000 0:8466d47a6819
       
     1 /*
       
     2 * Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: This file implements class CESMRICalContentLineReader.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // Class include.
       
    20 #include "emailtrace.h"
       
    21 #include "cesmricalcontentlinereader.h" // CESMRICalContentLineReader
       
    22 
       
    23 //debug
       
    24 
       
    25 // System includes.
       
    26 #include <s32strm.h>    // RReadStream
       
    27 #include <utf.h>        // CnvUtfConverter
       
    28 
       
    29 // User includes.
       
    30 #include "esmricalkeywords.h"   // Literals.
       
    31 
       
    32 namespace
       
    33 {
       
    34 // Constants.
       
    35 const TInt KICalSkipWhiteSpaceLength = 1;
       
    36 const TInt KICalSkipCRLength = 1;
       
    37 const TInt KICalStartChar = 0;
       
    38 
       
    39 /*
       
    40 The iCalendar specification states that a content line should be no longer than
       
    41 75 octets in length, excluding the CRLF delimiter. It appears that MS Outlook
       
    42 does not include the length of the property string when calculating the length
       
    43 of a content line, meaning that a content line in an iCalendar exported from MS
       
    44 Outlook may be longer than the allowed 75 octets. KICalMaxContentLineLength
       
    45 allows a little extra space to support this.
       
    46 */
       
    47 const TInt KICalMaxContentLineLength = 120;
       
    48 }//namespace
       
    49 
       
    50 // ======== MEMBER FUNCTIONS ========
       
    51 
       
    52 // ---------------------------------------------------------------------------
       
    53 // CESMRICalContentLineReader::NewL
       
    54 // ---------------------------------------------------------------------------
       
    55 //
       
    56 CESMRICalContentLineReader* CESMRICalContentLineReader::NewL(RReadStream& aStream)
       
    57     {
       
    58     FUNC_LOG;
       
    59 
       
    60     CESMRICalContentLineReader* self = CESMRICalContentLineReader::NewLC(aStream);
       
    61     CleanupStack::Pop(self);
       
    62 
       
    63     return self;
       
    64     }
       
    65 
       
    66 // ---------------------------------------------------------------------------
       
    67 // CESMRICalContentLineReader::NewLC
       
    68 // ---------------------------------------------------------------------------
       
    69 //
       
    70 CESMRICalContentLineReader* CESMRICalContentLineReader::NewLC(RReadStream& aStream)
       
    71     {
       
    72     FUNC_LOG;
       
    73 
       
    74     CESMRICalContentLineReader* self = new (ELeave) CESMRICalContentLineReader(aStream);
       
    75     CleanupStack::PushL(self);
       
    76     self->ConstructL();
       
    77 
       
    78     return self;
       
    79     }
       
    80 
       
    81 // ---------------------------------------------------------------------------
       
    82 // CESMRICalContentLineReader::~CESMRICalContentLineReader
       
    83 // ---------------------------------------------------------------------------
       
    84 //
       
    85 CESMRICalContentLineReader::~CESMRICalContentLineReader()
       
    86     {
       
    87     FUNC_LOG;
       
    88 
       
    89     delete iCurrentLine;
       
    90     delete iNextLine;
       
    91 
       
    92     }
       
    93 
       
    94 // ---------------------------------------------------------------------------
       
    95 // CESMRICalContentLineReader::GetNextContentLine
       
    96 // ---------------------------------------------------------------------------
       
    97 //
       
    98 TInt CESMRICalContentLineReader::GetNextContentLine(TPtrC& aPtr)
       
    99     {
       
   100     FUNC_LOG;
       
   101 
       
   102     if (iFlags & EEof)
       
   103         {
       
   104         return KErrEof;
       
   105         }
       
   106 
       
   107     TInt error(KErrNone);
       
   108 
       
   109     // Trap errors as the stream will leave with KErrEof when we reach the end.
       
   110     TRAP(error, GetNextContentLineL());
       
   111 
       
   112     aPtr.Set(iCurrentLine->Des());
       
   113 
       
   114     if (error == KErrEof)
       
   115         {
       
   116         iFlags |= EEof;
       
   117         error = KErrNone;
       
   118         }
       
   119 
       
   120     return error;
       
   121     }
       
   122 
       
   123 // ---------------------------------------------------------------------------
       
   124 // CESMRICalContentLineReader::SkipComponentL
       
   125 // ---------------------------------------------------------------------------
       
   126 //
       
   127 void CESMRICalContentLineReader::SkipComponentL(const TDesC& aName)
       
   128     {
       
   129     FUNC_LOG;
       
   130 
       
   131     // Take a copy of the name, since GetNextContentLine may corrupt the original
       
   132     HBufC* beginName = aName.AllocLC();
       
   133 
       
   134     // Find the next BEGIN: or END:
       
   135     TPtrC contentLine;
       
   136     TInt error(GetNextContentLine(contentLine));
       
   137     while (error == KErrNone)
       
   138         {
       
   139         // Find the colon separator
       
   140         const TInt colonPos = contentLine.Locate(KICalColonChar);
       
   141         // If there isn't one it's an error
       
   142         if (colonPos == KErrNotFound)
       
   143             {
       
   144             User::Leave(KErrCorrupt);
       
   145             }
       
   146         // Find the string preceding the colon
       
   147         TPtrC name(contentLine.Left(colonPos));
       
   148         // If it's a begin, recursively skip this component also
       
   149         if (name.CompareF(KICalBegin) == 0)
       
   150             {
       
   151             TPtrC value(contentLine.Mid(colonPos + 1));
       
   152             SkipComponentL(value);
       
   153             }
       
   154         // If it's an end, check that it's the right end
       
   155         else if (name.CompareF(KICalEnd) == 0)
       
   156             {
       
   157             TPtrC value(contentLine.Mid(colonPos + 1));
       
   158             if (value.CompareF(*beginName) == 0)
       
   159                 {
       
   160                 // We have successfully skipped the component
       
   161                 CleanupStack::PopAndDestroy(beginName);
       
   162                 return;
       
   163                 }
       
   164             else
       
   165                 {
       
   166                 User::Leave(KErrCorrupt);
       
   167                 }
       
   168             }
       
   169         // If it is neither a begin nor an end, try the next line
       
   170         error = GetNextContentLine(contentLine);
       
   171         }
       
   172     // If any errors occur in reading we may as well leave with them
       
   173     if (error != KErrEof)
       
   174         {
       
   175         User::Leave(error);
       
   176         }
       
   177     // If we get this far we have failed to find an end
       
   178     User::Leave(KErrCorrupt);
       
   179 
       
   180     }
       
   181 
       
   182 // ---------------------------------------------------------------------------
       
   183 // CESMRICalContentLineReader::CESMRICalContentLineReader
       
   184 // ---------------------------------------------------------------------------
       
   185 //
       
   186 CESMRICalContentLineReader::CESMRICalContentLineReader(RReadStream& aStream)
       
   187     : iReadStream(aStream)
       
   188     {
       
   189     FUNC_LOG;
       
   190     //do nothing
       
   191     }
       
   192 
       
   193 // ---------------------------------------------------------------------------
       
   194 // CESMRICalContentLineReader::ConstructL
       
   195 // ---------------------------------------------------------------------------
       
   196 //
       
   197 void CESMRICalContentLineReader::ConstructL()
       
   198     {
       
   199     FUNC_LOG;
       
   200 
       
   201     iCurrentLine = HBufC::NewL(KICalMaxContentLineLength);
       
   202     iNextLine = HBufC::NewL(KICalMaxContentLineLength);
       
   203 
       
   204     }
       
   205 
       
   206 // ---------------------------------------------------------------------------
       
   207 // CESMRICalContentLineReader::GetLineL
       
   208 // ---------------------------------------------------------------------------
       
   209 //
       
   210 /**
       
   211 Reads from the stream to the next line feed.
       
   212 @param aPtr A modifiable pointer to a buffer to read the line into.
       
   213 @leave With KErrEof when the end of the stream is reached or KErrCorrupt if the
       
   214 line is invalid.
       
   215 @internalTechnology
       
   216 */
       
   217 void CESMRICalContentLineReader::GetLineL(TPtr& aPtr)
       
   218     {
       
   219     FUNC_LOG;
       
   220 
       
   221     // Read stream as binary. ReadL() will leave with KErrEof when the end of the stream
       
   222     // is reached. Note that we will ignore any text read when leaving as the line must end
       
   223     // with a carriage return (and line feed) to be valid.
       
   224     TBuf8<KICalMaxContentLineLength> text;
       
   225     iReadStream.ReadL(text, TChar(KICalCarriageReturnChar));    // Read up to the next CR.
       
   226 
       
   227     // Check next char is line feed
       
   228     TUint8 nextChar(iReadStream.ReadUint8L());
       
   229 
       
   230     if (nextChar != KICalNewlineChar)
       
   231         {
       
   232         User::Leave(KErrCorrupt);
       
   233         }
       
   234 
       
   235     // Handle any character set conversion here
       
   236     CnvUtfConverter::ConvertToUnicodeFromUtf8(aPtr, text);  // Convert from UTF-8.
       
   237 
       
   238     // Set the length of aPtr to exclude the carriage return.
       
   239     if (aPtr.Length())
       
   240         {
       
   241         aPtr.SetLength(aPtr.Length() - KICalSkipCRLength);
       
   242         }
       
   243 
       
   244     }
       
   245 
       
   246 // ---------------------------------------------------------------------------
       
   247 // CESMRICalContentLineReader::GetNextContentLineL
       
   248 // ---------------------------------------------------------------------------
       
   249 //
       
   250 /**
       
   251 Reads the next content line from the stream into aPtr. If the content line has
       
   252 been folded, it will be unfolded. After completion aPtr will point to the new
       
   253 content line
       
   254 @param aPtr TPtrC& to set to the new content line.
       
   255 @leave Leaves with KErrEof when we reach the end of the stream.
       
   256 @internalTechnology
       
   257 */
       
   258 void CESMRICalContentLineReader::GetNextContentLineL()
       
   259     {
       
   260     FUNC_LOG;
       
   261 
       
   262     TPtr currentLine(iCurrentLine->Des());
       
   263 
       
   264     if (iNextLine->Length() == 0)
       
   265         {
       
   266         // If iNextLine is empty then this is the first line of the file.
       
   267         GetLineL(currentLine);
       
   268         }
       
   269     else
       
   270         {
       
   271         // Copy iNextLine to currentLine.
       
   272         currentLine.Copy(*iNextLine);
       
   273         }
       
   274 
       
   275     // Get the next line.
       
   276     TPtr nextPtr(iNextLine->Des());
       
   277     GetLineL(nextPtr);
       
   278 
       
   279     // Folded lines are delimited by a CRLF followed by single whitepace
       
   280     while (iNextLine->Length() && ((nextPtr[KICalStartChar] == KICalSpaceChar) ||
       
   281         (nextPtr[KICalStartChar] == KICalHTabChar)))
       
   282         {
       
   283         // Append the lines - reallocate buffer if needed.
       
   284         if (currentLine.MaxLength() < (iCurrentLine->Length() + nextPtr.Length()))
       
   285             {
       
   286             iCurrentLine = iCurrentLine->ReAllocL(currentLine.MaxLength() + KICalMaxContentLineLength);
       
   287             currentLine.Set(iCurrentLine->Des());
       
   288             }
       
   289 
       
   290         currentLine.Append(nextPtr.Mid(KICalSkipWhiteSpaceLength));
       
   291         GetLineL(nextPtr);
       
   292         }
       
   293 
       
   294     }
       
   295 
       
   296 // End of File
       
   297