presadap12/Parser2/SrcXmlParser/CPEngXMLParser.cpp
changeset 0 094583676ce7
equal deleted inserted replaced
-1:000000000000 0:094583676ce7
       
     1 /*
       
     2 * Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  XML Parser implementation
       
    15 *
       
    16 */
       
    17 
       
    18 // INCLUDE FILES
       
    19 
       
    20 #include <e32base.h>
       
    21 #include <utf.h>
       
    22 #include <imcvcodc.h>
       
    23 #include <PEngWVPresenceErrors2.h>
       
    24 
       
    25 #include "CPEngXMLParser.h"
       
    26 #include "MPEngAdvTransactionStatus2.h"
       
    27 #include "CPEngParserStack.h"
       
    28 
       
    29 
       
    30 
       
    31 
       
    32 // =================== MACROS =======================
       
    33 #define STORE_AND_RETURN_IF_IN_ERROR( aParser, aErr ) \
       
    34     if ( aErr < KErrNone ) \
       
    35         { \
       
    36         aParser->SetError( aErr ); \
       
    37         return NW_STAT_FAILURE; \
       
    38         } \
       
    39      
       
    40 
       
    41 
       
    42 // ================= LOCAL FUNCTIONS =======================
       
    43 /**
       
    44  * Maps given CSP status code to WV error code range
       
    45  * defined in PEngWVPresenceErrors.h
       
    46  *
       
    47  * @since 3.0
       
    48  * @param aCSPStatusCode The CSP status code to map.
       
    49  * @return WV Error code.
       
    50  */
       
    51 TInt MapWVCspStatusToError( TInt aCSPStatusCode )
       
    52     {
       
    53     //Map the CSP successful (200) ==> KErrNone
       
    54     if ( aCSPStatusCode == 200 )
       
    55         {
       
    56         return KErrNone;
       
    57         }
       
    58 
       
    59     return KPEngErrorWVServerResponseBase - aCSPStatusCode;
       
    60     }
       
    61 
       
    62 
       
    63 /**
       
    64  * Checks is the given CSP status code in the CSP status code range.
       
    65   *
       
    66  * @since 3.0
       
    67  * @param aCSPStatusCode The CSP status code to check.
       
    68  * @return ETrue if the given int is inside of the CSP status code range.
       
    69  *         Else EFalse.
       
    70  */
       
    71 TInt IsInCspStatusCodeRange( TInt aCSPStatusCode )
       
    72     {
       
    73     return ( aCSPStatusCode >= KPEngWVStatusCodeBase ) &&
       
    74            ( aCSPStatusCode <= KPEngWVStatusCodeTop );
       
    75     }
       
    76 
       
    77 
       
    78 /**
       
    79  * Decodes given CSP status code descriptor block
       
    80  * to WV error code.
       
    81  *
       
    82  * @since 3.0
       
    83  * @param aCSPStatusCode The CSP status code to map.
       
    84  * @param aWVErrorCode The mapped error code
       
    85  * @return ETrue if the decode was successful.
       
    86  *         Else EFalse.
       
    87  */
       
    88 TBool DecodeWVCspStatusCodeToError( const TDesC8& aCSPStatusCode,
       
    89                                     TInt& aWVErrorCode )
       
    90     {
       
    91     //Try decode the CSP status code to integer & map it to WV Error Code
       
    92     TInt cspStatusInt;
       
    93     TLex8 lexer( aCSPStatusCode );
       
    94     lexer.SkipSpace();
       
    95     TInt lexErr = lexer.Val( cspStatusInt );
       
    96     if ( lexErr == KErrNone )
       
    97         {
       
    98         if ( IsInCspStatusCodeRange( cspStatusInt ) )
       
    99             {
       
   100             aWVErrorCode = MapWVCspStatusToError( cspStatusInt );
       
   101             return ETrue;
       
   102             }
       
   103         }
       
   104 
       
   105     return EFalse;
       
   106     }
       
   107 
       
   108 
       
   109 
       
   110 
       
   111 
       
   112 
       
   113 
       
   114 // ================= MEMBER FUNCTIONS =======================
       
   115 
       
   116 
       
   117 // Two-phased constructor.
       
   118 EXPORT_C CPEngXMLParser* CPEngXMLParser::NewLC()
       
   119     {
       
   120     CPEngXMLParser* self = new ( ELeave ) CPEngXMLParser;
       
   121 
       
   122     CleanupStack::PushL( self );
       
   123     self->ConstructL();
       
   124 
       
   125     return self;
       
   126     }
       
   127 
       
   128 // Destructor
       
   129 CPEngXMLParser::~CPEngXMLParser()
       
   130     {
       
   131     iResults.Close();
       
   132     delete iIntervals;
       
   133 
       
   134 
       
   135 #if _BullseyeCoverage
       
   136     cov_write();
       
   137 #endif
       
   138     }
       
   139 
       
   140 
       
   141 
       
   142 // C++ default constructor can NOT contain any code, that
       
   143 // might leave.
       
   144 //
       
   145 CPEngXMLParser::CPEngXMLParser()
       
   146     {
       
   147     }
       
   148 
       
   149 // Symbian OS default constructor can leave.
       
   150 void CPEngXMLParser::ConstructL()
       
   151     {
       
   152     iIntervals = CPEngParserStack::NewL();
       
   153 
       
   154     iCallBacks.StartDocument_CB = StartDocument_CB; //StartDocument_CB;
       
   155     iCallBacks.EndDocument_CB = EndDocument_CB; //EndDocument_CB;
       
   156     iCallBacks.Tag_Start_CB = Tag_Start_CB;
       
   157     iCallBacks.Attr_Start_CB = NULL; //Attr_Start_CB;
       
   158     iCallBacks.Attr_VarVal_CB = NULL; //Attr_VarVal_CB;
       
   159     iCallBacks.Attributes_End_CB = NULL; //Attributes_End_CB;
       
   160     iCallBacks.Tag_End_CB = Tag_End_CB;
       
   161     iCallBacks.Content_CB = NULL; //Content_CB;
       
   162     iCallBacks.Cdata_CB = NULL; //Cdata_CB;
       
   163     iCallBacks.Comment_CB = NULL; //Comment_CB;
       
   164     iCallBacks.PiForm_CB = NULL; //PiForm_CB;
       
   165     iCallBacks.Exception_CB = Exception_CB;  // Mostly for debugging purposes
       
   166     iCallBacks.Extension_CB = NULL; //Extension_CB;
       
   167     iCallBacks.Attr_Entity_VarVal_CB = NULL; //Attr_Entity_VarVal_CB;
       
   168 
       
   169 
       
   170     iCallBacks.pClientPointer = ( void* ) this;
       
   171     }
       
   172 
       
   173 
       
   174 
       
   175 
       
   176 // ---------------------------------------------------------
       
   177 // CPEngAttributeLibraryModel::DecodeL()
       
   178 //
       
   179 // ---------------------------------------------------------
       
   180 //
       
   181 TBool CPEngXMLParser::DecodeL( const TDesC8& aBuffer,
       
   182                                const TDesC8& aString,
       
   183                                TBool aTags,
       
   184                                TInt aLevel )
       
   185     {
       
   186     iMaxParseLevel = aLevel;
       
   187     iData.Set( aBuffer );
       
   188     iSearchable.Set( aString );
       
   189     iIncludeTags = aTags;
       
   190     ResetResults();
       
   191 
       
   192 
       
   193     NW_XML_Reader_InitFromBuffer( &iReader, aBuffer.Size(), const_cast<TUint8*>( iData.Ptr() ) );
       
   194     NW_XML_Reader_SetEncoding( &iReader, HTTP_iso_8859_1 );
       
   195 
       
   196 
       
   197     //Parse & Handle Errors
       
   198     NW_Status_t status = NW_XML_Parse( &iReader, &iCallBacks );
       
   199     if ( iError != KErrNone )
       
   200         {
       
   201         User::Leave( iError );
       
   202         }
       
   203 
       
   204     if ( status == NW_STAT_OUT_OF_MEMORY )
       
   205         {
       
   206         User::Leave( KErrNoMemory );
       
   207         }
       
   208 
       
   209     if ( status != NW_STAT_SUCCESS )
       
   210         {
       
   211         User::Leave( KPEngNwErrInternalServerOrNetworkError );
       
   212         }
       
   213 
       
   214     //And return did we find something
       
   215     if ( iResults.Count() > 0 )
       
   216         {
       
   217         return ETrue;
       
   218         }
       
   219     else
       
   220         {
       
   221         return EFalse;
       
   222         }
       
   223     }
       
   224 
       
   225 
       
   226 
       
   227 // ---------------------------------------------------------
       
   228 // CPEngXMLParser::Count()
       
   229 // Returns the result count
       
   230 // ---------------------------------------------------------
       
   231 //
       
   232 TInt CPEngXMLParser::Count()
       
   233     {
       
   234     return iResults.Count();
       
   235     }
       
   236 
       
   237 
       
   238 
       
   239 // ---------------------------------------------------------
       
   240 // CPEngXMLParser::ResultL()
       
   241 // ---------------------------------------------------------
       
   242 //
       
   243 TPtrC8 CPEngXMLParser::ResultL( TInt aIndex )
       
   244     {
       
   245     //Get plain result
       
   246     if ( aIndex >= iResults.Count() || aIndex < 0 )
       
   247         {
       
   248         User::Leave( KErrArgument );
       
   249         }
       
   250 
       
   251     return iResults[aIndex];
       
   252     }
       
   253 
       
   254 
       
   255 // ---------------------------------------------------------
       
   256 // CPEngXMLParser::ResultAsNarrowTextL()
       
   257 // ---------------------------------------------------------
       
   258 //
       
   259 HBufC8* CPEngXMLParser::ResultAsNarrowTextL( TInt aIndex )
       
   260     {
       
   261     //Performed steps:
       
   262     //1. UnEscapes XML entities.
       
   263 
       
   264     return DoXMLUnEscapingL( ResultL( aIndex ) );
       
   265     }
       
   266 
       
   267 
       
   268 
       
   269 // ---------------------------------------------------------
       
   270 // CPEngXMLParser::ResultAsUnicodeTextL()
       
   271 // ---------------------------------------------------------
       
   272 //
       
   273 HBufC16* CPEngXMLParser::ResultAsUnicodeTextL( TInt aIndex )
       
   274     {
       
   275     // Performed steps:
       
   276     // 1. UnEscapes XML entities.
       
   277     // 2. Converts text from Utf8 to Unicode.
       
   278 
       
   279     HBufC8* xmlUnEscaped = DoXMLUnEscapingL( ResultL( aIndex ) );
       
   280 
       
   281     CleanupStack::PushL( xmlUnEscaped );
       
   282     HBufC16* unicode = CnvUtfConverter::ConvertToUnicodeFromUtf8L( *xmlUnEscaped );
       
   283     CleanupStack::PopAndDestroy( xmlUnEscaped );
       
   284 
       
   285     return unicode;
       
   286     }
       
   287 
       
   288 
       
   289 // ---------------------------------------------------------
       
   290 // CPEngXMLParser::ResultAsWVAddressL()
       
   291 // ---------------------------------------------------------
       
   292 //
       
   293 HBufC16* CPEngXMLParser::ResultAsWVAddressL( TInt aIndex )
       
   294     {
       
   295     // Performed steps:
       
   296     // 1. UnEscapes XML entities.
       
   297     // 2. Converts text from Utf8 to Unicode.
       
   298     // 3. UnEscapes WV Address characters
       
   299 
       
   300     HBufC8* xmlUnEscaped = DoXMLUnEscapingL( ResultL( aIndex ) );
       
   301 
       
   302     CleanupStack::PushL( xmlUnEscaped );
       
   303     HBufC16* unicode = CnvUtfConverter::ConvertToUnicodeFromUtf8L( *xmlUnEscaped );
       
   304     CleanupStack::PopAndDestroy( xmlUnEscaped );
       
   305 
       
   306 
       
   307     CleanupStack::PushL( unicode );
       
   308     HBufC16* wvAddress = DoWVAddressUnescapeL( *unicode );
       
   309     CleanupStack::PopAndDestroy( unicode );
       
   310 
       
   311 
       
   312     return wvAddress;
       
   313     }
       
   314 
       
   315 
       
   316 
       
   317 // ---------------------------------------------------------
       
   318 // CPEngXMLParser::ResultAsBase64DecodedL()
       
   319 // ---------------------------------------------------------
       
   320 //
       
   321 HBufC8* CPEngXMLParser::ResultAsBase64DecodedL(  TInt aIndex )
       
   322     {
       
   323     // Performed steps:
       
   324     // 1. Coverts data from the BASE64 format
       
   325 
       
   326 
       
   327     HBufC8* decodedBuffer8 = HBufC8::NewLC( ResultL( aIndex ).Length() );
       
   328     TPtr8 decodedPtr8( decodedBuffer8->Des() );
       
   329 
       
   330     TImCodecB64 base64Decoder;
       
   331     base64Decoder.Initialise();
       
   332 
       
   333     // Decode returns ETrue, more data is needed to complete the decoding
       
   334     // ==> in this case the received buffer is considered as corrupted
       
   335     TBool moreDataNeeded = base64Decoder.Decode( ResultL( aIndex ), decodedPtr8 );
       
   336     if ( moreDataNeeded )
       
   337         {
       
   338         User::Leave( KErrCorrupt );
       
   339         }
       
   340 
       
   341     decodedBuffer8 = decodedBuffer8->ReAllocL( decodedBuffer8->Length() );
       
   342     CleanupStack::Pop(); //decodedBuffer8
       
   343     return decodedBuffer8;
       
   344     }
       
   345 
       
   346 
       
   347 // ---------------------------------------------------------
       
   348 // CPEngXMLParser::ParseResultL()
       
   349 // Parses the generic WV result from the XML packet
       
   350 // ---------------------------------------------------------
       
   351 //
       
   352 TInt CPEngXMLParser::ParseResultL( const TDesC8& aBuffer,
       
   353                                    TInt aOperationID,
       
   354                                    MPEngAdvTransactionStatus2& aStatus,
       
   355                                    TBool& aResultRequired )
       
   356     {
       
   357     return DoParseResultL( aBuffer,
       
   358                            aStatus,
       
   359                            aOperationID,
       
   360                            NULL,
       
   361                            NULL,
       
   362                            aResultRequired );
       
   363     }
       
   364 
       
   365 
       
   366 // ---------------------------------------------------------
       
   367 // CPEngXMLParser::ParseResultL()
       
   368 // Parses the generic WV result from the XML packet
       
   369 // ---------------------------------------------------------
       
   370 //
       
   371 TInt CPEngXMLParser::ParseResultL( const TDesC8& aBuffer,
       
   372                                    TInt aOperationID,
       
   373                                    MPEngAdvTransactionStatus2& aStatus )
       
   374     {
       
   375     //By default - result is required
       
   376     TBool resultRequired = ETrue;
       
   377     return DoParseResultL( aBuffer,
       
   378                            aStatus,
       
   379                            aOperationID,
       
   380                            NULL,
       
   381                            NULL,
       
   382                            resultRequired );
       
   383     }
       
   384 
       
   385 
       
   386 
       
   387 // ---------------------------------------------------------
       
   388 // CPEngXMLParser::ParseContactListResultL()
       
   389 // Parses the contact list related WV result from the
       
   390 // XML packet.
       
   391 // ---------------------------------------------------------
       
   392 //
       
   393 TInt CPEngXMLParser::ParseContactListResultL( const TDesC8& aBuffer,
       
   394                                               TInt aOperationID,
       
   395                                               const TDesC& aContactList,
       
   396                                               MPEngAdvTransactionStatus2& aStatus )
       
   397     {
       
   398     //By default - result is required
       
   399     TBool resultRequired = ETrue;
       
   400     return DoParseResultL( aBuffer,
       
   401                            aStatus,
       
   402                            aOperationID,
       
   403                            NULL,
       
   404                            &aContactList,
       
   405                            resultRequired );
       
   406     }
       
   407 
       
   408 
       
   409 
       
   410 // ---------------------------------------------------------
       
   411 // CPEngXMLParser::Close()
       
   412 // ---------------------------------------------------------
       
   413 //
       
   414 void CPEngXMLParser::Close()
       
   415     {
       
   416     delete this;
       
   417     }
       
   418 
       
   419 
       
   420 
       
   421 // ---------------------------------------------------------
       
   422 // CPEngXMLParser::ResetResults()
       
   423 // ---------------------------------------------------------
       
   424 //
       
   425 void CPEngXMLParser::ResetResults()
       
   426     {
       
   427     iResults.Reset();
       
   428     iIntervals->Reset();
       
   429     iParsingLevel = 0;
       
   430     iError = KErrNone;
       
   431     }
       
   432 
       
   433 
       
   434 
       
   435 
       
   436 // ---------------------------------------------------------
       
   437 // CPEngXMLParser::DoWVAddressUnescapeL()
       
   438 // ---------------------------------------------------------
       
   439 //
       
   440 HBufC16* CPEngXMLParser::DoWVAddressUnescapeL( const TDesC16& aSrc )
       
   441     {
       
   442     HBufC16* destBuffer = HBufC16::NewLC( aSrc.Length() );
       
   443     TPtr16 dest( destBuffer->Des() );
       
   444 
       
   445 
       
   446     // the length of the escape sequence, without the percent sign
       
   447     TBuf8<2> value;
       
   448 
       
   449     TInt srcLen( aSrc.Length() );
       
   450     for ( TInt i( 0 ); i < srcLen; i++ )
       
   451         {
       
   452         if ( aSrc[i] == '%' )
       
   453             {
       
   454             // check if there is enough characters to resolve the next real,
       
   455             // unescaped character
       
   456             if ( ( i + 2 ) >= srcLen )
       
   457                 {
       
   458                 // not enough chars to resolve the last escaped sequence
       
   459                 // bail out
       
   460                 break;
       
   461                 }
       
   462             // let's take the next two characters, the encoded char is
       
   463             // of format %20
       
   464             value.Zero();
       
   465             value.Append( aSrc[++i] );
       
   466             value.Append( aSrc[++i] );
       
   467 
       
   468             // find the hexadecimal value from the string
       
   469             // and convert it to a character
       
   470             TLex8 lexer( value );
       
   471             TUint8 charVal;
       
   472             TInt retVal( lexer.Val( charVal, EHex ) );
       
   473             if ( retVal == KErrGeneral )
       
   474                 {
       
   475                 // could not convert escape chars to character value
       
   476                 // just append the percent sign and characters
       
   477                 dest.Append( '%' );
       
   478                 dest.Append( value[0] );
       
   479                 dest.Append( value[1] );
       
   480                 }
       
   481             else if ( retVal != KErrNone )
       
   482                 {
       
   483                 User::Leave( retVal );
       
   484                 }
       
   485             else
       
   486                 {
       
   487                 // append the found character to the destination buffer
       
   488                 TChar escapedChar( charVal );
       
   489                 dest.Append( escapedChar );
       
   490                 }
       
   491             }
       
   492         else
       
   493             {
       
   494             // the character wasn't any escaped sequence starter -> just copy it
       
   495             dest.Append( aSrc[i] );
       
   496             }
       
   497         }
       
   498 
       
   499 
       
   500     destBuffer = destBuffer->ReAllocL( destBuffer->Length() );
       
   501     CleanupStack::Pop(); //old destBuffer
       
   502     return destBuffer;
       
   503     }
       
   504 
       
   505 
       
   506 
       
   507 // ---------------------------------------------------------
       
   508 // CPEngXMLParser::DoXMLUnEscaping()
       
   509 // Decodes the XML escaped character sequences
       
   510 // ---------------------------------------------------------
       
   511 //
       
   512 HBufC8* CPEngXMLParser::DoXMLUnEscapingL( const TDesC8& aSrc )
       
   513     {
       
   514     HBufC8* destBuffer = HBufC8::NewLC( aSrc.Length() );
       
   515     TPtr8 dest( destBuffer->Des() );
       
   516 
       
   517     TInt srcLen( aSrc.Length() );
       
   518     for ( TInt i( 0 ); i < srcLen; i++ )
       
   519         {
       
   520         if ( aSrc[i] == '&' )
       
   521             {
       
   522             // check if there is enough characters to resolve the next real,
       
   523             // unescaped character
       
   524             if ( ( i + 2 ) >= srcLen )
       
   525                 {
       
   526                 // not enough chars to resolve the last escaped sequence
       
   527                 // bail out
       
   528                 break;
       
   529                 }
       
   530             if ( aSrc[i+1] == 'a' )
       
   531                 {
       
   532                 // only two possibilities if the escape string starts
       
   533                 // with &a
       
   534                 if ( aSrc[i+2] == 'm' )
       
   535                     {
       
   536                     dest.Append( '&' );
       
   537                     i += 4; // jump over rest of the &amp; string
       
   538                     }
       
   539                 else
       
   540                     {
       
   541                     dest.Append( '\'' );
       
   542                     i += 5; // jump over rest of the &apos; string
       
   543                     }
       
   544                 }
       
   545             else if ( aSrc[i+1] == 'g' )
       
   546                 {
       
   547                 dest.Append( '>' );
       
   548                 i += 3; // jump over rest of the &gt; string
       
   549                 }
       
   550             else if ( aSrc[i+1] == 'l' )
       
   551                 {
       
   552                 dest.Append( '<' );
       
   553                 i += 3; // jump over rest of the &lt; string
       
   554                 }
       
   555             else if ( aSrc[i+1] == 'q' )
       
   556                 {
       
   557                 dest.Append( '\"' );
       
   558                 i += 5; // jump over rest of the &quot; string
       
   559                 }
       
   560             else
       
   561                 {
       
   562                 User::Leave( KErrCorrupt );
       
   563                 }
       
   564             }
       
   565         else
       
   566             {
       
   567             dest.Append( aSrc[i] );
       
   568             }
       
   569         }
       
   570 
       
   571     destBuffer = destBuffer->ReAllocL( destBuffer->Length() );
       
   572     CleanupStack::Pop(); //old destBuffer
       
   573     return destBuffer;
       
   574     }
       
   575 
       
   576 
       
   577 
       
   578 
       
   579 // ---------------------------------------------------------
       
   580 // CPEngXMLParser::DoParseResultL()
       
   581 // Parses the WV result from the XML packet.
       
   582 // ---------------------------------------------------------
       
   583 //
       
   584 TInt CPEngXMLParser::DoParseResultL( const TDesC8& aBuffer,
       
   585                                      MPEngAdvTransactionStatus2& aStatus,
       
   586                                      TInt aOperationID,
       
   587                                      const TUint32* aAttributeTypeID,
       
   588                                      const TDesC* aContactListID,
       
   589                                      TBool& aResultRequired )
       
   590     {
       
   591     //DTD: Result (Code, Description?, DetailedResult*)
       
   592 
       
   593     TPtrC8 resultBlock( NULL, 0 );
       
   594     TInt wvErrorCode = KErrNone;
       
   595     TBool errorCodeDecoded = EFalse;
       
   596 
       
   597 
       
   598     //Look for mandatory parts
       
   599     if ( DecodeL( aBuffer, KResultXMLTag, ETrue ) )
       
   600         {
       
   601         resultBlock.Set( ResultL() );
       
   602         if ( DecodeL( resultBlock, KCodeXMLTag, EFalse ) )
       
   603             {
       
   604             TPtrC8 cspStatusCodeBlock( ResultL() );
       
   605             errorCodeDecoded = DecodeWVCspStatusCodeToError( cspStatusCodeBlock,
       
   606                                                              wvErrorCode );
       
   607             }
       
   608         }
       
   609 
       
   610 
       
   611     //And act wether the mandatory part was found or not..
       
   612     if ( !errorCodeDecoded )
       
   613         {
       
   614         if ( aResultRequired )
       
   615             {
       
   616             aStatus.SetStatus( KPEngNwErrInternalServerOrNetworkError );
       
   617             }
       
   618         else
       
   619             {
       
   620             aStatus.SetStatus( KErrNone );
       
   621             }
       
   622 
       
   623         //Return to client that mandatory part wasn't found
       
   624         aResultRequired = EFalse;
       
   625         }
       
   626 
       
   627 
       
   628     else
       
   629         {
       
   630         //Mandatory part fine. Return it also to client.
       
   631         aStatus.SetStatus( wvErrorCode );
       
   632         aResultRequired = ETrue;
       
   633 
       
   634 
       
   635         //Process possible detailed entries
       
   636         TInt detailEntriesStartCount = aStatus.DetailedResultCount();
       
   637         if ( wvErrorCode == KPEngNwErrPartiallySuccessful )
       
   638             {
       
   639             DoParseDetailedResultsL( resultBlock,
       
   640                                      aStatus,
       
   641                                      aOperationID,
       
   642                                      aAttributeTypeID,
       
   643                                      aContactListID );
       
   644             }
       
   645         TInt detailEntriesEndCount = aStatus.DetailedResultCount();
       
   646 
       
   647 
       
   648 
       
   649         if ( detailEntriesStartCount == detailEntriesEndCount )
       
   650             {
       
   651             //No detail entries added ==>
       
   652             //Look for description and if having a valid one,
       
   653             //add it as a detail
       
   654 
       
   655             //Parse only 2 tag levels.
       
   656             //(Check the the result packet DTD.)
       
   657             if ( DecodeL( resultBlock, KDescriptionXMLTag, EFalse, 2 ) )
       
   658                 {
       
   659                 HBufC* descriptionBuf = ResultAsUnicodeTextL();
       
   660                 CleanupStack::PushL( descriptionBuf );
       
   661                 if ( descriptionBuf->Length() > 0 )
       
   662                     {
       
   663                     aStatus.AddDetailedResultL( aOperationID, wvErrorCode,
       
   664                                                 aAttributeTypeID, NULL,
       
   665                                                 aContactListID, descriptionBuf );
       
   666                     }
       
   667 
       
   668                 CleanupStack::PopAndDestroy( descriptionBuf );
       
   669                 }
       
   670             }
       
   671         }
       
   672 
       
   673 
       
   674     return aStatus.Status();
       
   675     }
       
   676 
       
   677 
       
   678 
       
   679 // ---------------------------------------------------------
       
   680 // CPEngXMLParser::DoParseDetailedResultsL()
       
   681 // ---------------------------------------------------------
       
   682 //
       
   683 void CPEngXMLParser::DoParseDetailedResultsL( const TDesC8& aBuffer,
       
   684                                               MPEngAdvTransactionStatus2& aStatus,
       
   685                                               TInt aOperationID,
       
   686                                               const TUint32* aAttributeTypeID,
       
   687                                               const TDesC* aContactListID )
       
   688     {
       
   689     CPtrC8Array* detailedResults = new ( ELeave ) CPtrC8Array( 5 );
       
   690     CleanupStack::PushL( detailedResults );
       
   691 
       
   692     if ( DecodeL( aBuffer, KDetailedResultXMLTag, ETrue ) )
       
   693         {
       
   694         //Gather detailed result blocks..
       
   695         const TInt detailedResultCount = Count();
       
   696         TInt ii;
       
   697         for ( ii = 0; ii < detailedResultCount; ii++ )
       
   698             {
       
   699             detailedResults->AppendL( ResultL( ii ) );
       
   700             }
       
   701 
       
   702 
       
   703         //And handle each detailed result block..
       
   704         for ( ii = 0; ii < detailedResultCount; ii++ )
       
   705             {
       
   706             DoParseOneDetailedResultL( ( *detailedResults )[ ii ],
       
   707                                        aStatus,
       
   708                                        aOperationID,
       
   709                                        aAttributeTypeID,
       
   710                                        aContactListID );
       
   711             }
       
   712         }
       
   713 
       
   714     CleanupStack::PopAndDestroy( detailedResults );
       
   715     }
       
   716 
       
   717 
       
   718 
       
   719 // ---------------------------------------------------------
       
   720 // CPEngXMLParser::DoParseOneDetailedResultL()
       
   721 // ---------------------------------------------------------
       
   722 //
       
   723 void CPEngXMLParser::DoParseOneDetailedResultL( const TDesC8& aDetailedResult,
       
   724                                                 MPEngAdvTransactionStatus2& aStatus,
       
   725                                                 TInt aOperationID,
       
   726                                                 const TUint32* aAttributeTypeID,
       
   727                                                 const TDesC* aContactListID )
       
   728     {
       
   729     //DTD: DetailedResult (Code, Description?, UserID*, GroupID*,
       
   730     //                     ScreenName*, MessageID*, ContactList*, Domain*)
       
   731 
       
   732     TInt wvErrorCode = KErrNone;
       
   733     TBool errorCodeDecoded = EFalse;
       
   734 
       
   735 
       
   736     //Look for mandatory parts
       
   737     if ( DecodeL( aDetailedResult, KCodeXMLTag, EFalse ) )
       
   738         {
       
   739         TPtrC8 cspStatusCodeBlock( ResultL() );
       
   740         errorCodeDecoded = DecodeWVCspStatusCodeToError( cspStatusCodeBlock,
       
   741                                                          wvErrorCode );
       
   742         }
       
   743 
       
   744 
       
   745 
       
   746     if ( !errorCodeDecoded )
       
   747         {
       
   748         //Detailed result is somehow malformed...
       
   749         aStatus.AddDetailedResultL( aOperationID,
       
   750                                     KPEngNwErrInternalServerOrNetworkError,
       
   751                                     aAttributeTypeID, NULL,
       
   752                                     aContactListID, NULL );
       
   753         }
       
   754 
       
   755 
       
   756     else
       
   757         {
       
   758         //Detailed result mandatory parts ok
       
   759         //Get the detailed description if any
       
   760         HBufC* descriptionBuf = NULL;
       
   761         if ( DecodeL( aDetailedResult, KDescriptionXMLTag, EFalse ) )
       
   762             {
       
   763             descriptionBuf = ResultAsUnicodeTextL();
       
   764             if ( descriptionBuf->Length() == 0 )
       
   765                 {
       
   766                 delete descriptionBuf;
       
   767                 descriptionBuf = NULL;
       
   768                 }
       
   769             }
       
   770         if ( descriptionBuf )
       
   771             {
       
   772             CleanupStack::PushL( descriptionBuf );
       
   773             }
       
   774 
       
   775 
       
   776 
       
   777         // And process the detailed "main" entries
       
   778         TInt detailMainEntriesStartCount = aStatus.DetailedResultCount();
       
   779             {
       
   780             //First user id's
       
   781             if ( DecodeL( aDetailedResult, KUserIDXMLTag, EFalse ) )
       
   782                 {
       
   783                 const TInt detailedUserIDsCount = Count();
       
   784 
       
   785                 for ( TInt ii( 0 ); ii < detailedUserIDsCount; ii++ )
       
   786                     {
       
   787                     HBufC* userID = ResultAsWVAddressL( ii );
       
   788                     CleanupStack::PushL( userID );
       
   789                     if ( userID->Length() > 0 )
       
   790                         {
       
   791                         aStatus.AddDetailedResultL( aOperationID, wvErrorCode,
       
   792                                                     aAttributeTypeID, userID,
       
   793                                                     aContactListID, descriptionBuf );
       
   794 
       
   795                         }
       
   796 
       
   797                     CleanupStack::PopAndDestroy( userID );
       
   798                     }
       
   799                 }
       
   800 
       
   801             if ( DecodeL( aDetailedResult, KContactList, EFalse ) )
       
   802                 {
       
   803                 const TInt detailedContactListsCount = Count();
       
   804 
       
   805                 for ( TInt ii( 0 ); ii < detailedContactListsCount; ii++ )
       
   806                     {
       
   807                     HBufC* contactList = ResultAsWVAddressL( ii );
       
   808                     CleanupStack::PushL( contactList );
       
   809                     if ( contactList->Length() > 0 )
       
   810                         {
       
   811                         aStatus.AddDetailedResultL( aOperationID, wvErrorCode,
       
   812                                                     aAttributeTypeID, NULL,
       
   813                                                     contactList, descriptionBuf );
       
   814 
       
   815                         }
       
   816 
       
   817                     CleanupStack::PopAndDestroy( contactList );
       
   818                     }
       
   819                 }
       
   820             }
       
   821 
       
   822         TInt detailMainEntriesEndCount = aStatus.DetailedResultCount();
       
   823 
       
   824 
       
   825 
       
   826 
       
   827         if ( detailMainEntriesStartCount == detailMainEntriesEndCount )
       
   828             {
       
   829             //No main type entries added ==> add code and possible
       
   830             //description as one
       
   831             aStatus.AddDetailedResultL( aOperationID,
       
   832                                         wvErrorCode,
       
   833                                         NULL,
       
   834                                         NULL,
       
   835                                         NULL,
       
   836                                         descriptionBuf );
       
   837             }
       
   838 
       
   839 
       
   840         if ( descriptionBuf )
       
   841             {
       
   842             CleanupStack::PopAndDestroy( descriptionBuf );
       
   843             }
       
   844         }
       
   845     }
       
   846 
       
   847 
       
   848 
       
   849 // ---------------------------------------------------------
       
   850 // CPEngXMLParser::SetError()
       
   851 // ---------------------------------------------------------
       
   852 //
       
   853 void CPEngXMLParser::SetError( TInt aError )
       
   854     {
       
   855     iError = aError;
       
   856     }
       
   857 
       
   858 
       
   859 
       
   860 
       
   861 // ==================== cXML CALLBACK FUNCTIONS ====================
       
   862 // ---------------------------------------------------------
       
   863 // CPEngXMLParser::StartDocument_CB()
       
   864 // ---------------------------------------------------------
       
   865 //
       
   866 NW_Status_t CPEngXMLParser::StartDocument_CB( NW_XML_Reader_t*, void* )
       
   867     {
       
   868     //No leaving code allowed
       
   869     return NW_STAT_SUCCESS;
       
   870     }
       
   871 
       
   872 
       
   873 // ---------------------------------------------------------
       
   874 // CPEngXMLParser::EndDocument_CB()
       
   875 // ---------------------------------------------------------
       
   876 //
       
   877 NW_Status_t CPEngXMLParser::EndDocument_CB( NW_XML_Reader_t*, void* )
       
   878     {
       
   879     //No leaving code allowed
       
   880     return NW_STAT_SUCCESS;
       
   881     }
       
   882 
       
   883 
       
   884 // ---------------------------------------------------------
       
   885 // CPEngXMLParser::Tag_Start_CB()
       
   886 // ---------------------------------------------------------
       
   887 //
       
   888 NW_Status_t CPEngXMLParser::Tag_Start_CB( NW_XML_Reader_t* /*aReader*/,
       
   889                                           const NW_XML_Reader_Interval_t* aName,
       
   890                                           void* aParser )
       
   891     {
       
   892     //No leaving code allowed
       
   893 
       
   894     CPEngXMLParser* parser = reinterpret_cast<CPEngXMLParser*> ( aParser );
       
   895 
       
   896     parser->iParsingLevel++;
       
   897 
       
   898     TInt len( aName->stop - aName->start );
       
   899     TPtrC8 buffer( parser->iData.Mid( aName->start, len ) );
       
   900 
       
   901     // now check if the found tag was the one we were looking for
       
   902     if ( buffer.Compare( parser->iSearchable ) == 0 )
       
   903         {
       
   904         TUint itemStart;
       
   905         if ( parser->iIncludeTags )
       
   906             {
       
   907             // the interval includes the tag and the first '<' also
       
   908             itemStart = aName->start - 1;
       
   909             }
       
   910         else
       
   911             {
       
   912             //Locate next tag end char
       
   913             TPtrC8 fullRemainder( parser->iData.Mid( aName->start ) );
       
   914             TInt endMarkOffset = fullRemainder.Locate( '>' );
       
   915             STORE_AND_RETURN_IF_IN_ERROR( parser, endMarkOffset );
       
   916 
       
   917             // here the interval doesn't include the tag nor the ending '>'
       
   918             itemStart = aName->start + endMarkOffset + 1;
       
   919             }
       
   920 
       
   921         TInt err = parser->iIntervals->PushStart( itemStart );
       
   922         STORE_AND_RETURN_IF_IN_ERROR( parser, err );
       
   923         }
       
   924 
       
   925     return NW_STAT_SUCCESS;
       
   926     }
       
   927 
       
   928 
       
   929 
       
   930 
       
   931 
       
   932 // ---------------------------------------------------------
       
   933 // CPEngXMLParser::Tag_End_CB()
       
   934 // ---------------------------------------------------------
       
   935 //
       
   936 NW_Status_t CPEngXMLParser::Tag_End_CB( NW_XML_Reader_t* /*aReader*/,
       
   937                                         const NW_XML_Reader_Interval_t* aName,
       
   938                                         NW_Uint32 /*emptyTagFlag*/,
       
   939                                         void* aParser )
       
   940     {
       
   941 
       
   942     //No leaving code allowed
       
   943     CPEngXMLParser* parser = reinterpret_cast<CPEngXMLParser*> ( aParser );
       
   944 
       
   945     TInt len( aName->stop - aName->start );
       
   946     TPtrC8 buffer( parser->iData.Mid( aName->start, len ) );
       
   947 
       
   948     // check the current XML level
       
   949     // now check if the found tag was the one we were looking for
       
   950     if ( buffer.Compare( parser->iSearchable ) == 0 )
       
   951         {
       
   952         TUint itemEnd;
       
   953         if ( parser->iIncludeTags )
       
   954             {
       
   955             // the interval includes the tag and the last '>' also
       
   956 
       
   957             //Locate next end char
       
   958             TPtrC8 fullRemainder( parser->iData.Mid( aName->stop ) );
       
   959             TInt endMarkOffset = fullRemainder.Locate( '>' );
       
   960             STORE_AND_RETURN_IF_IN_ERROR( parser, endMarkOffset );
       
   961 
       
   962             itemEnd = aName->stop + endMarkOffset + 1;
       
   963             }
       
   964         else
       
   965             {
       
   966             // here the interval doesn't include the tag nor the starting '</'
       
   967             itemEnd = aName->start - 2;
       
   968             }
       
   969 
       
   970 
       
   971         TInt err = parser->iIntervals->PushEnd( itemEnd );
       
   972         STORE_AND_RETURN_IF_IN_ERROR( parser, err );
       
   973 
       
   974 
       
   975         // next grab the data between the tags from the original XML data,
       
   976         //if we are at allowed level
       
   977         if ( ( parser->iMaxParseLevel == 0 ) ||
       
   978              ( parser->iParsingLevel <= parser->iMaxParseLevel ) )
       
   979             {
       
   980             TPoint dataInterval( parser->iIntervals->Pop() );
       
   981             TInt intervalLength( dataInterval.iY - dataInterval.iX );
       
   982 
       
   983 
       
   984             TPtrC8 resultSection( NULL, 0 );
       
   985             if ( intervalLength > 0 ) // if the stack was broken, the length will be 0
       
   986                 {
       
   987                 resultSection.Set( parser->iData.Mid( dataInterval.iX, intervalLength ) );
       
   988                 }
       
   989 
       
   990 
       
   991             TInt err = parser->iResults.Append( resultSection );
       
   992             STORE_AND_RETURN_IF_IN_ERROR( parser, err );
       
   993             }
       
   994         }
       
   995 
       
   996 
       
   997     parser->iParsingLevel--;
       
   998     return NW_STAT_SUCCESS;
       
   999     }
       
  1000 
       
  1001 
       
  1002 
       
  1003 
       
  1004 
       
  1005 // ---------------------------------------------------------
       
  1006 // CPEngXMLParser::Attr_Start_CB()
       
  1007 // ---------------------------------------------------------
       
  1008 //
       
  1009 NW_Status_t CPEngXMLParser::Attr_Start_CB( NW_XML_Reader_t*,
       
  1010                                            const NW_XML_Reader_Interval_t* /*pI_name*/,
       
  1011                                            void* )
       
  1012     {
       
  1013     //No leaving code allowed
       
  1014 
       
  1015     return NW_STAT_SUCCESS;
       
  1016     }
       
  1017 
       
  1018 
       
  1019 // ---------------------------------------------------------
       
  1020 // CPEngXMLParser::Attr_VarVal_CB()
       
  1021 // ---------------------------------------------------------
       
  1022 //
       
  1023 NW_Status_t CPEngXMLParser::Attr_VarVal_CB( NW_XML_Reader_t*,
       
  1024                                             const NW_XML_Reader_Interval_t* /*pI_name*/,
       
  1025                                             const NW_XML_Reader_Interval_t* /*pI_value*/,
       
  1026                                             void* )
       
  1027 
       
  1028     {
       
  1029     //No leaving code allowed
       
  1030 
       
  1031     return NW_STAT_SUCCESS;
       
  1032     }
       
  1033 
       
  1034 
       
  1035 
       
  1036 // ---------------------------------------------------------
       
  1037 // CPEngXMLParser::Attributes_End_CB()
       
  1038 // ---------------------------------------------------------
       
  1039 //
       
  1040 NW_Status_t CPEngXMLParser::Attributes_End_CB( NW_XML_Reader_t*,
       
  1041                                                NW_Uint32 /*attributeCount*/,
       
  1042                                                void* )
       
  1043     {
       
  1044     //No leaving code allowed
       
  1045 
       
  1046     return NW_STAT_SUCCESS;
       
  1047     }
       
  1048 
       
  1049 
       
  1050 
       
  1051 // ---------------------------------------------------------
       
  1052 // CPEngXMLParser::Attr_Entity_VarVal_CB()
       
  1053 // ---------------------------------------------------------
       
  1054 //
       
  1055 NW_Status_t CPEngXMLParser::Attr_Entity_VarVal_CB ( NW_XML_Reader_t* /*pT*/,
       
  1056                                                     const NW_XML_Reader_Interval_t* /*pI_name*/,
       
  1057                                                     NW_Uint8* /*pValue*/,
       
  1058                                                     NW_Uint32 /*valueByteLength*/,
       
  1059                                                     void* /*pV*/ )
       
  1060     {
       
  1061     //No leaving code allowed
       
  1062 
       
  1063     return NW_STAT_SUCCESS;
       
  1064     }
       
  1065 
       
  1066 
       
  1067 // ---------------------------------------------------------
       
  1068 // CPEngXMLParser::Exception_CB()
       
  1069 // ---------------------------------------------------------
       
  1070 //
       
  1071 NW_Status_t CPEngXMLParser::Exception_CB( NW_XML_Reader_t*, void* )
       
  1072     {
       
  1073     //No leaving code allowed
       
  1074 
       
  1075     return NW_STAT_FAILURE;
       
  1076     }
       
  1077 
       
  1078 
       
  1079 //  End of File
       
  1080 
       
  1081