ncdengine/provider/server/src/ncdpurchaseoperationimpl.cpp
changeset 0 ba25891c3a9e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2006-2008 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:   ?Description
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "ncdpurchaseoperationimpl.h"
       
    20 
       
    21 #include <badesca.h>
       
    22 #include <s32mem.h>
       
    23 #include <exterror.h> // for KErrGsmSMSShortMessageTransferRejected
       
    24 
       
    25 #include "ncdoperationfunctionids.h"
       
    26 #include "catalogsbasemessage.h"
       
    27 #include "catalogssmssession.h"
       
    28 #include "catalogshttpincludes.h"
       
    29 #include "ncdrequestgenerator.h"
       
    30 #include "ncdrequestbase.h"
       
    31 #include "ncdrequestpurchase.h"
       
    32 #include "ncdrequestconfigurationdata.h"
       
    33 #include "ncdprotocol.h"
       
    34 #include "ncdparser.h"
       
    35 #include "ncdnodemanager.h"
       
    36 #include "ncdnodeidentifier.h"
       
    37 #include "ncdnodeimpl.h"
       
    38 #include "ncdnodemetadataimpl.h"
       
    39 #include "ncdnodecontentinfoimpl.h"
       
    40 #include "ncdparserfactory.h"
       
    41 #include "ncdpaymentmethod.h"
       
    42 #include "ncd_pp_purchaseinformationimpl.h"
       
    43 #include "ncd_pp_purchaseprocessedimpl.h"
       
    44 #include "ncd_pp_information.h"
       
    45 #include "ncd_pp_error.h"
       
    46 #include "ncd_cp_queryresponse.h"
       
    47 #include "ncd_cp_query.h"
       
    48 #include "ncd_cp_queryimpl.h"
       
    49 #include "ncd_cp_queryelement.h"
       
    50 #include "ncd_cp_detail.h"
       
    51 #include "ncdstring.h"
       
    52 
       
    53 #include "ncdpurchaseoptionimpl.h"
       
    54 
       
    55 #include "ncdpurchasehistorydbimpl.h"
       
    56 #include "ncdutils.h"
       
    57 #include "ncddelay.h"
       
    58 #include "ncdnodelink.h"
       
    59 #include "catalogsconstants.h"
       
    60 #include "catalogsutils.h"
       
    61 #include "ncd_pp_download.h"
       
    62 #include "ncd_pp_descriptor.h"
       
    63 #include "ncd_pp_rights.h"
       
    64 #include "ncdqueryimpl.h"
       
    65 #include "ncdqueryselectionitemimpl.h"
       
    66 #include "ncdnodeiconimpl.h"
       
    67 #include "ncdoperationremovehandler.h"
       
    68 #include "ncdnodedownloadimpl.h"
       
    69 #include "ncddownloadinfo.h"
       
    70 
       
    71 #include "ncdsubscriptionmanagerimpl.h"
       
    72 #include "ncderrors.h"
       
    73 #include "ncdsessionhandler.h"
       
    74 #include "ncdprotocoldefaultobserver.h"
       
    75 #include "ncdnodedependencyimpl.h"
       
    76 #include "ncdnodeupgradeimpl.h"
       
    77 
       
    78 #include "ncdproviderutils.h"
       
    79 #include "ncdengineconfiguration.h"
       
    80 #include "catalogscontext.h"
       
    81 #include "ncdsearchnodefolder.h"
       
    82 #include "ncdhttputils.h"
       
    83 #include "ncdgeneralmanager.h"
       
    84 
       
    85 #include "catalogsdebug.h"
       
    86 
       
    87 // ======== MEMBER FUNCTIONS ========
       
    88 
       
    89 // Resend after timer is not needed if iResendAfter is -1
       
    90 const TInt KResendAfterDisabled = -1;
       
    91 
       
    92 // ---------------------------------------------------------------------------
       
    93 // ?description_if_needed
       
    94 // ---------------------------------------------------------------------------
       
    95 //
       
    96 CNcdPurchaseOperationImpl* CNcdPurchaseOperationImpl::NewL(
       
    97     const TDesC& aNameSpace,
       
    98     const TDesC& aNodeId,
       
    99     const TUid& aClientUid,
       
   100     const TDesC& aPurchaseOptionId,
       
   101     CNcdGeneralManager& aGeneralManager,
       
   102     MCatalogsHttpSession& aHttpSession,
       
   103     MCatalogsSmsSession& aSmsSession,
       
   104     CNcdSubscriptionManager& aSubscriptionManager,
       
   105     MNcdOperationRemoveHandler* aRemoveHandler,
       
   106     MCatalogsSession& aSession )
       
   107     {
       
   108     CNcdPurchaseOperationImpl* self = 
       
   109         CNcdPurchaseOperationImpl::NewLC(
       
   110             aNameSpace,
       
   111             aNodeId,
       
   112             aClientUid,
       
   113             aPurchaseOptionId,
       
   114             aGeneralManager,
       
   115             aHttpSession,
       
   116             aSmsSession,
       
   117             aSubscriptionManager,
       
   118             aRemoveHandler,
       
   119             aSession );
       
   120     CleanupStack::Pop( self );
       
   121     return self;
       
   122     }
       
   123 
       
   124 
       
   125 // ---------------------------------------------------------------------------
       
   126 // ?description_if_needed
       
   127 // ---------------------------------------------------------------------------
       
   128 //
       
   129 CNcdPurchaseOperationImpl* CNcdPurchaseOperationImpl::NewLC(
       
   130     const TDesC& aNameSpace,
       
   131     const TDesC& aNodeId,
       
   132     const TUid& aClientUid,
       
   133     const TDesC& aPurchaseOptionId,
       
   134     CNcdGeneralManager& aGeneralManager,
       
   135     MCatalogsHttpSession& aHttpSession,
       
   136     MCatalogsSmsSession& aSmsSession,
       
   137     CNcdSubscriptionManager& aSubscriptionManager,
       
   138     MNcdOperationRemoveHandler* aRemoveHandler,
       
   139     MCatalogsSession& aSession )
       
   140     {
       
   141     CNcdPurchaseOperationImpl* self = 
       
   142         new( ELeave ) CNcdPurchaseOperationImpl(
       
   143             aGeneralManager,
       
   144             aHttpSession,
       
   145             aSmsSession,
       
   146             aSubscriptionManager,
       
   147             aRemoveHandler,
       
   148             aSession );
       
   149     CleanupClosePushL( *self );
       
   150     self->ConstructL( aNameSpace, aNodeId, aClientUid, aPurchaseOptionId );
       
   151     return self;
       
   152     }
       
   153     
       
   154 
       
   155 // ---------------------------------------------------------------------------
       
   156 // ?description_if_needed
       
   157 // ---------------------------------------------------------------------------
       
   158 //
       
   159 CNcdPurchaseOperationImpl::CNcdPurchaseOperationImpl(
       
   160     CNcdGeneralManager& aGeneralManager,
       
   161     MCatalogsHttpSession& aHttpSession,
       
   162     MCatalogsSmsSession& aSmsSession,
       
   163     CNcdSubscriptionManager& aSubscriptionManager,
       
   164     MNcdOperationRemoveHandler* aRemoveHandler,
       
   165     MCatalogsSession& aSession )
       
   166     : CNcdBaseOperation( aGeneralManager, aRemoveHandler, EPurchaseOperation,
       
   167         aSession ),
       
   168       iAccessPointManager( aGeneralManager.AccessPointManager() ),
       
   169       iPurchaseHistory( &aGeneralManager.PurchaseHistory() ),
       
   170       iHttpSession( aHttpSession ),
       
   171       iSmsSession( &aSmsSession ),
       
   172       iProtocol( aGeneralManager.ProtocolManager() ),
       
   173       iSubscriptionManager( aSubscriptionManager ),
       
   174       iLocked( EFalse )
       
   175     {
       
   176     iPurchaseOperationState = EBegin;
       
   177     
       
   178     }
       
   179     
       
   180 
       
   181 // ---------------------------------------------------------------------------
       
   182 // ?description_if_needed
       
   183 // ---------------------------------------------------------------------------
       
   184 //
       
   185 void CNcdPurchaseOperationImpl::ConstructL(
       
   186     const TDesC& aNameSpace,
       
   187     const TDesC& aNodeId,
       
   188     const TUid& aClientUid,
       
   189     const TDesC& aPurchaseOptionId )
       
   190     {
       
   191     DLTRACEIN((""));
       
   192 
       
   193     CNcdBaseOperation::ConstructL();
       
   194 
       
   195     iNodeIdentifier = CNcdNodeIdentifier::NewL( aNameSpace, aNodeId, aClientUid );
       
   196 
       
   197     // Get the node where the purchase operation was started from
       
   198     iNode = &iNodeManager->NodeL( *iNodeIdentifier );
       
   199 
       
   200     // Get the selected purchase option
       
   201     RPointerArray<CNcdPurchaseOptionImpl> purchaseOptions = 
       
   202         iNode->NodeMetaDataL().PurchaseOptions();
       
   203 
       
   204     for( TInt i = 0; i < purchaseOptions.Count(); i++ )
       
   205         {
       
   206         if( purchaseOptions[i]->Id().CompareF( aPurchaseOptionId ) == 0 )
       
   207             {
       
   208             iSelectedPurchaseOption = purchaseOptions[i];
       
   209             }
       
   210         }
       
   211     
       
   212     // Purchase option is needed so leave if not found    
       
   213     if ( !iSelectedPurchaseOption )
       
   214         {
       
   215         User::Leave( KErrNotFound );
       
   216         }
       
   217     }
       
   218 
       
   219 
       
   220 // ---------------------------------------------------------------------------
       
   221 // ?description_if_needed
       
   222 // ---------------------------------------------------------------------------
       
   223 //
       
   224 CNcdPurchaseOperationImpl::~CNcdPurchaseOperationImpl()
       
   225     {
       
   226     delete iPurchaseOptionId;
       
   227     delete iNodeIdentifier;
       
   228     delete iParser;
       
   229     if ( iHttpTransaction ) 
       
   230         {
       
   231         // Cancel also releases the operation
       
   232         iHttpTransaction->Cancel();        
       
   233         }
       
   234     
       
   235     delete iSmsRegistrationRequest;
       
   236     delete iPurchaseInformationData;
       
   237     delete iPurchaseProcessedData;
       
   238     if( iPurchaseQuery )
       
   239         {
       
   240         iPurchaseQuery->InternalRelease();
       
   241         }
       
   242     delete iRedirectUri;
       
   243     delete iDelay;
       
   244     iPendingSmsOperations.Reset();
       
   245     }
       
   246 
       
   247 // ---------------------------------------------------------------------------
       
   248 // Node Id getter
       
   249 // ---------------------------------------------------------------------------
       
   250 //
       
   251 const CNcdNodeIdentifier& CNcdPurchaseOperationImpl::NodeIdentifier() const
       
   252     {
       
   253     return *iNodeIdentifier;
       
   254     }
       
   255 
       
   256 // ---------------------------------------------------------------------------
       
   257 // ?implementation_description
       
   258 // ---------------------------------------------------------------------------
       
   259 //
       
   260 void CNcdPurchaseOperationImpl::Cancel()
       
   261     {
       
   262     DLTRACEIN( ( "" ) );
       
   263     if ( iHttpTransaction )
       
   264         {
       
   265         iHttpTransaction->Cancel();
       
   266         iHttpTransaction = NULL;
       
   267         }
       
   268     
       
   269     if ( iParser )
       
   270         {
       
   271         iParser->CancelParsing();        
       
   272         }
       
   273     
       
   274     DeletePtr( iDelay );
       
   275     
       
   276     TInt i = iPendingSmsOperations.Count();
       
   277     while( i-- )
       
   278         {
       
   279         iPendingSmsOperations[i]->Cancel();
       
   280         // The previous cancel will result with current implementation
       
   281         // in HandleSmsEvent() call. Although this happens release
       
   282         // and removal is done here to be sure that they are done.
       
   283         // (This way this function is not dependant whether the
       
   284         // HandleSmsEvent callback occurs or not)                    
       
   285 	    iPendingSmsOperations[i]->Release();
       
   286         iPendingSmsOperations.Remove( i );
       
   287         }
       
   288     	
       
   289     }
       
   290     
       
   291 // ---------------------------------------------------------------------------
       
   292 // ?implementation_description
       
   293 // ---------------------------------------------------------------------------
       
   294 //
       
   295 void CNcdPurchaseOperationImpl::HandleHttpEventL( 
       
   296         MCatalogsHttpOperation& aOperation, 
       
   297         TCatalogsHttpEvent aEvent )
       
   298     {
       
   299     DLTRACEIN((""));
       
   300 
       
   301     DASSERT( aOperation.OperationType() == ECatalogsHttpTransaction );
       
   302     
       
   303     TInt err = KErrNone;
       
   304     switch( aEvent.iOperationState )
       
   305         {
       
   306             
       
   307         case ECatalogsHttpOpInProgress:
       
   308             {
       
   309             // Don't bother to send empty bodies because this event 
       
   310             // is sent also for received headers etc.
       
   311             if ( aOperation.Body().Length() )
       
   312                 {                
       
   313                 // Send received data to the parser
       
   314                 TRAP(err, iParser->ParseL( aOperation.Body() ));
       
   315                 }
       
   316 
       
   317             break;
       
   318             }
       
   319 
       
   320         case ECatalogsHttpOpCompleted:
       
   321             {
       
   322             TRAP( err, iParser->EndL() );
       
   323             break;
       
   324             }
       
   325         }
       
   326 
       
   327     if( err != KErrNone )
       
   328         {
       
   329         iError = err;
       
   330         iPurchaseOperationState = EFailed;
       
   331         Cancel();
       
   332         RunOperation();
       
   333         }
       
   334         
       
   335     DLTRACEOUT((""));
       
   336     }
       
   337     
       
   338 
       
   339 
       
   340 
       
   341 // ---------------------------------------------------------------------------
       
   342 // From class CNcdBaseOperation.
       
   343 // ?implementation_description
       
   344 // ---------------------------------------------------------------------------
       
   345 //
       
   346 TInt CNcdPurchaseOperationImpl::RunOperation()
       
   347     {
       
   348     DLTRACEIN((""));
       
   349     
       
   350     if ( !iPendingMessage )
       
   351         {
       
   352         DLTRACEOUT(("No pending message -> return"));
       
   353         return KErrNone;
       
   354         }
       
   355 
       
   356     DLTRACE(("Purchase operation state: %d", iPurchaseOperationState));
       
   357     
       
   358     if ( iLocked ) 
       
   359         {
       
   360         DLINFO(("Operation locked"));
       
   361         return KErrNone;
       
   362         }
       
   363     
       
   364     TRAPD( err, DoRunOperationL() );
       
   365      
       
   366      if ( err != KErrNone )
       
   367         {
       
   368         DLTRACE(("error: %d", err));
       
   369         Cancel();
       
   370         iPurchaseOperationState = EFailed;
       
   371         iError = err;
       
   372         if ( iPendingMessage )
       
   373             {
       
   374             // error ignored because operation already failed
       
   375             CNcdBaseOperation::CompleteMessage( iPendingMessage,
       
   376                 ENCDOperationMessageCompletionError, err );
       
   377             }
       
   378         }
       
   379     DLTRACEOUT((""));
       
   380     return err;
       
   381     }
       
   382 
       
   383 
       
   384 void CNcdPurchaseOperationImpl::DoRunOperationL()
       
   385     {
       
   386     DLTRACEIN((""));
       
   387     switch ( iPurchaseOperationState )
       
   388         {
       
   389         case EBegin:
       
   390             {
       
   391             DLTRACE( _L( "->EBegin" ) );
       
   392             
       
   393             // At first check if there is enough disk space for the downloadable
       
   394             // content. Stop the purchase process if this is not the case.
       
   395             TInt contentSize = 0;
       
   396             TRAP_IGNORE( contentSize = iNode->NodeMetaDataL().ContentInfoL().TotalContentSize() );          
       
   397             DLINFO((("contentSize=%d"), contentSize ));
       
   398             if ( contentSize > 0 ) 
       
   399                 {                
       
   400                 HBufC* clientDataPath = CNcdProviderUtils::EngineConfig().ClientDataPathLC( 
       
   401                     iGeneralManager.FamilyName(), EFalse );    
       
   402                 DLINFO(( _L("Client data path: %S"), clientDataPath )); 
       
   403                 WouldDiskSpaceGoBelowCriticalLevelL(
       
   404                     *clientDataPath, CNcdProviderUtils::FileSession(), contentSize );
       
   405                 CleanupStack::PopAndDestroy( clientDataPath );                
       
   406                 }
       
   407             
       
   408             // Skip purchase process for free items that doesn't implicitely
       
   409             // require going through it
       
   410             // Notice that we don't support purchasing of a subscription
       
   411             // that is free and does not require purchase process. Purchase
       
   412             // process is used as no downloadinfo is received!!
       
   413             if( iSelectedPurchaseOption->IsFree() && 
       
   414                 !iSelectedPurchaseOption->RequirePurchaseProcess() &&
       
   415                 iSelectedPurchaseOption->DownloadInfoCount() > 0 ) 
       
   416                 {
       
   417                 iPurchaseOperationState = EDownloadDetailsReceived;
       
   418                 
       
   419                 CNcdBaseOperation::CompleteMessage( 
       
   420                     iPendingMessage, 
       
   421                     ENCDOperationMessageCompletionProgress,
       
   422                     iProgress,
       
   423                     KErrNone );
       
   424                 }
       
   425             else
       
   426                 {
       
   427 
       
   428                 // Create purchase request and send it. Next callback will be
       
   429                 // HandleHttpEventL or HandleHttpError.
       
   430                 HBufC8* purchaseRequest = CreatePurchaseRequestLC(
       
   431                     EPurchaseRequest,
       
   432                     iNode->NodeLinkL().ServerUri() );
       
   433 
       
   434                 SendRequestL( iNode->NodeLinkL().ServerUri(), *purchaseRequest );
       
   435                 CleanupStack::PopAndDestroy( purchaseRequest );
       
   436 
       
   437                 iPurchaseOperationState = EPurchaseRequestSent;
       
   438                 }
       
   439             DLTRACE(( "EBegin done" ));
       
   440             break;
       
   441             }
       
   442 
       
   443         case EPurchaseInformationReceived:
       
   444             {
       
   445             DLTRACE( _L( "->EPurchaseInformationReceived" ) );
       
   446             
       
   447             if( !iPurchaseInformationData )
       
   448                 {
       
   449                 User::Leave( KNcdErrorNoPurchaseInformationReceived );
       
   450                 }
       
   451 
       
   452             // Handle redirection if server requested for it.
       
   453             if( iPurchaseInformationData->Uri() != KNullDesC )
       
   454                 {
       
   455                 // store redirect uri
       
   456                 delete iRedirectUri;
       
   457                 iRedirectUri = NULL;
       
   458                 iRedirectUri = iPurchaseInformationData->Uri().AllocL();
       
   459                 
       
   460                 HBufC8* purchaseRequest;
       
   461 
       
   462                 // Redirection with new session
       
   463                 if( iPurchaseInformationData->InitiateSession() )
       
   464                     {
       
   465                     // remove session if there is one
       
   466                     iProtocol.SessionHandlerL( iSession.Context() ).RemoveSession(
       
   467                     iPurchaseInformationData->Uri(), iNodeIdentifier->NodeNameSpace() );
       
   468                     purchaseRequest = 
       
   469                         CreatePurchaseRequestLC( 
       
   470                             EPurchaseRequest,
       
   471                             iPurchaseInformationData->Uri() );
       
   472                     }
       
   473                 
       
   474                 // Redirection without new session
       
   475                 else
       
   476                     {
       
   477                     purchaseRequest = 
       
   478                         CreatePurchaseRequestLC( 
       
   479                             EPurchaseRequest,
       
   480                             iNode->NodeLinkL().ServerUri() ); 
       
   481                     }
       
   482                 
       
   483                 SendRequestL( 
       
   484                     *iRedirectUri, *purchaseRequest );
       
   485                 CleanupStack::PopAndDestroy( purchaseRequest );
       
   486                 iPurchaseOperationState = EPurchaseRequestResent;
       
   487                 }
       
   488             else if( iPurchaseInformationData->Disclaimer() )
       
   489                 {
       
   490                 DLTRACE(("Sending purchase disclaimer"));
       
   491                 if ( iPurchaseQuery )
       
   492                     {
       
   493                     iPurchaseQuery->InternalRelease();
       
   494                     iPurchaseQuery = NULL;
       
   495                     }
       
   496                 iPurchaseQuery = 
       
   497                     CNcdQuery::NewL( *iPurchaseInformationData->Disclaimer() );
       
   498                 CNcdBaseOperation::QueryReceivedL( iPurchaseQuery );
       
   499                 
       
   500                 iPurchaseOperationState = EDisclaimerQueried;
       
   501                 }
       
   502             else
       
   503                 {
       
   504                 iPurchaseOperationState = EDisclaimerQueried;
       
   505 
       
   506                 // Send progress info to the proxy
       
   507                 CNcdBaseOperation::CompleteMessage( iPendingMessage,
       
   508                          ENCDOperationMessageCompletionProgress,
       
   509                          iProgress,
       
   510                          KErrNone );
       
   511                 }
       
   512             DLTRACE(( "EPurchaseInformationReceived done" ));
       
   513             break;
       
   514             }
       
   515             
       
   516         case EDisclaimerQueried:
       
   517             {
       
   518             DLTRACE(( "EDisclaimerQueried" ));
       
   519                       
       
   520             // purchase option is free but payment methods exist
       
   521             // -> there may be querys that need showing
       
   522             if( iSelectedPurchaseOption->IsFree() &&
       
   523                 iPurchaseInformationData->PaymentCount() == 1 )
       
   524                 {
       
   525                 // automatically select the purchase option
       
   526                 iSelectedPaymentMethod = &iPurchaseInformationData->PaymentL( 0 );
       
   527                 // continue operation so that possible querys get shown
       
   528                 iPurchaseOperationState = EPaymentMethodsQueried;
       
   529                 
       
   530                 // Send progress info to the proxy
       
   531                 CNcdBaseOperation::CompleteMessage( iPendingMessage,
       
   532                          ENCDOperationMessageCompletionProgress,
       
   533                          iProgress,
       
   534                          KErrNone );
       
   535                 }
       
   536             // purchase option is free but no payment methods exist
       
   537             else if( iSelectedPurchaseOption->IsFree() &&
       
   538                 iPurchaseInformationData->PaymentCount() < 1 )
       
   539                 {
       
   540                 // send purchase confirmation next
       
   541                 iPurchaseOperationState = EPaymentProcessed;
       
   542                 // Send progress info to the proxy
       
   543                 CNcdBaseOperation::CompleteMessage( iPendingMessage,
       
   544                          ENCDOperationMessageCompletionProgress,
       
   545                          iProgress,
       
   546                          KErrNone );
       
   547                 }
       
   548             // Send received payment methods to the proxy
       
   549             else
       
   550                 {
       
   551                 // Set received price text to the purchase option.
       
   552                 iSelectedPurchaseOption->SetPriceTextL( 
       
   553                     iPurchaseInformationData->EntityL( 0 ).PriceText() );
       
   554 
       
   555                 // Now that the purchase option has been updated (new price)
       
   556                 // on the server side, it has to be reinternalized into
       
   557                 // proxy side. This is done in
       
   558                 // CNcdPurchaseOperationProxy::QueryReceivedCallback.
       
   559 				//
       
   560                 // It might be nicer to pass the updated price
       
   561                 // some way in the query instead of updating the
       
   562                 // purchase option. This way the same updated price
       
   563                 // would not (in update situations) be in two places
       
   564                 // in purchase history (final price and the price of
       
   565                 // purchase option).
       
   566 
       
   567 
       
   568                 RPointerArray<CNcdString> paymentMethodNames( KListGranularity );
       
   569                 CleanupResetAndDestroyPushL( paymentMethodNames );
       
   570 
       
   571                 CDesC8ArrayFlat* paymentMethodTypes =
       
   572                     new ( ELeave ) CDesC8ArrayFlat( KListGranularity );
       
   573 
       
   574                 CleanupStack::PushL( paymentMethodTypes );
       
   575 
       
   576                 HBufC8* paymentMethodType;
       
   577 
       
   578                 TInt count = iPurchaseInformationData->PaymentCount();
       
   579                 
       
   580                 // must have at least one payment method
       
   581                 if( count < 1 )
       
   582                     {
       
   583                     DLERROR(("No payment methods!"));
       
   584                     DASSERT(0);
       
   585                     User::Leave( KNcdErrorNoPurchaseInformation );
       
   586                     }
       
   587                 
       
   588                 for( TInt i = 0; i < count; i++ )
       
   589                     {
       
   590                     CNcdString* paymentMethodName = CNcdString::NewLC( 
       
   591                         iPurchaseInformationData->PaymentL( i ).Name() );
       
   592                     paymentMethodNames.AppendL( paymentMethodName );
       
   593                     CleanupStack::Pop( paymentMethodName );
       
   594 
       
   595                     paymentMethodType = IntToDes8LC( iPurchaseInformationData->PaymentL( i ).Method() );
       
   596                     paymentMethodTypes->AppendL( *paymentMethodType );
       
   597                     CleanupStack::PopAndDestroy( paymentMethodType );
       
   598                     }
       
   599 
       
   600                 
       
   601                 if ( iPurchaseQuery )
       
   602                     {
       
   603                     iPurchaseQuery->InternalRelease();
       
   604                     iPurchaseQuery = NULL;
       
   605                     }
       
   606                 iPurchaseQuery = 
       
   607                     CNcdQuery::NewL( paymentMethodNames, *paymentMethodTypes );
       
   608                 CNcdBaseOperation::QueryReceivedL( iPurchaseQuery );
       
   609                 
       
   610                 CleanupStack::PopAndDestroy( paymentMethodTypes );
       
   611                 CleanupStack::PopAndDestroy( &paymentMethodNames );
       
   612                 iPurchaseOperationState = EPaymentMethodsQueried;
       
   613 
       
   614                 }
       
   615             DLTRACE(( "EDisclaimerQueried done" ));
       
   616             break;
       
   617             }
       
   618 
       
   619         case EPaymentMethodsQueried:
       
   620             {
       
   621             DLTRACE( _L( "->EPaymentMethodsQueried" ) );
       
   622             
       
   623             // Query exists for the selected payment method. 
       
   624             if( iSelectedPaymentMethod->QueryId() != KNullDesC() )
       
   625                 {
       
   626                 if ( iPurchaseQuery )
       
   627                     {
       
   628                     iPurchaseQuery->InternalRelease();
       
   629                     iPurchaseQuery = NULL;
       
   630                     }
       
   631                 
       
   632                 TBool secureConnection = EFalse;
       
   633                 if ( iRedirectUri )
       
   634                     {
       
   635                     secureConnection = IsHttpsUri( *iRedirectUri );
       
   636                     }
       
   637                 else
       
   638                     {
       
   639                     secureConnection = IsHttpsUri( iNode->NodeLinkL().ServerUri() );
       
   640                     }
       
   641                     
       
   642                 iPurchaseQuery = 
       
   643                     CNcdQuery::NewL( CNcdBaseOperation::QueryEntityL( 
       
   644                         iSelectedPaymentMethod->QueryId() ), secureConnection );
       
   645                         
       
   646                 CNcdBaseOperation::QueryReceivedL( iPurchaseQuery );
       
   647                 
       
   648                 iPurchaseOperationState = EPaymentInformationQueried;
       
   649                 }
       
   650 
       
   651             // No query available. Continue purchase process.
       
   652             else
       
   653                 {
       
   654                 iPurchaseOperationState = EPaymentInformationQueried;
       
   655 
       
   656                 // Send progress info to the proxy
       
   657                 CNcdBaseOperation::CompleteMessage( iPendingMessage, 
       
   658                          ENCDOperationMessageCompletionProgress,
       
   659                          iProgress,
       
   660                          KErrNone );
       
   661                 }
       
   662             DLTRACE(("EPaymentMethodsQueried done"));
       
   663             break;
       
   664             }
       
   665 
       
   666         case EPaymentInformationQueried:
       
   667             {
       
   668             DLTRACE(("EPaymentInformationQueried"));
       
   669             // Send payment SMSs if SMS payment method was selected.
       
   670             if( iSelectedPaymentMethod->Method() == 
       
   671                 MNcdPaymentMethod::EPaymentSms
       
   672                 && iSelectedPaymentMethod->SmsDetailsCount() > 0 )
       
   673                 {
       
   674                 // Sms payments are processed if there is something to process.
       
   675                 // If sms details were not given, then this operation should be
       
   676                 // continued in the else clause below as in normal case.
       
   677                 ProcessSmsPaymentL();
       
   678                 }
       
   679             else
       
   680                 {
       
   681                 iPurchaseOperationState = EPaymentProcessed;
       
   682 
       
   683                 // Send progress info to the proxy
       
   684                 CNcdBaseOperation::CompleteMessage( iPendingMessage, 
       
   685                          ENCDOperationMessageCompletionProgress,
       
   686                          iProgress,
       
   687                          KErrNone );
       
   688                 }
       
   689             DLTRACE(("EPaymentInformationQueried"));
       
   690             break;
       
   691             }
       
   692 
       
   693         case EPaymentProcessed:
       
   694             {
       
   695             DLTRACE( _L( "->EPaymentProcessed" ) );
       
   696             
       
   697             // Create purchase confirmation and send it.
       
   698             
       
   699             // Handle redirection if server requested for it.
       
   700             if( iPurchaseInformationData->Uri() != KNullDesC )
       
   701                 {
       
   702                 DLTRACE(( "Redirection." ));
       
   703                 delete iRedirectUri;
       
   704                 iRedirectUri = NULL;
       
   705                 iRedirectUri = iPurchaseInformationData->Uri().AllocL();
       
   706                 
       
   707                 HBufC8* purchaseRequest;
       
   708 
       
   709                 // Redirection with new session
       
   710                 if( iPurchaseInformationData->InitiateSession() )
       
   711                     {
       
   712                     DLTRACE(( "Redirection with a new session." ));
       
   713                     // remove session if there is one
       
   714                     iProtocol.SessionHandlerL( iSession.Context() ).RemoveSession(
       
   715                     iPurchaseInformationData->Uri(), iNodeIdentifier->NodeNameSpace() );
       
   716                     purchaseRequest = 
       
   717                         CreatePurchaseRequestLC( 
       
   718                             EPurchaseConfirmation,
       
   719                             iPurchaseInformationData->Uri() );
       
   720                     }
       
   721                 
       
   722                 // Redirection without new session
       
   723                 else
       
   724                     {
       
   725                     DLTRACE(( "Redirection without a new session." ));
       
   726                     purchaseRequest = 
       
   727                         CreatePurchaseRequestLC( 
       
   728                             EPurchaseConfirmation,
       
   729                             iNode->NodeLinkL().ServerUri() ); 
       
   730                     }
       
   731                 SendRequestL( iPurchaseInformationData->Uri(), *purchaseRequest );
       
   732                 CleanupStack::PopAndDestroy( purchaseRequest );
       
   733                 }
       
   734             // previously redirected
       
   735             else if ( iRedirectUri )
       
   736                 {
       
   737                 DLTRACE(( "Previously redirected" ));
       
   738                 HBufC8* purchaseRequest = 
       
   739                     CreatePurchaseRequestLC( EPurchaseConfirmation, *iRedirectUri );
       
   740                 SendRequestL( *iRedirectUri, *purchaseRequest );
       
   741                 CleanupStack::PopAndDestroy( purchaseRequest );
       
   742                 }
       
   743             // Otherwise use original server URI.
       
   744             else
       
   745                 {
       
   746                 DLTRACE(( "No redirection, using original server URI." ));
       
   747                 HBufC8* purchaseRequest = 
       
   748                     CreatePurchaseRequestLC( EPurchaseConfirmation, iNode->NodeLinkL().ServerUri() );
       
   749                 SendRequestL( iNode->NodeLinkL().ServerUri(), *purchaseRequest );
       
   750                 CleanupStack::PopAndDestroy( purchaseRequest );
       
   751                 }
       
   752 
       
   753             iPurchaseOperationState = EPurchaseConfirmationSent;
       
   754             DLTRACE(( "EPaymentProcessed done" ));
       
   755             break;
       
   756             }
       
   757 
       
   758         case EDownloadDetailsReceived:
       
   759             {
       
   760             DLTRACE( _L( "->EDownloadDetailsReceived" ) );
       
   761 
       
   762             MNcdPurchaseOption::TType selectedOptionType = 
       
   763                 iSelectedPurchaseOption->PurchaseOptionType();
       
   764 
       
   765             if( selectedOptionType ==
       
   766                     MNcdPurchaseOption::EPurchase ||
       
   767                 selectedOptionType ==
       
   768                     MNcdPurchaseOption::ESubscriptionPurchase )
       
   769                 {
       
   770                 DLTRACE(("Purchase done normally or with subscription."));
       
   771                 
       
   772                 // Update purchase information to the purchase history and notify
       
   773                 // node to refresh itself.
       
   774                 UpdatePurchaseHistoryL();
       
   775                 
       
   776                 DLTRACE(("Purchase history updated."));
       
   777                 
       
   778                 // Update node from the purchase db
       
   779                 iNodeManager->PurchaseHandlerL( iNode->Identifier() );
       
   780                 
       
   781                 DLTRACE(("Node download internalized."));                
       
   782                 }
       
   783                 
       
   784 
       
   785             iPurchaseOperationState = EPurchaseComplete;
       
   786             
       
   787             if( iPurchaseProcessedData && iPurchaseProcessedData->Information() )
       
   788                 {
       
   789                 if ( iPurchaseQuery )
       
   790                     {
       
   791                     iPurchaseQuery->InternalRelease();
       
   792                     iPurchaseQuery = NULL;
       
   793                     }
       
   794                 iPurchaseQuery = 
       
   795                     CNcdQuery::NewL( *iPurchaseProcessedData->Information() );
       
   796                 CNcdBaseOperation::QueryReceivedL( iPurchaseQuery );
       
   797                 }
       
   798             else 
       
   799                 {                
       
   800                 // Send info about operation completion to the proxy
       
   801                 CNcdBaseOperation::CompleteMessage( iPendingMessage, 
       
   802                          ENCDOperationMessageCompletionComplete,
       
   803                          iProgress,
       
   804                         KErrNone );
       
   805                 }
       
   806             break;
       
   807             }
       
   808             
       
   809         case EPurchaseComplete:
       
   810             {
       
   811             DLTRACE(("EPurchaseComplete"));
       
   812             if ( iPendingMessage )
       
   813                 {                
       
   814                 // Send info about operation completion to the proxy
       
   815                 CNcdBaseOperation::CompleteMessage( iPendingMessage, 
       
   816                          ENCDOperationMessageCompletionComplete,
       
   817                          iProgress,
       
   818                         KErrNone );
       
   819                 }
       
   820             DLTRACE(("EPurchaseComplete done"));
       
   821             break;
       
   822             }
       
   823         
       
   824         case EFailed:
       
   825             {
       
   826             DLTRACE(( "->EFailed" ));
       
   827             Cancel();
       
   828             if ( iPendingMessage )                                 
       
   829                 {                
       
   830                 User::LeaveIfError( CNcdBaseOperation::CompleteMessage(
       
   831                     iPendingMessage, ENCDOperationMessageCompletionError, iProgress, iError ) );
       
   832                 }
       
   833             DLTRACE(("EFailed done"));
       
   834             break;
       
   835             }
       
   836         
       
   837         default:
       
   838             {
       
   839             // RunOperation should not be called for other states.
       
   840             DASSERT( 0 );
       
   841             }
       
   842 
       
   843         }     
       
   844     }
       
   845 
       
   846 
       
   847 void CNcdPurchaseOperationImpl::ChangeToPreviousStateL()
       
   848     {
       
   849     DLTRACEIN((""));
       
   850     switch( iPurchaseOperationState )
       
   851         {
       
   852         case EPurchaseRequestSent:
       
   853         case EPurchaseInformationReceived:
       
   854             {
       
   855             iPurchaseOperationState = EBegin;
       
   856             break;
       
   857             }
       
   858         case EPurchaseRequestResent:
       
   859             {
       
   860             iPurchaseOperationState = EPurchaseInformationReceived;
       
   861             break;
       
   862             }
       
   863         case EPurchaseConfirmationSent:
       
   864             {
       
   865             iPurchaseOperationState = EPaymentProcessed;
       
   866             break;
       
   867             }
       
   868         default:
       
   869             {
       
   870             DLTRACE(("CAN'T GO BACK FROM THIS STATE: %d, ERROR!", iPurchaseOperationState));
       
   871             DASSERT(0);
       
   872             User::Leave( KErrArgument );
       
   873             break;
       
   874             }
       
   875         }
       
   876     }
       
   877 
       
   878 
       
   879 
       
   880 HBufC8* CNcdPurchaseOperationImpl::CreatePurchaseRequestLC( 
       
   881     TPurchaseRequestType aType,
       
   882     const TDesC& aServerUri )
       
   883     {
       
   884     DLTRACEIN((""));
       
   885     // Create a purchase request
       
   886     CNcdRequestPurchase* req =
       
   887         NcdRequestGenerator::CreatePurchaseRequestLC();
       
   888 
       
   889     req->SetNamespaceL( iNodeIdentifier->NodeNameSpace() );
       
   890 
       
   891     // Fill necessary information to the purchase request.
       
   892     switch( aType )
       
   893         {
       
   894         case EPurchaseRequest:
       
   895             {
       
   896             DLTRACE(("EPurchaseRequest"));
       
   897             req->AddEntityDetailsL( iNode->NodeLinkL().MetaDataIdentifier().NodeId(),
       
   898             						iNode->NodeMetaDataL().TimeStamp(),
       
   899                                     iSelectedPurchaseOption->Id() );
       
   900             DLTRACE(("EPurchaseRequest done"));
       
   901             break;
       
   902             }
       
   903         case EPurchaseConfirmation:
       
   904             {
       
   905             DLTRACE(("EPurchaseConfirmation"));
       
   906             // Set transaction id
       
   907             if( iPurchaseInformationData->TransactionId() != KNullDesC() )
       
   908             	{
       
   909                 DLTRACE(("set transaction id"));
       
   910 	            req->SetTransactionIdL( iPurchaseInformationData->TransactionId() );
       
   911             	}
       
   912             	
       
   913             DLTRACE(("set purchase confirmation"));
       
   914             if ( iSelectedPaymentMethod ) 
       
   915                 {
       
   916                 if( iPurchaseQuery )
       
   917                     {
       
   918                     DLTRACE(("adding query id"));
       
   919                     req->SetPurchaseConfirmationL( iSelectedPaymentMethod->QueryId(),
       
   920             							   iSelectedPaymentMethod->Method() );
       
   921                     }
       
   922                 else
       
   923                     {
       
   924                     DLTRACE(("not adding query id"));
       
   925                     req->SetPurchaseConfirmationL( iSelectedPaymentMethod->Method() );
       
   926                     }
       
   927                 }
       
   928             else 
       
   929                 {
       
   930                 req->SetPurchaseConfirmationL( KNullDesC, // free item -> no query id
       
   931             							   MNcdPaymentMethod::EPaymentDirect );
       
   932                 }
       
   933             
       
   934             if( iPurchaseInformationData->EntityCount() > 0 &&
       
   935                 iPurchaseInformationData->EntityL( 0 ).Ticket() != KNullDesC )
       
   936 				{
       
   937                 DLTRACE(("add entity with ticket"));
       
   938                 req->AddPurchaseConfirmationEntityL( iNode->NodeLinkL().MetaDataIdentifier().NodeId(),
       
   939                                                      iNode->NodeMetaDataL().TimeStamp(),
       
   940                                                      iSelectedPurchaseOption->Id(),
       
   941                                                      iPurchaseInformationData->EntityL( 0 ).Ticket() );
       
   942 				}
       
   943             else
       
   944 				{
       
   945                 DLTRACE(("add entity"));
       
   946                 req->AddPurchaseConfirmationEntityL( iNode->NodeLinkL().MetaDataIdentifier().NodeId(),
       
   947                                                      iNode->NodeMetaDataL().TimeStamp(),
       
   948                                                      iSelectedPurchaseOption->Id() );
       
   949 				}
       
   950 		    DLTRACE(("EPurchaseConfirmation done"));
       
   951             break;
       
   952             }
       
   953         }
       
   954 
       
   955     
       
   956     AddQueryResponsesL( req );
       
   957     
       
   958     if( iPurchaseQuery )
       
   959         {
       
   960         DLTRACE(("Adding query response"));
       
   961         req->AddQueryResponseL( CreateResponseL( *iPurchaseQuery ) );
       
   962         }
       
   963     
       
   964     HBufC8* data = iProtocol.ProcessPreminetRequestL( iSession.Context(), *req, aServerUri );
       
   965     DLINFO( ( "Request: %S", data  ) );
       
   966     CleanupStack::PopAndDestroy( req );
       
   967     CleanupStack::PushL( data );
       
   968     return data;
       
   969     }
       
   970 
       
   971 
       
   972 void CNcdPurchaseOperationImpl::SendRequestL( const TDesC& aServerUri,
       
   973                                               const TDesC8& aData )
       
   974 {
       
   975     DLTRACEIN((""));
       
   976 	// Create a parser to handle the response
       
   977 	if( iParser )
       
   978 	    {
       
   979 	    iParser->CancelParsing();
       
   980 	    delete iParser;
       
   981 	    iParser = NULL;
       
   982 	    }
       
   983 	
       
   984 	iParser = iProtocol.CreateParserL( iSession.Context(), aServerUri );
       
   985     
       
   986     iParser->Observers().SetParserObserver( this );
       
   987     iParser->Observers().SetPurchaseObserver( this );
       
   988     iParser->Observers().SetQueryObserver( this );
       
   989     iParser->Observers().SetInformationObserver( this );
       
   990     iParser->Observers().SetErrorObserver( this );
       
   991 
       
   992     iParser->BeginAsyncL();
       
   993 
       
   994 	
       
   995     // Create a HTTP transaction
       
   996     iGeneralManager.HttpUtils().CreateTransactionL( 
       
   997         iHttpSession,
       
   998         iHttpTransaction,
       
   999         aServerUri,
       
  1000         *this,
       
  1001         aData,
       
  1002         *iNodeIdentifier,
       
  1003         MCatalogsAccessPointManager::EPurchase,
       
  1004         iNodeIdentifier->ClientUid() );
       
  1005     
       
  1006     // Start transaction
       
  1007     User::LeaveIfError( iHttpTransaction->Start() );    
       
  1008     }
       
  1009 
       
  1010 
       
  1011 TBool CNcdPurchaseOperationImpl::HandleHttpError( 
       
  1012     MCatalogsHttpOperation& /* aOperation */, 
       
  1013     TCatalogsHttpError aError )
       
  1014     {
       
  1015     DLTRACEIN(("Error type: %d, code: %d", aError.iType, aError.iError ));
       
  1016     iError = aError.iError;
       
  1017     iPurchaseOperationState = EFailed;
       
  1018     Cancel();
       
  1019     RunOperation();
       
  1020     return ETrue;
       
  1021     }
       
  1022 
       
  1023 
       
  1024 // ---------------------------------------------------------------------------
       
  1025 // ?implementation_description
       
  1026 // ---------------------------------------------------------------------------
       
  1027 //
       
  1028 void CNcdPurchaseOperationImpl::ParseError( TInt aErrorCode )
       
  1029     {
       
  1030     DLTRACEIN(("error:%d", aErrorCode ));
       
  1031     // Handle only if not handling an error already.
       
  1032     if( iError == KErrNone )
       
  1033         {
       
  1034         iPurchaseOperationState = EFailed;
       
  1035         iError = aErrorCode;
       
  1036         Cancel();
       
  1037         RunOperation();
       
  1038         }
       
  1039     }
       
  1040 
       
  1041 // ---------------------------------------------------------------------------
       
  1042 // ?implementation_description
       
  1043 // ---------------------------------------------------------------------------
       
  1044 //
       
  1045 void CNcdPurchaseOperationImpl::ParseCompleteL( TInt /*aError*/ )
       
  1046     {
       
  1047     DLTRACEIN((""));
       
  1048     
       
  1049     // Should the error cases be handled here or in the ParseError 
       
  1050     // callback? Probably not in both.
       
  1051     if ( iLocked ) 
       
  1052         {
       
  1053         // do not complete the message in case the operation is locked
       
  1054         return;
       
  1055         }
       
  1056     
       
  1057 
       
  1058     switch( iPurchaseOperationState )
       
  1059         {
       
  1060         case EPurchaseRequestSent:
       
  1061         case EPurchaseRequestResent:
       
  1062             {
       
  1063             iPurchaseOperationState = EPurchaseInformationReceived;
       
  1064             break;
       
  1065             }
       
  1066         case EPurchaseConfirmationSent:
       
  1067             {
       
  1068             iPurchaseOperationState = EDownloadDetailsReceived;
       
  1069             break;
       
  1070             }
       
  1071         default:
       
  1072             {
       
  1073             DLERROR(( "Unexpected state!" ));
       
  1074             DASSERT( EFalse );
       
  1075             break;
       
  1076             }
       
  1077         }
       
  1078     
       
  1079     // Clear the completed queries from base op, so that we don't send them
       
  1080     // again in the next request.
       
  1081     ClearCompletedQueries();
       
  1082     
       
  1083     // handle querys if any, calls RunOperation after querys have been handled
       
  1084     HandleQuerysL();
       
  1085     }
       
  1086 
       
  1087 //
       
  1088 void CNcdPurchaseOperationImpl::InformationL(
       
  1089     MNcdPreminetProtocolPurchaseInformation* aData )
       
  1090     {
       
  1091     delete iPurchaseInformationData;
       
  1092     iPurchaseInformationData = aData;
       
  1093     }
       
  1094 
       
  1095 void CNcdPurchaseOperationImpl::ProcessedL(
       
  1096     MNcdPreminetProtocolPurchaseProcessed* aData )
       
  1097     {
       
  1098     delete iPurchaseProcessedData;
       
  1099     iPurchaseProcessedData = aData;
       
  1100     if ( iPurchaseProcessedData->ResultCode() != 0 )
       
  1101         {
       
  1102         DLTRACE(("Error: %d, Stop operation!",
       
  1103             iPurchaseProcessedData->ResultCode() ));
       
  1104         iPurchaseOperationState = EFailed;
       
  1105         iError = iPurchaseProcessedData->ResultCode();
       
  1106         Cancel();
       
  1107         RunOperation();
       
  1108         }
       
  1109     }
       
  1110     
       
  1111 void CNcdPurchaseOperationImpl::InformationL(
       
  1112     MNcdPreminetProtocolInformation* aData ) 
       
  1113     {
       
  1114     DLTRACEIN((""));
       
  1115     
       
  1116     // handle resend after
       
  1117     iResendAfter = aData->ResendAfter();
       
  1118     if ( iResendAfter > KResendAfterDisabled ) 
       
  1119         {
       
  1120         DLINFO(( "Resend after %d requested", iResendAfter ));
       
  1121         switch ( iPurchaseOperationState ) 
       
  1122             {
       
  1123             case EPurchaseRequestSent:
       
  1124                 iPurchaseOperationState = EBegin;
       
  1125                 break;
       
  1126                 
       
  1127             case EPurchaseConfirmationSent:
       
  1128                 iPurchaseOperationState = EPaymentProcessed;
       
  1129                 break;
       
  1130                 
       
  1131             default:
       
  1132                 // Resend after should not be requested in other cases.
       
  1133                 DASSERT( EFalse );
       
  1134                 break;
       
  1135             }
       
  1136 
       
  1137         StartResendAfterTimer();
       
  1138         }
       
  1139         
       
  1140     CNcdBaseOperation::InformationL( aData );    
       
  1141     }
       
  1142 
       
  1143 
       
  1144 void CNcdPurchaseOperationImpl::ErrorL( MNcdPreminetProtocolError* aData ) 
       
  1145     {
       
  1146     DLTRACEIN((""));
       
  1147     // Map error codes to correct enumeration values.
       
  1148     
       
  1149     CleanupDeletePushL( aData );
       
  1150     
       
  1151     switch ( aData->Code() ) 
       
  1152         {
       
  1153         case 404:
       
  1154             {
       
  1155             iError = KNcdErrorNotFound;
       
  1156             iSubscriptionManager.RemoveSubscriptionL(
       
  1157                 *iNodeIdentifier, *iPurchaseOptionId );
       
  1158             break;
       
  1159             }
       
  1160         case 416:
       
  1161             {
       
  1162             DLTRACE(("session expired"));
       
  1163             Cancel();
       
  1164             if( iPurchaseInformationData && iPurchaseInformationData->Uri() != KNullDesC )
       
  1165                 {
       
  1166                 iProtocol.SessionHandlerL( iSession.Context() ).RemoveSession( 
       
  1167                     iPurchaseInformationData->Uri(), iNodeIdentifier->NodeNameSpace() );
       
  1168                 }
       
  1169             iProtocol.SessionHandlerL( iSession.Context() ).RemoveSession(
       
  1170                 iNode->NodeLinkL().ServerUri(), iNodeIdentifier->NodeNameSpace() );
       
  1171             DLINFO(("Continue operation from previous state"));
       
  1172             ChangeToPreviousStateL();
       
  1173             // continue operation asynchronously to prevent problems with parser
       
  1174             ContinueOperationL();
       
  1175             break;
       
  1176             }
       
  1177         case 426:
       
  1178             iError = KNcdErrorSubscriptionPaymentAlreadyDone;
       
  1179             break;
       
  1180         case 427:
       
  1181             iError = KNcdErrorSubscriptionNotSubscribed;
       
  1182             iSubscriptionManager.RemoveSubscriptionL(
       
  1183                 *iNodeIdentifier, *iPurchaseOptionId );
       
  1184             break;
       
  1185         case 428:
       
  1186             iError = KNcdErrorSubscriptionInvalid;
       
  1187             iSubscriptionManager.RemoveSubscriptionL(
       
  1188                 *iNodeIdentifier, *iPurchaseOptionId );
       
  1189             break;
       
  1190         case 429:
       
  1191             iError = KNcdErrorSubscriptionNotEnoughCredits;
       
  1192             break;
       
  1193         default:
       
  1194             iError = KNcdProtocolErrorBase - aData->Code();
       
  1195             break;
       
  1196         }
       
  1197     
       
  1198     CleanupStack::Pop( aData );
       
  1199     
       
  1200     // Default observer deletes aData
       
  1201     iParser->DefaultObserver().ErrorL( aData );
       
  1202     
       
  1203     if ( iError != KErrNone )
       
  1204         {
       
  1205         iPurchaseOperationState = EFailed;
       
  1206         Cancel();
       
  1207         RunOperation();
       
  1208         }
       
  1209     }    
       
  1210 
       
  1211 
       
  1212 void CNcdPurchaseOperationImpl::QueryL( MNcdConfigurationProtocolQuery* aData )
       
  1213     {
       
  1214     DLTRACEIN(("query: sem=%d", aData->Semantics()));    
       
  1215     // check if we need to do something special here,
       
  1216     // otherwise forward the query to the base operation
       
  1217     
       
  1218     if ( aData->Semantics() == MNcdQuery::ESemanticsRegistrationQuery ) 
       
  1219         {
       
  1220         DLTRACE(("received sms registration query"));
       
  1221         CleanupDeletePushL( aData );        
       
  1222         
       
  1223         TInt err( KErrNone );
       
  1224         TRAP( err, 
       
  1225         for ( TInt i = 0; i < aData->QueryElementCount(); ++i ) 
       
  1226             {
       
  1227             const MNcdConfigurationProtocolQueryElement& element = 
       
  1228                 aData->QueryElementL(i);
       
  1229 
       
  1230             if ( element.Type() == MNcdConfigurationProtocolQueryElement::ESms ) 
       
  1231                 {
       
  1232                 DLTRACE(("sms query element"));    
       
  1233                 const MNcdConfigurationProtocolDetail* detail = 
       
  1234                     element.Detail();
       
  1235                 _LIT(KValueSmsAddress, "smsAddress");
       
  1236                 _LIT(KValueSmsMessage, "smsMessage");
       
  1237 
       
  1238                 delete iSmsRegistrationRequest;
       
  1239                 iSmsRegistrationRequest = NULL;
       
  1240 
       
  1241                 const RPointerArray<MNcdConfigurationProtocolContent>& contents(
       
  1242                     detail->Contents() );
       
  1243 
       
  1244                 TInt addressKey = KErrNotFound;
       
  1245                 TInt messageKey = KErrNotFound;
       
  1246                 for ( TInt k = 0; k < contents.Count(); ++k ) 
       
  1247                     {
       
  1248                     MNcdConfigurationProtocolContent* content = contents[ k ];
       
  1249 
       
  1250                     if ( content->Key() == KValueSmsAddress ) 
       
  1251                         {
       
  1252                         DLTRACE(( _L("got sms address: %S"), &content->Value() ));                            
       
  1253                         addressKey = k;
       
  1254                         }
       
  1255                     else if ( content->Key() == KValueSmsMessage ) 
       
  1256                         {
       
  1257                         DLTRACE(( _L("got sms message: %S"), &content->Value() ));    
       
  1258                         messageKey = k;
       
  1259                         }
       
  1260                     }
       
  1261 
       
  1262                 if ( addressKey != KErrNotFound &&
       
  1263                      messageKey != KErrNotFound )
       
  1264                     {
       
  1265                     iSmsRegistrationRequest = CNcdKeyValuePair::NewL(
       
  1266                         contents[ addressKey ]->Value(),
       
  1267                         contents[ messageKey ]->Value() );
       
  1268                     DLTRACE(("sms address and messager ok"));    
       
  1269                         
       
  1270                     // both values are now set, create query
       
  1271                     CNcdConfigurationProtocolQueryImpl* cpQuery = 
       
  1272                         CNcdConfigurationProtocolQueryImpl::NewLC();
       
  1273 
       
  1274                     cpQuery->iTitle->SetDataL( aData->Title().Data() );
       
  1275                     cpQuery->iTitle->SetKeyL( aData->Title().Key() );
       
  1276                     cpQuery->iBodyText->SetDataL( aData->BodyText().Data() );
       
  1277                     cpQuery->iBodyText->SetKeyL( aData->BodyText().Key() );
       
  1278                     cpQuery->iSemantics = MNcdQuery::ESemanticsRegistrationQuery;
       
  1279                     if ( iPurchaseQuery )
       
  1280                         {
       
  1281                         iPurchaseQuery->InternalRelease();
       
  1282                         iPurchaseQuery = NULL;
       
  1283                         }
       
  1284                     iPurchaseQuery  = CNcdQuery::NewL( *cpQuery );
       
  1285 
       
  1286                     CleanupStack::PopAndDestroy( cpQuery );
       
  1287                     cpQuery = NULL;
       
  1288                     
       
  1289                     // Canceling resendAfter timer since there's no point
       
  1290                     // sending a request until the query has been handled
       
  1291                     DeletePtr( iDelay );
       
  1292                     CNcdBaseOperation::QueryReceivedL( iPurchaseQuery );
       
  1293 
       
  1294                     DLTRACE(("created sms registration request ok"));    
       
  1295                     break;
       
  1296                     }
       
  1297                 else 
       
  1298                     {
       
  1299                     DLTRACE(("incomplete"));    
       
  1300                     break;
       
  1301                     }
       
  1302                 }
       
  1303             }
       
  1304         ); // TRAPD 
       
  1305         CleanupStack::PopAndDestroy( aData );
       
  1306         if( err != KErrNone )
       
  1307             {
       
  1308             iPurchaseOperationState = EFailed;
       
  1309             iError = err;
       
  1310             Cancel();
       
  1311             RunOperation();            
       
  1312             return;
       
  1313             }
       
  1314         }
       
  1315     else
       
  1316         {
       
  1317         CNcdBaseOperation::QueryL(aData);
       
  1318         }
       
  1319     DLTRACEOUT((""));
       
  1320     }
       
  1321 
       
  1322 
       
  1323 void CNcdPurchaseOperationImpl::ProcessSmsPaymentL()
       
  1324     {
       
  1325     // Create a SMS for every SMS details received from the server.
       
  1326     for( TInt i = 0; i < iSelectedPaymentMethod->SmsDetailsCount(); i++ )
       
  1327 	    {
       
  1328 	    const MNcdPreminetProtocolSmsDetails* smsDetails = 
       
  1329 	        &iSelectedPaymentMethod->SmsDetailsL( i );
       
  1330 	    
       
  1331         // Store ongoing SMS operations to the array. They are removed in the 
       
  1332         // HandleSmsEvent callback.
       
  1333         iPendingSmsOperations.AppendL( 
       
  1334 	    	iSmsSession->CreateSmsL( smsDetails->Address(),
       
  1335 	    				             smsDetails->Message(),
       
  1336                                      this ) );
       
  1337 	    }
       
  1338     }
       
  1339 
       
  1340 
       
  1341 TInt CNcdPurchaseOperationImpl::HandleSmsEvent(
       
  1342 	MCatalogsSmsOperation& aOperation, 
       
  1343 	TCatalogsSmsEvent aEvent )
       
  1344 	{
       
  1345     DLTRACEIN(("sms event: %d", aEvent));
       
  1346     
       
  1347     if ( iOperationState == EStateCancelled )
       
  1348         {
       
  1349         // If cancellation is originating from this operation let's
       
  1350         // not call runoperation with state EFailed as it calls the
       
  1351         // cancel again.
       
  1352         // Notice also that the runoperation is not called and therefore
       
  1353         // no observers are called in there. If necessary this has to
       
  1354         // be done in the cancel.
       
  1355         // No sms operation removal is done here. It is done in cancel.
       
  1356         return KErrNone;
       
  1357         }
       
  1358     
       
  1359 	switch ( aEvent )
       
  1360 	    {
       
  1361 	    case ECatalogsSmsSent:
       
  1362 	        {
       
  1363             // Remove completed SMS operation
       
  1364             RemovePendingSmsOp( aOperation.OperationId() );
       
  1365         	break;    
       
  1366 	        }
       
  1367 	    case ECatalogsSmsSending:
       
  1368 	        {
       
  1369 	        // Nothing to do
       
  1370 	        break;
       
  1371 	        }
       
  1372 	        
       
  1373 	    // Cancel here is a cancel that is not originating from 
       
  1374 	    // this operation.
       
  1375 	    // This is highly improbable, but the handling is here if anyone
       
  1376 	    // would ever do such an implementation.	    
       
  1377 	    case ECatalogsSmsCancelled: // Flow through
       
  1378 	    case ECatalogsSmsSendingFailed:
       
  1379 	        {
       
  1380             // Remove SMS operation
       
  1381         	RemovePendingSmsOp( aOperation.OperationId() );
       
  1382 	        iPurchaseOperationState = EFailed;
       
  1383 	        iError = KErrGsmSMSShortMessageTransferRejected;
       
  1384             break;
       
  1385 	        }
       
  1386         default:
       
  1387             {
       
  1388             break;
       
  1389             }
       
  1390 	    }
       
  1391 	
       
  1392     // All SMS operations have been completed. Continue purchase process.
       
  1393     if( iPendingSmsOperations.Count() == 0 )
       
  1394 	    {
       
  1395 	    if ( iSmsRegistrationRequest ) 
       
  1396 	        {	        
       
  1397 	        // If the operation is already in failed state, let's not change
       
  1398 	        // the state.
       
  1399 	        if ( iPurchaseOperationState != EFailed )
       
  1400                 {
       
  1401     	        iPurchaseOperationState = EBegin;
       
  1402                 }
       
  1403     	    
       
  1404     	    delete iSmsRegistrationRequest;
       
  1405     	    iSmsRegistrationRequest = NULL;
       
  1406     	    
       
  1407     	    if ( iResendAfter != KResendAfterDisabled ) 
       
  1408     	        {
       
  1409     	        StartResendAfterTimer();
       
  1410     	        // we don't want to call RunOperation now
       
  1411     	        return KErrNone;
       
  1412     	        }
       
  1413 	        }
       
  1414         else 
       
  1415             {
       
  1416             // If the operation is already in failed state, let's not change
       
  1417 	        // the state.
       
  1418 	        if ( iPurchaseOperationState != EFailed )
       
  1419                 {
       
  1420     	        iPurchaseOperationState = EPaymentProcessed;
       
  1421                 }
       
  1422             }
       
  1423         // continue operation
       
  1424         RunOperation();
       
  1425         }
       
  1426         
       
  1427         
       
  1428 	DLTRACEOUT((""));
       
  1429 	return KErrNone;
       
  1430 	}
       
  1431 
       
  1432 
       
  1433 
       
  1434 void CNcdPurchaseOperationImpl::UpdatePurchaseHistoryL()
       
  1435     {
       
  1436     DLTRACEIN((""));
       
  1437     // Create purchase details and fill necessary information to it.
       
  1438     CNcdPurchaseDetails* purchaseDetails = CNcdPurchaseDetails::NewLC();
       
  1439     
       
  1440     // Fill purchase info
       
  1441 
       
  1442     purchaseDetails->SetClientUid( iNode->NodeLinkL().MetaDataIdentifier().ClientUid() );
       
  1443     purchaseDetails->SetNamespaceL( iNode->NodeLinkL().MetaDataIdentifier().NodeNameSpace() );
       
  1444     purchaseDetails->SetEntityIdL( iNode->NodeLinkL().MetaDataIdentifier().NodeId() );
       
  1445     purchaseDetails->SetItemNameL( iNode->NodeMetaDataL().NodeName() );
       
  1446     
       
  1447     purchaseDetails->SetCatalogSourceNameL( iNode->NodeLinkL().CatalogsSourceName() );
       
  1448     purchaseDetails->SetPurchaseOptionIdL( iSelectedPurchaseOption->Id() );
       
  1449     purchaseDetails->SetServerUriL( iNode->NodeLinkL().ServerUri() );
       
  1450     purchaseDetails->SetItemType( MNcdPurchaseDetails::EItem ); // Should set this from node!
       
  1451     
       
  1452     TRAPD( err, SetContentInfoToPurchaseDetailsL( 
       
  1453         *purchaseDetails, iNode->NodeMetaDataL() ) );
       
  1454     
       
  1455     LeaveIfNotErrorL( err, KErrNotFound );
       
  1456          
       
  1457     
       
  1458     if( iNode->ClassId() == NcdNodeClassIds::ENcdSearchItemNodeClassId )
       
  1459         {
       
  1460         // this is a search node, get the origin id from parent node
       
  1461         CNcdSearchNodeFolder& searchFolder = iNodeManager->SearchFolderL(
       
  1462             iNode->NodeLinkL().ParentIdentifier() );
       
  1463         // NOTE: This sets some parent node's origin id as origin id.
       
  1464         // This is ok as the origin id is used only for retrieving the correct
       
  1465         // acccess point and ap:s are set only for catalogs/folders. Thus using 
       
  1466         // a parent catalog's/folder's origin id will result in correct results.
       
  1467         DLTRACE((_L("Search node, set origin node id from parent, resulting id=: %S"),
       
  1468             &searchFolder.OriginIdentifierL().NodeId() ));
       
  1469         purchaseDetails->SetOriginNodeIdL( searchFolder.OriginIdentifierL().NodeId() );
       
  1470         }
       
  1471     else
       
  1472         {
       
  1473         // this is a normal node, use it's id directly
       
  1474         DLTRACE((_L("Normal node use own id as origin node id=: %S"),
       
  1475             &iNode->Identifier().NodeId() ));
       
  1476         DLTRACE((_L("iNodeIdentifier=: %S"),
       
  1477             &iNodeIdentifier->NodeId() ));
       
  1478         purchaseDetails->SetOriginNodeIdL( iNode->Identifier().NodeId() );
       
  1479         }
       
  1480 
       
  1481     DLINFO(("Node info set."));
       
  1482     
       
  1483     TRAP_IGNORE( HandleDependenciesL( *purchaseDetails ) );
       
  1484     
       
  1485     DLINFO(("Dependencies handled"));
       
  1486     
       
  1487             
       
  1488     CNcdPurchaseDownloadInfo* downloadInfo( NULL );
       
  1489         
       
  1490     TInt count( 0 );
       
  1491     if( !iSelectedPurchaseOption->IsFree() ||
       
  1492         iSelectedPurchaseOption->RequirePurchaseProcess() ||
       
  1493         iSelectedPurchaseOption->DownloadInfoCount() < 1 )
       
  1494         {
       
  1495         DLINFO(("Setting download details according to info received."));
       
  1496         
       
  1497         count = iPurchaseProcessedData->EntityL( 0 ).DownloadDetailsCount();
       
  1498         for( TInt i = 0; i < count; i++ )
       
  1499             {
       
  1500             downloadInfo = 
       
  1501                 CNcdDownloadInfo::NewLC( 
       
  1502                     iPurchaseProcessedData->EntityL( 0 ).DownloadDetailsL( i ) );
       
  1503             purchaseDetails->AddDownloadInfoL( downloadInfo );           
       
  1504             CleanupStack::Pop( downloadInfo );
       
  1505             }
       
  1506             
       
  1507         // Only the price of one item is needed so it has to be taken from purchase option.
       
  1508         // Total price of iPurchaseInformationData is a price of a group of items if
       
  1509         // such a group is bought.
       
  1510         purchaseDetails->SetFinalPriceL( iSelectedPurchaseOption->PriceText() );
       
  1511         }
       
  1512     else
       
  1513         {
       
  1514         DLINFO(("Setting download details according to purchase option."));
       
  1515         
       
  1516         count = iSelectedPurchaseOption->DownloadInfoCount();
       
  1517         for( TInt i = 0; i < count; i++ )
       
  1518             {
       
  1519             downloadInfo = 
       
  1520                 CNcdPurchaseDownloadInfo::NewLC( 
       
  1521                     iSelectedPurchaseOption->DownloadInfo( i ) );            
       
  1522             purchaseDetails->AddDownloadInfoL( downloadInfo );            
       
  1523             CleanupStack::Pop( downloadInfo );
       
  1524             }
       
  1525         purchaseDetails->SetFinalPriceL( iSelectedPurchaseOption->PriceText() );
       
  1526         }
       
  1527     DLINFO(("Download details set."));
       
  1528 
       
  1529     // Add the correct number of empty file paths
       
  1530     for ( TInt i = 0; i < purchaseDetails->DownloadInfoCount(); ++i ) 
       
  1531         {
       
  1532         purchaseDetails->AddDownloadedFileL( KNullDesC );
       
  1533         }
       
  1534 
       
  1535     purchaseDetails->SetDescriptionL( iNode->NodeMetaDataL().Description() );
       
  1536     DLINFO(("Description set."));
       
  1537     purchaseDetails->SetPurchaseOptionNameL( iSelectedPurchaseOption->PurchaseOptionName() );
       
  1538     purchaseDetails->SetPurchaseOptionPriceL( iSelectedPurchaseOption->PriceText() );
       
  1539     DLINFO(("Purchase option info set."));
       
  1540     
       
  1541     // Set the purchase time. Note that this is universal time, not local time.
       
  1542     // This helps in syncing the purchase history with pc client front end.
       
  1543     // UI must convert this to local time before showing it.
       
  1544     TTime time;
       
  1545     time.UniversalTime();
       
  1546     purchaseDetails->SetPurchaseTime( time );
       
  1547     DLINFO(("Purchase time set."));
       
  1548     
       
  1549    
       
  1550     // If icon can not be found, set null. Done because at the moment
       
  1551     // we don't have icons for all items.
       
  1552     HBufC8* iconData( NULL );
       
  1553     TRAP_IGNORE( iconData = iNode->NodeMetaDataL().IconL().IconDataL() );
       
  1554     
       
  1555     if ( iconData ) 
       
  1556         {        
       
  1557         purchaseDetails->SetIcon( iconData );
       
  1558     
       
  1559         DLINFO(("Icon set."));
       
  1560         }
       
  1561     
       
  1562     purchaseDetails->SetLastUniversalOperationTime();
       
  1563     purchaseDetails->SetLastOperationErrorCode( KErrNone );    
       
  1564     
       
  1565     // Save it to the purchase history
       
  1566     iPurchaseHistory->SavePurchaseL( *purchaseDetails );
       
  1567     
       
  1568     CleanupStack::PopAndDestroy( purchaseDetails );
       
  1569     DLTRACEOUT((""));
       
  1570     }
       
  1571 
       
  1572 
       
  1573 void CNcdPurchaseOperationImpl::SetContentInfoToPurchaseDetailsL( 
       
  1574     CNcdPurchaseDetails& aDetails, 
       
  1575     const CNcdNodeMetaData& aMetadata ) const
       
  1576     {
       
  1577     DLTRACEIN((""));
       
  1578     const CNcdNodeContentInfo& info( aMetadata.ContentInfoL() );
       
  1579         
       
  1580     aDetails.SetTotalContentSize( info.TotalContentSize() );
       
  1581     aDetails.SetVersionL( info.Version() );
       
  1582     aDetails.SetItemPurpose( info.Purpose() );  
       
  1583     aDetails.SetAttributeL( 
       
  1584         MNcdPurchaseDetails::EPurchaseAttributeContentUid, 
       
  1585         info.Uid().iUid );
       
  1586 
       
  1587     aDetails.SetAttributeL( 
       
  1588         MNcdPurchaseDetails::EPurchaseAttributeContentMimeType, 
       
  1589         info.MimeType() );
       
  1590     
       
  1591     }
       
  1592 
       
  1593 
       
  1594 void CNcdPurchaseOperationImpl::HandleDependenciesL( 
       
  1595     CNcdPurchaseDetails& aDetails )
       
  1596     {
       
  1597     DLTRACEIN((""));
       
  1598     CNcdNodeMetaData& metadata( iNode->NodeMetaDataL() );
       
  1599     
       
  1600     const CNcdNodeDependency& dep( metadata.DependencyL() );
       
  1601     AddDownloadInfosToDetailsL( aDetails, dep.ContentTargets() );
       
  1602     DLTRACEOUT(("Dependencies handled successfully"));
       
  1603     }
       
  1604 
       
  1605 
       
  1606 void CNcdPurchaseOperationImpl::AddDownloadInfosToDetailsL( 
       
  1607     CNcdPurchaseDetails& aDetails, 
       
  1608     const RPointerArray<CNcdDownloadInfo>& aInfos )
       
  1609     {
       
  1610     DLTRACEIN((""));
       
  1611     CNcdPurchaseDownloadInfo* downloadInfo( NULL );
       
  1612     CNcdPurchaseInstallInfo* installInfo( NULL );
       
  1613     for( TInt i = 0; i < aInfos.Count(); i++ )
       
  1614         {
       
  1615         downloadInfo = 
       
  1616             CNcdPurchaseDownloadInfo::NewLC( 
       
  1617                 *aInfos[ i ] );
       
  1618         aDetails.AddDownloadInfoL( downloadInfo );           
       
  1619         CleanupStack::Pop( downloadInfo );        
       
  1620         
       
  1621         DLTRACE(( _L("Adding install info, uid: %x, version: %S"), 
       
  1622             aInfos[i]->ContentId(), &aInfos[i]->ContentVersion() ));
       
  1623             
       
  1624         installInfo = CNcdPurchaseInstallInfo::NewLC();
       
  1625         installInfo->SetApplicationUid( aInfos[i]->ContentId() );
       
  1626         installInfo->SetApplicationVersionL( aInfos[i]->ContentVersion() );
       
  1627         aDetails.AddInstallInfoL( installInfo );
       
  1628         CleanupStack::Pop( installInfo );
       
  1629         }
       
  1630     DLTRACEOUT(("Download infos added successfully"));
       
  1631     }
       
  1632 
       
  1633 
       
  1634 TInt CNcdPurchaseOperationImpl::RemovePendingSmsOp(
       
  1635     const TCatalogsTransportOperationId& aId )
       
  1636     {
       
  1637 	for( TInt i = 0; i < iPendingSmsOperations.Count(); i++ )
       
  1638 	    {
       
  1639 	    if( iPendingSmsOperations[i]->OperationId() == aId )
       
  1640 	        {
       
  1641     	    iPendingSmsOperations[i]->Release();
       
  1642 	        iPendingSmsOperations.Remove( i );
       
  1643 	        return KErrNone;
       
  1644 	        }
       
  1645 	    }
       
  1646 	return KErrNotFound;
       
  1647     }
       
  1648 
       
  1649 TBool CNcdPurchaseOperationImpl::QueryCompletedL( CNcdQuery* aQuery )
       
  1650     {
       
  1651     DLTRACEIN((""));
       
  1652     DLINFO(("query response: %d", aQuery->Response() ));
       
  1653     TBool handled = EFalse;
       
  1654     aQuery->InternalAddRef();
       
  1655     CleanupInternalReleasePushL( *aQuery );
       
  1656     
       
  1657     if( iPurchaseQuery && iPurchaseQuery == aQuery )
       
  1658         {
       
  1659         // this is a purchase query (i.e. initiated directly from purchase op)
       
  1660         if( iPurchaseOperationState == EPurchaseComplete )
       
  1661             {
       
  1662             // Operation is already complete.
       
  1663             // This is needed for purchase information, which is sent last 
       
  1664             // just before completing the operation.
       
  1665             iPurchaseQuery->InternalRelease();
       
  1666             iPurchaseQuery = NULL;
       
  1667             }
       
  1668         else if ( aQuery->Semantics() == MNcdQuery::ESemanticsRegistrationQuery &&
       
  1669                     iSmsRegistrationRequest ) 
       
  1670             {
       
  1671             if ( aQuery->Response() == MNcdQuery::EAccepted ) 
       
  1672                 {
       
  1673                 iPendingSmsOperations.AppendL( 
       
  1674         	    	iSmsSession->CreateSmsL( iSmsRegistrationRequest->Key(),
       
  1675         	    				             iSmsRegistrationRequest->Value(),
       
  1676                                              this ) );
       
  1677                 }
       
  1678             else 
       
  1679                 {
       
  1680                 delete iSmsRegistrationRequest;
       
  1681                 iSmsRegistrationRequest = 0;
       
  1682                 }
       
  1683             // query is now handled, release it
       
  1684             iPurchaseQuery->InternalRelease();
       
  1685             iPurchaseQuery = NULL;
       
  1686             }
       
  1687         // in the rest of the cases the query must not be rejected or op will fail
       
  1688         else if ( aQuery->Response() == MNcdQuery::ERejected )
       
  1689             {
       
  1690             DLTRACE(("Query rejected -> fail operation"));
       
  1691             iError = KNcdErrorMandatoryQueryRejected;
       
  1692             iPurchaseOperationState = EFailed;
       
  1693             // query is now handled, release it
       
  1694             iPurchaseQuery->InternalRelease();
       
  1695             iPurchaseQuery = NULL;
       
  1696             User::Leave( KNcdErrorMandatoryQueryRejected );
       
  1697             }
       
  1698         else if( aQuery->Id() == KQueryIdPaymentMethod )
       
  1699             {
       
  1700             CNcdQuerySelectionItem* item = static_cast<CNcdQuerySelectionItem*>( &aQuery->QueryItemL( 0 ) );
       
  1701             iSelectedPaymentMethod = &iPurchaseInformationData->PaymentL( item->Selection() );
       
  1702             // query is now handled, release it
       
  1703             iPurchaseQuery->InternalRelease();
       
  1704             iPurchaseQuery = NULL;
       
  1705             }
       
  1706         else if ( aQuery->Semantics() == MNcdQuery::ESemanticsDisclaimer )
       
  1707             {
       
  1708             // disclaimer does not require a response
       
  1709             // query is now handled, release it
       
  1710             iPurchaseQuery->InternalRelease();
       
  1711             iPurchaseQuery = NULL;
       
  1712             }
       
  1713         else
       
  1714             {
       
  1715             // payment info query, don't release, response needs to be added to
       
  1716             // confirmation request
       
  1717             }
       
  1718         handled = ETrue;
       
  1719         }
       
  1720     CleanupStack::PopAndDestroy( aQuery );
       
  1721     return handled;
       
  1722     }
       
  1723 
       
  1724 TInt CNcdPurchaseOperationImpl::ResendAfterCallBack( TAny* aOperation ) 
       
  1725     {
       
  1726     DLTRACEIN((""));
       
  1727     CNcdPurchaseOperationImpl* purchaseOp = static_cast<CNcdPurchaseOperationImpl*>( aOperation );
       
  1728     purchaseOp->iLocked = EFalse;
       
  1729     purchaseOp->iResendAfter = KResendAfterDisabled;
       
  1730     return purchaseOp->RunOperation();
       
  1731     }
       
  1732 
       
  1733 
       
  1734 TInt CNcdPurchaseOperationImpl::StartResendAfterTimer()
       
  1735     {
       
  1736     DLTRACEIN((""));
       
  1737     TCallBack cb( ResendAfterCallBack, this );
       
  1738     delete iDelay;
       
  1739     iDelay = NULL;
       
  1740     
       
  1741     TRAPD( err, iDelay = CNcdDelay::NewL( cb ) );
       
  1742     if ( err == KErrNone ) 
       
  1743         {
       
  1744         iDelay->After( iResendAfter * 1000000 );
       
  1745         iLocked = ETrue;
       
  1746         }
       
  1747     else
       
  1748         {
       
  1749         iPurchaseOperationState = EFailed;
       
  1750         iError = err;
       
  1751         Cancel();
       
  1752         RunOperation();
       
  1753         }
       
  1754     
       
  1755     return err;
       
  1756     }