diff -r 000000000000 -r f979ecb2b13e pimappsupport/vcardandvcal/src/VERSIT.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pimappsupport/vcardandvcal/src/VERSIT.CPP Tue Feb 02 10:12:19 2010 +0200 @@ -0,0 +1,2997 @@ +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#include "versittlscontainer.h" +#include "versit_internal.h" +#endif + +// System includes +#include +#include +#include +#include +#include +#include +#include +#include + +// User includes +#include +#include +#include +#include "verror.h" +#include +#include +#include "VersitAdditionalStorage.h" + +// Constants +_LIT8(KReplacementChars, "?"); +const TInt KVersitDatePropertySymbianConnectMessageMaximumLenght=1; + +#define UNUSED_VAR(a) a = a + +// +// CLineReader +// + +EXPORT_C CLineReader* CLineReader::NewL(RReadStream& aStream) +/** Constructs and returns a CLineReader. + +@param aStream The stream to read the lines from. */ + { + CLineReader* self=new(ELeave) CLineReader(aStream); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +EXPORT_C void CLineReader::ConstructL() + { + iSkipWhiteSpaceAtStart=ETrue; + iLineBuf=HBufC8::NewL(EInitialLineSize); + iBufPtr=iLineBuf->Des(); +#if defined(__VC32__) + iBufPtr.Set(iLineBuf->Des()); // workaround for VC6 bug +#endif + iExtension=CLineReaderExtension::NewL(); + } + +EXPORT_C CLineReader::~CLineReader() +/** Frees all resources owned by the line reader prior to its destruction. */ + { + delete iLineBuf; + + if (iExtension && iReadStream) + { + if (iExtension->iSize - iExtension->iOffset > 0) + { + // there is data in the buffer that has not yet been parsed + // so we must adjust the seek pointer for the input stream to + // point exactly to the end of the data that has been parsed + // so that the rest will be re-read when the file is next accessed. + // The traps are neccesary because a destructor can't leave. + MStreamBuf* source = iReadStream->Source(); + if (source != NULL) + { + TStreamPos pos(0); + TRAPD(err, pos = source->TellL(MStreamBuf::ERead)); + if (err == KErrNone) + { + pos -= (iExtension->iSize - iExtension->iOffset); + TRAP(err, source->SeekL(MStreamBuf::ERead, pos)); + } + } + } + } + + delete iExtension; + } + +/** Read base64 multiple lines + +This should be only called when parsing multi-line base64 data, and the interface +MVersitPlugInExtensionBase64Ending::BlankLineAndLeadingSpaceNotRequired returns ETrue + +If the character ':' is not contained in the current line,we know it is base64 value.It is therefore appended to +iBufPtr. Otherwise we know it is a new property which will be held in CLineReaderExtension::iLineBase64Value +temporarily until the next propery is to be parsed. + +@param aPosValueStart The position in the iLineBuffer where base64 value starts +*/ +void CLineReader::ReadBase64ValueL(TInt aPosValueStart) + { + HBufC8* base64Buffer = iExtension->CreateBase64ValueBufferL();//Creat a buffer to hold a + + iBufPtr.Delete(0, aPosValueStart);//To make sure iBufPtr only contains base64 value + TInt err = KErrNone; + TInt ret = ELineIsWhiteSpace; + TPtr8 ptr = base64Buffer->Des(); + while (ret != ELineHasColon) + { + __ASSERT_DEBUG(ret==ELineHasContent ||ret==ELineIsWhiteSpace||ret==ELineIsCRLFOnly, Panic(ECurrentTokenNotFound)); + if (ret == ELineHasContent) + { + iLineBuf = iLineBuf->ReAllocL(iLineBuf->Length() + ptr.Length()); + iBufPtr.Set(iLineBuf->Des()); + iBufPtr.Append(ptr); + } + + ptr.SetLength(0); + ret = ReadLineL(base64Buffer, 0, err); + ptr.Set(base64Buffer->Des()); + } + } + +/** Reads in a line from the stream. + +The line is stored in a buffer pointed to by iBufPtr. Data from the stream +is appended to the buffer, starting at buffer position aPos, until the next +'CRLF' ("/r/n") is reached. The line feed and carriage return are not added +to the buffer. Using only linefeeds LF(\n) as the line delimiters is also supported. + +The buffer will be expanded if necessary to fit the line into it. + +If the end of stream is reached, aErr will contain KErrEof upon return. + +It would be normal to set aPos to the start of the buffer unless reading a +multi-line value. + +@param aPos The position in the buffer pointed to by iBufPtr at which to begin +appending data to the buffer. Allows lines to be appended to the buffer when +reading multi-line values. +@param aErr On return, this will be KErrEof if the end of the stream is reached +and KErrNone otherwise. +@return ELineHasContent if the line has content; ELineIsWhiteSpace if the line +has only white space before the CRLF; ELineIsCRLFOnly if the line is only +a CRLF. +*/ +EXPORT_C TInt CLineReader::ReadLineL(TInt aPos,TInt& aErr) + { + TInt ret = ELineHasContent; + HBufC8* base64Buffer = iExtension->Base64ValueBuffer(); + if(aPos==0 && base64Buffer && base64Buffer->Length()>0) + {//If the base64Buffer is not empty, we know the current line has + // already been read and the data is held in CLineReaderExtension::iLineBase64Value + // for a new property (see ReadBase64ValueL) + if(iBufPtr.MaxLength() < base64Buffer->Length()) + { + iLineBuf = iLineBuf->ReAllocL(base64Buffer->Length()); + } + + *iLineBuf = *base64Buffer; + iBufPtr.Set(iLineBuf->Des()); + iBufPtr.SetLength(base64Buffer->Length()); + iExtension->DeleteBase64ValueBuffer(); + } + else //Otherwise read the current line + { + ret = ReadLineL(iLineBuf, aPos, aErr); + if(ret == ELineHasColon) + { + ret = ELineHasContent;//For the sake of backwards compatability - ELineHasColon is only used by ReadBase64ValueL. + } + iBufPtr.Set(iLineBuf->Des()); + } + + return ret; + } + +TInt CLineReader::ReadLineL(HBufC8*& aHBuf, TInt aPos,TInt& aErr) +/** Reads in a line from the stream. + +The line is stored in a buffer pointed to by aHBuf. Data from the stream +is appended to the buffer, starting at buffer position aPos, until the next +'CRLF' ("/r/n") is reached. The line feed and carriage return are not added +to the buffer. Using only linefeeds LF(\n) as the line delimiters is also supported. + +The buffer will be expanded if necessary to fit the line into it. + +If the end of stream is reached, aErr will contain KErrEof upon return. + +It would be normal to set aPos to the start of the buffer unless reading a +multi-line value. + +@param aPos The position in the buffer pointed to by aHBuf at which to begin +appending data to the buffer. Allows lines to be appended to the buffer when +reading multi-line values. +@param aErr On return, this will be KErrEof if the end of the stream is reached +and KErrNone otherwise. +@return +ELineHasContent if the line has content; +ELineIsWhiteSpace if the line has only white space before the CRLF; +ELineIsCRLFOnly if the line is only a CRLF. +EELineHasColon If character ':' contained in the line +*/ + { + TInt crPos=-1; + TUint8 ch=STATIC_CAST(TUint8,iFirstCharNextLine); + TInt whiteSpaceLine=ELineIsCRLFOnly; + TBool truncateLine=ETrue; + TBool skipWhiteSpaceAtStart=iSkipWhiteSpaceAtStart; + TPtr8 ptrHbuf = aHBuf->Des(); + ptrHbuf.SetLength(aPos); + if (iFirstCharNextLine>=0) + { + iFirstCharNextLine=-1; + goto CharacterRead; + } + FOREVER + { + ch=ReadChar(aErr); + if (aErr!=KErrEof) + User::LeaveIfError(aErr); + else + { + crPos=aPos-1; + while (crPos>=0 && (ptrHbuf[crPos]==CVersitParser::ELineFeed || ptrHbuf[crPos]==CVersitParser::ECarriageReturn)) + { + --crPos; + } + truncateLine=(++crPosDeleteAllSpaces(); + } + else + { + if (aPos==ptrHbuf.MaxLength()) + { + aHBuf=aHBuf->ReAllocL(aPos+EExpandSize); + ptrHbuf.Set(aHBuf->Des()); + } + + ++aPos; + ptrHbuf.Append(ch); + } + } + if (truncateLine) + ptrHbuf.SetLength(crPos); + return whiteSpaceLine; + } + +EXPORT_C TBool CLineReader::AppendLineIfSpaceNextL() +/** Checks the first character of the next line and, if it is a white space, reads +the next line into the buffer (pointed to by iBufPtr). + +The line is appended to the buffer rather than overwriting data already in +the buffer. + +A plug-in option can determine that no space is to be written to the buffer +between the lines. By default, a space will be written. + +Used by the Versit parser while it is reading multi-line property values. + +@return ETrue if a line was read (because the first character of the next +line is a space); EFalse if a line wasn't read (because the first character +of the next line isn't a space or an error occured). */ + { + TInt err=KErrNone; + if (iFirstCharNextLine<0) + iFirstCharNextLine=ReadChar(err); + if (err!=KErrNone || !VersitUtils::IsWhiteSpace(iFirstCharNextLine)) + return EFalse; + TInt len; + if (iPlugIn && !iPlugIn->AddSpace()) + len=iBufPtr.Length(); + else + len=AppendSpaceL(); + ReadLineL(len,err); + return ETrue; + } + +EXPORT_C TBool CLineReader::IsSpaceNextL() +/** Checks to see if the first character of the next line is white space. + +This function should not be called more than once without a line being read +in. + +Used by the Versit parser while it is reading multi-line property values. + +@return ETrue if the next line starts with a white space character; EFalse +if it doesn't or an error occurs. */ + { + TInt err; + iFirstCharNextLine=ReadChar(err); + return (err==KErrNone && VersitUtils::IsWhiteSpace(iFirstCharNextLine)); + } + +EXPORT_C TInt CLineReader::AppendSpaceL() +/** Appends a space to the end of the buffer (pointed to by iBufPtr). + +The buffer will be expanded if necessary. + +This is called by AppendLineIfSpaceNextL() to create a space in the buffer +between the lines being read (as long as there is no plug-in option to to +indicate there should be no space). + +@param The length of the buffer after the space has been added. */ + { + TInt len=iBufPtr.Length(); + if (len==iBufPtr.MaxLength()) + ExpandBufferL(len); + iBufPtr.Append(CVersitParser::ESpace); + return len+1; + } + +EXPORT_C void CLineReader::ExpandBufferL(TInt aCurrentSize) + { + iLineBuf=iLineBuf->ReAllocL(aCurrentSize+EExpandSize); + iBufPtr.Set(iLineBuf->Des()); + } + +EXPORT_C TUint8 CLineReader::ReadChar(TInt& aErr) + { + // Return the next character from the read buffer. If it is the + // end of the buffer or it is empty then refill the buffer. + aErr = KErrNone; + if (iExtension->iOffset >= iExtension->iSize) + { + iExtension->iOffset = 0; + MStreamBuf* source = iReadStream->Source(); + TRAP(aErr, iExtension->iSize = source->ReadL(iExtension->iBuf, 1024)); + if (aErr != KErrNone) + { + return 0; + } + if (iExtension->iSize == 0) + { + aErr = KErrEof; + return 0; + } + } + return iExtension->iBuf[iExtension->iOffset++]; + } + +EXPORT_C void CLineReader::Reserved() + {} + + +// +// CVersitParser +// + +EXPORT_C CVersitParser::CVersitParser(TUint aFlags) : iFlags(aFlags) +/** The first phase constructor for a Versit parser. + +Sets the default encoding to Versit::ENoEncoding and the default character +set to Versit::EUSAsciiCharSet. + +Note: this function is called by the CParserVCal and CParserVCard constructors. It +should only be called directly by a user if creating a new parser + +@param aFlags The flag to indicate whether this entity needs a version property. +The possible values for this flag are given in the TVersitParserFlags enumeration. +If a version property is needed, one will be created and appended to the +start of the array of properties. */ + { + SetDefaultEncoding(Versit::ENoEncoding); + SetDefaultCharSet(Versit::EUSAsciiCharSet); + + RestoreLineCodingDetailsToDefault(); + } + +void CloseTlsData(TAny *aData) + { + CVersitTlsData *data = static_cast(aData); + data->CloseVersitTlsData(); + } + +EXPORT_C void CVersitParser::ConstructL() +/** The second phase constructor for a Versit parser. + +Stores a pointer to a CVersitTlsData (thread local storage data class). This +is used to allow an instance of CVersitUnicodeUtils to be shared by all co-existing +parsers, which provides a major performance improvement. + +Called by the CParserVCal and CParserVCard constructors. + +Should only be called directly by a user if creating a new parser. */ + { + _LIT8(KEscapeCharacter8, "\\"); + iStaticUtils=&CVersitTlsData::VersitTlsDataL(); + + //query charconv for the plugin dependant shift-jis escape character, + //store in TLS to be accessed by versit static utils + CCnvCharacterSetConverter::TAvailability avail=UnicodeUtils().SetCurrentCharSetL(KCharacterSetIdentifierShiftJis); + if (avail == CCnvCharacterSetConverter::EAvailable) + { + // Do the conversion + CCnvCharacterSetConverter& converter=UnicodeUtils().CharacterSetConverter(); + TInt ignore = 0; + converter.SetReplacementForUnconvertibleUnicodeCharactersL(KReplacementChars); + + CVersitTlsData& data = CVersitTlsData::VersitTlsDataL(); + CleanupStack::PushL( TCleanupItem( CloseTlsData, &data ) ); + + CVersitAdditionalStorage& additionalStorage = data.AdditionalStorage(); + CBase* storedValue = additionalStorage.FromStorage(KTLSVars); + + if( NULL == storedValue ) + { + CVersitTLSContainer *tlsContainer = CVersitTLSContainer::NewLC(2); + TPtrC8 ptr8 = KEscapeCharacter8(); + TPtr ptr16( tlsContainer->iShiftJisEscape->Des() ); + converter.ConvertToUnicode(ptr16, ptr8, ignore); + additionalStorage.AddToStorageL(KTLSVars, tlsContainer); + CleanupStack::Pop( tlsContainer ); + } + + CleanupStack::PopAndDestroy();//data + } + } + +EXPORT_C CVersitParser::~CVersitParser() +// Note: CVersitParser never owns iReadStream/iWriteStream +/** Frees all resources owned by the object, prior to its destruction. */ + { + if (iArrayOfEntities) + { + iArrayOfEntities->ResetAndDestroy(); + delete iArrayOfEntities; + } + if (iArrayOfProperties) + { + iArrayOfProperties->ResetAndDestroy(); + delete iArrayOfProperties; + } + delete iCurrentProperty; + delete iEntityName; + delete iOwnedLineReader; + delete iLargeDataBuf; + delete iDecodedValue; + + // Close any TLS storage + if (iStaticUtils) + iStaticUtils->VersitTlsDataClose(); + } + +EXPORT_C void CVersitParser::InternalizeL(RFile& aInputFile,TInt& aBytesThroughFile) +/** Internalises a versit entity (vCard or vCalendar) and all of its +sub-entities and properties from a file. + +Stores all date/time in same format as received + +@param aInputFile The file from which to internalise the entity. +@param aBytesThroughFile The number of bytes into the file at which to begin +reading. On return, is updated to contain the last position in the file which +was read. +@leave KErrEof The file position specified is beyond the end of the file. */ + { + TInt size; + if (aInputFile.Size(size)==KErrNone) + { + RFileReadStream stream(aInputFile,aBytesThroughFile); + TInt size=stream.Source()->SizeL(); + TRAPD(err,InternalizeL(stream)); + if (err==KErrNone) + TRAP(err,aBytesThroughFile+=(size-stream.Source()->SizeL())); + STATIC_CAST(RFileBuf*,stream.Source())->Reset(); + stream.Close(); + User::LeaveIfError(err); + } + } + +EXPORT_C void CVersitParser::InternalizeL(RReadStream& aStream) +/** Internalises a Versit entity (vCard or vCalendar) contained in the incoming stream +and parses it, breaking it down into its constituent sub-entities (e.g. to-dos, +events, and nested vCards) and properties. + +The presence of this function means that the standard templated operator>>() +(defined in s32strm.h) is available to internalise objects of this class. + +This virtual function serves as a base function for derived classes to internalise an entity. + +@param aStream Stream from which the vCalendar should be internalised. */ + { + iOwnedLineReader=CLineReader::NewL(aStream); + iOwnedLineReader->SetPlugIn(iPlugIn); + iLineReader=iOwnedLineReader; + + TRAPD(err,DoInternalizeL()); + + delete iDecodedValue; + iDecodedValue=NULL; + delete iOwnedLineReader; + iOwnedLineReader=NULL; + iLineReader=NULL; + + User::LeaveIfError(err); + } + +void CVersitParser::DoInternalizeL() + { + iParseBegin = TRUE; + ParseBeginL(); + iParseBegin = FALSE; + + do + { + delete iCurrentProperty; + iCurrentProperty=NULL; + ParsePropertiesL(); + } while(ParseEntityL()); + ParseEndL(); + } + +EXPORT_C void CVersitParser::InternalizeL(HBufC* aEntityName,CLineReader* aLineReader) +/** Internalises a vCalendar or vCard sub-entity. + +(Assumes "BEGIN : CRLF" has been parsed). + +This virtual function serves as a base function for derived classes to parse a +sub-entity. + +@param aEntityName The entity name to be parsed. Ownership of aEntityName is taken by +the parser. +@param aLineReader Pointer to a line reader which is used by the super-entity. */ + { + iLineReader=aLineReader; + + ParsePropertiesL(); + ParseEndL(*aEntityName); + + delete iEntityName; + iEntityName = aEntityName; + + iLineReader=NULL; + delete iDecodedValue; + iDecodedValue=NULL; + } + +EXPORT_C void CVersitParser::ExternalizeL(RFile& aOutputFile) +/** Externalises a Versit entity (vCard or vCalendar) and all of its sub-entities +and properties to a file. + +Adds a version property to the start of the current entity's array of properties +if the entity supports this. + +This is a thin layer over the CVersitParser::ExternalizeL(RWriteStream& aStream) +function to enable a versit entity to be externalised into an RFile. + +@param aOutputFile The file to which to write the entity. */ + { + RFileWriteStream stream(aOutputFile); + CleanupClosePushL(stream); + ExternalizeL(stream); + CleanupStack::PopAndDestroy(&stream); + } + +EXPORT_C void CVersitParser::ExternalizeL(RWriteStream& aStream) +/** Externalises a Versit entity (vCard or vCalendar) and all of its sub-entities +and properties to a write stream. + +Adds a version property to the start of the current entity's array of properties +if the entity supports this. (If there isn't an array of properties then one is made). + +The presence of this function means that the standard templated operator<<() (defined +in s32strm.h) is available to externalise objects of this class. + +This virtual function serves as a base function for derived classes to externalise +an entity. + +@param aStream Stream to which the entity should be externalised. */ + { + iWriteStream=&aStream; + + if (SupportsVersion()) + { + if (!iArrayOfProperties) + iArrayOfProperties = new(ELeave)CArrayPtrFlat(5); + TUid uid = TUid::Uid(KVersitPropertyHBufCUid); + + // get properties but don't take ownership of the elements of the array + CArrayPtr* properties = PropertyL(KVersitTokenVERSION, uid, EFalse); + if (properties) + delete properties; + else //Need to add a version property + { + CParserPropertyValue* value = CParserPropertyValueHBufC::NewL(iDefaultVersion); + value->SetPlugIn(iPlugIn); + CleanupStack::PushL(value); + CParserProperty* property = CParserProperty::NewL(*value, KVersitTokenVERSION, NULL); + CleanupStack::Pop(value); + CleanupStack::PushL(property); + iArrayOfProperties->InsertL(0,property); + CleanupStack::Pop(property); + } + } + AppendBeginL(); + if (iArrayOfProperties) + { + TInt noOfProperties=iArrayOfProperties->Count(); + for (TInt ii=0; iiExternalizeL(aStream, this); + } + } + if (iArrayOfEntities) + { + const TInt noOfEntities = iArrayOfEntities->Count(); + for (TInt ii=0; iiAt(ii); + // + entity.SetDefaultCharSet(DefaultCharSet()); + entity.SetDefaultEncoding(DefaultEncoding()); + // + entity.ExternalizeL(aStream); + } + } + AppendEndL(); + iWriteStream = NULL; + } + +/*void CVersitParser::AddTimeZonePropertyL() //Function that may be useful one day + { + TLocale locale; + TTimeIntervalSeconds offSet(locale.UniversalTimeOffset()); + CParserPropertyValue* timeZone=new(ELeave)CParserPropertyValueTimeZone(offSet); + CleanupStack::PushL(timeZone); + CParserProperty* property = CParserProperty::NewL(*timeZone,KVersitTokenTZ,NULL); + CleanupStack::Pop(timeZone); + CleanupStack::PushL(property); + iArrayOfProperties->InsertL(0,property); + CleanupStack::Pop(property); + }*/ + +EXPORT_C void CVersitParser::AddPropertyL(CParserProperty* aProperty,TBool aInternalizing) +/** Appends a property to the current entity's array of properties. + +This function may be used when building up a Versit parser object from +a client application. It is not called internally. + +@param aProperty Pointer to the property to add to the entity. +@param aInternalizing This parameter is used to distinguish between reading +an entity from a stream or file (i.e. internalising), in which case the argument +should have a value of ETrue, and building an entity "by hand" (e.g. creating +a vCard in the Contacts application), in which case the argument should have +a value of EFalse. */ + { + if (!aProperty) + return; + + TUid tokenId=RecognizeToken(aProperty->Name()); + CleanupStack::PushL(aProperty); + + if ((tokenId.iUid==KVersitTokenUnknownUid) && aProperty->Name().CompareF(KVersitTokenATTACH)==0) + { + tokenId.iUid = KVersitPropertyBinaryUid;//In vCal standard, default value is binary + CParserParam* valueParam = aProperty->Param(KVersitTokenVALUE); + if (valueParam) + { + TPtrC8 pParameterValue(valueParam->Value()); + + if (pParameterValue.CompareF(KVersitTokenINLINE) && pParameterValue.CompareF(KVersitTokenBINARY)) + {//If VALUE isn't specified as INLINE or BINARY, value is text type. + tokenId.iUid = KVersitPropertyHBufCUid; + } + } + } + + aProperty->SetNameUid(tokenId); + + if ((tokenId.iUid==KVersitTokenUnknownUid) && !aInternalizing) + { + //Do not prefix X-EPOC incase the property already has a prefix X- at the begining + if(aProperty->NameBuf()->Find(KVersitTokenXDash)!=0) + { + HBufC8*& name=aProperty->NameBuf(); + HBufC8* newName=HBufC8::NewL(name->Length()+KVersitTokenXDashEPOC.iTypeLength); + TPtr8 ptr=newName->Des(); + ptr=KVersitTokenXDashEPOC; + ptr+=*name; + delete name; + name=newName; + } + } + + DoAddPropertyL(aProperty); + CleanupStack::Pop(aProperty); + } + +EXPORT_C void CVersitParser::DoAddPropertyL(CParserProperty* aProperty) + { + if (!aProperty) + return; + + if (!iArrayOfProperties) + iArrayOfProperties = new(ELeave)CArrayPtrFlat(5); + + if (aProperty->Value()) + aProperty->Value()->SetPlugIn(iPlugIn); + iArrayOfProperties->AppendL(aProperty); + } + + +EXPORT_C void CVersitParser::AddEntityL(CVersitParser* aEntity) +/** Adds a sub-entity (e.g. a to-do, event or a nested vCard) to the current entity. + +Sets the default encoding and character set to the default ones of the current +Versit parser, then adds the entity to the array of entities owned by the +parser. + +Note: This function may be used when building up a Versit parser object from +a client application. + +Called by ParseEntityL(). + +@param aEntity The entity to be added into the array of entities. Ownership +of aEntity is taken at beginning of the function. */ + { + CleanupStack::PushL(aEntity); + + if (!iArrayOfEntities) + iArrayOfEntities = new(ELeave)CArrayPtrFlat(5); + + if (aEntity) + { + // Ensure that the entity contains the same defaults as this parser + aEntity->SetDefaultCharSet(DefaultCharSet()); + aEntity->SetDefaultEncoding(DefaultEncoding()); + // + aEntity->SetLineCharacterSet(LineCharSet()); + aEntity->SetLineEncoding(LineEncoding()); + // + iArrayOfEntities->AppendL(aEntity); + } + + CleanupStack::Pop(); //aEntity + } + +EXPORT_C CArrayPtr* CVersitParser::EntityL(const TDesC& aEntityName,TBool aTakeOwnership) +/** Gets all sub-entities in the current entity, whose name matches the +name specified. + +@param aEntityName The sub-entity name of interest, e.g. KVersitVarTokenVEVENT or +KVersitVarTokenVTODO. All sub-entities which match this name are returned in the +array of pointers. +@param aTakeOwnership If ETrue, the calling code takes ownership of each matching +sub-entity, in which case the sub-entities are deleted from the current object's +array of entities. If EFalse, ownership remains with the Versit parser. +@return An array of pointers to all sub-entities with the specified name. +(Ownership is taken by the calling code). */ + { + CArrayPtr* arrayOfNamedEntities = NULL; + if (iArrayOfEntities) + { + TInt entities=iArrayOfEntities->Count(); + arrayOfNamedEntities=new(ELeave) CArrayPtrFlat(5); + //CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfEntities,arrayOfNamedEntities)); + CleanupStack::PushL(arrayOfNamedEntities); + for (TInt ii=0; iiEntityName()==aEntityName) + { + arrayOfNamedEntities->AppendL((*iArrayOfEntities)[ii]); + } + } + CleanupStack::Pop(); //arrayOfNamedEntities + if (arrayOfNamedEntities->Count() == 0) + { + delete arrayOfNamedEntities; + arrayOfNamedEntities = NULL; + } + else if(aTakeOwnership) + { + for (TInt ii = entities-1; ii>=0; --ii) + { + if ((*iArrayOfEntities)[ii]->EntityName()==aEntityName) + { + iArrayOfEntities->Delete(ii); + } // if + } // for + } // else if + } + return arrayOfNamedEntities; + } + +EXPORT_C CArrayPtr* CVersitParser::ArrayOfEntities(TBool aTakeOwnership) +/** Gets the current entity's array of sub-entities. + +Note: the current entity may be a top level entity, or may itself be a sub-entity. + +@param aTakeOwnership If ETrue, the calling code takes ownership of the array; +the array of entities owned by the current entity is then deleted. If EFalse, +ownership remains with the Versit parser. +@return Array of pointers to the current entity's array of sub-entities. */ + { + CArrayPtr* arrayOfEntities=iArrayOfEntities; + if (aTakeOwnership) + iArrayOfEntities=NULL; + return arrayOfEntities; + } + +EXPORT_C CArrayPtr* CVersitParser::PropertyL(const TDesC8& aPropertyName,const TUid& aPropertyUid,TBool aTakeOwnership) const +/** Gets all properties in the current entity's array of properties whose name and +value match the name and value specified. + +@param aPropertyName The property name of interest. Property names are defined +in vtoken.h. +@param aPropertyUid The ID of the property value of interest (which has the +format "KPropertyUid"). The values are defined in file vuid.h. +@param aTakeOwnership If ETrue, the calling code takes ownership of each matching +property; the property is then deleted from the current entity's array. If +EFalse, ownership remains with the entity. +@return An array of pointers to all properties with the name and value specified, +or NULL if there are none. */ + { + CArrayPtr* arrayOfNamedProperties = NULL; + if (iArrayOfProperties) + { + const TInt properties = iArrayOfProperties->Count(); + arrayOfNamedProperties = new(ELeave) CArrayPtrFlat(5); + //CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfProperties, arrayOfNamedProperties)); + CleanupStack::PushL(arrayOfNamedProperties); + CParserProperty* parserProperty = NULL; + for (TInt ii = 0; ii < properties; ++ii) + { + parserProperty = (*iArrayOfProperties)[ii]; + if (parserProperty->Value() && parserProperty->Name().CompareF(aPropertyName)==0) + { + if(parserProperty->Value()->Uid()==aPropertyUid || aPropertyUid == KNullUid) + { + arrayOfNamedProperties->AppendL(parserProperty); + } + } + } + CleanupStack::Pop(arrayOfNamedProperties); + if (arrayOfNamedProperties->Count() == 0) + { + delete arrayOfNamedProperties; + arrayOfNamedProperties = NULL; + } + else if (aTakeOwnership) + { + for (TInt ii = properties-1; ii>=0; --ii) + { + parserProperty = (*iArrayOfProperties)[ii]; + if (parserProperty->Name().CompareF(aPropertyName)==0) + { + if (parserProperty->Value()->Uid()==aPropertyUid || aPropertyUid == KNullUid) + { + iArrayOfProperties->Delete(ii); + } + } + } + } + } + return arrayOfNamedProperties; + } + +EXPORT_C CArrayPtr* CVersitParser::ArrayOfProperties(TBool aTakeOwnership) +/** Gets the current entity's array of properties. + +@param aTakeOwnership If ETrue, the calling code takes ownership of the array; +the entity's array of properties is then deleted . If EFalse, ownership +remains with the entity. +@return Array of pointers to the entity's properties. */ + { + CArrayPtr* arrayOfProperties=iArrayOfProperties; + if (aTakeOwnership) + iArrayOfProperties=NULL; + return arrayOfProperties; + } + +EXPORT_C void CVersitParser::SetEntityNameL(const TDesC& aEntityName) +/** Sets the name for the current entity to one of: VCARD, VCALENDAR, VEVENT or +VTODO. + +@param aEntityName The new name for the current parser entity. Any existing +name is first deleted. +@leave KErrNoMemory Memory is allocated for the new entity name on the heap, +so it can leave if there is insufficient memory available. */ + { + delete iEntityName; + iEntityName = NULL; + iEntityName = aEntityName.AllocL(); + } + +EXPORT_C TPtrC CVersitParser::EntityName() const +/** Gets the current entity's name. + +If no name has been set, returns an empty descriptor. + +@return The current entity's name. */ + { + if (iEntityName) + return iEntityName->Des(); + return KVersitTokenEmpty(); + } + +EXPORT_C TBool CVersitParser::IsValidLabel(const TDesC& aLabel, TInt& aPos) +/** Tests whether a property name is valid. + +The property name is invalid if it contains any of the following characters:- + +[] (left or right square bracket) + += (equals sign) + +: (colon) + +. (dot) + +, (comma) + +@param aLabel The property name to test. +@param aPos On return, contains the character position within the property +name of the first invalid character found. +@return ETrue if valid, EFalse if invalid. */ + { + return !(((aPos = aLabel.Locate(KVersitTokenLSquareBracketVal)) != KErrNotFound) || + ((aPos = aLabel.Locate(KVersitTokenRSquareBracketVal)) != KErrNotFound) || + ((aPos = aLabel.Locate(KVersitTokenEqualsVal)) != KErrNotFound) || + ((aPos = aLabel.Locate(KVersitTokenColonVal)) != KErrNotFound) || + ((aPos = aLabel.Locate(KVersitTokenPeriodVal)) != KErrNotFound) || + ((aPos = aLabel.Locate(KVersitTokenCommaVal)) != KErrNotFound)); + } + +EXPORT_C CArrayPtr* CVersitParser::ReadLineAndDecodeParamsLC(TInt& aValueStart,TInt& aNameLen) + { + //Read in line from stream skipping lines made up only of white space TChar + TInt err; + do + { + const TInt readLineResponse = iLineReader->ReadLineL(0,err); + if (readLineResponse == CLineReader::ELineIsWhiteSpace || readLineResponse == CLineReader::ELineIsCRLFOnly) + { + aValueStart = 0; + } + else + { + TBool continueSearch; + do + { + continueSearch = EFalse; + aValueStart = BufPtr().Find(KVersitTokenColon) + 1; + if (aValueStart == 0) + { + continueSearch = iLineReader->AppendLineIfSpaceNextL(); + } + } + while (continueSearch && aValueStart == 0); + } + } + while (aValueStart==0 && err!=KErrEof); + // + if (aValueStart==0) + User::Leave(err); + iFlags&=~ECharSetIdentified; + + if(iFlags & EUseDefaultCharSetForAllProperties) + { + SetLineCharacterSet(DefaultCharSet()); + iFlags|= ECharSetIdentified; + } + + //Scan for semi-colon and split off params + CArrayPtr* arrayOfParams=NULL; + aNameLen=BufPtr().Find(KVersitTokenSemiColon); //First ";" can't be escaped + TInt lenParams=aValueStart-aNameLen-2; + if (aNameLen==KErrNotFound || lenParams<=0) + { + aNameLen=(lenParams==0&&aNameLen>=0 ? aNameLen:aValueStart-1); + CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfParams,arrayOfParams)); + } + else + { + TPtr8 params(&BufPtr()[aNameLen+1],lenParams,lenParams); + arrayOfParams=GetPropertyParamsLC(params); + AnalysesEncodingCharset(arrayOfParams); + } + return arrayOfParams; + } + +EXPORT_C void CVersitParser::MakePropertyL(TPtr8& aPropName,TInt aValueStart) + { + VersitUtils::StripWhiteSpace(aPropName); + TUid propertyUid=RecognizeToken(aPropName); + iCurrentProperty->SetNameL(aPropName); + //Deal with the value + TInt lenValue=BufPtr().Length()-aValueStart; + TPtr8 propValue(NULL,0); + if (lenValue>0) + propValue.Set(&BufPtr()[aValueStart],lenValue,lenValue); + TBool beginOrEnd=VersitUtils::IsBeginOrEnd(propertyUid); + TBool readMultiLine=!beginOrEnd; + Versit::TVersitEncoding encoding=Versit::ENoEncoding; + if (!readMultiLine) + { + encoding=LineEncoding(); + readMultiLine=(encoding==Versit::EBase64Encoding || encoding==Versit::EQuotedPrintableEncoding); + } + /** + Ignore junk lines between vCal entities. + Skip readMultiLine within ParseBegin. + */ + if (readMultiLine && !iParseBegin) + + { + CParserParam* valueParam = iCurrentProperty->Param(KVersitTokenVALUE); + if (valueParam) + { + TPtrC8 pParameterValue(valueParam->Value()); + + if (!pParameterValue.CompareF(KVersitTokenINLINE)) + { + encoding = Versit::EBase64Encoding; + } + } + + TBool isBinary = ((propertyUid.iUid==KVersitPropertyBinaryUid) || + ((propertyUid.iUid==KVCalPropertyExtendedAlarmUid) && (encoding==Versit::EBase64Encoding))); + ReadMultiLineValueL(propValue, aValueStart, isBinary); + } + if (beginOrEnd) + { + VersitUtils::StripWhiteSpace(propValue); + if (encoding!=Versit::EBase64Encoding) + propValue.UpperCase(); + } + iCurrentProperty->SetNameUid(propertyUid); + + HBufC* valueBuf=DecodePropertyValueL(propValue); + CleanupStack::PushL(TCleanupItem(DestroyHBufC, &valueBuf)); + if (iPlugIn && (valueBuf != NULL)) + { + TPtr ptr(valueBuf->Des()); + #if defined(__VC32__) // workaround for VC6 bug + ptr.Set(valueBuf->Des()); + #endif + iPlugIn->RemoveEscaping(ptr); + } + CParserPropertyValue* value = MakePropertyValueL(propertyUid,valueBuf); + delete iLargeDataBuf; + iLargeDataBuf=NULL; + iCurrentProperty->SetValue(value); + CleanupStack::PopAndDestroy(&valueBuf); + + } + +EXPORT_C void CVersitParser::ParsePropertyL() + { + TInt valueStart; + TInt lenName; + CArrayPtr* arrayOfParams=ReadLineAndDecodeParamsLC(valueStart,lenName); + delete iCurrentProperty; + iCurrentProperty=NULL; + iCurrentProperty=new(ELeave) CParserProperty(arrayOfParams); + CleanupStack::Pop(arrayOfParams); + if (lenName>0) + { + TPtr8 propName(&BufPtr()[0],lenName,lenName); + MakePropertyL(propName,valueStart); + } + } + +EXPORT_C void CVersitParser::ReadMultiLineValueL(TPtr8& aValue,TInt aValueStart,TBool aBinaryData) + { + if (iLargeDataBuf) + iLargeDataBuf->Reset(); + Versit::TVersitEncoding encoding=LineEncoding(); + TInt lineLen=BufPtr().Length(); + TInt err; + TBool secondLine=ETrue; + __ASSERT_DEBUG(encoding!=Versit::EEightBitEncoding, Panic(EVersitPanicUnexpectedEightBitEncoding)); + if (encoding!=Versit::EBase64Encoding) + { + if (encoding==Versit::EQuotedPrintableEncoding) + { + iLineReader->SetSkipWhiteSpaceAtStart(EFalse); // avoid space skiping for Quoted Printable encoding + } + TBool moreLinesToCome=ETrue; + if (encoding!=Versit::EQuotedPrintableEncoding) + moreLinesToCome=iLineReader->IsSpaceNextL(); + while (moreLinesToCome && (BufPtr()[lineLen-1]==KVersitTokenEqualsVal || encoding!=Versit::EQuotedPrintableEncoding)) + { + if (secondLine) + { + lineLen-=aValueStart; + BufPtr()=BufPtr().Mid(aValueStart,lineLen); + secondLine=EFalse; + } + if (encoding==Versit::EQuotedPrintableEncoding) + { + --lineLen; + moreLinesToCome=!iLineReader->ReadLineL(lineLen,err); + } + else if (lineLen==0) + { + iLineReader->ReadLineL(lineLen,err); + moreLinesToCome=iLineReader->IsSpaceNextL(); + } + else + { + moreLinesToCome=iLineReader->AppendLineIfSpaceNextL(); + } + lineLen=BufPtr().Length(); + } + iLineReader->SetSkipWhiteSpaceAtStart(ETrue); //The SetSkipWhiteSpaceAtStart function as been added for a defect fixing this line ensure that every other code calling ReadLineL behave the same than before. Stephane Lenclud. + } + else // encoding == Versit::EBase64Encoding + { + if (aBinaryData) + { + if (!iLargeDataBuf) + iLargeDataBuf=CBufSeg::NewL(128); + } + TInt bufLen=0; //Initialise to stop warning "local variable may be used without having been initialized" + TBool moreLinesToCome=ETrue; + + if (iPlugIn) + { + TAny* extPlugIn = NULL; + iPlugIn->GetInterface(KUidVersitPluginExtensionBase64Termination, extPlugIn); + if (extPlugIn && static_cast(extPlugIn)->BlankLineAndLeadingSpaceNotRequired()) + { + iLineReader->ReadBase64ValueL(aValueStart); + if(aBinaryData) + { + iLargeDataBuf->InsertL(bufLen,BufPtr()); + } + lineLen=BufPtr().Length(); + moreLinesToCome = EFalse; + secondLine=EFalse; + } + } + + while (moreLinesToCome) + { + if (secondLine) + { + lineLen-=aValueStart; + TPtrC8 data=BufPtr().Mid(aValueStart,lineLen); + if (aBinaryData) + { + iLargeDataBuf->InsertL(0,data); + bufLen=lineLen; + lineLen=0; + } + else + BufPtr()=data; + secondLine=EFalse; + } + + if (iPlugIn && !iPlugIn->NeedsBlankLine()) + { + moreLinesToCome=iLineReader->AppendLineIfSpaceNextL(); + } + else + { + TPtrC8 lineData = BufPtr().Mid(0); //Grab a copy of last line, used to check if the end has been reached if only whitespace is present + TInt lineEval = iLineReader->ReadLineL(lineLen,err); + moreLinesToCome=(lineEval !=CLineReader::ELineIsCRLFOnly); + if (lineEval == CLineReader::ELineIsWhiteSpace) + { + //White space lines are not really part of the spec, however can be present + //through transmission errors. For the sake of robustness it is ignored, however if + //it is present after the last line instead of CRLF then it is a problem. We can check + //for the other delimiter mentioned in the spec to see if the last line has been reached + //by checking for the '=' character. This is not perfect as these are padding characters and + //will not be present if the length of the data is a multiple of 3 but as the data is not + //conformant with the spec then this is the best we can do to recover from the error + //which is present. + + if ( lineData.LocateReverse('=') != KErrNotFound) + { + //Found an '=' so the end has been reached. + moreLinesToCome = EFalse; + } + } + } + if (aBinaryData) + { + iLargeDataBuf->InsertL(bufLen,BufPtr()); + bufLen+=BufPtr().Length(); + } + else + lineLen=BufPtr().Length(); + }//while + if (!aBinaryData && lineLen==0) + { //The bad ending, to the Base64 data, in other situations does not cause a crash + BufPtr().Append(KVersitLineBreak); + BufPtr().Append(KVersitTokenCRLF); + lineLen=BufPtr().Length(); + } + }//base64 + if (aBinaryData) + { + if (!iLargeDataBuf) + iLargeDataBuf=CBufSeg::NewL(128); + if (secondLine) + iLargeDataBuf->InsertL(0,aValue); + else if (encoding!=Versit::EBase64Encoding) + iLargeDataBuf->InsertL(0,BufPtr()); + aValue.Set(NULL,0,0); + } + else + { + if (!secondLine && BufPtr().Length() > 0) + aValue.Set(&BufPtr()[0],lineLen,lineLen); + delete iLargeDataBuf; + iLargeDataBuf=NULL; + } + } + + + +// +// Parsing +// + + +EXPORT_C void CVersitParser::ParseBeginL() +// Parse start of entity (and extract iEntityName) + { + ParsePropertyL(); + // Parse until token Begin or EOF is reached. + while (iCurrentProperty->NameUid().iUid!=KVersitTokenBeginUid) + { + delete iCurrentProperty; + iCurrentProperty=NULL; + + ParsePropertyL(); + } + + delete iEntityName; + iEntityName=NULL; + iEntityName=STATIC_CAST(CParserPropertyValueHBufC*,iCurrentProperty->Value())->TakeValueOwnership(); + } + +EXPORT_C void CVersitParser::ParseEndL() +// Parse end of entity + { + ParseEndL(*iEntityName); + } + +void CVersitParser::ParseEndL(HBufC16& aEntityName) +// Parse end of entity + { + if (iCurrentProperty->NameUid().iUid!=KVersitTokenEndUid) + { + User::Leave(KErrNotFound); + } + + TBool result = (aEntityName==STATIC_CAST(CParserPropertyValueHBufC*,iCurrentProperty->Value())->Value()); + delete iCurrentProperty; + iCurrentProperty=NULL; + if (!result) + User::Leave(KErrNotFound); + } + +EXPORT_C TBool CVersitParser::ParseEntityL() +// +// Parse next entity in stream, and add to iArrayOfEntities +// + { + TBool entityWasFound = EFalse; + TInt32 uid=0; + if (iCurrentProperty) + uid=iCurrentProperty->NameUid().iUid; + if (uid==KVersitTokenBeginUid) + { + TInt uid = RecognizeEntityName(); + HBufC* entityName=STATIC_CAST(CParserPropertyValueHBufC*,iCurrentProperty->Value())->TakeValueOwnership(); + CleanupStack::PushL(entityName); + CVersitParser* entity = MakeEntityL(uid,entityName); + CleanupStack::Pop(entityName); + AddEntityL(entity); + + entityWasFound = ETrue; + } + + // Returns whether or not an entity was found + return entityWasFound; + } + +EXPORT_C void CVersitParser::ParsePropertiesL() +//Parse all properties in stream + { +#if defined(_DEBUG) + TInt propCount = 0; +#endif + FOREVER + { +#if defined(_DEBUG) + propCount++; +#endif + // For every single property that is parsed, any decoding or character set conversion + // will use the default character set and encoding type set during the call to this + // class' constructor. + // To ensure (after a property is read) that the default is restored, a call to this + // method is made before each property is read. + RestoreLineCodingDetailsToDefault(); + TRAPD(err, ParsePropertyL()); + if (VersitUtils::CheckAndIgnoreCustomErrorL(err)) + { + delete iCurrentProperty; + iCurrentProperty = NULL; + } + else + { + if (iCurrentProperty) + { + if (VersitUtils::IsBeginOrEnd(iCurrentProperty->NameUid())) + return; + DoAddPropertyL(iCurrentProperty); + if (iObserver && iCurrentProperty->Name()==KVersitTokenVERSION) + iObserver->VersionSet(this,STATIC_CAST(CParserPropertyValueHBufC*,iCurrentProperty->Value())->Value()); + iCurrentProperty=NULL; + } + else + { + User::Leave(KErrEof); + } + } + } + } + + + +EXPORT_C void CVersitParser::ConvertAllPropertyDateTimesToMachineLocalL(const TTimeIntervalSeconds& aIncrement,const CVersitDaylight* aDaylight) +/** Converts all date/time property values contained in the current entity's array +of properties into machine local values. + +This conversion is needed because of differences in universal and local times +due to time zones and daylight savings (seasonal time shifts). + +First, all of the date/times are converted to universal time, if they are +not already: + +If daylight saving is in effect then the daylight savings rule (held in the +aDaylight parameter) will be used to compensate for differences between universal +and local times due to both time zones and the daylight saving. Otherwise, +the aIncrement parameter is used to compensate for any difference due to time +zones alone. + +Then, these universal time values are converted into machine local +times by adding the universal time offset for the machine's locale. + +@param aIncrement A time interval in seconds which represents the negative +of the time zone of the originating machine. For instance, if the time zone +is +04:30, aIncrement should be set to -04:30. +@param aDaylight Pointer to the specification for daylight saving. If the date/time +value is within the period for daylight saving, the value is modified by the +daylight saving offset (which accounts for both the time zone and daylight +saving rule). +@deprecated since 9.1 + */ + { + TUid uid; + uid.iUid = KVersitTimePropertyUid; + if (iArrayOfProperties) + { + CParserTimePropertyValue* timeValue; + TInt properties = iArrayOfProperties->Count(); + for (TInt ii = 0; ii < properties; ii++) + { + CParserPropertyValue* value=(*iArrayOfProperties)[ii]->Value(); + if (value && value->SupportsInterface(uid)) + { + timeValue = STATIC_CAST(CParserTimePropertyValue*, value); + timeValue->ConvertAllDateTimesToUTCL(aIncrement, aDaylight); + } + } + TLocale locale; + TTimeIntervalSeconds localeIncrement(locale.UniversalTimeOffset()); + if ((iFlags&EImportSyncML) && aDaylight && localeIncrement.Int()==-aIncrement.Int()) //If Importing from a SyncML Server and working in same time zone which has a daylight rule + ConvertAllUTCDateTimesToMachineLocalL(localeIncrement,aDaylight); + else + { + AdjustAllPropertyDateTimesToMachineLocalL(); + } + } + } + + +/* + * Converts all date/time property values contained in the current + * array of properties into machine local values. + @deprecated since 9.1 + */ +EXPORT_C void CVersitParser::AdjustAllPropertyDateTimesToMachineLocalL() + { + if (iArrayOfProperties) + { + TUid uid; + uid.iUid = KVersitTimePropertyUid; + TInt properties = iArrayOfProperties->Count(); + CParserTimePropertyValue* timeValue; + TLocale locale; + TTimeIntervalSeconds localeIncrement(locale.UniversalTimeOffset()); + for (TInt jj = 0; jj < properties; jj++) + { + CParserPropertyValue* value=(*iArrayOfProperties)[jj]->Value(); + if (value && value->SupportsInterface(uid)) + { + timeValue = STATIC_CAST(CParserTimePropertyValue*, value); + timeValue->ConvertAllUTCDateTimesToMachineLocalL(localeIncrement); + } + } + } + } + + +void CVersitParser::ConvertAllUTCDateTimesToMachineLocalL(const TTimeIntervalSeconds& aIncrement,const CVersitDaylight* aDaylight) + { + CParserPropertyValue* value; + CParserTimePropertyValue* timeValue; + TInt properties=iArrayOfProperties->Count(); + TUid uid; + uid.iUid = KVersitTimePropertyUid; + for (TInt jj = 0; jj < properties; jj++) + { + value=(*iArrayOfProperties)[jj]->Value(); + if (value && value->SupportsInterface(uid)) + { + timeValue = STATIC_CAST(CParserTimePropertyValue*, value); + switch (timeValue->Uid().iUid) + { + case KVCalPropertyAlarmUid: + { + CVersitAlarm* alarm=STATIC_CAST(CParserPropertyValueAlarm*,timeValue)->Value(); + if (alarm && alarm->iRunTime) + ConvertUTCDateTimeToMachineLocal(alarm->iRunTime,aIncrement,aDaylight); + } + break; + case KVersitPropertyDateTimeUid: + { + TVersitDateTime* dateTime=STATIC_CAST(CParserPropertyValueDateTime*,timeValue)->Value(); + if (dateTime) + ConvertUTCDateTimeToMachineLocal(dateTime,aIncrement,aDaylight); + } + break; + case KVersitPropertyMultiDateTimeUid: + { + CArrayPtr* values=STATIC_CAST(CParserPropertyValueMultiDateTime*,timeValue)->Value(); + if (values) + { + TInt count=values->Count(); + for (TInt ii=0;iiConvertAllUTCDateTimesToMachineLocalL(aIncrement); + } + } + } + } + +void CVersitParser::ConvertUTCDateTimeToMachineLocal(TVersitDateTime* aDateTime,const TTimeIntervalSeconds& aIncrement,const CVersitDaylight* aDaylight) + { + if (aDateTime && aDateTime->iRelativeTime==TVersitDateTime::EIsUTC) + { + CParserTimePropertyValue::ConvertDateTime(aDateTime->iDateTime,aIncrement,aDaylight,EFalse); + aDateTime->iRelativeTime=TVersitDateTime::EIsMachineLocal; + } + } + + +// +// Recognition +// + +EXPORT_C TBool CVersitParser::IsValidParameterValue(TInt& aPos,const TDesC& aParamValue) +/** Tests whether a property parameter name or value is valid. + +If the string aParamValue contains any punctuation characters, the string +is invalid. Otherwise, it is valid. Punctuation characters are defined as +any of the following:- + +[] (left or right square bracket) + += (equals sign) + +: (colon) + +; (semi colon) + +. (dot) + +, (comma) + +@param aPos On return, contains the character position of the first invalid +character in the property parameter name or value. +@param aParamValue The property parameter name or value to test. +@return ETrue if valid, EFalse if invalid. */ + { + TInt length = aParamValue.Length(); + for (aPos = 0; aPos < length; aPos++) + { + if (IsPunctuationToken(aParamValue[aPos])) + return EFalse; + } + return ETrue; + } + +EXPORT_C CArrayPtr* CVersitParser::GetPropertyParamsLC(TPtr8 aParams) + { + CArrayPtr* arrayOfParams=new(ELeave)CArrayPtrFlat(5); + CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfParams,arrayOfParams)); + TUint8* currentChar=&aParams[0]; + TUint8* dest; + TUint8* afterLastChar=currentChar+aParams.Length(); + TUint8* startField; + TBool escaping; + TInt len; + while (currentChar<=afterLastChar) + { + startField=currentChar; + escaping=EFalse; + while (currentChar0) + ParseParamL(arrayOfParams,TPtr8(startField,len,len)); + ++currentChar; + } + return arrayOfParams; + } + +EXPORT_C void CVersitParser::ParseParamL(CArrayPtr* aArray,TPtr8 aParam) + { + TPtr8 paramName(aParam); + TPtr8 paramValue(NULL,0); + TInt equalsPos=aParam.Find(KVersitTokenEquals); + if (equalsPos>KErrNotFound) + { + paramName.Set(&aParam[0],equalsPos,equalsPos); + ++equalsPos; + TInt valLen=aParam.Length()-equalsPos; + if (valLen>0) + { + paramValue.Set(&aParam[equalsPos],valLen,valLen); + VersitUtils::StripWhiteSpace(paramValue); + } + } + VersitUtils::StripWhiteSpace(paramName); + CParserParam* newParam = CParserParam::NewL(paramName, paramValue); + CleanupStack::PushL(newParam); + aArray->AppendL(newParam); + CleanupStack::Pop(newParam); + } + +EXPORT_C void CVersitParser::AnalysesEncodingCharset(CArrayPtr* aArrayOfParams) +// +// This method checks each parameter in turn to establish if any of the parameters (should some +// exist) contain references to the CHARSET parameter or the ENCODING parameter. +// +// Should references exist to CHARSET then a character set override is applied to the current +// property value during the decoding process. +// +// Note that it is also valid syntax to simply indicate that the property value is encoded +// using QUOTED-PRINTABLE simply by specifying QUOTED-PRINTABLE without following the normal +// PARAMETER_NAME=VALUE syntax (i.e the parameter might just consist of the PARAMETER_NAME +// part (in which case VALUE will be null and PARAMETER_NAME will be QUOTED-PRINTABLE etc). +// +// Method could leave while creating a UID +// + { + CParserParam* parameter; + TPtrC8 pParameterName; + TPtrC8 pParameterValue; + TInt noOfParams = (aArrayOfParams)? aArrayOfParams->Count() : 0; + TInt tokenUidValue = 0; + + // + // Check each parameter for coding related tags, such as CHARSET, ENCODING, etc and + // set up state ready for the decoding of the parameter value + // + for(TInt ii = 0; ii < noOfParams; ii++) + { + parameter = aArrayOfParams->At(ii); + pParameterName.Set(parameter->Name()); + pParameterValue.Set(parameter->Value()); + + // Attempt to recognize this property parameter + tokenUidValue = RecognizeToken(pParameterName).iUid; + + // The parameter NAME is CHARSET + if (tokenUidValue == KVersitParamCharsetUid) + { + // Charset identifier found, so establish the encoding type (e.g UTF8, ISO8859-X etc). + TUint charSetUid=KCharacterSetIdentifierAscii; + charSetUid=UnicodeUtils().ConvertStandardNameL(pParameterValue); // Method could leave while creating a UID + if (charSetUid!=0) + { + SetLineCharacterSetId(charSetUid); + iFlags|=ECharSetIdentified; + } + + // The CHARSET parameter of this property is no longer required so remove it from the array. + delete parameter; + aArrayOfParams->Delete(ii); + --ii; + --noOfParams; + } + // The parameter NAME is ENCODING + else if (tokenUidValue == KVersitParamEncodingUid) + { + const TUint conversionUid = RecognizeToken(pParameterValue).iUid; + SetLineEncoding(conversionUid); + } + // The parameter NAME is QUOTED-PRINTABLE + else if (tokenUidValue == KVersitParamEncodingQuotedPrintableUid) + { + SetLineEncoding(Versit::EQuotedPrintableEncoding); + } + // The parameter NAME is BASE64 + else if (tokenUidValue == KVersitParamEncodingBase64Uid) + { + SetLineEncoding(Versit::EBase64Encoding); + } + } // end FOR + } + +HBufC* CVersitParser::ConvertToUnicodeL(const TDesC8& aValue) + { + if (!(iFlags&ECharSetIdentified)) + { + if (iFlags&EUseAutoDetection && !VersitUtils::IsBeginOrEnd(iCurrentProperty->NameUid()) + && iCurrentProperty->NameUid().iUid!=KVersitTokenVersionUid) + SetLineCharacterSetId(UnicodeUtils().AutoDetectCharSetL(aValue,iAutoDetectCharSets)); + else + SetLineCharacterSet(Versit::EUSAsciiCharSet); + } + if (LineCharSet() != Versit::EUSAsciiCharSet) + { + HBufC* value = HBufC::NewLC(aValue.Size()); + TPtr ptr(value->Des()); + + if (aValue.Length()) + { + User::LeaveIfError(ConvertToUnicodeFromISOL(ptr, aValue, LineCharSetId())); + __ASSERT_DEBUG(ptr.Length(), User::Invariant()); + } + + CleanupStack::Pop(value); + return value; + } + else + return UnicodeUtils().WidenL(aValue); + } + +EXPORT_C HBufC* CVersitParser::DecodePropertyValueL(const TDesC8& aValue) +// +// This method is used to decode the property value given that any +// parameters to the property have been established. +// + { + // If this property has an overridden encoding type, or the default encoding is not ENoEncoding + // then do the decode here... otherwise leave it up to MakeXXXX instead. + if (LineEncoding() != Versit::ENoEncoding) + { + const TUid propertyEncodingUid = { LineEncodingId() }; + TRAPD(err,DecodePropertyValueL(aValue,propertyEncodingUid)); + if (err != KErrNotSupported) + { + User::LeaveIfError(err); + if (iLargeDataBuf) + return NULL; + return ConvertToUnicodeL(*iDecodedValue); + } + } + if (iLargeDataBuf) + return NULL; + return ConvertToUnicodeL(aValue); + } + +EXPORT_C void CVersitParser::DecodePropertyValueL(const TDesC8& aValue,const TUid& aEncodingUid) + { + CCnaConverterList* convList=CCnaConverterList::NewLC(); + CConverterBase* conv = convList->NewConverterL(aEncodingUid); + if (!conv) + User::Leave(KErrNotSupported); + CleanupStack::PushL(conv); + + CBufSeg* destBuf=NULL; //Initialise to stop warning "local variable may be used without having been initialized" + RBufReadStream bufRead; + RBufWriteStream bufWrite; + RDesReadStream desRead; + RDesWriteStream desWrite; + RReadStream* readStream; + RWriteStream* writeStream; + if (iLargeDataBuf) + { + destBuf=CBufSeg::NewL(128); + CleanupStack::PushL(destBuf); + bufRead.Open(*iLargeDataBuf); + bufWrite.Open(*destBuf); + readStream=&bufRead; + writeStream=&bufWrite; + } + else + { + if (!iDecodedValue) + iDecodedValue=HBufC8::NewL(aValue.Length()); + else + { + TPtr8 value=iDecodedValue->Des(); + if(value.MaxLength()ReAllocL(aValue.Length()); + } + desRead.Open(aValue); + TPtr8 ptr=iDecodedValue->Des(); //To stop warning: nonstandard extension used : 'argument' : conversion from 'class TPtr8' to 'class TDes8 &' + desWrite.Open(ptr); + readStream=&desRead; + writeStream=&desWrite; + } + // + conv->ConvertObjectL(*readStream,*writeStream); + // + writeStream->CommitL(); + readStream->Close(); + writeStream->Close(); + // + if (iLargeDataBuf) + { + CleanupStack::Pop(destBuf); + delete iLargeDataBuf; + iLargeDataBuf=destBuf; + } + CleanupStack::PopAndDestroy(2, convList); // conv, convList + } + + +EXPORT_C void CVersitParser::AppendBeginL() +// Write beginning of entity to stream + { + iWriteStream->WriteL(KVersitTokenBEGIN); + AppendEntityNameL(); + } + +EXPORT_C void CVersitParser::AppendEndL() +// Write end of entity to stream + { + iWriteStream->WriteL(KVersitTokenEND); + AppendEntityNameL(); + } + +void CVersitParser::AppendEntityNameL() + { + iWriteStream->WriteL(KVersitTokenColon); + if (iEntityName) + { + UnicodeUtils().SetCurrentCharSetL(KCharacterSetIdentifierCodePage1252); + HBufC8* narrow = UnicodeUtils().NarrowLC(*iEntityName); + iWriteStream->WriteL(*narrow); + CleanupStack::PopAndDestroy(narrow); + } + iWriteStream->WriteL(KVersitTokenCRLF); + } + +EXPORT_C CVersitParser* CVersitParser::MakeEntityL(TInt /*aEntityUid*/,HBufC* /*aEntityName*/) +// Make an entity from iReadStream + { + User::Leave(KErrNotSupported); //entities not supported + return NULL; + } + +EXPORT_C CParserPropertyValue* CVersitParser::MakePropertyValueL(const TUid& aPropertyUid,HBufC16*& aValue) +// Every property value has a specific property UID type which identifies the type of +// container object the property value (returned from this method) is derived from. + { + if(!aValue && (aPropertyUid.iUid != KVersitPropertyBinaryUid || !iLargeDataBuf)) + { + return NULL; + } + + CParserPropertyValue* value = NULL; + + switch(aPropertyUid.iUid) + { + case KVersitPropertyCDesCArrayUid: + { + CDesCArray* array=MakePropertyValueCDesCArrayL(aValue->Des()); + CleanupStack::PushL(array); + value=new(ELeave)CParserPropertyValueCDesCArray(array); + CleanupStack::Pop(array); + break; + } + case KVersitPropertyTimeZoneUid: + { + TPtr16 ptr=aValue->Des(); + VersitUtils::StripWhiteSpace(ptr); + TTimeIntervalSeconds timeZone=DecodeTimeZoneL(ptr); + value=new(ELeave)CParserPropertyValueTimeZone(timeZone); + break; + } + case KVersitPropertyDaylightUid: + { + CVersitDaylight* daylight=MakePropertyValueDaylightL(aValue->Des()); + CleanupStack::PushL(daylight); + value=new(ELeave)CParserPropertyValueDaylight(daylight); + CleanupStack::Pop(daylight); + break; + } + case KVersitPropertyDateTimeUid: + { + TPtr16 ptr=aValue->Des(); + if (ptr.Length()<=KVersitDatePropertySymbianConnectMessageMaximumLenght) + { + //date is not valid, exception implemented to satisfy symbian connect protocol + value=MakeDefaultPropertyValueL(aValue); + } + else + { + TVersitDateTime* dateTime=DecodeDateTimeL(ptr); + CleanupStack::PushL(dateTime); + value=new(ELeave)CParserPropertyValueDateTime(dateTime); + CleanupStack::Pop(dateTime); + } + break; + } + case KVersitPropertyDateUid: + { + TPtr16 ptr=aValue->Des(); + if (ptr.Length()<=KVersitDatePropertySymbianConnectMessageMaximumLenght) + { + //date is not valid, exception implemented to satisfy symbian connect protocol + value=MakeDefaultPropertyValueL(aValue); + } + else + { + TVersitDateTime* dateTime=DecodeDateTimeL(ptr); + CleanupStack::PushL(dateTime); + value=new(ELeave)CParserPropertyValueDate(dateTime); + CleanupStack::Pop(dateTime); + } + break; + } + case KVersitPropertyMultiDateTimeUid: + { + CArrayPtr* multiDateTime=MakePropertyValueMultiDateTimeL(aValue->Des()); + CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfDateTimes,multiDateTime)); + value=new(ELeave)CParserPropertyValueMultiDateTime(multiDateTime); + CleanupStack::Pop(multiDateTime); + break; + } + case KVersitPropertyIntUid: + { + TInt number; + Val(*aValue, number); + value=new(ELeave)CParserPropertyValueInt(number); + break; + } + case KVersitPropertyBinaryUid: + value=new(ELeave) CParserPropertyValueBinary(*iLargeDataBuf); + iLargeDataBuf=NULL; + break; + default://KVersitPropertyHBufCUid + { + value=MakeDefaultPropertyValueL(aValue); + } + } + return value; + } + +CParserPropertyValueHBufC* CVersitParser::MakeDefaultPropertyValueL(HBufC16*& aValue) +/** + * Instantiates and gives ownership of a CParserPropertyValueHBufC object. + */ + { + if(!aValue && !iLargeDataBuf) + return NULL; + + VersitUtils::RemoveEscapeChars(*aValue,LineCharSetId()); + CParserPropertyValueHBufC* returnedValue=new(ELeave) CParserPropertyValueHBufC(aValue); + aValue=NULL; + return returnedValue; + } + + +EXPORT_C CDesCArray* CVersitParser::MakePropertyValueCDesCArrayL(TPtr16 aStringValue) +/** Parses a compound property value string. + +The sub-values found are appended to an array, after removal of escape characters. +The array is returned, and ownership is transferred to the caller. + +@param aStringValue Compound property value string. +@return Array of property values found in the string. */ + { + CDesCArray* arrayOfValues = VersitUtils::ParseForArrayPropertiesL(aStringValue, LineCharSetId()); + return arrayOfValues; + } + +EXPORT_C TBool CVersitParser::FindFirstField(TPtr16& aField,TPtr16& aRemaining, TBool aTrimSpace) + { + TInt len=aRemaining.Length(); + TInt posSemicolon=aRemaining.Locate(KVersitTokenSemiColonVal); + TInt startRest=posSemicolon+1; + TBool ret=(posSemicolon==KErrNotFound); + if (ret) + { + if (len==0) + { + aField.Set(NULL,0,0); + return ETrue; + } + posSemicolon=len; + startRest=len; + } + aField.Set(&aRemaining[0],posSemicolon,posSemicolon); + len-=startRest; + if (len==0) + startRest=0; + aRemaining.Set(&aRemaining[startRest],len,len); + if(aTrimSpace) + VersitUtils::StripWhiteSpace(aField); + return ret; + } + +/** Sets up a pointer to the remaining field. Sets the original remaining field pointers length to 0. +@param aField on return points to the data and length that aRemaining originally pointed to. +@param aRemaining as input references a location that the descriptor is to represent. On return length is set to 0. +*/ +EXPORT_C void CVersitParser::FindRemainingField(TPtr16& aField,TPtr16& aRemaining) + { + TInt len=aRemaining.Length(); + aField.Set(&aRemaining[0],len,len); + aRemaining.Set(&aRemaining[0], 0, 0); + } + +EXPORT_C CVersitDaylight* CVersitParser::MakePropertyValueDaylightL(TPtr16 aDaylightValue) + { + if(aDaylightValue.MatchF(KVersitVarTokenFALSE)>KErrNotFound) + return CVersitDaylight::NewL(EFalse, NULL, NULL, NULL, KVersitTokenEmpty, KVersitTokenEmpty); + + TPtr16 field(NULL,0); + FindFirstField(field,aDaylightValue); + if(field.CompareC(KVersitVarTokenTRUE)) + return NULL; + + FindFirstField(field,aDaylightValue); + TTimeIntervalSeconds offset=0; + if(field.Length()>0) + offset = DecodeTimeZoneL(field); + + FindFirstField(field,aDaylightValue); + TVersitDateTime* startTime = NULL; + if(field.Length()>0) + startTime = DecodeDateTimeL(field); + CleanupStack::PushL(startTime); + + FindFirstField(field,aDaylightValue); + TVersitDateTime* endTime = NULL; + if(field.Length()>0) + endTime = DecodeDateTimeL(field); + CleanupStack::PushL(endTime); + + FindFirstField(field,aDaylightValue); + TPtr16 edt(NULL,0); + FindFirstField(edt,aDaylightValue); + + if(!startTime || !endTime) + User::Leave(KVersitErrBadDateTime); + + CVersitDaylight* daylight = CVersitDaylight::NewL(ETrue, offset, startTime, endTime, field, edt); + CleanupStack::Pop(2,startTime); + return (daylight); + } + +EXPORT_C CArrayPtr* CVersitParser::MakePropertyValueMultiDateTimeL(TPtr16 aDateTimeGroup) +// Make a property from aDateTimeGroup, with a CArrayPtr value + { + VersitUtils::StripWhiteSpace(aDateTimeGroup); + if(aDateTimeGroup.Length()==0) + return NULL; + CArrayPtr* arrayOfDateTimes=new(ELeave)CArrayPtrFlat(5); + CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfDateTimes,arrayOfDateTimes)); + TPtr16 field(NULL,0); + do + { + FindFirstField(field,aDateTimeGroup); + if(field.Length()>0) + { + TVersitDateTime* dateTime = DecodeDateTimeL(field); + CleanupStack::PushL(dateTime); + arrayOfDateTimes->AppendL(dateTime); + CleanupStack::Pop(dateTime); + } + }while (aDateTimeGroup.Length()!=0); + + CleanupStack::Pop(arrayOfDateTimes); //arrayOfDateTimes + return arrayOfDateTimes; + } + +EXPORT_C TInt CVersitParser::Val(const TDesC& aString, TInt& aNumber) +// static +/** Converts a string into an integer, for example, it converts "438" to 438. + +@param aString The string to be converted. Every character contained in +the string needs to be number presentable, i.e. between '0' and '9'. +@param aNumber On return, the integer corresponding to aString. +@return KErrNone if the number has been converted from the string; +KVersitErrNumberExpected otherwise. */ + { + aNumber = 0; + TInt length=aString.Length(); + for(TInt i=0;i'9') + return(KVersitErrNumberExpected); + aNumber = aNumber * 10 + aString[i] - '0'; + } + return KErrNone; + } + + +EXPORT_C TVersitDateTime* CVersitParser::DecodeDateTimeL(TDes& aToken) const +// Extracts the date and time portion from aToken and returns it as a +// TVersitDateTime (Format YYYY(:)MM(:)DD(:)(THH(:)MM(:)SS(:)(Z)) + { + const TInt KSymbianOSDefaultMidnightValue = 0; + const TInt KVersitAlternativeMidnightValue = 24; + + aToken.TrimAll(); + TInt length = aToken.Length(); + if (length==0) + User::Leave(KVersitErrBadDateTime); + TInt position = 0; + if (length < 8) + User::Leave(KVersitErrBadDateTime); + TVersitDateTime::TRelativeTime relativeTime = TVersitDateTime::EIsVCardLocal; + TInt year; + User::LeaveIfError(Val(aToken.Left(4), year)); + position += 4; + if(aToken[position] == KVersitTokenMinusVal) + position++; + TInt month; + User::LeaveIfError(Val(aToken.Mid(position, 2), month)); + position += 2; + if(aToken[position] == KVersitTokenMinusVal) + position++; + if (length < (position + 2)) + User::Leave(KVersitErrBadDateTime); + TInt day; + User::LeaveIfError(Val(aToken.Mid(position, 2), day)); + position += 2; + // + // Parse time aspect + // + TBool adjustDayToNextAvailable = EFalse; + TInt hour = 0; + TInt minute = 0; + TInt second = 0; + + // position is now sitting left of the "T" in the date string YYYY(-)MM(-)DD(-)THH(:)MM(:SS) + if (length >= (position + 5)) + { + TBool parseSeconds = EFalse; + + // Time value can be in "HHMM" or "HHMMSS" format. + if(length >= (position + 7)) + parseSeconds = ETrue; + + if(aToken[position++] != KVersitTimePeriodTimeVal) + User::Leave(KVersitErrBadDateTime); + + User::LeaveIfError(Val(aToken.Mid(position, 2), hour)); + // If the hour value is "24" then, this is deemed to be at the end + // of the specified day. This can be thought of as synonymous with the + // start of the next day. + if (hour == KVersitAlternativeMidnightValue) + { + adjustDayToNextAvailable = ETrue; + hour = KSymbianOSDefaultMidnightValue; + } + + position += 2; + if(aToken[position] == KVersitTokenColonVal) + position++; + + if(length < position+2) + User::Leave(KVersitErrBadDateTime); + + User::LeaveIfError(Val(aToken.Mid(position, 2), minute)); + position += 2; + + if(parseSeconds) + { + if(aToken[position] == KVersitTokenColonVal) + position++; + if (length < (position + 2)) + User::Leave(KVersitErrBadDateTime); + User::LeaveIfError(Val(aToken.Mid(position, 2), second)); + position += 2; + } + + if ((length > position) && (aToken[position] == KVersitTokenUniversalTimeVal)) + relativeTime = TVersitDateTime::EIsUTC; + } + TDateTime date; + const TInt error = date.Set(year, (TMonth)(month - 1), day - 1, hour, minute, second, 0); + if(error!=KErrNone) + User::LeaveIfError(KVersitErrBadDateTime); + + // In the instance whereby we need to treat 24 as being the start of the next + // day, we should increment the day value by one. + if (adjustDayToNextAvailable) + { + const TInt KVersitSingleDay = 1; + // + TTime time(date); + time += TTimeIntervalDays(KVersitSingleDay); + date = time.DateTime(); + } + return new(ELeave) TVersitDateTime(date, relativeTime); + } + +EXPORT_C TTimeIntervalSeconds CVersitParser::DecodeTimeZoneL(const TDesC& aToken) const +// Extracts the date and time portion from aToken and returns it as a +// TVersitDateTime Format: (-)(+)HH((:)MM) + { + TInt length = aToken.Length(); + if (length < 1) + User::Leave(KVersitErrBadTimeZone); + TInt position = 0; + TInt sign = 1; + TInt hour = 0,minute = 0; + if(aToken[position] == KVersitTokenMinusVal) + { + position++; + sign = -1; + } + else if(aToken[position] == KVersitTokenPlusVal) + position++; + if(length-position<1) + User::Leave(KVersitErrBadTimeZone); + if((length-position)==1 || aToken.Mid(position+1,1)==KVersitTokenColonUnicode) + { + User::LeaveIfError(Val(aToken.Mid(position, 1), hour)); + position += 1; + } + else + { + User::LeaveIfError(Val(aToken.Mid(position, 2), hour)); + position += 2; + } + + if (length >= (position + 1)) + { + if(aToken[position] == KVersitTokenColonVal) + position++; + if(length-1==position) + User::LeaveIfError(Val(aToken.Mid(position, 1), minute)); + else if(length-1>position) + User::LeaveIfError(Val(aToken.Mid(position, 2), minute)); + } + return TTimeIntervalSeconds(sign * (hour * 3600 + minute * 60)); + } + +EXPORT_C TTime* CVersitParser::DecodeTimePeriodL(const TDesC& aToken) const +// Extracts the date and time portion from aToken and returns it as a +// TDateTime time period + { + TInt length = aToken.Length(); + TInt ii = 0; + if (!length || (aToken[ii++] != KVersitTimePeriodBeginVal)) + User::Leave(KVersitErrBadTimePeriod); + TInt number = 0; + TInt year = 0; + TInt month = 0; + TInt week = 0; + TInt day = 0; + TInt hour = 0; + TInt minute = 0; + TInt second = 0; + TBool isTimeOfDay = EFalse; + while (ii < length) + { + TChar tokenChar = aToken[ii]; + if ((tokenChar >= '0') && (tokenChar <= '9')) + { + TInt numChars; + number = GetNumberL(aToken.Right(length - ii),numChars); + ii+=numChars; + } + else + { + if (isTimeOfDay) + { + if (tokenChar == KVersitTimePeriodHourVal) + hour = number; + else if (tokenChar == KVersitTimePeriodMinuteVal) + minute = number; + else if (tokenChar == KVersitTimePeriodSecondVal) + second = number; + } + else + { + if (tokenChar == KVersitTimePeriodTimeVal) + isTimeOfDay = ETrue; + else if (tokenChar == KVersitTimePeriodYearVal) + year = number; + else if (tokenChar == KVersitTimePeriodMonthVal) + month = number; + else if (tokenChar == KVersitTimePeriodWeekVal) + week = number; + else if (tokenChar == KVersitTimePeriodDayVal) + day = number; + } + ii++; + number = 0; + } + } + //TBuf time; + //_LIT(formatString, "%04d%02d%02d:%02d%02d%02d."); + //time.Format(formatString, year, month, day, hour, minute, second); + TDateTime dateTime(year,REINTERPRET_CAST(TMonth&,month),day,hour,minute,second,0); + //TTime* timeVal = new(ELeave) TTime(time); + TTime* timeVal = new(ELeave) TTime(dateTime); + *timeVal += TTimeIntervalDays(week * 7); + return timeVal; + } + +EXPORT_C TInt CVersitParser::GetNumberL(const TDesC& aToken,TInt& aNumChars) const +// Converts aToken to an integer + { + TInt length = aToken.Length(); + TPtrC numBuf(aToken); + TInt num; + aNumChars = 0; + while ((aNumChars < length) && (aToken[aNumChars] >= '0') && (aToken[aNumChars] <= '9')) + ++aNumChars; + numBuf.Set(aToken.Left(aNumChars)); + User::LeaveIfError(Val(numBuf, num)); + return num; + } + +EXPORT_C TUid CVersitParser::RecognizeToken(const TDesC8& aToken) const +/** Returns a UID for the specified token. + +This function only recognizes generic Versit tokens. For example, if aToken +contains the property name KVersitTokenBEGIN, the function returns KVersitTokenBeginUid. +More specific recognition should occur in derived classes which implement +this function, using this as the base recogniser. + +@param aToken The token to be recognized. +@return A defined UID value if the token has been recognized; KVersitTokenUnknownUid +otherwise. */ + { + TUid uid = TUid::Uid(KVersitTokenUnknownUid); + TChar firstChar(aToken.Ptr()[0]); + firstChar=firstChar.GetUpperCase(); + switch (firstChar) + { + case 'B': + if (!aToken.CompareF(KVersitTokenBEGIN)) + uid.iUid = KVersitTokenBeginUid; + else if (!aToken.CompareF(KVersitTokenBASE64)) + uid.iUid = KVersitParamEncodingBase64Uid; + break; + case 'C': + if (!aToken.CompareF(KVersitTokenCHARSET)) + uid.iUid = KVersitParamCharsetUid; + break; + case 'E': + if (!aToken.CompareF(KVersitTokenEND)) + uid.iUid = KVersitTokenEndUid; + else if (!aToken.CompareF(KVersitTokenENCODING)) + uid.iUid = KVersitParamEncodingUid; + break; + case 'Q': + if (!aToken.CompareF(KVersitTokenQUOTEDPRINTABLE)) + uid.iUid = KVersitParamEncodingQuotedPrintableUid; + break; + default: + break; + } + return uid; + } + +EXPORT_C TInt CVersitParser::RecognizeEntityName() const +// From CVersitParser +/** Tests the current entity to see if it is a vEvent or vTodo. + +This function is virtual. Actual testing only occurs in derived classes which +implement this function. + +@return Zero. Derived classes' implementations would return a value that indicates +the current entity's type. */ + { + return 0; + } + +EXPORT_C void CVersitParser::ResetAndDestroyArrayOfParams(TAny* aObject) +/** Destroys an array of parameters. + +@param aObject Pointer to the array of parameters to be destroyed. */ + { + CArrayPtr* array=REINTERPRET_CAST(CArrayPtr*,aObject); + if (array) + array->ResetAndDestroy(); + delete array; + } + +EXPORT_C void CVersitParser::ResetAndDestroyArrayOfProperties(TAny* aObject) +/** Destroys an array of properties. + +@param aObject Pointer to the array of properties to be destroyed. */ + { + CArrayPtr* array=REINTERPRET_CAST(CArrayPtr*,aObject); + if (array) + array->ResetAndDestroy(); + delete array; + } + +EXPORT_C void CVersitParser::ResetAndDestroyArrayOfEntities(TAny* aObject) +/** Destroys an array of entities. + +@param aObject Pointer to the array of entities to be destroyed. */ + { + CArrayPtr* array=REINTERPRET_CAST(CArrayPtr*,aObject); + if (array) + array->ResetAndDestroy(); + delete array; + } + +EXPORT_C void CVersitParser::ResetAndDestroyArrayOfDateTimes(TAny* aObject) +/** Destroys an array of Versit dates and times. + +@param aObject Pointer to the array of Versit dates and times to be destroyed. */ + { + CArrayPtr* array=REINTERPRET_CAST(CArrayPtr*,aObject); + if (array) + array->ResetAndDestroy(); + delete array; + } + +TBool CVersitParser::IsPunctuationToken(TUint aChar) //static function + { + return (aChar == KVersitTokenColonVal || + aChar == KVersitTokenSemiColonVal || + aChar == KVersitTokenEqualsVal || + aChar == KVersitTokenPeriodVal || + aChar == KVersitTokenCommaVal || + aChar == KVersitTokenLSquareBracketVal || + aChar == KVersitTokenRSquareBracketVal); + } + +EXPORT_C TInt CVersitParser::ConvertFromUnicodeToISOL(TDes8& aIso, const TDesC16& aUnicode, CCnvCharacterSetConverter* aConverter) +/** Converts text in the Unicode character set (UCS-2) into a +non-unicode (International Standards Organisation) character set. + +Which ISO character set the string is converted to is determined by +the value of the character set identifier in the aConverter parameter. + +@param aIso On return, the converted text string in the specified ISO +character set. +@param aUnicode The Unicode text string to be converted. +@param aConverter The character set converter. +@return If no error occurs, this is the number of unconverted characters +left at the end of the input descriptor. This is zero if the whole string +is converted, but may be greater than zero (e.g. because the output +descriptor is not long enough to hold all the text). Otherwise, one of +the error values defined in TError in the CCnvCharacterSetConverter class, or +KErrNotFound if aConverter does not point to a valid character +set converter object. */ + { + if (aConverter) + { + // Do the conversion + aConverter->SetReplacementForUnconvertibleUnicodeCharactersL(KReplacementChars); + return aConverter->ConvertFromUnicode(aIso, aUnicode); + } + return KErrNotFound; + } + +EXPORT_C TInt CVersitParser::ConvertToUnicodeFromISOL(TDes16& aUnicode, const TDesC8& aIso,TUint aCharacterSet) +/** Converts text in a non-Unicode character set into Unicode (UCS-2). + +@param aUnicode On return, the converted text string in the Unicode character set. +@param aIso The non-Unicode text string to be converted. +@param aCharacterSet The non-Unicode character set in which aIso is encoded. +@return If no error occurs, the number of unconverted bytes left at the end of +the input descriptor. This is zero if the whole string is converted; but it may +be greater than zero, e.g. because the output descriptor is not long enough to +hold all the text. Otherwise, one of the error values defined in TError in the +CCnvCharacterSetConverter class, or KErrNotFound if aCharacterSet cannot be +converted. */ + { + CCnvCharacterSetConverter::TAvailability avail=UnicodeUtils().SetCurrentCharSetL(aCharacterSet); + if (avail == CCnvCharacterSetConverter::EAvailable) + { + // Do the conversion + CCnvCharacterSetConverter& converter=UnicodeUtils().CharacterSetConverter(); + TInt ignore = 0; + converter.SetReplacementForUnconvertibleUnicodeCharactersL(KReplacementChars); + return converter.ConvertToUnicode(aUnicode, aIso, ignore); + } + return KErrNotFound; + } + +EXPORT_C void CVersitParser::SetDefaultEncoding(Versit::TVersitEncoding aEncoding) +/** Sets the parser's default encoding to aEncoding. + +@param aEncoding An encoding. Cannot be 8-bit. +@panic Versit-Parser 7 aEncoding is Versit::EEightBitEncoding. */ + { + // 8-bit is reserved for versit - it uses it when it needs to, but it's not + // settable by 3rd parties. + __ASSERT_ALWAYS(aEncoding!=Versit::EEightBitEncoding, Panic(EVersitPanicCannotSetEightBitEncoding)); + // + iDefaultCodingDetails.iEncoding = aEncoding; + iDefaultCodingDetails.iEncodingUid = MapVersitEncodingToConArcUid(aEncoding); + } + +EXPORT_C void CVersitParser::SetDefaultCharSet(Versit::TVersitCharSet aCharSet) +/** Sets the default character set or transformation format. + +This may be used to represent property values in Versit objects. + +@param aCharSet The default character set. */ + { + iDefaultCodingDetails.iCharSet = aCharSet; + iDefaultCodingDetails.iCharSetUid = MapVersitCharsetToCharConvCharset(aCharSet); + } + +EXPORT_C void CVersitParser::SetDefaultCharSetId(TUint aCharSetId) +/** Sets the default character set or transformation format. + +This may be used to represent property values in Versit objects. + +@param aCharSetId The UID for the character set. These are defined in charconv.h. */ + { + iDefaultCodingDetails.iCharSet = VersitUtils::CharSet(aCharSetId); + iDefaultCodingDetails.iCharSetUid = aCharSetId; + } + +EXPORT_C void CVersitParser::RestoreLineCodingDetailsToDefault() + { + // Set the [en|de]coding details for the current line back to the default values specified + SetLineCharsetDetailsToDefault(); + SetLineEncodingDetailsToDefault(); + } + +EXPORT_C void CVersitParser::SetLineEncoding(Versit::TVersitEncoding aLineEncoding) + { + iCurrentPropertyCodingDetails.iEncoding = aLineEncoding; + iCurrentPropertyCodingDetails.iEncodingUid = MapVersitEncodingToConArcUid(aLineEncoding); + } + +EXPORT_C void CVersitParser::SetLineEncoding(TUint aVersitEncodingUid) + { + switch (aVersitEncodingUid) + { + case KQuotedPrintableToTextConverter: + case KVersitParamEncodingQuotedPrintableUid: + iCurrentPropertyCodingDetails.iEncoding = Versit::EQuotedPrintableEncoding; + iCurrentPropertyCodingDetails.iEncodingUid = KQuotedPrintableToTextConverter; + break; + case KBase64ToTextConverter: + case KVersitParamEncodingBase64Uid: + iCurrentPropertyCodingDetails.iEncoding = Versit::EBase64Encoding; + iCurrentPropertyCodingDetails.iEncodingUid = KBase64ToTextConverter; + break; + default: + iCurrentPropertyCodingDetails.iEncoding = Versit::ENoEncoding; + iCurrentPropertyCodingDetails.iEncodingUid = 0; + break; + } + } + +EXPORT_C void CVersitParser::SetLineCharacterSet(Versit::TVersitCharSet aLineCharSet) + { + iCurrentPropertyCodingDetails.iCharSet = aLineCharSet; + iCurrentPropertyCodingDetails.iCharSetUid = MapVersitCharsetToCharConvCharset(aLineCharSet); + } + +EXPORT_C void CVersitParser::SetLineCharacterSetId(TUint aLineCharSetId) + { + iCurrentPropertyCodingDetails.iCharSet = VersitUtils::CharSet(aLineCharSetId); + iCurrentPropertyCodingDetails.iCharSetUid = aLineCharSetId; + } + +EXPORT_C void CVersitParser::SetLineCoding(Versit::TVersitCharSet aLineCharSet,Versit::TVersitEncoding aLineEncoding) + { + SetLineCharacterSet(aLineCharSet); + SetLineEncoding(aLineEncoding); + } + + +EXPORT_C Versit::TVersitEncoding CVersitParser::DefaultEncoding() const +/** Gets the parser's default encoding. + +This value is initialised on construction, to ENoEncoding. + +@return The parser's default encoding. */ + { + return iDefaultCodingDetails.iEncoding; + } + +EXPORT_C Versit::TVersitCharSet CVersitParser::DefaultCharSet() const +/** Gets the default character set or transformation format. This may be used to +represent property values in Versit objects. + +@return The default character set. */ + { + return iDefaultCodingDetails.iCharSet; + } + +EXPORT_C TUint CVersitParser::DefaultCharSetId() const +/** Gets the default character set or transformation format. + +This may be used to represent property values in Versit objects. + +@return The default character set identifier. Possible values are defined in charconv.h. */ + { + return iDefaultCodingDetails.iCharSetUid; + } + +EXPORT_C Versit::TVersitEncoding CVersitParser::LineEncoding() const + { + return iCurrentPropertyCodingDetails.iEncoding; + } + +EXPORT_C Versit::TVersitCharSet CVersitParser::LineCharSet() const + { + return iCurrentPropertyCodingDetails.iCharSet; + } + +EXPORT_C TUint CVersitParser::LineEncodingId() const + { + return iCurrentPropertyCodingDetails.iEncodingUid; + } + +EXPORT_C TUint CVersitParser::LineCharSetId() const + { + return iCurrentPropertyCodingDetails.iCharSetUid; + } + + +TUint CVersitParser::MapVersitCharsetToCharConvCharset(Versit::TVersitCharSet aVersitSet) +// Converts between the Versit character set enumeration and the constant character set identifier that CharConv +// uses during the conversion process + { + return VersitUtils::CharConvCharSetUid(aVersitSet).iUid; + } + + +TUint CVersitParser::MapVersitEncodingToConArcUid(Versit::TVersitEncoding aVersitEncoding) +// Map from a versit specific encoding enumeration... + { + switch(aVersitEncoding) + { + case Versit::EQuotedPrintableEncoding: + return KQuotedPrintableToTextConverter; + case Versit::EBase64Encoding: + return KBase64ToTextConverter; + default: + return 0; + } + } + + + +void CVersitParser::SetLineCharsetDetailsToDefault() + { + iCurrentPropertyCodingDetails.iCharSet = iDefaultCodingDetails.iCharSet; + iCurrentPropertyCodingDetails.iCharSetUid = iDefaultCodingDetails.iCharSetUid; + } + + +void CVersitParser::SetLineEncodingDetailsToDefault() + { + iCurrentPropertyCodingDetails.iEncoding = iDefaultCodingDetails.iEncoding; + iCurrentPropertyCodingDetails.iEncodingUid = iDefaultCodingDetails.iEncodingUid; + } + +EXPORT_C void CVersitParser::SetCharacterConverter(Versit::TEncodingAndCharset& aEncodingAndCharset) +/** Sets a character converter suitable for converting strings between +Unicode and the specified character set. + +The function finds a suitable converter for the character set +specified in aEncodingAndCharset.iCharSetId, if one is available, +and assigns it to aEncodingAndCharset.iConverter. + +If there is no converter available for the specified character set then iConverter +is set to NULL. + +This function is only of use if executing a major change to the externalisation +behaviour, particularly if overriding CParserProperty::ExternalizeL() - the +function from which this function is called. + +@param aEncodingAndCharset A utility class from which the character set +information is extracted (from its member iCharSetId) and to which the +suitable character converter is set (to its member iConverter). */ + { + CCnvCharacterSetConverter::TAvailability avail=CCnvCharacterSetConverter::ENotAvailable; + TRAPD(err,avail=UnicodeUtils().SetCurrentCharSetL(aEncodingAndCharset.iCharSetId)); + UNUSED_VAR(err); // used to suppress build warnings + if (avail==CCnvCharacterSetConverter::EAvailable) + aEncodingAndCharset.iConverter=&UnicodeUtils().CharacterSetConverter(); + else + aEncodingAndCharset.iConverter=NULL; + } + +EXPORT_C void CVersitParser::SetAutoDetect(TBool aOn,const CArrayFix* aAutoDetectCharSets/*=NULL*/) +/** Turns auto detection of character sets on or off. + +If a property does not specify a character set, then it is possible to +guess its character set. This function turns this behaviour on or off. +When the behaviour is on, it also lets the caller specify a restricted +set of character sets to be considered. + +Auto-detection of character sets is used (if auto detection is on) +when converting a property value to Unicode while internalising a stream. + +@param aOn If ETrue, auto detection is turned on; if EFalse (the default value), +auto detection is turned off +@param aAutoDetectCharSets If specified then auto detection will only consider +the character sets listed. If NULL, all available character sets are considered. */ + { + if (aOn) + { + iAutoDetectCharSets=aAutoDetectCharSets; + iFlags|=EUseAutoDetection; + } + else + iFlags&=~EUseAutoDetection; + } + + +EXPORT_C TInt CVersitParser::SaveBinaryValuesToFilesL(TInt aSizeThreshold,const TDesC& aPath) +/** Saves all binary property values larger than a specified threshold to files, +and sets each property value to be a URI representing the file, rather than +the binary data iself. + +The files are created in the folder identified by aPath, and are assigned +unique filenames that consist of the property name and some random numbers. + +Each new URI property value is prefixed with file:// and contains the path +and filename of the file created. + +If a vCard contains any agent property values and if they contain binary data +whose size exceeds the threshold, these property values are replaced with +URI property values. + +The function sets up its own file server session, which is needed to create +the files. It leaves if there is a problem creating any of the files. + +@param aSizeThreshold The threshold number of bytes for the binary data, above +which the binary data is stored in a file. +@param aPath The path identifying the location in which the files are created. +This must not be greater than 240 characters long or the function leaves with +KErrArgument. If it doesn't end in a slash, then one is appended. +@return The number of files created. */ + { + + TInt files = 0; + // create a file server session + RFs fs; + User::LeaveIfError(fs.Connect()); + CleanupClosePushL(fs); + + // parse through all the properties + const TInt countofproperties = iArrayOfProperties->Count(); + for (TInt i = 0; i < countofproperties; i++) + { + files += iArrayOfProperties->At(i)->SaveBinaryValuesToFilesL(aSizeThreshold,aPath,fs); + } + + // this never gets executed for a vcard since there are no entities for a vcard. + // But since this implementation is in the generic parser class, the code had been added. + if(iArrayOfEntities) + { + const TInt countofentities = iArrayOfEntities->Count(); + for (TInt i = 0; i < countofentities; i++) + { + files += iArrayOfEntities->At(i)->SaveBinaryValuesToFilesL(aSizeThreshold,aPath,fs); + } + } + + CleanupStack::PopAndDestroy(&fs); + + return files; + } + + +EXPORT_C TInt CVersitParser::LoadBinaryValuesFromFilesL() +/** Loads all files represented by URI property values and sets the binary data +contained in the files to be the property values instead of the URIs. + +For every property in the parser, if its value is a URI containing file:// +followed by a path and filename, then the file is opened and the binary data +it contains is read into a CParserPropertyValueBinary object. This replaces +the URI as the property value. The function also operates on any agents in +the vCard that contain URI property values. + +The function creates its own file server session, which is needed to open +the files. It leaves if there is a problem opening any of the files. + +@return The number of files that were read. */ + { + + TInt files = 0; + // create a file server session + RFs fs; + User::LeaveIfError(fs.Connect()); + CleanupClosePushL(fs); + + // parse through all the properties + const TInt countofproperties = iArrayOfProperties->Count(); + for (TInt i = 0; i < countofproperties; i++) + { + files += iArrayOfProperties->At(i)->LoadBinaryValuesFromFilesL(fs); + } + + // this never gets executed for a vcard since there are no entities for a vcard. + // But since this implementation is in the generic parser class, the code had been added. + if(iArrayOfEntities) + { + const TInt countofentities = iArrayOfEntities->Count(); + for (TInt i = 0; i < countofentities; i++) + { + files += iArrayOfEntities->At(i)->LoadBinaryValuesFromFilesL(fs); + } + } + + CleanupStack::PopAndDestroy(&fs); + + return files; + } + + +EXPORT_C TInt CVersitParser::SaveBinaryValuesToFilesL(TInt aSizeThreshold,const TDesC& aPath,RFs& aFileSession) +/** Saves all binary property values larger than a specified threshold to files, +and sets each property value to be a URI representing the file rather than +the binary data iself. + +The files are created in the folder identified by aPath, and are assigned +unique filenames that consist of the property name and some random numbers. + +Each new URI property value is prefixed with file:// and contains the path +and filename of the file created. + +If a vCard contains any agent property values and if they contain binary data +whose size exceeds the threshold, these property values are replaced with +URI property values. + +The function uses the file server session supplied, which is needed to create +the files. It leaves if there is a problem creating any of the files. + +@param aSizeThreshold The threshold number of bytes for the binary data, above +which the binary data is stored in a file. +@param aPath The path identifying the location in which the files are created. +This must not be greater than 240 characters long or the function leaves with +KErrArgument. If it doesn't end in a slash, then one is appended. +@param aFileSession The file server session used to create the files. +@return The number of files created. */ + { + + TInt files = 0; + + const TInt countofproperties = iArrayOfProperties->Count(); + for (TInt i = 0; i < countofproperties; i++) + { + files += iArrayOfProperties->At(i)->SaveBinaryValuesToFilesL(aSizeThreshold,aPath,aFileSession); + } + // this never gets executed for a vcard since there are no entities for a vcard. + // But since this implementation is in the generic parser class, the code had been added. + if(iArrayOfEntities) + { + const TInt countofentities = iArrayOfEntities->Count(); + for (TInt i = 0; i < countofentities; i++) + { + files += iArrayOfEntities->At(i)->SaveBinaryValuesToFilesL(aSizeThreshold,aPath,aFileSession); + } + } + + return files; + } + + +EXPORT_C TInt CVersitParser::LoadBinaryValuesFromFilesL(RFs& aFileSession) +/** Loads all files represented by URI property values and sets the binary data +contained in the files to be the property values instead of the URIs. + +For every property in the parser, if its value is a URI containing file:// +followed by a path and filename, then the file is opened and the binary data +it contains is read into a CParserPropertyValueBinary object. This replaces +the URI as the property value. The function also operates on any agents in +the vCard that contain URI property values. + +The function uses the file server session supplied, which is needed to open +the files. It leaves if there is a problem opening any of the files. + +@param aFileSession The file server session used to open the files. +@return The number of files that were read. */ + { + + TInt files = 0; + + const TInt countofproperties = iArrayOfProperties->Count(); + for (TInt i = 0; i < countofproperties; i++) + { + files += iArrayOfProperties->At(i)->LoadBinaryValuesFromFilesL(aFileSession); + } + // this never gets executed for a vcard since there are no entities for a vcard. + // But since this implementation is in the generic parser class, the code had been added. + if(iArrayOfEntities) + { + const TInt countofentities = iArrayOfEntities->Count(); + for (TInt i = 0; i < countofentities; i++) + { + files += iArrayOfEntities->At(i)->LoadBinaryValuesFromFilesL(aFileSession); + } + } + + return files; + } + +CVersitTLSContainer *CVersitTLSContainer::NewLC(const TInt aSize) + { + CVersitTLSContainer *ret = new (ELeave) CVersitTLSContainer(); + CleanupStack::PushL( ret ); + ret->iShiftJisEscape = HBufC::NewL(aSize); + return ret; + } + +CVersitTLSContainer::~CVersitTLSContainer() + { + delete iShiftJisEscape; + iShiftJisEscape = NULL; + } + +EXPORT_C void CVersitParser::Reserved1() + {} + +EXPORT_C void CVersitParser::Reserved2() + {} + + +// +// MVersitObserver +// + +EXPORT_C void MVersitObserver::Reserved1() + {} + +EXPORT_C void MVersitObserver::Reserved2() + {} + + +// +// MVersitPlugIn +// +EXPORT_C void MVersitPlugIn::GetInterface(TUid /*aInterfaceUid*/, TAny*& /*aInterface*/) + {} + +EXPORT_C void MVersitPlugIn::Reserved2() +/** +Reserved function. + +@internalComponent +*/ + {} + + +// +// Dll entry point +// + +EXPORT_C void Panic(TVersitParserPanic aPanic) + { + _LIT(KCategory,"Versit-Parser"); + User::Panic(KCategory,aPanic); + } + +// +// class CLineReaderExtension +// +CLineReaderExtension::CLineReaderExtension() + {} + +CLineReaderExtension::~CLineReaderExtension() + { + delete iLineBase64Value; + } + +void CLineReaderExtension::DeleteBase64ValueBuffer() + { + delete iLineBase64Value; + iLineBase64Value = NULL; + } + +HBufC8* CLineReaderExtension::CreateBase64ValueBufferL() + { + if (!iLineBase64Value) + { + iLineBase64Value = HBufC8::NewL(CLineReader::EInitialLineSize); + } + return iLineBase64Value; + } + +HBufC8* CLineReaderExtension::Base64ValueBuffer() + { + return iLineBase64Value; + } + +CLineReaderExtension* CLineReaderExtension::NewL() + { + CLineReaderExtension* self=new(ELeave) CLineReaderExtension(); + return self; + } +