diff -r 000000000000 -r dab8a81a92de omads/omadsextensions/dsutils/emailxmlutils/src/NSmlEmailParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omads/omadsextensions/dsutils/emailxmlutils/src/NSmlEmailParser.cpp Mon Nov 23 14:46:41 2009 +0200 @@ -0,0 +1,793 @@ +/* +* Copyright (c) 2004 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: Sources +* +*/ + + + +// INCLUDE FILES +#include +#include + +#include "nsmlxmlparser.h" + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +EXPORT_C CNSmlEmailParser* CNSmlEmailParser::NewL() + { + CNSmlEmailParser* self = CNSmlEmailParser::NewLC(); + CleanupStack::Pop(); + + return self; + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::NewLC +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +EXPORT_C CNSmlEmailParser* CNSmlEmailParser::NewLC() + { + CNSmlEmailParser* self = new (ELeave) CNSmlEmailParser(); + CleanupStack::PushL(self); + self->ConstructL(); + + return self; + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::~CNSmlEmailParser +// Destructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CNSmlEmailParser::~CNSmlEmailParser() + { + if( iTruncated ) + delete iTruncated; + + if( iExt ) + { + iExt->ResetAndDestroy(); + delete iExt; + } + + if( iEmailItem ) delete iEmailItem; + + if( iTruncType ) delete iTruncType; + if( iTruncName ) delete iTruncName; + if( iExtData ) delete iExtData; + + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::ParseXml +// Parses through the given XML and puts the data it contains +// to member variables. +// Note: The string-values in CNSmlEmailParser are NOT copies, but +// references to aXml. The method does not check, if member variables +// already contain data, but just writes it (if some of them are already +// instantiated dynamically, they should be deleted before this method is called). +// ----------------------------------------------------------------------------- +// +EXPORT_C TNSmlParserGeneratorError CNSmlEmailParser::ParseXml( HBufC8* aXml ) + { + + // pre-process the data (remove cdata over ) + TRAPD( cdataErr, PreProcessL(aXml)); + if (cdataErr != EErrorNone) + return (TNSmlParserGeneratorError)cdataErr; + + // reset state + iSetValues.Reset(); + iCurrentState = ENone; + iLastState = ENone; + TPtrC8 ptr(*aXml); + + // parse + TRAPD(err, ParseL( ptr )); + + // return error, if in wrong state + if( err == EErrorNone && iCurrentState != ENone ) + return EInvalidXmlError; + + return CheckError(err); + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::GenerateXml +// Generates Email-XML using the data in member variables. aXml contains the +// generated xml when the function returns successfully. Note: caller should not +// instantiate the HBufC8, since this method first counts the size of the xml to +// be generated and then instatiates the HBufC8 with a correct maximum size. If +// the given buffer is not NULL, it is destroyed and a new one is instantiated. +// However, the caller gets the control of the HBufC8 when the function returns. +// ----------------------------------------------------------------------------- +// +EXPORT_C TNSmlParserGeneratorError CNSmlEmailParser::GenerateXml( HBufC8*& aXml ) + { + + TRAPD( err, GenerateEmailXmlL( aXml ) ); + + return CheckError(err); + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::GenerateEmailXmlL +// Private method that does the actual email xml generation +// ----------------------------------------------------------------------------- +// +void CNSmlEmailParser::GenerateEmailXmlL( HBufC8*& aXml ) + { + ConvertIntoEntitiesL(); + + // count the size of the xml + TInt size = CountXmlSizeL(); + + // create buffer for the xml + + if ( aXml ) + { + delete aXml; + aXml = NULL; + } + + aXml = HBufC8::NewLC(size); + TPtr8 ptr = aXml->Des(); + + // append data to buffer + AppendElement(ptr, KEmailElement()); + + if ( iRead ) + { + AppendElement(ptr, KEmailReadElement(), BooleanToString( iRead )); + } + + if ( iForwarded ) + { + AppendElement(ptr, KEmailForwardedElement(), BooleanToString( iForwarded )); + } + + if ( iReplied ) + { + AppendElement(ptr, KEmailRepliedElement(), BooleanToString( iReplied )); + } + + if (iReceived != Time::NullTTime()) + { + AppendElement(ptr, KEmailReceivedElement(), DateTimeToStringL(iReceived)); + } + + if (iCreated != Time::NullTTime()) + { + AppendElement(ptr, KEmailCreatedElement(), DateTimeToStringL(iCreated)); + } + + if (iModified != Time::NullTTime()) + { + AppendElement(ptr, KEmailModifiedElement(), DateTimeToStringL(iModified)); + } + + if ( iDeleted ) + { + AppendElement(ptr, KEmailDeletedElement(), BooleanToString( iDeleted )); + } + + if ( iFlagged ) + { + AppendElement(ptr, KEmailFlaggedElement(), BooleanToString( iFlagged )); + } + + if ( iEmailItem ) + { + AppendElement(ptr, KEmailItemElement()); + ptr.Append(KCDataStart); + ptr.Append( *iEmailItem ); + ptr.Append(KCDataEnd); + AppendEndElement(ptr, KEmailItemElement()); + } + + if ( iTruncated ) + { + iTruncated->GenerateXmlL(ptr, this); + } + + if ( iExt ) + { + for (TInt i=0; i < iExt->Count(); ++i) + { + iExt->At(i)->GenerateXmlL(ptr, this); + } + + } + + + AppendEndElement(ptr, KEmailElement()); + + CleanupStack::Pop(); // aXml + + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::CountXmlSizeL +// Counts how long the xml string will be if it was generated using +// the values currently in member variables. +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CNSmlEmailParser::CountXmlSizeL() + { + TInt size = 0; + + size += KCDataStart().Length() + KCDataEnd().Length(); + size += SizeOfElements( KEmailElement() ); + + if ( iRead ) + { + size += SizeOfBoolean( iRead, KEmailReadElement() ); + } + + if ( iForwarded ) + { + size += SizeOfBoolean( iForwarded, KEmailForwardedElement() ); + } + + if ( iReplied ) + { + size += SizeOfBoolean( iReplied, KEmailRepliedElement() ); + } + + if (iReceived != Time::NullTTime()) + { + size += SizeOfDatetime( KEmailReceivedElement() ); + } + + if (iCreated != Time::NullTTime()) + { + size += SizeOfDatetime( KEmailCreatedElement() ); + } + + if (iModified != Time::NullTTime()) + { + size += SizeOfDatetime( KEmailModifiedElement() ); + } + + if ( iDeleted ) + { + size += SizeOfBoolean( iDeleted, KEmailDeletedElement() ); + } + + if ( iFlagged ) + { + size += SizeOfBoolean( iFlagged, KEmailFlaggedElement() ); + } + + if ( iEmailItem ) + { + size += SizeOfString( iEmailItem, KEmailItemElement() ); + size += KCDataStart().Length() + KCDataInnerEnd().Length(); + } + + if ( iTruncated ) + { + size += iTruncated->CountXmlSizeL( this ); + } + + if ( iExt ) + { + for (TInt i=0; i < iExt->Count(); ++i) + { + size += iExt->At(i)->CountXmlSize( this ); + } + } + + return size; + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::AddExtL +// Adds the given extension to iExt +// ----------------------------------------------------------------------------- +// +EXPORT_C void CNSmlEmailParser::AddExtL( CNSmlExtData* aExt ) + { + iExt->AppendL(aExt); + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::NextElementL +// Base class' ParseL method calls this method, when a new element is found. aElement +// is the name of that element (string inside '<' and '>' characters). +// ----------------------------------------------------------------------------- +// +void CNSmlEmailParser::NextElementL( TPtrC8 aElement ) + { + if (aElement.Length() == 0) + User::Leave(EInvalidXmlError); + + TBool startElement = ETrue; + + if(aElement[0] == KCharacterSlash) + { + // take off the '/' character from the beginning + aElement.Set(aElement.Right(aElement.Length()-1)); + // end element + startElement = EFalse; + } +#ifndef __NO_EMPTY_ELEMENTS_ + else if (aElement[aElement.Length()-1] == KCharacterSlash) + { + // take off the '/' character from the end + aElement.Set(aElement.Left(aElement.Length()-1)); + + // empty element == start element, empty data, end element + NextElementL( aElement ); // simulates start element + NextDataL( _L8("") ); // simulates empty data + + // create the end element + HBufC8* end = HBufC8::NewLC(aElement.Length()+1); + TPtr8 ptr = end->Des(); + ptr.Append( _L8("/") ); + ptr.Append( aElement ); + + NextElementL( ptr ); // simulates end element + + CleanupStack::PopAndDestroy(); // end + + return; + } +#endif + + // variables used for state, init to and not set + TNSmlCurrentEmailElement inner = EEmail; + TNSmlCurrentEmailElement outer = EEmail; + TBool isSet = EFalse; + + // check which element we've got + if( aElement == KEmailElement ) + { + outer = ENone; + isSet = iSetValues.iEmail; + if ( startElement ) iSetValues.iEmail = ETrue; + } + else if( aElement == KEmailReadElement ) + { + inner = ERead; + isSet = iSetValues.iRead; + } + else if( aElement == KEmailForwardedElement ) + { + inner = EForwarded; + isSet = iSetValues.iForwarded; + } + else if( aElement == KEmailRepliedElement ) + { + inner = EReplied; + isSet = iSetValues.iReplied; + } + else if( aElement == KEmailReceivedElement ) + { + inner = EReceived; + isSet = iSetValues.iReceived; + } + else if( aElement == KEmailCreatedElement ) + { + inner = ECreated; + isSet = iSetValues.iCreated; + } + else if( aElement == KEmailModifiedElement ) + { + inner = EModified; + isSet = iSetValues.iModified; + } + else if( aElement == KEmailDeletedElement ) + { + inner = EDeleted; + isSet = iSetValues.iDeleted; + } + else if( aElement == KEmailFlaggedElement ) + { + inner = EFlagged; + isSet = iSetValues.iFlagged; + } + else if( aElement == KEmailItemElement ) + { + inner = EEmailItem; + isSet = iSetValues.iEmailItem; + if ( startElement ) + HandleNextEmailItemStartL(); + else + HandleNextEmailItemEndL(); + } + else if( aElement == KTruncatedElement ) + { + inner = ETrunc; + isSet = iSetValues.iTrunc; + + if ( startElement ) + { + if ( !iTruncated ) + iTruncated = CNSmlTruncatedData::NewL(); + iSetValues.iTrunc = ETrue; + } + } + else if( aElement == KTruncatedBodyElement ) + { + inner = ETruncBody; + outer = ETrunc; + if ( startElement ) + { + if( iTruncType ) + { + delete iTruncType; + iTruncType = NULL; + } + iTruncSize = KErrNotFound; + + iSetValues.iTruncBodySize = EFalse; + iSetValues.iTruncBodyType = EFalse; + } + else + { + iTruncated->AddBodyL(iTruncSize, iTruncType); + } + } + else if( aElement == KTruncatedAttachElement ) + { + inner = ETruncAttach; + outer = ETrunc; + if ( startElement ) + { + if( iTruncType ) + { + delete iTruncType; + iTruncType = NULL; + } + if( iTruncName ) + { + delete iTruncName; + iTruncName = NULL; + } + iTruncSize = KErrNotFound; + + iSetValues.iTruncAttachName = EFalse; + iSetValues.iTruncAttachType = EFalse; + iSetValues.iTruncAttachSize = EFalse; + } + else + { + iTruncated->AddAttachmentL(iTruncName, iTruncSize, iTruncType); + } + } + else if( aElement == KTruncatedSizeElement ) + { + if ( (startElement && iCurrentState == ETruncBody) + || (!startElement && iCurrentState == ETruncBodySize) ) + { + inner = ETruncBodySize; + outer = ETruncBody; + isSet = iSetValues.iTruncBodySize; + } + else if ( (startElement && iCurrentState == ETruncAttach) + || (!startElement && iCurrentState == ETruncAttachSize) ) + { + inner = ETruncAttachSize; + outer = ETruncAttach; + isSet = iSetValues.iTruncAttachSize; + } + else + { + User::Leave(EInvalidXmlError); // wrong state + } + } + else if( aElement == KTruncatedTypeElement ) + { + if ( (startElement && iCurrentState == ETruncBody) + || (!startElement && iCurrentState == ETruncBodyType) ) + { + inner = ETruncBodyType; + outer = ETruncBody; + isSet = iSetValues.iTruncBodyType; + } + else if ( (startElement && iCurrentState == ETruncAttach) + || (!startElement && iCurrentState == ETruncAttachType) ) + { + inner = ETruncAttachType; + outer = ETruncAttach; + isSet = iSetValues.iTruncAttachType; + } + else + { + User::Leave(EInvalidXmlError); // wrong state + } + } + else if( aElement == KTruncatedNameElement ) + { + inner = ETruncAttachName; + outer = ETruncAttach; + isSet = iSetValues.iTruncAttachName; + } + else if( aElement == KExtElement ) + { + inner = EExt; + if ( startElement ) + { + if( iExtData ) + { + delete iExtData; + iExtData = NULL; + } + iExtData = CNSmlExtData::NewL(); + iSetValues.iXNam = EFalse; + } + else + { + if( !iSetValues.iXNam ) User::Leave(EMandatoryFieldNotFound); // xnam not set + iExt->AppendL(iExtData); + iExtData = NULL; + } + } + else if( aElement == KExtXNamElement ) + { + inner = EExtXNam; + outer = EExt; + isSet = iSetValues.iXNam; + } + else if( aElement == KExtXValElement ) + { + inner = EExtXVal; + outer = EExt; + } + else + { // unknown element + User::Leave(EInvalidXmlError); + } + + + // finally, change state depending on was the element start or end element + if ( startElement ) + { + StartElementStateChangeL( outer, inner, isSet ); + } + else + { + EndElementStateChangeL( inner, outer ); + } + + + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::NextDataL +// Base class' ParseL method calls this method, when a data is read from xml, but that +// data is not element name (data inside or between elements). +// ----------------------------------------------------------------------------- +// +void CNSmlEmailParser::NextDataL( TPtrC8 aData ) + { + switch(iCurrentState) + { + case ENone: + case EEmail: + case ETrunc: + case ETruncBody: + case ETruncAttach: + case EExt: + LeaveIfNotWhiteSpaceL( aData ); + break; + case ERead: + iRead = StringToBooleanL(aData); + iSetValues.iRead = ETrue; + break; + case EForwarded: + iForwarded = StringToBooleanL(aData); + iSetValues.iForwarded = ETrue; + break; + case EReplied: + iReplied = StringToBooleanL(aData); + iSetValues.iReplied = ETrue; + break; + case EDeleted: + iDeleted = StringToBooleanL(aData); + iSetValues.iDeleted = ETrue; + break; + case EFlagged: + iFlagged = StringToBooleanL(aData); + iSetValues.iFlagged = ETrue; + break; + case EReceived: + iReceived = StringToTTimeL(aData); + iSetValues.iReceived = ETrue; + break; + case ECreated: + iCreated = StringToTTimeL(aData); + iSetValues.iCreated = ETrue; + break; + case EModified: + iModified = StringToTTimeL(aData); + iSetValues.iModified = ETrue; + break; + case EEmailItem: + HandleNextEmailItemDataL( aData ); // implementation dependent behavior + iSetValues.iEmailItem = ETrue; + break; + case ETruncBodySize: + iTruncSize = StringToIntegerL(aData); + iSetValues.iTruncBodySize = ETrue; + break; + case ETruncBodyType: + iTruncType = aData.AllocL(); + iSetValues.iTruncBodyType = ETrue; + break; + case ETruncAttachSize: + iTruncSize = StringToIntegerL(aData); + iSetValues.iTruncAttachSize = ETrue; + break; + case ETruncAttachName: + iTruncName = aData.AllocL(); + iSetValues.iTruncAttachName = ETrue; + break; + case ETruncAttachType: + iTruncType = aData.AllocL(); + iSetValues.iTruncAttachType = ETrue; + break; + case EExtXNam: + iExtData->iXNam = aData.AllocL(); + iSetValues.iXNam = ETrue; + break; + case EExtXVal: + iExtData->AddXValL(aData.AllocL()); + break; + default: + User::Leave(EUnknownError); // should never happen + break; + } + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::HandleNextEmailItemDataL +// Next emailitem data +// ----------------------------------------------------------------------------- +// +void CNSmlEmailParser::HandleNextEmailItemDataL( TPtrC8 aData ) + { + iEmailItem = aData.AllocL(); + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::StartElementStateChangeL +// Checks that the state change (new start element) is legal (right order of +// elements and element not already set) and changes the state. +// ----------------------------------------------------------------------------- +// +void CNSmlEmailParser::StartElementStateChangeL(TNSmlCurrentEmailElement aCurrentState, + TNSmlCurrentEmailElement aNextState, + TBool aIsSet) + { + if( aIsSet || iCurrentState != aCurrentState || aNextState < iLastState ) + { + User::Leave(EInvalidXmlError); + } + + iLastState = iCurrentState; + iCurrentState = aNextState; + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::EndElementStateChangeL +// Checks that the state change (new end element) is legal (right order of +// elements and element not already set) and changes the state. +// ----------------------------------------------------------------------------- +// +void CNSmlEmailParser::EndElementStateChangeL(TNSmlCurrentEmailElement aCurrentState, + TNSmlCurrentEmailElement aNextState ) + { + if( iCurrentState != aCurrentState ) + { + User::Leave(EInvalidXmlError); + } + + iLastState = iCurrentState; + iCurrentState = aNextState; + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::ConvertIntoEntitiesL +// Converts special characters of this email-dataobject to corresponding +// characters. Emailitem needs not to be changed, since it is always +// placed inside cdata (when generating xml). +// ----------------------------------------------------------------------------- +// +void CNSmlEmailParser::ConvertIntoEntitiesL() + { + + // truncate info + if ( iTruncated ) + { + iTruncated->ConvertIntoEntitiesL(this); + } + + // extensions + if ( iExt ) + { + for (TInt i=0; i < iExt->Count(); ++i) + { + iExt->At(i)->ConvertIntoEntitiesL(this); + } + } + + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::CNSmlEmailParser +// Private constructor +// ----------------------------------------------------------------------------- +// +CNSmlEmailParser::CNSmlEmailParser() + : iReceived(Time::NullTTime()), iCreated(Time::NullTTime()), iModified(Time::NullTTime()), + iTruncSize(KErrNotFound) + { + } + +// ----------------------------------------------------------------------------- +// CNSmlEmailParser::ConstructL +// Second phase construction +// ----------------------------------------------------------------------------- +// +void CNSmlEmailParser::ConstructL() + { + iExt = new (ELeave) CNSmlExtDataArray(3); + } + +// ----------------------------------------------------------------------------- +// TNSmlSetEmailValues::TNSmlSetEmailValues +// ----------------------------------------------------------------------------- +// +CNSmlEmailParser::TNSmlSetEmailValues::TNSmlSetEmailValues() + { + Reset(); + } + + +// ----------------------------------------------------------------------------- +// TNSmlSetEmailValues::Reset +// ----------------------------------------------------------------------------- +// +void CNSmlEmailParser::TNSmlSetEmailValues::Reset() + { + iEmail = EFalse; + iRead = EFalse; + iForwarded = EFalse; + iReplied = EFalse; + iDeleted = EFalse; + iFlagged = EFalse; + iReceived = EFalse; + iCreated = EFalse; + iModified = EFalse; + iEmailItem = EFalse; + iTrunc = EFalse; + iTruncBodySize = EFalse; + iTruncBodyType = EFalse; + iXNam = EFalse; + iTruncAttachSize = EFalse; + iTruncAttachType = EFalse; + iTruncAttachName = EFalse; + } + +// End of File