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