--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/presadap12/Parser2/SrcXmlParser/CPEngXMLParser.cpp Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,1081 @@
+/*
+* 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: XML Parser implementation
+*
+*/
+
+// INCLUDE FILES
+
+#include <e32base.h>
+#include <utf.h>
+#include <imcvcodc.h>
+#include <PEngWVPresenceErrors2.h>
+
+#include "CPEngXMLParser.h"
+#include "MPEngAdvTransactionStatus2.h"
+#include "CPEngParserStack.h"
+
+
+
+
+// =================== MACROS =======================
+#define STORE_AND_RETURN_IF_IN_ERROR( aParser, aErr ) \
+ if ( aErr < KErrNone ) \
+ { \
+ aParser->SetError( aErr ); \
+ return NW_STAT_FAILURE; \
+ } \
+
+
+
+// ================= LOCAL FUNCTIONS =======================
+/**
+ * Maps given CSP status code to WV error code range
+ * defined in PEngWVPresenceErrors.h
+ *
+ * @since 3.0
+ * @param aCSPStatusCode The CSP status code to map.
+ * @return WV Error code.
+ */
+TInt MapWVCspStatusToError( TInt aCSPStatusCode )
+ {
+ //Map the CSP successful (200) ==> KErrNone
+ if ( aCSPStatusCode == 200 )
+ {
+ return KErrNone;
+ }
+
+ return KPEngErrorWVServerResponseBase - aCSPStatusCode;
+ }
+
+
+/**
+ * Checks is the given CSP status code in the CSP status code range.
+ *
+ * @since 3.0
+ * @param aCSPStatusCode The CSP status code to check.
+ * @return ETrue if the given int is inside of the CSP status code range.
+ * Else EFalse.
+ */
+TInt IsInCspStatusCodeRange( TInt aCSPStatusCode )
+ {
+ return ( aCSPStatusCode >= KPEngWVStatusCodeBase ) &&
+ ( aCSPStatusCode <= KPEngWVStatusCodeTop );
+ }
+
+
+/**
+ * Decodes given CSP status code descriptor block
+ * to WV error code.
+ *
+ * @since 3.0
+ * @param aCSPStatusCode The CSP status code to map.
+ * @param aWVErrorCode The mapped error code
+ * @return ETrue if the decode was successful.
+ * Else EFalse.
+ */
+TBool DecodeWVCspStatusCodeToError( const TDesC8& aCSPStatusCode,
+ TInt& aWVErrorCode )
+ {
+ //Try decode the CSP status code to integer & map it to WV Error Code
+ TInt cspStatusInt;
+ TLex8 lexer( aCSPStatusCode );
+ lexer.SkipSpace();
+ TInt lexErr = lexer.Val( cspStatusInt );
+ if ( lexErr == KErrNone )
+ {
+ if ( IsInCspStatusCodeRange( cspStatusInt ) )
+ {
+ aWVErrorCode = MapWVCspStatusToError( cspStatusInt );
+ return ETrue;
+ }
+ }
+
+ return EFalse;
+ }
+
+
+
+
+
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+
+// Two-phased constructor.
+EXPORT_C CPEngXMLParser* CPEngXMLParser::NewLC()
+ {
+ CPEngXMLParser* self = new ( ELeave ) CPEngXMLParser;
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+
+ return self;
+ }
+
+// Destructor
+CPEngXMLParser::~CPEngXMLParser()
+ {
+ iResults.Close();
+ delete iIntervals;
+
+
+#if _BullseyeCoverage
+ cov_write();
+#endif
+ }
+
+
+
+// C++ default constructor can NOT contain any code, that
+// might leave.
+//
+CPEngXMLParser::CPEngXMLParser()
+ {
+ }
+
+// Symbian OS default constructor can leave.
+void CPEngXMLParser::ConstructL()
+ {
+ iIntervals = CPEngParserStack::NewL();
+
+ iCallBacks.StartDocument_CB = StartDocument_CB; //StartDocument_CB;
+ iCallBacks.EndDocument_CB = EndDocument_CB; //EndDocument_CB;
+ iCallBacks.Tag_Start_CB = Tag_Start_CB;
+ iCallBacks.Attr_Start_CB = NULL; //Attr_Start_CB;
+ iCallBacks.Attr_VarVal_CB = NULL; //Attr_VarVal_CB;
+ iCallBacks.Attributes_End_CB = NULL; //Attributes_End_CB;
+ iCallBacks.Tag_End_CB = Tag_End_CB;
+ iCallBacks.Content_CB = NULL; //Content_CB;
+ iCallBacks.Cdata_CB = NULL; //Cdata_CB;
+ iCallBacks.Comment_CB = NULL; //Comment_CB;
+ iCallBacks.PiForm_CB = NULL; //PiForm_CB;
+ iCallBacks.Exception_CB = Exception_CB; // Mostly for debugging purposes
+ iCallBacks.Extension_CB = NULL; //Extension_CB;
+ iCallBacks.Attr_Entity_VarVal_CB = NULL; //Attr_Entity_VarVal_CB;
+
+
+ iCallBacks.pClientPointer = ( void* ) this;
+ }
+
+
+
+
+// ---------------------------------------------------------
+// CPEngAttributeLibraryModel::DecodeL()
+//
+// ---------------------------------------------------------
+//
+TBool CPEngXMLParser::DecodeL( const TDesC8& aBuffer,
+ const TDesC8& aString,
+ TBool aTags,
+ TInt aLevel )
+ {
+ iMaxParseLevel = aLevel;
+ iData.Set( aBuffer );
+ iSearchable.Set( aString );
+ iIncludeTags = aTags;
+ ResetResults();
+
+
+ NW_XML_Reader_InitFromBuffer( &iReader, aBuffer.Size(), const_cast<TUint8*>( iData.Ptr() ) );
+ NW_XML_Reader_SetEncoding( &iReader, HTTP_iso_8859_1 );
+
+
+ //Parse & Handle Errors
+ NW_Status_t status = NW_XML_Parse( &iReader, &iCallBacks );
+ if ( iError != KErrNone )
+ {
+ User::Leave( iError );
+ }
+
+ if ( status == NW_STAT_OUT_OF_MEMORY )
+ {
+ User::Leave( KErrNoMemory );
+ }
+
+ if ( status != NW_STAT_SUCCESS )
+ {
+ User::Leave( KPEngNwErrInternalServerOrNetworkError );
+ }
+
+ //And return did we find something
+ if ( iResults.Count() > 0 )
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::Count()
+// Returns the result count
+// ---------------------------------------------------------
+//
+TInt CPEngXMLParser::Count()
+ {
+ return iResults.Count();
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::ResultL()
+// ---------------------------------------------------------
+//
+TPtrC8 CPEngXMLParser::ResultL( TInt aIndex )
+ {
+ //Get plain result
+ if ( aIndex >= iResults.Count() || aIndex < 0 )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ return iResults[aIndex];
+ }
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::ResultAsNarrowTextL()
+// ---------------------------------------------------------
+//
+HBufC8* CPEngXMLParser::ResultAsNarrowTextL( TInt aIndex )
+ {
+ //Performed steps:
+ //1. UnEscapes XML entities.
+
+ return DoXMLUnEscapingL( ResultL( aIndex ) );
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::ResultAsUnicodeTextL()
+// ---------------------------------------------------------
+//
+HBufC16* CPEngXMLParser::ResultAsUnicodeTextL( TInt aIndex )
+ {
+ // Performed steps:
+ // 1. UnEscapes XML entities.
+ // 2. Converts text from Utf8 to Unicode.
+
+ HBufC8* xmlUnEscaped = DoXMLUnEscapingL( ResultL( aIndex ) );
+
+ CleanupStack::PushL( xmlUnEscaped );
+ HBufC16* unicode = CnvUtfConverter::ConvertToUnicodeFromUtf8L( *xmlUnEscaped );
+ CleanupStack::PopAndDestroy( xmlUnEscaped );
+
+ return unicode;
+ }
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::ResultAsWVAddressL()
+// ---------------------------------------------------------
+//
+HBufC16* CPEngXMLParser::ResultAsWVAddressL( TInt aIndex )
+ {
+ // Performed steps:
+ // 1. UnEscapes XML entities.
+ // 2. Converts text from Utf8 to Unicode.
+ // 3. UnEscapes WV Address characters
+
+ HBufC8* xmlUnEscaped = DoXMLUnEscapingL( ResultL( aIndex ) );
+
+ CleanupStack::PushL( xmlUnEscaped );
+ HBufC16* unicode = CnvUtfConverter::ConvertToUnicodeFromUtf8L( *xmlUnEscaped );
+ CleanupStack::PopAndDestroy( xmlUnEscaped );
+
+
+ CleanupStack::PushL( unicode );
+ HBufC16* wvAddress = DoWVAddressUnescapeL( *unicode );
+ CleanupStack::PopAndDestroy( unicode );
+
+
+ return wvAddress;
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::ResultAsBase64DecodedL()
+// ---------------------------------------------------------
+//
+HBufC8* CPEngXMLParser::ResultAsBase64DecodedL( TInt aIndex )
+ {
+ // Performed steps:
+ // 1. Coverts data from the BASE64 format
+
+
+ HBufC8* decodedBuffer8 = HBufC8::NewLC( ResultL( aIndex ).Length() );
+ TPtr8 decodedPtr8( decodedBuffer8->Des() );
+
+ TImCodecB64 base64Decoder;
+ base64Decoder.Initialise();
+
+ // Decode returns ETrue, more data is needed to complete the decoding
+ // ==> in this case the received buffer is considered as corrupted
+ TBool moreDataNeeded = base64Decoder.Decode( ResultL( aIndex ), decodedPtr8 );
+ if ( moreDataNeeded )
+ {
+ User::Leave( KErrCorrupt );
+ }
+
+ decodedBuffer8 = decodedBuffer8->ReAllocL( decodedBuffer8->Length() );
+ CleanupStack::Pop(); //decodedBuffer8
+ return decodedBuffer8;
+ }
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::ParseResultL()
+// Parses the generic WV result from the XML packet
+// ---------------------------------------------------------
+//
+TInt CPEngXMLParser::ParseResultL( const TDesC8& aBuffer,
+ TInt aOperationID,
+ MPEngAdvTransactionStatus2& aStatus,
+ TBool& aResultRequired )
+ {
+ return DoParseResultL( aBuffer,
+ aStatus,
+ aOperationID,
+ NULL,
+ NULL,
+ aResultRequired );
+ }
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::ParseResultL()
+// Parses the generic WV result from the XML packet
+// ---------------------------------------------------------
+//
+TInt CPEngXMLParser::ParseResultL( const TDesC8& aBuffer,
+ TInt aOperationID,
+ MPEngAdvTransactionStatus2& aStatus )
+ {
+ //By default - result is required
+ TBool resultRequired = ETrue;
+ return DoParseResultL( aBuffer,
+ aStatus,
+ aOperationID,
+ NULL,
+ NULL,
+ resultRequired );
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::ParseContactListResultL()
+// Parses the contact list related WV result from the
+// XML packet.
+// ---------------------------------------------------------
+//
+TInt CPEngXMLParser::ParseContactListResultL( const TDesC8& aBuffer,
+ TInt aOperationID,
+ const TDesC& aContactList,
+ MPEngAdvTransactionStatus2& aStatus )
+ {
+ //By default - result is required
+ TBool resultRequired = ETrue;
+ return DoParseResultL( aBuffer,
+ aStatus,
+ aOperationID,
+ NULL,
+ &aContactList,
+ resultRequired );
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::Close()
+// ---------------------------------------------------------
+//
+void CPEngXMLParser::Close()
+ {
+ delete this;
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::ResetResults()
+// ---------------------------------------------------------
+//
+void CPEngXMLParser::ResetResults()
+ {
+ iResults.Reset();
+ iIntervals->Reset();
+ iParsingLevel = 0;
+ iError = KErrNone;
+ }
+
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::DoWVAddressUnescapeL()
+// ---------------------------------------------------------
+//
+HBufC16* CPEngXMLParser::DoWVAddressUnescapeL( const TDesC16& aSrc )
+ {
+ HBufC16* destBuffer = HBufC16::NewLC( aSrc.Length() );
+ TPtr16 dest( destBuffer->Des() );
+
+
+ // the length of the escape sequence, without the percent sign
+ TBuf8<2> value;
+
+ TInt srcLen( aSrc.Length() );
+ for ( TInt i( 0 ); i < srcLen; i++ )
+ {
+ if ( aSrc[i] == '%' )
+ {
+ // check if there is enough characters to resolve the next real,
+ // unescaped character
+ if ( ( i + 2 ) >= srcLen )
+ {
+ // not enough chars to resolve the last escaped sequence
+ // bail out
+ break;
+ }
+ // let's take the next two characters, the encoded char is
+ // of format %20
+ value.Zero();
+ value.Append( aSrc[++i] );
+ value.Append( aSrc[++i] );
+
+ // find the hexadecimal value from the string
+ // and convert it to a character
+ TLex8 lexer( value );
+ TUint8 charVal;
+ TInt retVal( lexer.Val( charVal, EHex ) );
+ if ( retVal == KErrGeneral )
+ {
+ // could not convert escape chars to character value
+ // just append the percent sign and characters
+ dest.Append( '%' );
+ dest.Append( value[0] );
+ dest.Append( value[1] );
+ }
+ else if ( retVal != KErrNone )
+ {
+ User::Leave( retVal );
+ }
+ else
+ {
+ // append the found character to the destination buffer
+ TChar escapedChar( charVal );
+ dest.Append( escapedChar );
+ }
+ }
+ else
+ {
+ // the character wasn't any escaped sequence starter -> just copy it
+ dest.Append( aSrc[i] );
+ }
+ }
+
+
+ destBuffer = destBuffer->ReAllocL( destBuffer->Length() );
+ CleanupStack::Pop(); //old destBuffer
+ return destBuffer;
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::DoXMLUnEscaping()
+// Decodes the XML escaped character sequences
+// ---------------------------------------------------------
+//
+HBufC8* CPEngXMLParser::DoXMLUnEscapingL( const TDesC8& aSrc )
+ {
+ HBufC8* destBuffer = HBufC8::NewLC( aSrc.Length() );
+ TPtr8 dest( destBuffer->Des() );
+
+ TInt srcLen( aSrc.Length() );
+ for ( TInt i( 0 ); i < srcLen; i++ )
+ {
+ if ( aSrc[i] == '&' )
+ {
+ // check if there is enough characters to resolve the next real,
+ // unescaped character
+ if ( ( i + 2 ) >= srcLen )
+ {
+ // not enough chars to resolve the last escaped sequence
+ // bail out
+ break;
+ }
+ if ( aSrc[i+1] == 'a' )
+ {
+ // only two possibilities if the escape string starts
+ // with &a
+ if ( aSrc[i+2] == 'm' )
+ {
+ dest.Append( '&' );
+ i += 4; // jump over rest of the & string
+ }
+ else
+ {
+ dest.Append( '\'' );
+ i += 5; // jump over rest of the ' string
+ }
+ }
+ else if ( aSrc[i+1] == 'g' )
+ {
+ dest.Append( '>' );
+ i += 3; // jump over rest of the > string
+ }
+ else if ( aSrc[i+1] == 'l' )
+ {
+ dest.Append( '<' );
+ i += 3; // jump over rest of the < string
+ }
+ else if ( aSrc[i+1] == 'q' )
+ {
+ dest.Append( '\"' );
+ i += 5; // jump over rest of the " string
+ }
+ else
+ {
+ User::Leave( KErrCorrupt );
+ }
+ }
+ else
+ {
+ dest.Append( aSrc[i] );
+ }
+ }
+
+ destBuffer = destBuffer->ReAllocL( destBuffer->Length() );
+ CleanupStack::Pop(); //old destBuffer
+ return destBuffer;
+ }
+
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::DoParseResultL()
+// Parses the WV result from the XML packet.
+// ---------------------------------------------------------
+//
+TInt CPEngXMLParser::DoParseResultL( const TDesC8& aBuffer,
+ MPEngAdvTransactionStatus2& aStatus,
+ TInt aOperationID,
+ const TUint32* aAttributeTypeID,
+ const TDesC* aContactListID,
+ TBool& aResultRequired )
+ {
+ //DTD: Result (Code, Description?, DetailedResult*)
+
+ TPtrC8 resultBlock( NULL, 0 );
+ TInt wvErrorCode = KErrNone;
+ TBool errorCodeDecoded = EFalse;
+
+
+ //Look for mandatory parts
+ if ( DecodeL( aBuffer, KResultXMLTag, ETrue ) )
+ {
+ resultBlock.Set( ResultL() );
+ if ( DecodeL( resultBlock, KCodeXMLTag, EFalse ) )
+ {
+ TPtrC8 cspStatusCodeBlock( ResultL() );
+ errorCodeDecoded = DecodeWVCspStatusCodeToError( cspStatusCodeBlock,
+ wvErrorCode );
+ }
+ }
+
+
+ //And act wether the mandatory part was found or not..
+ if ( !errorCodeDecoded )
+ {
+ if ( aResultRequired )
+ {
+ aStatus.SetStatus( KPEngNwErrInternalServerOrNetworkError );
+ }
+ else
+ {
+ aStatus.SetStatus( KErrNone );
+ }
+
+ //Return to client that mandatory part wasn't found
+ aResultRequired = EFalse;
+ }
+
+
+ else
+ {
+ //Mandatory part fine. Return it also to client.
+ aStatus.SetStatus( wvErrorCode );
+ aResultRequired = ETrue;
+
+
+ //Process possible detailed entries
+ TInt detailEntriesStartCount = aStatus.DetailedResultCount();
+ if ( wvErrorCode == KPEngNwErrPartiallySuccessful )
+ {
+ DoParseDetailedResultsL( resultBlock,
+ aStatus,
+ aOperationID,
+ aAttributeTypeID,
+ aContactListID );
+ }
+ TInt detailEntriesEndCount = aStatus.DetailedResultCount();
+
+
+
+ if ( detailEntriesStartCount == detailEntriesEndCount )
+ {
+ //No detail entries added ==>
+ //Look for description and if having a valid one,
+ //add it as a detail
+
+ //Parse only 2 tag levels.
+ //(Check the the result packet DTD.)
+ if ( DecodeL( resultBlock, KDescriptionXMLTag, EFalse, 2 ) )
+ {
+ HBufC* descriptionBuf = ResultAsUnicodeTextL();
+ CleanupStack::PushL( descriptionBuf );
+ if ( descriptionBuf->Length() > 0 )
+ {
+ aStatus.AddDetailedResultL( aOperationID, wvErrorCode,
+ aAttributeTypeID, NULL,
+ aContactListID, descriptionBuf );
+ }
+
+ CleanupStack::PopAndDestroy( descriptionBuf );
+ }
+ }
+ }
+
+
+ return aStatus.Status();
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::DoParseDetailedResultsL()
+// ---------------------------------------------------------
+//
+void CPEngXMLParser::DoParseDetailedResultsL( const TDesC8& aBuffer,
+ MPEngAdvTransactionStatus2& aStatus,
+ TInt aOperationID,
+ const TUint32* aAttributeTypeID,
+ const TDesC* aContactListID )
+ {
+ CPtrC8Array* detailedResults = new ( ELeave ) CPtrC8Array( 5 );
+ CleanupStack::PushL( detailedResults );
+
+ if ( DecodeL( aBuffer, KDetailedResultXMLTag, ETrue ) )
+ {
+ //Gather detailed result blocks..
+ const TInt detailedResultCount = Count();
+ TInt ii;
+ for ( ii = 0; ii < detailedResultCount; ii++ )
+ {
+ detailedResults->AppendL( ResultL( ii ) );
+ }
+
+
+ //And handle each detailed result block..
+ for ( ii = 0; ii < detailedResultCount; ii++ )
+ {
+ DoParseOneDetailedResultL( ( *detailedResults )[ ii ],
+ aStatus,
+ aOperationID,
+ aAttributeTypeID,
+ aContactListID );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( detailedResults );
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::DoParseOneDetailedResultL()
+// ---------------------------------------------------------
+//
+void CPEngXMLParser::DoParseOneDetailedResultL( const TDesC8& aDetailedResult,
+ MPEngAdvTransactionStatus2& aStatus,
+ TInt aOperationID,
+ const TUint32* aAttributeTypeID,
+ const TDesC* aContactListID )
+ {
+ //DTD: DetailedResult (Code, Description?, UserID*, GroupID*,
+ // ScreenName*, MessageID*, ContactList*, Domain*)
+
+ TInt wvErrorCode = KErrNone;
+ TBool errorCodeDecoded = EFalse;
+
+
+ //Look for mandatory parts
+ if ( DecodeL( aDetailedResult, KCodeXMLTag, EFalse ) )
+ {
+ TPtrC8 cspStatusCodeBlock( ResultL() );
+ errorCodeDecoded = DecodeWVCspStatusCodeToError( cspStatusCodeBlock,
+ wvErrorCode );
+ }
+
+
+
+ if ( !errorCodeDecoded )
+ {
+ //Detailed result is somehow malformed...
+ aStatus.AddDetailedResultL( aOperationID,
+ KPEngNwErrInternalServerOrNetworkError,
+ aAttributeTypeID, NULL,
+ aContactListID, NULL );
+ }
+
+
+ else
+ {
+ //Detailed result mandatory parts ok
+ //Get the detailed description if any
+ HBufC* descriptionBuf = NULL;
+ if ( DecodeL( aDetailedResult, KDescriptionXMLTag, EFalse ) )
+ {
+ descriptionBuf = ResultAsUnicodeTextL();
+ if ( descriptionBuf->Length() == 0 )
+ {
+ delete descriptionBuf;
+ descriptionBuf = NULL;
+ }
+ }
+ if ( descriptionBuf )
+ {
+ CleanupStack::PushL( descriptionBuf );
+ }
+
+
+
+ // And process the detailed "main" entries
+ TInt detailMainEntriesStartCount = aStatus.DetailedResultCount();
+ {
+ //First user id's
+ if ( DecodeL( aDetailedResult, KUserIDXMLTag, EFalse ) )
+ {
+ const TInt detailedUserIDsCount = Count();
+
+ for ( TInt ii( 0 ); ii < detailedUserIDsCount; ii++ )
+ {
+ HBufC* userID = ResultAsWVAddressL( ii );
+ CleanupStack::PushL( userID );
+ if ( userID->Length() > 0 )
+ {
+ aStatus.AddDetailedResultL( aOperationID, wvErrorCode,
+ aAttributeTypeID, userID,
+ aContactListID, descriptionBuf );
+
+ }
+
+ CleanupStack::PopAndDestroy( userID );
+ }
+ }
+
+ if ( DecodeL( aDetailedResult, KContactList, EFalse ) )
+ {
+ const TInt detailedContactListsCount = Count();
+
+ for ( TInt ii( 0 ); ii < detailedContactListsCount; ii++ )
+ {
+ HBufC* contactList = ResultAsWVAddressL( ii );
+ CleanupStack::PushL( contactList );
+ if ( contactList->Length() > 0 )
+ {
+ aStatus.AddDetailedResultL( aOperationID, wvErrorCode,
+ aAttributeTypeID, NULL,
+ contactList, descriptionBuf );
+
+ }
+
+ CleanupStack::PopAndDestroy( contactList );
+ }
+ }
+ }
+
+ TInt detailMainEntriesEndCount = aStatus.DetailedResultCount();
+
+
+
+
+ if ( detailMainEntriesStartCount == detailMainEntriesEndCount )
+ {
+ //No main type entries added ==> add code and possible
+ //description as one
+ aStatus.AddDetailedResultL( aOperationID,
+ wvErrorCode,
+ NULL,
+ NULL,
+ NULL,
+ descriptionBuf );
+ }
+
+
+ if ( descriptionBuf )
+ {
+ CleanupStack::PopAndDestroy( descriptionBuf );
+ }
+ }
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::SetError()
+// ---------------------------------------------------------
+//
+void CPEngXMLParser::SetError( TInt aError )
+ {
+ iError = aError;
+ }
+
+
+
+
+// ==================== cXML CALLBACK FUNCTIONS ====================
+// ---------------------------------------------------------
+// CPEngXMLParser::StartDocument_CB()
+// ---------------------------------------------------------
+//
+NW_Status_t CPEngXMLParser::StartDocument_CB( NW_XML_Reader_t*, void* )
+ {
+ //No leaving code allowed
+ return NW_STAT_SUCCESS;
+ }
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::EndDocument_CB()
+// ---------------------------------------------------------
+//
+NW_Status_t CPEngXMLParser::EndDocument_CB( NW_XML_Reader_t*, void* )
+ {
+ //No leaving code allowed
+ return NW_STAT_SUCCESS;
+ }
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::Tag_Start_CB()
+// ---------------------------------------------------------
+//
+NW_Status_t CPEngXMLParser::Tag_Start_CB( NW_XML_Reader_t* /*aReader*/,
+ const NW_XML_Reader_Interval_t* aName,
+ void* aParser )
+ {
+ //No leaving code allowed
+
+ CPEngXMLParser* parser = reinterpret_cast<CPEngXMLParser*> ( aParser );
+
+ parser->iParsingLevel++;
+
+ TInt len( aName->stop - aName->start );
+ TPtrC8 buffer( parser->iData.Mid( aName->start, len ) );
+
+ // now check if the found tag was the one we were looking for
+ if ( buffer.Compare( parser->iSearchable ) == 0 )
+ {
+ TUint itemStart;
+ if ( parser->iIncludeTags )
+ {
+ // the interval includes the tag and the first '<' also
+ itemStart = aName->start - 1;
+ }
+ else
+ {
+ //Locate next tag end char
+ TPtrC8 fullRemainder( parser->iData.Mid( aName->start ) );
+ TInt endMarkOffset = fullRemainder.Locate( '>' );
+ STORE_AND_RETURN_IF_IN_ERROR( parser, endMarkOffset );
+
+ // here the interval doesn't include the tag nor the ending '>'
+ itemStart = aName->start + endMarkOffset + 1;
+ }
+
+ TInt err = parser->iIntervals->PushStart( itemStart );
+ STORE_AND_RETURN_IF_IN_ERROR( parser, err );
+ }
+
+ return NW_STAT_SUCCESS;
+ }
+
+
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::Tag_End_CB()
+// ---------------------------------------------------------
+//
+NW_Status_t CPEngXMLParser::Tag_End_CB( NW_XML_Reader_t* /*aReader*/,
+ const NW_XML_Reader_Interval_t* aName,
+ NW_Uint32 /*emptyTagFlag*/,
+ void* aParser )
+ {
+
+ //No leaving code allowed
+ CPEngXMLParser* parser = reinterpret_cast<CPEngXMLParser*> ( aParser );
+
+ TInt len( aName->stop - aName->start );
+ TPtrC8 buffer( parser->iData.Mid( aName->start, len ) );
+
+ // check the current XML level
+ // now check if the found tag was the one we were looking for
+ if ( buffer.Compare( parser->iSearchable ) == 0 )
+ {
+ TUint itemEnd;
+ if ( parser->iIncludeTags )
+ {
+ // the interval includes the tag and the last '>' also
+
+ //Locate next end char
+ TPtrC8 fullRemainder( parser->iData.Mid( aName->stop ) );
+ TInt endMarkOffset = fullRemainder.Locate( '>' );
+ STORE_AND_RETURN_IF_IN_ERROR( parser, endMarkOffset );
+
+ itemEnd = aName->stop + endMarkOffset + 1;
+ }
+ else
+ {
+ // here the interval doesn't include the tag nor the starting '</'
+ itemEnd = aName->start - 2;
+ }
+
+
+ TInt err = parser->iIntervals->PushEnd( itemEnd );
+ STORE_AND_RETURN_IF_IN_ERROR( parser, err );
+
+
+ // next grab the data between the tags from the original XML data,
+ //if we are at allowed level
+ if ( ( parser->iMaxParseLevel == 0 ) ||
+ ( parser->iParsingLevel <= parser->iMaxParseLevel ) )
+ {
+ TPoint dataInterval( parser->iIntervals->Pop() );
+ TInt intervalLength( dataInterval.iY - dataInterval.iX );
+
+
+ TPtrC8 resultSection( NULL, 0 );
+ if ( intervalLength > 0 ) // if the stack was broken, the length will be 0
+ {
+ resultSection.Set( parser->iData.Mid( dataInterval.iX, intervalLength ) );
+ }
+
+
+ TInt err = parser->iResults.Append( resultSection );
+ STORE_AND_RETURN_IF_IN_ERROR( parser, err );
+ }
+ }
+
+
+ parser->iParsingLevel--;
+ return NW_STAT_SUCCESS;
+ }
+
+
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::Attr_Start_CB()
+// ---------------------------------------------------------
+//
+NW_Status_t CPEngXMLParser::Attr_Start_CB( NW_XML_Reader_t*,
+ const NW_XML_Reader_Interval_t* /*pI_name*/,
+ void* )
+ {
+ //No leaving code allowed
+
+ return NW_STAT_SUCCESS;
+ }
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::Attr_VarVal_CB()
+// ---------------------------------------------------------
+//
+NW_Status_t CPEngXMLParser::Attr_VarVal_CB( NW_XML_Reader_t*,
+ const NW_XML_Reader_Interval_t* /*pI_name*/,
+ const NW_XML_Reader_Interval_t* /*pI_value*/,
+ void* )
+
+ {
+ //No leaving code allowed
+
+ return NW_STAT_SUCCESS;
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::Attributes_End_CB()
+// ---------------------------------------------------------
+//
+NW_Status_t CPEngXMLParser::Attributes_End_CB( NW_XML_Reader_t*,
+ NW_Uint32 /*attributeCount*/,
+ void* )
+ {
+ //No leaving code allowed
+
+ return NW_STAT_SUCCESS;
+ }
+
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::Attr_Entity_VarVal_CB()
+// ---------------------------------------------------------
+//
+NW_Status_t CPEngXMLParser::Attr_Entity_VarVal_CB ( NW_XML_Reader_t* /*pT*/,
+ const NW_XML_Reader_Interval_t* /*pI_name*/,
+ NW_Uint8* /*pValue*/,
+ NW_Uint32 /*valueByteLength*/,
+ void* /*pV*/ )
+ {
+ //No leaving code allowed
+
+ return NW_STAT_SUCCESS;
+ }
+
+
+// ---------------------------------------------------------
+// CPEngXMLParser::Exception_CB()
+// ---------------------------------------------------------
+//
+NW_Status_t CPEngXMLParser::Exception_CB( NW_XML_Reader_t*, void* )
+ {
+ //No leaving code allowed
+
+ return NW_STAT_FAILURE;
+ }
+
+
+// End of File
+
+