xdmprotocols/XcapProtocol/XcapOperations/src/XcapHttpOperation.cpp
branchRCL_3
changeset 17 2669f8761a99
parent 16 2580314736af
child 18 fbd2e7cec7ef
equal deleted inserted replaced
16:2580314736af 17:2669f8761a99
     1 /*
       
     2 * Copyright (c) 2005 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:   CXcapHttpOperation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <XdmErrors.h>
       
    21 #include <escapeutils.h>
       
    22 #include "XcapDocument.h"
       
    23 #include "XcapProtocol.h"
       
    24 #include "XcapAppUsage.h"
       
    25 #include "XcapUriParser.h"
       
    26 #include "XdmXmlParser.h"
       
    27 #include "XcapHttpRequest.h"
       
    28 #include "XdmNodeAttribute.h"
       
    29 #include "XcapEngineDefines.h"
       
    30 #include "XcapHttpOperation.h"
       
    31 #include "XcapHttpContSupplier.h"
       
    32 #include "XcapOperationFactory.h"
       
    33 
       
    34 // ---------------------------------------------------------
       
    35 // C++ constructor can NOT contain any code, that
       
    36 // might leave.
       
    37 // ---------------------------------------------------------
       
    38 //
       
    39 CXcapHttpOperation::CXcapHttpOperation( const CXdmDocument& aTargetDoc,
       
    40                                         CXcapDocumentNode* aDocumentSubset,
       
    41                                         CXcapOperationFactory& aOperationFactory ) :
       
    42                                         CActive( EPriorityStandard ),
       
    43                                         iDocumentSubset( aDocumentSubset ),
       
    44                                         iTargetDoc( ( CXcapDocument& )aTargetDoc ),
       
    45                                         iOperationFactory( aOperationFactory ) 
       
    46                                                                                 
       
    47     {
       
    48     }
       
    49 
       
    50 // ---------------------------------------------------------
       
    51 // CXcapHttpOperation::BaseConstructL
       
    52 //
       
    53 // ---------------------------------------------------------
       
    54 //
       
    55 void CXcapHttpOperation::BaseConstructL()
       
    56     {
       
    57     #ifdef _DEBUG
       
    58         iOperationFactory.WriteToLog( _L8( "-> CXcapHttpOperation::BaseConstructL" ) ); 
       
    59     #endif
       
    60     iXmlParser = &iTargetDoc.Protocol().Parser();
       
    61     iUriParser = CXcapUriParser::NewL( iTargetDoc, iOperationFactory );
       
    62     #ifdef _DEBUG
       
    63         TPtrC8 contType( iTargetDoc.ApplicationUsage().ContentType() );
       
    64         iOperationFactory.WriteToLog( _L8( " Content-Type: %S" ), &contType ); 
       
    65     #endif
       
    66     CActiveScheduler::Add( this );
       
    67     #ifdef _DEBUG
       
    68         iOperationFactory.WriteToLog( _L8( "<- CXcapHttpOperation::BaseConstructL" ) ); 
       
    69     #endif
       
    70     }
       
    71 
       
    72 // ---------------------------------------------------------
       
    73 // Destructor
       
    74 //
       
    75 // ---------------------------------------------------------
       
    76 //
       
    77 CXcapHttpOperation::~CXcapHttpOperation()
       
    78     {
       
    79     #ifdef _DEBUG
       
    80         iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::~CXcapHttpOperation()" ) );  
       
    81     #endif
       
    82     delete iUriParser;
       
    83     iRequestQueue.ResetAndDestroy();
       
    84     }
       
    85 
       
    86 // ---------------------------------------------------------
       
    87 // CXcapOperationBase::IsCompleted
       
    88 //
       
    89 // ---------------------------------------------------------
       
    90 //
       
    91 TBool CXcapHttpOperation::IsCompleted() const
       
    92     {
       
    93     #ifdef _DEBUG
       
    94         iOperationFactory.WriteToLog( _L8( "CXcapOperationBase::IsCompleted()" ) );  
       
    95     #endif
       
    96     return iCompleted;
       
    97     }
       
    98     
       
    99 // ---------------------------------------------------------
       
   100 // CXcapOperationBase::CompletionData
       
   101 //
       
   102 // ---------------------------------------------------------
       
   103 //
       
   104 const TXdmCompletionData& CXcapHttpOperation::CompletionData() const
       
   105     {
       
   106     return *iRequestData;
       
   107     }
       
   108 
       
   109 // ---------------------------------------------------------
       
   110 // CXcapOperationBase::CompletionData
       
   111 //
       
   112 // ---------------------------------------------------------
       
   113 //
       
   114 CXdmDocumentNode* CXcapHttpOperation::TargetNode() const
       
   115     {
       
   116     return iDocumentSubset;
       
   117     }
       
   118     
       
   119 // ---------------------------------------------------------
       
   120 // CXcapOperationBase::CompletionData
       
   121 //
       
   122 // ---------------------------------------------------------
       
   123 //
       
   124 void CXcapHttpOperation::Destroy()
       
   125     {
       
   126     delete this;
       
   127     }
       
   128     
       
   129 // ---------------------------------------------------------
       
   130 // CXcapHttpOperation::Result
       
   131 //
       
   132 // ---------------------------------------------------------
       
   133 //
       
   134 TInt CXcapHttpOperation::Result() const
       
   135     {
       
   136     #ifdef _DEBUG
       
   137         iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::Result()" ) );  
       
   138     #endif
       
   139     return iRequestData != NULL ? iRequestData->iHttpStatus : KErrUnknown;
       
   140     }
       
   141 
       
   142 // ---------------------------------------------------------
       
   143 // CXcapHttpOperation::ExecuteL
       
   144 //
       
   145 // ---------------------------------------------------------
       
   146 //
       
   147 void CXcapHttpOperation::ExecuteL( TRequestStatus& aStatus, TUint aOptions )
       
   148     {
       
   149     #ifdef _DEBUG
       
   150         iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::ExecuteL( &status )" ) );  
       
   151     #endif
       
   152     iOptionFlags = aOptions;
       
   153     iClientStatus = &aStatus;
       
   154     aStatus = KRequestPending;
       
   155     if( !IsActive() )
       
   156         {
       
   157         iActiveRequest = iRequestQueue[iCurrentIndex];
       
   158         TRAPD( error, ExecuteL() );
       
   159         if( error == KErrNone )
       
   160             {
       
   161             if( StartOperationL() )
       
   162                 SetActive();
       
   163             else
       
   164                 {
       
   165                 iFailureData.iCompletion = KXcapErrorNetworkNotAvailabe;
       
   166                 User::RequestComplete( iClientStatus, KXcapErrorNetworkNotAvailabe );
       
   167                 iRequestData = &iFailureData;
       
   168                 }      
       
   169             }
       
   170         else
       
   171             {
       
   172             #ifdef _DEBUG
       
   173                 iOperationFactory.WriteToLog( _L8( " Execution failed with %d" ), error );  
       
   174             #endif
       
   175             iFailureData.iCompletion = error;
       
   176             User::RequestComplete( iClientStatus, error );
       
   177             iRequestData = &iFailureData;
       
   178             }
       
   179         }
       
   180     else  //This is a re-run of a previously failed request
       
   181         {
       
   182         if( !StartOperationL() )
       
   183             {
       
   184             #ifdef _DEBUG
       
   185                 iOperationFactory.WriteToLog( _L8( " Execution succeeded, network not ready" ) );  
       
   186             #endif
       
   187             User::RequestComplete( iClientStatus, KXcapErrorNetworkNotAvailabe );
       
   188             }
       
   189         }  
       
   190     }
       
   191 
       
   192 // ---------------------------------------------------------
       
   193 // CXcapHttpOperation::ExecuteL
       
   194 //       
       
   195 // ---------------------------------------------------------
       
   196 //
       
   197 void CXcapHttpOperation::ExecuteL( CXcapHttpRequest* aHttpRequest,
       
   198                                    CXdmDocumentNode* aDocumentNode )
       
   199     {
       
   200     #ifdef _DEBUG
       
   201         iOperationFactory.WriteToLog( _L8( "CXcapAddition::ExecuteL()" ) );  
       
   202     #endif
       
   203     CXdmDocumentNode* node = aDocumentNode == NULL ?
       
   204                              iTargetDoc.DocumentRoot() : aDocumentNode;
       
   205     __ASSERT_ALWAYS( node != NULL, User::Panic( _L( "CXcapAddition" ), 1 ) );
       
   206     User::LeaveIfError( FormatModRequestL( node ) );
       
   207     TRAPD( error, iUriParser->ParseL( aHttpRequest->RequestUriL() ) );
       
   208     if( error == KErrNone )
       
   209         {
       
   210         TPtrC8 uri = iUriParser->DesC8();
       
   211         HBufC8* escape = CXcapHttpOperation::EscapeLC( uri );
       
   212         aHttpRequest->UpdateRequestUriL( escape->Des() );
       
   213         CleanupStack::PopAndDestroy();  //escape
       
   214         }
       
   215     }
       
   216     
       
   217 // ---------------------------------------------------------
       
   218 // CXcapHttpOperation::StartOperationL
       
   219 //
       
   220 // ---------------------------------------------------------
       
   221 //
       
   222 TBool CXcapHttpOperation::StartOperationL()
       
   223     {
       
   224     #ifdef _DEBUG
       
   225         iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::StartOperationL()" ) );  
       
   226     #endif
       
   227     if( iTargetDoc.Protocol().IsNetworkAvailable() )
       
   228         {
       
   229         #ifdef _DEBUG
       
   230             iOperationFactory.WriteToLog( _L8( " All set, dispatch request to transport" ) );  
       
   231         #endif
       
   232         if( iOptionFlags & KUseIntendedIdentity )
       
   233             {
       
   234             TPtrC8 identity( iTargetDoc.Protocol().PublicID() );
       
   235             #ifdef _DEBUG
       
   236                 iOperationFactory.WriteToLog( _L8( " Early-IMS set, add X-3GPP-Intended-Identity header" ) );
       
   237                 iOperationFactory.WriteToLog( _L8( "  Public ID: %S" ), &identity );  
       
   238             #endif
       
   239             iActiveRequest->SetHeaderL( KHttpHeaderIntIdentity, identity );
       
   240             }
       
   241         iActiveRequest->DispatchRequestL( iStatus );
       
   242         return ETrue;
       
   243         }
       
   244     else return EFalse;
       
   245     }
       
   246     
       
   247 // ---------------------------------------------------------
       
   248 // CXcapHttpOperation::RunL
       
   249 //
       
   250 // ---------------------------------------------------------
       
   251 //
       
   252 void CXcapHttpOperation::RunL()
       
   253     {
       
   254     #ifdef _DEBUG
       
   255         iOperationFactory.WriteToLog( _L8( 
       
   256         "CXcapHttpOperation::RunL() - Status: %d" ), iStatus.Int() );  
       
   257     #endif
       
   258     TInt count = iRequestQueue.Count();
       
   259     iRequestData = iActiveRequest->ResponseData();
       
   260     __ASSERT_DEBUG( iRequestData != NULL, User::Panic( _L( "CXcapHttpOperation" ), 1 ) );
       
   261     TRAPD( error, iStatus != KErrNone ? OperationFailedL() : OperationCompleteL() );
       
   262     if( error == KErrNone && !iCompleted )
       
   263         SetActive();
       
   264     else
       
   265         {
       
   266         #ifdef _DEBUG
       
   267             iOperationFactory.WriteToLog( _L8( 
       
   268                 "  ** Operation completed - Result: %d  Error: %d **" ), iResult, error );  
       
   269         #endif
       
   270         iCurrentIndex = 0;
       
   271         iResult = error < KErrNone ? error : iResult;
       
   272         iRequestData->iCompletion = iResult;
       
   273         User::RequestComplete( iClientStatus, iResult );
       
   274         }
       
   275     }
       
   276 
       
   277 // ---------------------------------------------------------
       
   278 // CXcapRetrieval::CancelOperation
       
   279 //
       
   280 // ---------------------------------------------------------
       
   281 //
       
   282 void CXcapHttpOperation::CancelOperation()
       
   283     {
       
   284     #ifdef _DEBUG
       
   285         iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::CancelOperation()" ) );  
       
   286     #endif
       
   287     if( IsActive() )
       
   288         {
       
   289         #ifdef _DEBUG
       
   290             iOperationFactory.WriteToLog( _L8( "Active, cancel HTTP request" ) );  
       
   291         #endif
       
   292         Cancel();
       
   293         iRequestData = &iFailureData;
       
   294         iFailureData.iCompletion = KErrCancel;
       
   295         User::RequestComplete( iClientStatus, KErrCancel );
       
   296         }
       
   297     }
       
   298     
       
   299 // ---------------------------------------------------------
       
   300 // CXcapHttpOperation::CancelOperation
       
   301 //
       
   302 // ---------------------------------------------------------
       
   303 //
       
   304 void CXcapHttpOperation::DoCancel()
       
   305     {
       
   306     #ifdef _DEBUG
       
   307         iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::DoCancel()" ) );  
       
   308     #endif
       
   309     iRequestQueue[iCurrentIndex]->CancelRequest();   
       
   310     }
       
   311 
       
   312 // ---------------------------------------------------------
       
   313 // CXcapHttpOperation::Descriptor
       
   314 //
       
   315 // ---------------------------------------------------------
       
   316 //
       
   317 TPtrC8 CXcapHttpOperation::Descriptor( HBufC8* aBuffer )
       
   318     {
       
   319     #ifdef _DEBUG
       
   320         iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::Descriptor()" ) );  
       
   321     #endif
       
   322     if( aBuffer != NULL )
       
   323         {
       
   324         TPtrC8 descriptor( aBuffer->Des() );
       
   325         return descriptor.Length() > 0 ? descriptor : TPtrC8();
       
   326         }
       
   327     else
       
   328         {
       
   329         #ifdef _DEBUG
       
   330             iOperationFactory.WriteToLog( _L8( " Buffer is NULL, return empty descriptor" ) );  
       
   331         #endif
       
   332         return TPtrC8();
       
   333         }
       
   334     }
       
   335 
       
   336 // ---------------------------------------------------------
       
   337 // CXcapHttpOperation::Transport
       
   338 //
       
   339 // ---------------------------------------------------------
       
   340 //
       
   341 CXcapHttpTransport& CXcapHttpOperation::Transport() const
       
   342     {
       
   343     return iTargetDoc.Protocol().Transport();
       
   344     }
       
   345     
       
   346 // ---------------------------------------------------------
       
   347 // CXcapHttpOperation::FormatModRequestL
       
   348 //
       
   349 // ---------------------------------------------------------
       
   350 //
       
   351 TInt CXcapHttpOperation::FormatModRequestL( const CXdmDocumentNode* aDocumentNode )
       
   352     {
       
   353     #ifdef _DEBUG
       
   354         iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::FormatModRequestL()" ) );  
       
   355     #endif
       
   356     HBufC8* body = NULL;
       
   357     TInt error = KErrNone;
       
   358     CXcapAppUsage& usage = iTargetDoc.ApplicationUsage();
       
   359     CXcapHttpContSupplier* request = ( CXcapHttpContSupplier* )iActiveRequest;
       
   360     switch( iUriParser->NodeType() )
       
   361         {
       
   362         case EXdmElementAttribute:
       
   363             {
       
   364             CXdmNodeAttribute* attribute = ( CXdmNodeAttribute* )aDocumentNode;
       
   365             body = attribute->EightBitValueLC();
       
   366             request->SetRequestBodyL( body->Des() );
       
   367             CleanupStack::PopAndDestroy();  //body
       
   368             request->SetHeaderL( KHttpHeaderAccept, _L8( "application/xcap-diff+xml" ) );
       
   369             request->SetHeaderL( KHttpHeaderContentType, _L8( "application/xcap-att+xml" ) );
       
   370             }
       
   371             break;
       
   372         case EXdmElementNode:
       
   373             {
       
   374             #ifndef __OVERRIDE_VALIDATION__
       
   375                 error = usage.Validate( CONST_CAST( CXdmDocumentNode&, *aDocumentNode ), iUriParser, EFalse );
       
   376             #endif
       
   377             if( error == KErrNone )
       
   378                 {
       
   379                 #ifdef _DEBUG
       
   380                     iOperationFactory.WriteToLog( _L8( " Validation of a partial document OK" ) );  
       
   381                 #endif
       
   382                 body = iXmlParser->FormatToXmlLC( EFalse, &iTargetDoc, aDocumentNode );
       
   383                 request->SetRequestBodyL( body->Des() );
       
   384                 CleanupStack::PopAndDestroy();  //body
       
   385                 request->SetHeaderL( KHttpHeaderAccept, _L8( "application/xcap-diff+xml" ) );
       
   386                 request->SetHeaderL( KHttpHeaderContentType, _L8( "application/xcap-el+xml" ) );
       
   387                 }
       
   388             else
       
   389                 {
       
   390                 #ifdef _DEBUG
       
   391                     iOperationFactory.WriteToLog( _L8( " Validation failed: %d" ), error );  
       
   392                 #endif
       
   393                 }
       
   394             }
       
   395             break;
       
   396         default:
       
   397         #ifndef __OVERRIDE_VALIDATION__
       
   398             error = usage.Validate( iTargetDoc, ETrue );
       
   399         #endif
       
   400             if( error == KErrNone )
       
   401                 {
       
   402                 #ifdef _DEBUG
       
   403                     iOperationFactory.WriteToLog( _L8( " Validation OK" ) );  
       
   404                 #endif
       
   405                 body = iXmlParser->FormatToXmlLC( ETrue, &iTargetDoc, aDocumentNode );
       
   406                 request->SetRequestBodyL( body->Des() );
       
   407                 CleanupStack::PopAndDestroy();  //body
       
   408                 }
       
   409             else
       
   410                 {
       
   411                 #ifdef _DEBUG
       
   412                     iOperationFactory.WriteToLog( _L8( " Validation failed: %d" ), error );  
       
   413                 #endif
       
   414                 }
       
   415             break;
       
   416         }
       
   417     return error;
       
   418     }
       
   419 
       
   420 // ----------------------------------------------------------
       
   421 // CXcapHttpOperation::ReinterpretStatus
       
   422 // 
       
   423 // ----------------------------------------------------------
       
   424 //
       
   425 TInt CXcapHttpOperation::ReinterpretStatus( const TInt aHttpStatus ) const
       
   426     {
       
   427     #ifdef _DEBUG
       
   428         iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::ReinterpretStatus()" ) );  
       
   429     #endif
       
   430     switch( aHttpStatus )
       
   431         {
       
   432         case 500:  //Internal Server Error
       
   433         case 501:  //Not Implemented
       
   434         case 502:  //Bad Gateway
       
   435         case 503:  //Service Unavailable
       
   436         case 504:  //Gateway Timeout
       
   437         case 505:  //HTTP Version Not Supported
       
   438         case 405:  //Method Not Allowed
       
   439 		case 408:  //Request Timeout
       
   440 		case 410:  //Gone
       
   441 		case 411:  //Length Required
       
   442 		case 413:  //Request Entity Too Large
       
   443 		case 414:  //Request-URI Too Long
       
   444 		case 415:  //Unsupported Media Type
       
   445 		case 416:  //Requested Range Not Satisfiable
       
   446 		case 417:  //Expectation Failed
       
   447             return KXcapErrorHttpServer;
       
   448         case 400:
       
   449             return KXcapErrorHttpBadRequest;
       
   450         case 401:
       
   451             return KXcapErrorHttpUnauthorised;
       
   452         case 403:
       
   453             return KXcapErrorHttpForbidden;
       
   454         case 404:
       
   455             return KXcapErrorHttpNotFound;
       
   456         case 409:
       
   457             return KXcapErrorHttpConflict;
       
   458         case 412:
       
   459             return KXcapErrorHttpPrecondFailed;
       
   460         default:
       
   461             return KErrNone;
       
   462         }
       
   463     }
       
   464 
       
   465 // ---------------------------------------------------------
       
   466 // CXcapHttpOperation::Escape2LC
       
   467 // 
       
   468 // ---------------------------------------------------------
       
   469 //
       
   470 HBufC8* CXcapHttpOperation::Escape2LC( const TDesC& aDescriptor )
       
   471     {
       
   472     HBufC8* eight = EscapeUtils::ConvertFromUnicodeToUtf8L( aDescriptor );
       
   473     CleanupStack::PushL( eight );
       
   474     HBufC8* buf = EscapeUtils::EscapeEncodeL( eight->Des(), EscapeUtils::EEscapeNormal );
       
   475     CleanupStack::PopAndDestroy();  //eight
       
   476     CleanupStack::PushL( buf );
       
   477     return buf;
       
   478     }
       
   479     
       
   480 // ---------------------------------------------------------
       
   481 // CXcapHttpOperation::EscapeLC
       
   482 // 
       
   483 // ---------------------------------------------------------
       
   484 //
       
   485 HBufC8* CXcapHttpOperation::EscapeLC( const TDesC8& aDescriptor )
       
   486     {
       
   487     CBufFlat* buffer = CBufFlat::NewL( 50 );
       
   488     CleanupStack::PushL( buffer );
       
   489     TInt bufPos = 0;
       
   490     TBuf8<10> format;
       
   491     for( TInt i = 0;i < aDescriptor.Length();i++ )
       
   492         {
       
   493         TUint8 byte = aDescriptor[i];
       
   494         if( byte < 0x7F )                 //US-ASCII
       
   495             {
       
   496             switch( byte )
       
   497                 {
       
   498                 case 0x20:                // ' '
       
   499                 case 0x22:                // '"'
       
   500                 case 0x3B:                // ';'                 
       
   501                 case 0x26:                // '&'                  
       
   502                 case 0x3C:                // '<'                  
       
   503                 case 0x3E:                // '>'
       
   504                 case 0x5B:                // '['
       
   505                 case 0x5D:                // ']'                              
       
   506                     format.Append( _L8( "%" ) );
       
   507                     format.AppendFormat( _L8( "%x" ), byte );
       
   508                     break;               
       
   509                 default:
       
   510                     format.Append( byte );
       
   511                     break;
       
   512                 }
       
   513             }
       
   514         else
       
   515             {
       
   516             format.Append( _L8( "%" ) );  //UNICODE
       
   517             format.AppendFormat( _L8( "%x" ), byte );
       
   518             }
       
   519         buffer->InsertL( bufPos, format );
       
   520         bufPos = bufPos + format.Length();
       
   521         format.Zero();
       
   522         }
       
   523     HBufC8* ret = HBufC8::NewL( buffer->Size() );
       
   524     TPtr8 pointer( ret->Des() );
       
   525     buffer->Read( 0, pointer, buffer->Size() );
       
   526     CleanupStack::PopAndDestroy();  //buffer
       
   527     CleanupStack::PushL( ret );
       
   528     return ret;
       
   529     }
       
   530                
       
   531 // ---------------------------------------------------------
       
   532 // CXcapHttpOperation::HttpRequest
       
   533 //
       
   534 // ---------------------------------------------------------
       
   535 //
       
   536 CXcapHttpRequest* CXcapHttpOperation::HttpRequest() const
       
   537     {
       
   538     #ifdef _DEBUG
       
   539         iOperationFactory.WriteToLog( _L8( "CXcapHttpOperation::HttpRequest()" ) );  
       
   540     #endif
       
   541     return iActiveRequest;
       
   542     }
       
   543 
       
   544 
       
   545 
       
   546 //  End of File  
       
   547