diff -r dab8a81a92de -r 95fdac6ccb5c omads/omadsextensions/dsutils/emailxmlutils/src/NSmlEmailFileParser.cpp --- a/omads/omadsextensions/dsutils/emailxmlutils/src/NSmlEmailFileParser.cpp Mon Nov 23 14:46:41 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,814 +0,0 @@ -/* -* 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 =============================== - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::NewL -// Two-phased constructor. -// ----------------------------------------------------------------------------- -// -EXPORT_C CNSmlEmailFileParser* CNSmlEmailFileParser::NewL() - { - CNSmlEmailFileParser* self = CNSmlEmailFileParser::NewLC(); - CleanupStack::Pop(); - - return self; - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::NewLC -// Two-phased constructor. -// ----------------------------------------------------------------------------- -// -EXPORT_C CNSmlEmailFileParser* CNSmlEmailFileParser::NewLC() - { - CNSmlEmailFileParser* self = new (ELeave) CNSmlEmailFileParser(); - CleanupStack::PushL(self); - self->ConstructL(); - - return self; - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::~CNSmlEmailFileParser -// Destructor. -// ----------------------------------------------------------------------------- -// -EXPORT_C CNSmlEmailFileParser::~CNSmlEmailFileParser() - { - // close rfs and open streams - if ( iWriteStream.Sink() ) - iWriteStream.Close(); - - iRfs.Close(); - delete iEmailItemFile; - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::ParseXml -// Parses the email xml, that is located in the file whose name is given -// as aXml (path and filename) -// ----------------------------------------------------------------------------- -// -EXPORT_C TNSmlParserGeneratorError CNSmlEmailFileParser::ParseXml( HBufC8* aXml ) - { - if ( !aXml ) - return EInvalidFilename; - - HBufC* filename = Buf8ToBuf16( aXml ); - if ( !filename ) - { - return EOutOfMemory; - } - - // open the stream and parse - TNSmlParserGeneratorError err = EErrorNone; - RFileReadStream rs; - if ( rs.Open(iRfs, *filename, KFileReadAccess) != KErrNone ) - { - err = EInvalidFilename; - } - else - { - err = ParseXml( rs ); - rs.Close(); - } - - delete filename; - - return err; - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::ParseXml -// Parses the xml from the given stream, and writes the emailitem - if present - to a temp file -// ----------------------------------------------------------------------------- -// -EXPORT_C TNSmlParserGeneratorError CNSmlEmailFileParser::ParseXml( RReadStream& aRs ) - { - iSetValues.Reset(); - iCurrentState = ENone; - iLastState = ENone; - - TRAPD(err, ParseFromStreamL( aRs )); - - if( err == EErrorNone && iCurrentState != ENone ) - return EInvalidXmlError; - - return CheckError(err); - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::GenerateXml -// Generates the xml and writes it to the file whose name is given in aXml (path -// and filename). -// ----------------------------------------------------------------------------- -// -EXPORT_C TNSmlParserGeneratorError CNSmlEmailFileParser::GenerateXml( HBufC8*& aXml ) - { - if ( !aXml ) - return EInvalidFilename; - - HBufC* filename = Buf8ToBuf16( aXml ); - if ( !filename ) - { - return EOutOfMemory; - } - - // open the stream and generate - iWriteStream.Replace(iRfs, *filename, KFileWriteAccess); - TNSmlParserGeneratorError err = GenerateXml( iWriteStream ); - iWriteStream.Close(); - - delete filename; - - return err; - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::GenerateXml -// Generates the xml and writes it to the given stream. -// ----------------------------------------------------------------------------- -// -EXPORT_C TNSmlParserGeneratorError CNSmlEmailFileParser::GenerateXml( RWriteStream& aWs ) - { - TRAPD( err, GenerateEmailXmlL( aWs ) ); - - return CheckError(err); - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::GenerateEmailXmlL -// ----------------------------------------------------------------------------- -// -void CNSmlEmailFileParser::GenerateEmailXmlL( RWriteStream& aWs ) - { - ConvertIntoEntitiesL(); - - // count the size of the xml (does not include emailitem, since it is - if present - in a file) - TInt size = CNSmlEmailParser::CountXmlSizeL(); - if ( iUseEmailItem ) size += 20; // extra for emailitem tags - - // create a buffer for using the size - HBufC8* xml = HBufC8::NewLC(size); - TPtr8 ptr = xml->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 emailitem should be used in generation, write it to the stream - if ( iUseEmailItem ) - { - // append start tag and cdata start - AppendElement(ptr, KEmailItemElement()); - ptr.Append(KCDataStart); - - // open a stream to emailitem - RFileReadStream rs; - TInt err = rs.Open( iRfs, *iEmailItemFile, KFileReadAccess ); - if ( err != KErrNone ) - User::Leave( EInvalidFilename ); - - CleanupClosePushL(rs); - - // write the buffer to the stream - aWs.WriteL(ptr); - - // write emailitem from stream - aWs.WriteL(rs); - - // close the opened read stream - CleanupStack::Pop(); // rs - - // empty the buffer (i.e. set the length to zero) - ptr.SetLength(0); - - // append emailitem end tag and cdata inner end - ptr.Append(KCDataEnd); - AppendEndElement(ptr, KEmailItemElement()); - } - - // append the rest of the data to the buffer - 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()); - - // write the buffer to the stream and commit - aWs.WriteL(ptr); - aWs.CommitL(); - - CleanupStack::PopAndDestroy(); // xml - - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::CountXmlSizeL -// ----------------------------------------------------------------------------- -// -EXPORT_C TInt CNSmlEmailFileParser::CountXmlSizeL() - { - // counting the size is not essential, since xml is written to a file - return KErrNotSupported; - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::HandleNextEmailItemDataL -// Next emailitem data -// ----------------------------------------------------------------------------- -// -void CNSmlEmailFileParser::HandleNextEmailItemDataL( TPtrC8 aData ) - { - // write the given piece of data into a file (stream) - iWriteStream.WriteL(aData); - } - - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::HandleNextEmailItemStartL -// Emailitem element starts -// ----------------------------------------------------------------------------- -// -void CNSmlEmailFileParser::HandleNextEmailItemStartL() - { - // open the write stream - User::LeaveIfError( iWriteStream.Replace( iRfs, *iEmailItemFile, KFileWriteAccess ) ); - iReadingEmailItemData = ETrue; - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::HandleNextEmailItemEndL -// Emailitem element ends -// ----------------------------------------------------------------------------- -// -void CNSmlEmailFileParser::HandleNextEmailItemEndL() - { - // close the write stream - iWriteStream.Close(); - iReadingEmailItemData = EFalse; - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::ParseFromStreamL -// ----------------------------------------------------------------------------- -// -void CNSmlEmailFileParser::ParseFromStreamL( RReadStream& aRs ) - { - - // reset preprocess variables and parser - ResetPreProcessor(); - ResetParserL(); - - // read and process the data piece by piece - HBufC8* piece = HBufC8::NewLC(KReadDataLength); - TPtr8 ptr = piece->Des(); - TInt dataSize = aRs.Source()->SizeL(); - - TInt pos = 0; - iFirstPiece = ETrue; - for( pos = KReadDataLength; pos <= dataSize ; pos += KReadDataLength ) - { - // read piece of data from the stream - aRs.ReadL(ptr, KReadDataLength); - - // check that there are no incomplete cdata/comment/entity at the end - dataSize += RemoveIncompleteL( piece, aRs ); - - // pre-process - PreProcessPieceL( piece ); - - // parsing - TPtrC8 temp( *piece ); - ParsePieceL( temp ); - - iFirstPiece = EFalse; - } - - TInt lastPartLength = dataSize - pos + KReadDataLength; - aRs.ReadL(ptr, lastPartLength); - - PreProcessPieceL( piece ); - - // parsing - TPtrC8 temp( *piece ); - ParsePieceL( temp, ETrue ); - - CleanupStack::PopAndDestroy(); // piece - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::ParsePieceL -// ----------------------------------------------------------------------------- -// -void CNSmlEmailFileParser::ParsePieceL( TPtrC8& aXml, TBool aLastPiece ) - { - - // check if last cdata has not ended yet - if ( iReadingCData ) - { - TInt endPos = aXml.Find(KCDataEnd); - TPtrC8 cdata = _L8(""); - - if ( endPos == KErrNotFound && aLastPiece ) - { - User::Leave(EInvalidCDataStructure); - } - else if ( endPos == KErrNotFound ) - { - // cdata end was not found, read the whole piece as cdata - NextDataL( aXml ); - return; - } - else - { - // add data until cdata end to buffer - cdata.Set( aXml.Left( endPos ) ); - aXml.Set( aXml.Right( aXml.Length() - endPos - KCDataEnd().Length() ) ); - iReadingCData = EFalse; - } - - AddToCompleteL(cdata); - NextDataL(*iCompleteBuffer); - ResetBufferL(iCompleteBuffer); - - } -#ifndef __NO_XML_COMMENTS_ - else if ( iReadingComment ) // check if last comment has not ended yet - { - TInt endPos = aXml.Find(KCommentEnd); - - if ( endPos == KErrNotFound && aLastPiece ) - { // this is the last piece of data and end of comment has not been found -> error - User::Leave(EInvalidXmlError); - } - else if ( endPos == KErrNotFound ) - { - // end of comment was not found, no need to parse this piece of data - return; - } - else - { - // end of cdata was found, jump to that position - aXml.Set( aXml.Right( aXml.Length() - endPos - KCommentEnd().Length() ) ); - iReadingComment = EFalse; - } - } -#endif - - // parse through the string - TText c; - - for( TInt i=0; i < aXml.Length(); ++i ) - { - c = aXml[i]; - switch(c) - { - case KElementStart: - // if currently reading element, error - if( iReadingElementName ) - { - User::Leave(EInvalidXmlError); - } - - if( aXml.Length()-i >= KCDataStart().Length() && - !aXml.Mid(i, KCDataStart().Length()).Compare(KCDataStart()) ) - { // cdata - aXml.Set( aXml.Right( aXml.Length() - i ) ); - TInt endPos = aXml.Find(KCDataEnd); - - TPtrC8 cdata = _L8(""); - if ( endPos == KErrNotFound && aLastPiece ) - { - User::Leave(EInvalidCDataStructure); - } - else if ( endPos == KErrNotFound ) - { - // cdata end was not found, read all the rest as cdata - cdata.Set( aXml.Right( aXml.Length() - KCDataStart().Length() ) ); - i = aXml.Length(); // move to the end - iReadingCData = ETrue; - } - else - { - cdata.Set( aXml.Mid( KCDataStart().Length(), endPos - KCDataStart().Length() ) ); - aXml.Set( aXml.Right( aXml.Length() - endPos - KCDataEnd().Length() ) ); - - i = -1; - } - - // add current buffer to complete buffer - EntitiesToCharactersL( iBuffer, 0, iBuffer->Length() ); - AddToCompleteL(*iBuffer); - ResetBufferL(iBuffer); - AddToCompleteL(cdata); - } -#ifndef __NO_XML_COMMENTS_ - else if( aXml.Length()-i >= KCommentStart().Length() && - !aXml.Mid(i, KCommentStart().Length()).Compare(KCommentStart()) ) - { // comment - aXml.Set( aXml.Right( aXml.Length() - i ) ); - TInt endPos = aXml.Find(KCommentEnd); - - if ( endPos == KErrNotFound && aLastPiece) - { - // this is the last piece of data, and end of comment was not found -> error - User::Leave(EInvalidXmlError); - } - else if ( endPos == KErrNotFound ) - { - // the end was not found, no need to parse the rest since it is comment - iReadingComment = ETrue; - return; - } - else - { - // the end of comment was found, move to the end of comment and start parsing - // from there on - aXml.Set( aXml.Right( aXml.Length() - endPos - KCommentEnd().Length() ) ); - } - - i = -1; - } -#endif - else - { - // send the buffer - EntitiesToCharactersL( iBuffer, 0, iBuffer->Length() ); - AddToCompleteL(*iBuffer); - NextDataL(*iCompleteBuffer); - ResetBufferL(iBuffer); - ResetBufferL(iCompleteBuffer); - iReadingElementName = ETrue; - } - - break; - case KElementEnd: - // stop reading element name - if( !iReadingElementName ) - { - User::Leave(EInvalidXmlError); - } - else - { - NextElementL(*iBuffer); - ResetBufferL(iBuffer); - iReadingElementName = EFalse; - } - break; - default: - // add char to buffer - AddToBufferL(c, iBuffer); - break; - } - } - - // send the data in the buffer - if ( ( iReadingEmailItemData || aLastPiece ) && !iReadingElementName ) - { - EntitiesToCharactersL( iBuffer, 0, iBuffer->Length() ); - AddToCompleteL(*iBuffer); - NextDataL(*iCompleteBuffer); - ResetBufferL(iBuffer); - ResetBufferL(iCompleteBuffer); - } - - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::RemoveIncompleteL -// Checks if there is incomplete cdata/comment/entity at the end of the given -// piece. If one is found, it is removed from aPiece and the read mark of the -// stream is moved backwards the length of the removed item (i.e. the incomplete -// item will be read to the next piece as a whole). -// ----------------------------------------------------------------------------- -// -TUint CNSmlEmailFileParser::RemoveIncompleteL( HBufC8* aPiece, RReadStream& aStream ) - { - // we need to check only the last nine characters - TUint removeSize = CheckPiece( aPiece->Right( 9 ) ); - - if ( removeSize ) - { - // remove the incomplete item from aPiece - TPtr8 ptr = aPiece->Des(); - ptr.Delete( aPiece->Length() - removeSize, removeSize ); - - // move backwards in reading the stream - aStream.Source()->SeekL( MStreamBuf::ERead, aStream.Source()->TellL(MStreamBuf::ERead) - removeSize ); - } - - // no need to loop the rest of aPiece. If xml is not correctly formed, - // an error occures later in the parser - - return removeSize; - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::CheckPiece -// ----------------------------------------------------------------------------- -// -TUint CNSmlEmailFileParser::CheckPiece( const TPtrC8 aEnd ) const - { - // check that there are no incomplete cdata/comment/entity at the end - // (cdata start, cdata end, cdata inner end, comment start, comment end, entities) - // ( , , &xxxx; , ]]]]>> , ]]]]>> ) - // do not change the order - - // possible inner cdata end - TInt pos = aEnd.Find( _L8("]]]") ); - if ( pos != KErrNotFound ) - { - return aEnd.Length() - pos; - } - - // beginning part of comment or cdata - pos = aEnd.Find( _L8("Des(); - - // the string used for searching and moving in the string - TPtrC8 searchString(*aXml); - - // the current position in the original string - TInt searchStartPos = 0; - - // if start has been found and end has not, try to find end first - if ( iCdataEndPos == KErrNotFound && iCdataStartPos != KErrNotFound && iCdataFoundFromFirstPiece ) - { - // we're looking for a cdata end - iCdataEndPos = searchString.Find(KCDataEnd); - - // if the end was found, remove it and start looking for a cdata start - if ( iCdataEndPos != KErrNotFound ) - { - // remove cdata end - xml.Delete(iCdataEndPos, KCDataEnd().Length()); - searchStartPos = iCdataEndPos; - searchString.Set( xml.Right(xml.Length() - searchStartPos) ); - } - else - { - // end was not found, return - return; - } - } - - iCdataStartPos = searchString.Find(KCDataStart); - - // If CDATA is not found from beginning then data is not inside CDATA and then - // preprocessing is not needed - if ( iCdataStartPos != 0 && iFirstPiece ) - { - return; - } - else if ( !iFirstPiece && !iCdataFoundFromFirstPiece ) - { - return; - } - else if ( iCdataStartPos == 0 && iFirstPiece ) - { - iCdataFoundFromFirstPiece = ETrue; - } - - - // while cdata is found - while ( iCdataStartPos != KErrNotFound ) - { - iCdataStartPos += searchStartPos; - - // find an end of cdata before entities are converted - iCdataEndPos = searchString.Find(KCDataEnd); - - // convert entities between search start and cdata start - TInt entityChange = EntitiesToCharactersL(aXml, searchStartPos, iCdataStartPos); - xml.Set(aXml->Des()); - iCdataStartPos += entityChange; - - if ( iCdataEndPos != KErrNotFound ) - { - iCdataEndPos += entityChange; - iCdataEndPos += searchStartPos; - - // if the end is before start -> error - if ( iCdataEndPos < iCdataStartPos ) - User::Leave( EInvalidCDataStructure ); - - // remove cdata end - xml.Delete(iCdataEndPos, KCDataEnd().Length()); - // remove cdata start - xml.Delete(iCdataStartPos, KCDataStart().Length()); - - searchStartPos = iCdataEndPos - KCDataStart().Length(); - searchString.Set( xml.Right(xml.Length() - searchStartPos) ); - } - else - { - // remove cdata start - xml.Delete(iCdataStartPos, KCDataStart().Length()); - - // since there was no end found, return - return; - } - - // find a new cdata start that is after the found end - iCdataStartPos = searchString.Find(KCDataStart); - - } - - if ( iCdataStartPos == KErrNotFound ) - { - EntitiesToCharactersL(aXml, searchStartPos, aXml->Length()); - } - - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::ResetParserL -// Resets the state of the parser, should be called before starting the parsing. -// ----------------------------------------------------------------------------- -// -void CNSmlEmailFileParser::ResetParserL() - { - ResetBufferL(iBuffer); - ResetBufferL(iCompleteBuffer); - iReadingElementName = EFalse; - iReadingCData = EFalse; - iReadingEmailItemData = EFalse; - iFirstPiece = EFalse; - iCdataFoundFromFirstPiece = EFalse; - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::ResetPreProcessor -// Resets the variables used in preprocessor. -// ----------------------------------------------------------------------------- -// -void CNSmlEmailFileParser::ResetPreProcessor() - { - iCdataStartPos = KErrNotFound; - iCdataEndPos = KErrNotFound; - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::Buf8ToBuf16 -// ----------------------------------------------------------------------------- -// -HBufC* CNSmlEmailFileParser::Buf8ToBuf16( const HBufC8* buf8 ) const - { - HBufC* buf16 = HBufC::New(buf8->Length()); - if ( buf16 ) - { - TPtr ptr = buf16->Des(); - ptr.Copy( *buf8 ); - } - - return buf16; - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::CNSmlEmailFileParser -// Constructor. -// ----------------------------------------------------------------------------- -// -CNSmlEmailFileParser::CNSmlEmailFileParser() - : iUseEmailItem(ETrue) - { - } - -// ----------------------------------------------------------------------------- -// CNSmlEmailFileParser::ConstructL -// Second phase construction. -// ----------------------------------------------------------------------------- -// -void CNSmlEmailFileParser::ConstructL() - { - CNSmlEmailParser::ConstructL(); - User::LeaveIfError( iRfs.Connect() ); - - // create path+filename for emailitem - iEmailItemFile = HBufC::NewL( KMaxEmailItemFileNameLength ); - TPtr file = iEmailItemFile->Des(); - - file.Append( KEmailItemFile ); - - } - -// End of File