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