--- /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 <versit.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <versitlinereaderext.h>
+#include "versittlscontainer.h"
+#include "versit_internal.h"
+#endif
+
+// System includes
+#include <s32file.h>
+#include <s32mem.h>
+#include <utf.h>
+#include <charconv.h>
+#include <confndr.h>
+#include <concnf.h>
+#include <conlist.h>
+#include <e32base.h>
+
+// User includes
+#include <vutil.h>
+#include <vstaticutils.h>
+#include <versittls.h>
+#include "verror.h"
+#include <vobserv.h>
+#include <vcal.h>
+#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=(++crPos<aPos);
+ break;
+ }
+ CharacterRead:
+ if (ch==CVersitParser::ECarriageReturn)
+ {
+ if (crPos<0)
+ crPos=aPos;
+ skipWhiteSpaceAtStart=EFalse;
+ // next character should be a LF...
+ }
+ else if (ch==CVersitParser::ELineFeed)
+ {
+ if (crPos<0)
+ {
+ // LF without CR
+ crPos=aPos;
+ skipWhiteSpaceAtStart=EFalse;
+ }
+ break; // The end of a line.
+ }
+ else
+ {
+ crPos=-1;
+ if (whiteSpaceLine == ELineIsWhiteSpace || whiteSpaceLine == ELineIsCRLFOnly )
+ {
+ whiteSpaceLine=(VersitUtils::IsWhiteSpace(ch) ? ELineIsWhiteSpace:ELineHasContent);
+ if (!whiteSpaceLine)
+ skipWhiteSpaceAtStart=EFalse;
+ }
+
+ if (ch == CVersitParser::EColon)
+ {
+ whiteSpaceLine = ELineHasColon;
+ }
+ }
+ if (skipWhiteSpaceAtStart)
+ {
+ if (iPlugIn)
+ skipWhiteSpaceAtStart=iPlugIn->DeleteAllSpaces();
+ }
+ 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<CVersitTlsData *>(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 : <EntityName> 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<CParserProperty>(5);
+ TUid uid = TUid::Uid(KVersitPropertyHBufCUid);
+
+ // get properties but don't take ownership of the elements of the array
+ CArrayPtr<CParserProperty>* 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; ii<noOfProperties; ii++)
+ {
+ (*iArrayOfProperties)[ii]->ExternalizeL(aStream, this);
+ }
+ }
+ if (iArrayOfEntities)
+ {
+ const TInt noOfEntities = iArrayOfEntities->Count();
+ for (TInt ii=0; ii<noOfEntities; ii++)
+ {
+ // Ensure that the entities defaults match this parser's
+ CVersitParser& entity = *iArrayOfEntities->At(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<CParserProperty>(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<CVersitParser>(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>* 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<CVersitParser>* arrayOfNamedEntities = NULL;
+ if (iArrayOfEntities)
+ {
+ TInt entities=iArrayOfEntities->Count();
+ arrayOfNamedEntities=new(ELeave) CArrayPtrFlat<CVersitParser>(5);
+ //CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfEntities,arrayOfNamedEntities));
+ CleanupStack::PushL(arrayOfNamedEntities);
+ for (TInt ii=0; ii<entities; ii++)
+ {
+ if ((*iArrayOfEntities)[ii]->EntityName()==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>* 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<CVersitParser>* arrayOfEntities=iArrayOfEntities;
+ if (aTakeOwnership)
+ iArrayOfEntities=NULL;
+ return arrayOfEntities;
+ }
+
+EXPORT_C CArrayPtr<CParserProperty>* 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 "K<Versit/Card/Cal>Property<Type>Uid"). 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<CParserProperty>* arrayOfNamedProperties = NULL;
+ if (iArrayOfProperties)
+ {
+ const TInt properties = iArrayOfProperties->Count();
+ arrayOfNamedProperties = new(ELeave) CArrayPtrFlat<CParserProperty>(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<CParserProperty>* 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<CParserProperty>* 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<CParserParam>* 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<CParserParam>* 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<CParserParam>* 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<MVersitPlugInExtensionBase64Ending*>(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<TVersitDateTime>* values=STATIC_CAST(CParserPropertyValueMultiDateTime*,timeValue)->Value();
+ if (values)
+ {
+ TInt count=values->Count();
+ for (TInt ii=0;ii<count; ii++)
+ ConvertUTCDateTimeToMachineLocal((*values)[ii],aIncrement,aDaylight);
+ }
+ }
+ break;
+ default:
+ timeValue->ConvertAllUTCDateTimesToMachineLocalL(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<CParserParam>* CVersitParser::GetPropertyParamsLC(TPtr8 aParams)
+ {
+ CArrayPtr<CParserParam>* arrayOfParams=new(ELeave)CArrayPtrFlat<CParserParam>(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 (currentChar<afterLastChar && *currentChar!=KVersitTokenSemiColonVal && *currentChar!=KVersitTokenBackslashVal)
+ ++currentChar;
+ dest=currentChar;
+ if (*currentChar==KVersitTokenBackslashVal && currentChar<afterLastChar)
+ {
+ do {
+ if (!escaping)
+ {
+ if (*currentChar==KVersitTokenSemiColonVal)
+ break;
+ escaping=(*currentChar==KVersitTokenBackslashVal);
+ if (escaping)
+ {
+ ++currentChar;
+ continue;
+ }
+ }
+ else
+ {
+ if (*currentChar!=KVersitTokenBackslashVal && *currentChar!=KVersitTokenSemiColonVal)
+ *dest++=KVersitTokenBackslashVal;
+ escaping=EFalse;
+ }
+ *dest++=*currentChar++;
+ } while(currentChar<afterLastChar);
+ if (escaping)
+ *dest++=KVersitTokenBackslashVal;
+ }
+ len=dest-startField;
+ if (len>0)
+ ParseParamL(arrayOfParams,TPtr8(startField,len,len));
+ ++currentChar;
+ }
+ return arrayOfParams;
+ }
+
+EXPORT_C void CVersitParser::ParseParamL(CArrayPtr<CParserParam>* 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<CParserParam>* 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()<aValue.Length())
+ iDecodedValue=iDecodedValue->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<TVersitDateTime>* 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<TVersitDateTime>* CVersitParser::MakePropertyValueMultiDateTimeL(TPtr16 aDateTimeGroup)
+// Make a property from aDateTimeGroup, with a CArrayPtr<TDateTime> value
+ {
+ VersitUtils::StripWhiteSpace(aDateTimeGroup);
+ if(aDateTimeGroup.Length()==0)
+ return NULL;
+ CArrayPtr<TVersitDateTime>* arrayOfDateTimes=new(ELeave)CArrayPtrFlat<TVersitDateTime>(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<length;i++)
+ {
+ if(aString[i]<'0'||aString[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<KVersitDefaultBufferSize> 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<CParserParam>* array=REINTERPRET_CAST(CArrayPtr<CParserParam>*,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<CParserProperty>* array=REINTERPRET_CAST(CArrayPtr<CParserProperty>*,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<CVersitParser>* array=REINTERPRET_CAST(CArrayPtr<CVersitParser>*,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<TVersitDateTime>* array=REINTERPRET_CAST(CArrayPtr<TVersitDateTime>*,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<CCnvCharacterSetConverter::SCharacterSet>* 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;
+ }
+