upnp/upnpstack/serviceframework/src/upnpcontenthandlerscontroller.cpp
changeset 0 f5a58ecadc66
equal deleted inserted replaced
-1:000000000000 0:f5a58ecadc66
       
     1 /** @file
       
     2 * Copyright (c) 2007 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:  CUpnpContentHandlersController
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 #include "upnpcontenthandlerscontroller.h"
       
    20 
       
    21 #include <xml/parser.h>
       
    22 #include <xml/xmlparsererrors.h>
       
    23 #include <xml/matchdata.h>
       
    24 
       
    25 #include "upnpstring.h"
       
    26 #include "upnpservice.h"
       
    27 #include "upnpdevice.h"
       
    28 #include "upnpdeviceimplementation.h"
       
    29 #include "upnpsilentdeviceimplementation.h"
       
    30 
       
    31 #include "upnpserviceliterals.h"
       
    32 #include "upnpdeviceliterals.h"
       
    33 
       
    34 #include "upnpcontenthandler.h"
       
    35 #include "upnpignorecontenthandler.h"
       
    36 #include "upnpsoapcontenthandler.h"
       
    37 #include "upnppropertysetcontenthandler.h"
       
    38 #include "upnpservicecontenthandler.h"
       
    39 #include "upnpdevicecontenthandler.h"
       
    40 
       
    41 using namespace Xml;
       
    42 
       
    43 // CONSTANTS
       
    44 const TUint KUtfLowMax = 0x1F;
       
    45 const TUint KUtfHighMin = 0x7F;
       
    46 const TUint KUtfHighMax = 0xA0;
       
    47 
       
    48 // -----------------------------------------------------------------------------
       
    49 // CUpnpContentHandlersController::~CUpnpContentHandlersController
       
    50 // Destructor
       
    51 // -----------------------------------------------------------------------------
       
    52 //
       
    53 CUpnpContentHandlersController::~CUpnpContentHandlersController()
       
    54     {
       
    55     delete iParser;
       
    56     ASSERT( NULL == iStack || iStack->IsEmpty() );
       
    57     delete iStack;
       
    58     
       
    59     iContent.Close();
       
    60     }
       
    61 
       
    62 // -----------------------------------------------------------------------------
       
    63 // CUpnpContentHandlersController::NewL
       
    64 // Two-phased constructor
       
    65 // -----------------------------------------------------------------------------
       
    66 //
       
    67 EXPORT_C CUpnpContentHandlersController* CUpnpContentHandlersController::NewL()
       
    68     {
       
    69     CUpnpContentHandlersController* controller =
       
    70         CUpnpContentHandlersController::NewLC();    
       
    71     CleanupStack::Pop( controller );
       
    72     return controller;
       
    73     }
       
    74 
       
    75 // -----------------------------------------------------------------------------
       
    76 // CUpnpContentHandlersController::NewLC
       
    77 // Two-phased constructor. Leaves the object on the CleanupStack
       
    78 // -----------------------------------------------------------------------------
       
    79 //
       
    80 EXPORT_C CUpnpContentHandlersController* CUpnpContentHandlersController::NewLC()
       
    81     {
       
    82     CUpnpContentHandlersController* controller =
       
    83         new (ELeave) CUpnpContentHandlersController();
       
    84     CleanupStack::PushL( controller );
       
    85     controller->ConstructL();
       
    86     return controller;
       
    87     }
       
    88 
       
    89 // -----------------------------------------------------------------------------
       
    90 // CleanupResetAndDestroy
       
    91 // Releases array, and object keapt in it.
       
    92 // Used as method passed to TCleanupItem object.
       
    93 // -----------------------------------------------------------------------------
       
    94 //
       
    95 LOCAL_C void CleanupResetAndDestroy(TAny* aRPointerArray)
       
    96     {
       
    97     reinterpret_cast<RPointerArray<CUpnpDescriptionProperty>* >(aRPointerArray)
       
    98         ->ResetAndDestroy();
       
    99     }
       
   100 
       
   101 // -----------------------------------------------------------------------------
       
   102 // CUpnpContentHandlersController::UpdateActionWithOKResponseL
       
   103 // For internal use. Update all necessary information from a SOAP-message
       
   104 // that should be OK answer (e.g. received by Http 200 OK message).
       
   105 // -----------------------------------------------------------------------------
       
   106 //
       
   107 EXPORT_C void CUpnpContentHandlersController::UpdateActionWithOKResponseL(
       
   108     CUpnpSoapMessage* aMessage, CUpnpAction* aAction )
       
   109     {
       
   110     iSoapParser.UpdateActionWithOKResponseL( aMessage, aAction );
       
   111     }
       
   112 
       
   113 // -----------------------------------------------------------------------------
       
   114 // CUpnpContentHandlersController::UpdateActionWithErrorResponseL
       
   115 // For internal use. Update all necessary information from a SOAP-message
       
   116 // that should contain SOAP error (fault) message (eg. received by http
       
   117 // 500 InternalServerError message.
       
   118 // -----------------------------------------------------------------------------
       
   119 //
       
   120 EXPORT_C void CUpnpContentHandlersController::UpdateActionWithErrorResponseL(
       
   121     CUpnpSoapMessage* aMessage, CUpnpAction* aAction )
       
   122     {
       
   123     iSoapParser.UpdateActionWithErrorResponseL( aMessage, aAction );
       
   124     }
       
   125 
       
   126 // -----------------------------------------------------------------------------
       
   127 // CUpnpContentHandlersController::UpdateActionWithRequestL
       
   128 // Update action with all necessary information from
       
   129 // a SOAP request message.
       
   130 // -----------------------------------------------------------------------------
       
   131 //
       
   132 void CUpnpContentHandlersController::UpdateActionWithRequestL(
       
   133     CUpnpSoapMessage* aMessage, CUpnpAction* aAction )
       
   134     {
       
   135     iSoapParser.UpdateActionWithRequestL( aMessage, aAction );
       
   136     }
       
   137 
       
   138 // -----------------------------------------------------------------------------
       
   139 // CUpnpContentHandlersController::AttachL
       
   140 // For internal use. Attaches the information contained in a GENA buffer
       
   141 // to this service. In practice, this means handling of received GENA messages.
       
   142 // -----------------------------------------------------------------------------
       
   143 //
       
   144 EXPORT_C void CUpnpContentHandlersController::AttachL( const TDesC8& aGenaNotify,
       
   145                                                        CUpnpService& aService )
       
   146     {
       
   147     RPointerArray<CUpnpDescriptionProperty> parsedValues;
       
   148     CleanupStack::PushL( TCleanupItem( CleanupResetAndDestroy, &parsedValues ) );
       
   149 
       
   150     TRAPD( parseError, ParseGenaL( aGenaNotify, parsedValues ) );
       
   151     if ( KErrNone != parseError )
       
   152         {
       
   153         User::Leave( KErrGeneral );
       
   154         }
       
   155     for ( TInt i(0); i < parsedValues.Count(); ++i )
       
   156         {
       
   157         CUpnpDescriptionProperty* property = parsedValues[i];
       
   158         aService.SetStateVariableL( property->Name(), UpnpString::Trim( property->Value()) );
       
   159         }
       
   160     CleanupStack::PopAndDestroy( &parsedValues );
       
   161     }
       
   162 
       
   163 // -----------------------------------------------------------------------------
       
   164 // CUpnpContentHandlersController::ParseSoapL
       
   165 // Parses a xml document and returns set objects of CUpnpDescriptionProperties
       
   166 // It is used to parse action messages (soap)
       
   167 // @pre description property array should be leave safe
       
   168 // (there will be PopAndDestroy called on it in case of leave)
       
   169 // -----------------------------------------------------------------------------
       
   170 //
       
   171 void CUpnpContentHandlersController::ParseSoapL(
       
   172         const TDesC8& aDescription,
       
   173         RPointerArray<CUpnpDescriptionProperty>& aParsedValues )
       
   174     {
       
   175     CUpnpSoapContentHandler* soapCH =
       
   176         CUpnpSoapContentHandler::NewL( *this, aParsedValues );
       
   177     iCorrectUri.Set( KSoapNamespaceUri );
       
   178     ParseXmlL( aDescription, soapCH );
       
   179     delete soapCH;
       
   180     }
       
   181 
       
   182 // -----------------------------------------------------------------------------
       
   183 // CUpnpContentHandlersController::ParseParseDescriptionPropertiesL
       
   184 // Parses a xml document and returns set objects of CUpnpDescriptionProperties
       
   185 // It is used to parse event notification
       
   186 // @pre description property array should be leave safe
       
   187 // (there will be PopAndDestroy called on it in case of leave)
       
   188 // -----------------------------------------------------------------------------
       
   189 //
       
   190 void CUpnpContentHandlersController::ParseGenaL(
       
   191         const TDesC8& aDescription,
       
   192         RPointerArray<CUpnpDescriptionProperty>& aParsedValues )
       
   193     {
       
   194     CUpnpPropertysetContentHandler* propsetCH =
       
   195         CUpnpPropertysetContentHandler::NewL( *this, aParsedValues );
       
   196     iCorrectUri.Set( KEventNamespaceUri );
       
   197     ParseXmlL( aDescription, propsetCH );
       
   198     delete propsetCH;
       
   199     }
       
   200 
       
   201 // -----------------------------------------------------------------------------
       
   202 // CUpnpContentHandlersController::ParseServiceL
       
   203 // Parses a xml document and returns object of CUpnpService class
       
   204 // It is used for the first time the xml document is parsed
       
   205 // -----------------------------------------------------------------------------
       
   206 //
       
   207 EXPORT_C CUpnpService* CUpnpContentHandlersController::ParseServiceL(
       
   208         const TDesC8& aDescription, CUpnpDevice* aParentDevice )
       
   209     {
       
   210     CUpnpServiceContentHandler* serviceCH =
       
   211         CUpnpServiceContentHandler::NewL( *this, aParentDevice );
       
   212     iCorrectUri.Set( KServiceNamespaceUri );
       
   213     ParseXmlL( aDescription, serviceCH );
       
   214     CUpnpService* result = serviceCH->ResultService();
       
   215     delete serviceCH;
       
   216     return result;
       
   217     }
       
   218 
       
   219 // -----------------------------------------------------------------------------
       
   220 // CUpnpContentHandlersController::ParseServiceL
       
   221 // Parses an xml document
       
   222 // It is used in case when CUpnpService object already exists
       
   223 // -----------------------------------------------------------------------------
       
   224 //
       
   225 EXPORT_C void CUpnpContentHandlersController::ParseServiceL(
       
   226         const TDesC8& aDescription, CUpnpService* aService )
       
   227     {
       
   228     CUpnpServiceContentHandler* serviceCH =
       
   229         CUpnpServiceContentHandler::NewL( *this, *aService );
       
   230     iCorrectUri.Set( KServiceNamespaceUri );
       
   231     ParseXmlL(aDescription, serviceCH);
       
   232     delete serviceCH;
       
   233     }
       
   234 
       
   235 // -----------------------------------------------------------------------------
       
   236 // CUpnpContentHandlersController::ParseDeviceL
       
   237 // Parses an xml document and returns instance of CUpnpDevice class
       
   238 // It is used for the first time the device xml document is parsed
       
   239 // -----------------------------------------------------------------------------
       
   240 //
       
   241 EXPORT_C CUpnpDevice* CUpnpContentHandlersController::ParseDeviceL(
       
   242     const TDesC8& aDescription )
       
   243     {
       
   244     return DoParseDeviceL( aDescription, (CUpnpDevice*)NULL );
       
   245     }
       
   246 
       
   247 // -----------------------------------------------------------------------------
       
   248 // CUpnpContentHandlersController::ParseDeviceL
       
   249 // Parses an xml document and returns instance of CUpnpDevice class
       
   250 // It is used in case when CUpnpDevice object already exists and update of
       
   251 // device xml is required
       
   252 // -----------------------------------------------------------------------------
       
   253 //
       
   254 EXPORT_C void CUpnpContentHandlersController::ParseDeviceL(
       
   255     const TDesC8& aDescription, CUpnpDevice* aDevice )
       
   256     {
       
   257     ASSERT( NULL != aDevice );
       
   258     DoParseDeviceL( aDescription, aDevice );
       
   259     }
       
   260 
       
   261 template<class T> T* CUpnpContentHandlersController::DoParseDeviceL(
       
   262     const TDesC8& aDescription, T* aDevice )
       
   263     {
       
   264     CUpnpDeviceContentHandler* deviceCH = CUpnpDeviceContentHandler::NewL(
       
   265         *this, aDevice );
       
   266     iCorrectUri.Set( KDeviceNamespaceUri );
       
   267     ParseXmlL( aDescription, deviceCH );
       
   268     T* result(NULL);
       
   269     if ( !aDevice )
       
   270         {
       
   271         deviceCH->GetResultDevice( result );
       
   272         }
       
   273     delete deviceCH;
       
   274     return result;
       
   275     }
       
   276 
       
   277 // -----------------------------------------------------------------------------
       
   278 // CUpnpContentHandlersController::ParseDeviceImplL
       
   279 // Parses an xml document and returns instance of CUpnpDevice class
       
   280 // It is used for the first time the device xml document is parsed
       
   281 // -----------------------------------------------------------------------------
       
   282 //
       
   283 EXPORT_C CUpnpDeviceImplementation* CUpnpContentHandlersController::ParseDeviceImplL(
       
   284     const TDesC8& aDescription )
       
   285     {
       
   286     return DoParseDeviceL( aDescription, (CUpnpDeviceImplementation*)NULL );
       
   287     }
       
   288 
       
   289 // -----------------------------------------------------------------------------
       
   290 // CUpnpContentHandlersController::ParseDeviceImplL
       
   291 // Parses an xml document and returns instance of CUpnpDevice class
       
   292 // It is used in case when CUpnpDeviceImplementation object already exists and
       
   293 // update of device xml is required
       
   294 // -----------------------------------------------------------------------------
       
   295 //
       
   296 EXPORT_C void CUpnpContentHandlersController::ParseDeviceImplL(
       
   297     const TDesC8& aDescription, CUpnpDeviceImplementation* aDeviceImpl )
       
   298     {
       
   299     ASSERT( NULL != aDeviceImpl );
       
   300     DoParseDeviceL( aDescription, aDeviceImpl );
       
   301     }
       
   302 
       
   303 // -----------------------------------------------------------------------------
       
   304 // CUpnpContentHandlersController::ParseSilentDeviceImplL
       
   305 // Parses an xml document and returns instance of CUpnpDevice class
       
   306 // It is used for the first time the device xml document is parsed
       
   307 // -----------------------------------------------------------------------------
       
   308 //
       
   309 EXPORT_C CUpnpSilentDeviceImplementation* CUpnpContentHandlersController::ParseSilentDeviceImplL(
       
   310     const TDesC8& aDescription )
       
   311     {
       
   312     return DoParseDeviceL( aDescription, (CUpnpSilentDeviceImplementation*)NULL );
       
   313     }
       
   314 
       
   315 // -----------------------------------------------------------------------------
       
   316 // CUpnpContentHandlersController::ParseSilentDeviceImplL
       
   317 // Parses an xml document and returns instance of CUpnpDevice class
       
   318 // It is used in case when CUpnpSilentDeviceImplementation object already exists and
       
   319 // update of device xml is required
       
   320 // -----------------------------------------------------------------------------
       
   321 //
       
   322 EXPORT_C void CUpnpContentHandlersController::ParseSilentDeviceImplL(
       
   323     const TDesC8& aDescription, CUpnpSilentDeviceImplementation* aDeviceImpl )
       
   324     {
       
   325     ASSERT( NULL != aDeviceImpl );
       
   326     DoParseDeviceL( aDescription, aDeviceImpl );
       
   327     }
       
   328 
       
   329 // -----------------------------------------------------------------------------
       
   330 // ReleaseHandlersOnStack
       
   331 // Releases all handlers that are on CStack<CUpnpContentHandler, ETrue> object
       
   332 // Used as method passed to TCleanupItem object.
       
   333 // -----------------------------------------------------------------------------
       
   334 //
       
   335 LOCAL_C void ReleaseHandlersOnStack(TAny* aStack)
       
   336     {
       
   337     reinterpret_cast<CStack<CUpnpContentHandler, ETrue>*>(aStack)->Clear();
       
   338     }
       
   339 
       
   340 // -----------------------------------------------------------------------------
       
   341 // CUpnpContentHandlersController::ParseXmlL
       
   342 // Parses a xml document by passed content handler,
       
   343 // there is a guarantee that aHandlerToUse will be deleted in case of leave
       
   344 // precondition: iStack is empty
       
   345 // postcondition: iStack is empty
       
   346 // -----------------------------------------------------------------------------
       
   347 //
       
   348 void CUpnpContentHandlersController::ParseXmlL( const TDesC8& aDescription,
       
   349     CUpnpContentHandler* aHandlerToUse )
       
   350     {
       
   351     ASSERT( iStack->IsEmpty() );
       
   352     iCurrentContentHandler = aHandlerToUse;
       
   353     iStack->PushL( aHandlerToUse );
       
   354     CleanupStack::PushL( TCleanupItem( ReleaseHandlersOnStack, iStack ) );
       
   355     iDocStarted = EFalse;
       
   356     TRAPD( parseError, Xml::ParseL( *iParser, aDescription ) );
       
   357     if ( EXmlSyntax == parseError || EXmlInvalidToken == parseError ) 
       
   358         {
       
   359         while ( iStack->Count() > 1 )
       
   360             {
       
   361             delete iStack->Pop();
       
   362             }
       
   363         aHandlerToUse->ResetState();
       
   364         iCurrentContentHandler = aHandlerToUse;   
       
   365         iDocStarted = EFalse;
       
   366         RBuf8 fixedDes;
       
   367         fixedDes.CreateL( aDescription );
       
   368         CleanupClosePushL( fixedDes );                
       
   369         RemoveForbiddenCharacters( fixedDes );        
       
   370         TRAP( parseError, Xml::ParseL( *iParser, fixedDes ) );
       
   371         CleanupStack::PopAndDestroy( &fixedDes );
       
   372         }
       
   373     
       
   374     if ( EXmlJunkAfterDocElement != parseError ) 
       
   375         {
       
   376         User::LeaveIfError( parseError );
       
   377         }
       
   378     else
       
   379         {
       
   380         //EXmlJunkAfterDocElement must not be ignored when root isn't complete
       
   381         if ( !iDocStarted || iStack->Count() != 1 )
       
   382             {
       
   383             User::Leave( KErrArgument );     //no valid root element were found
       
   384             }
       
   385         }
       
   386     ASSERT( iStack->Count() == 1 );
       
   387     ASSERT( iStack->Head() == iCurrentContentHandler && iCurrentContentHandler == aHandlerToUse );
       
   388     iStack->Pop();
       
   389     CleanupStack::Pop( iStack );
       
   390     ASSERT( iStack->IsEmpty() );
       
   391     }
       
   392 
       
   393 // -----------------------------------------------------------------------------
       
   394 // CUpnpContentHandlersController::RemoveForbiddenCharacters
       
   395 // Removes forbidden characters
       
   396 // -----------------------------------------------------------------------------
       
   397 //
       
   398 void CUpnpContentHandlersController::RemoveForbiddenCharacters( TDes8& aDescription )
       
   399     {    
       
   400     for( TInt i=0; i<aDescription.Length(); i++ )
       
   401         {
       
   402         if ( ( aDescription[i] <= KUtfLowMax ) ||
       
   403             ( aDescription[i] >= KUtfHighMin && aDescription[i] <= KUtfHighMax ) )
       
   404             {
       
   405             aDescription.Delete( i, 1 );
       
   406             i--;
       
   407             }
       
   408         }
       
   409     }
       
   410     
       
   411 // -----------------------------------------------------------------------------
       
   412 // CUpnpContentHandlersController::CUpnpContentHandlersController
       
   413 // Default C++ constructor
       
   414 // -----------------------------------------------------------------------------
       
   415 //
       
   416 CUpnpContentHandlersController::CUpnpContentHandlersController()
       
   417     : iSoapParser( *this )
       
   418     {
       
   419     }
       
   420 
       
   421 // -----------------------------------------------------------------------------
       
   422 // CUpnpContentHandlersController::ConstructL
       
   423 // 2nd phase constructor, dedicated to be used by inherited classs
       
   424 // -----------------------------------------------------------------------------
       
   425 //
       
   426 void CUpnpContentHandlersController::ConstructL()
       
   427     {
       
   428     _LIT8( KXmlMimeType, "text/xml" );
       
   429     _LIT8( KLibxml2, "libxml2" );
       
   430     CMatchData *matchData = CMatchData::NewL();
       
   431     CleanupStack::PushL( matchData );
       
   432     matchData->SetMimeTypeL( KXmlMimeType );
       
   433     matchData->SetVariantL( KLibxml2 );
       
   434     iParser = CParser::NewL( *matchData, *this );
       
   435     CleanupStack::PopAndDestroy( matchData );
       
   436     iStack = new (ELeave) CStack<CUpnpContentHandler,ETrue>();
       
   437     }
       
   438 
       
   439 // -----------------------------------------------------------------------------
       
   440 // CUpnpContentHandlersController::OnStartDocumentL
       
   441 // This method is a callback to indicate the start of the document.
       
   442 // -----------------------------------------------------------------------------
       
   443 //
       
   444 void CUpnpContentHandlersController::OnStartDocumentL(
       
   445     const RDocumentParameters& /*aDocParam*/, TInt aErrorCode )
       
   446     {
       
   447     User::LeaveIfError( aErrorCode );
       
   448     iDocStarted = ETrue;
       
   449     }
       
   450 
       
   451 // -----------------------------------------------------------------------------
       
   452 // CUpnpContentHandlersController::OnEndDocumentL
       
   453 // This method is a callback to indicate the end of the document.
       
   454 // -----------------------------------------------------------------------------
       
   455 //
       
   456 void CUpnpContentHandlersController::OnEndDocumentL( TInt aErrorCode )
       
   457     {
       
   458     User::LeaveIfError( aErrorCode );
       
   459     }
       
   460 
       
   461 // -----------------------------------------------------------------------------
       
   462 // CUpnpContentHandlersController::OnStartElementL
       
   463 // This method is a callback to indicate an element has been parsed.
       
   464 // -----------------------------------------------------------------------------
       
   465 //
       
   466 void CUpnpContentHandlersController::OnStartElementL(
       
   467     const RTagInfo& aElement, const RAttributeArray& aAttributes,
       
   468     TInt aErrorCode )
       
   469     {
       
   470     User::LeaveIfError( aErrorCode );
       
   471     ChunksMergingEndL();
       
   472     if ( iCurrentContentHandler->InterestedInAllNamespaces()
       
   473             || aElement.Uri().DesC().Compare( iCorrectUri ) == 0 )
       
   474         {
       
   475         iCurrentContentHandler->OnStartElementL( aElement, aAttributes );
       
   476         }
       
   477     else
       
   478         {
       
   479         SetCurrentContentHandlerL( CUpnpIgnoreContentHandler::NewL( *this ) );
       
   480         }
       
   481     }
       
   482 
       
   483 // -----------------------------------------------------------------------------
       
   484 // CUpnpContentHandlersController::OnEndElementL
       
   485 // This method is a callback to indicate the end of the element has been reached.
       
   486 // -----------------------------------------------------------------------------
       
   487 //
       
   488 void CUpnpContentHandlersController::OnEndElementL( const RTagInfo& aElement,
       
   489     TInt aErrorCode )
       
   490     {
       
   491     User::LeaveIfError( aErrorCode );
       
   492     ChunksMergingEndL();
       
   493     iCurrentContentHandler->OnEndElementL( aElement );
       
   494     }
       
   495 
       
   496 // -----------------------------------------------------------------------------
       
   497 // CUpnpContentHandlersController::OnContentL
       
   498 // This method is a callback that sends the content of the element.
       
   499 // Not all the content may be returned in one go. The data may be sent in chunks.
       
   500 // This method just append chunk to chunks previously received. When we get all
       
   501 // chunks ChunksMergingEndL method pass merged chunks to current content handler.
       
   502 // -----------------------------------------------------------------------------
       
   503 //
       
   504 void CUpnpContentHandlersController::OnContentL( const TDesC8& aBytes,
       
   505     TInt aErrorCode )
       
   506     {
       
   507     User::LeaveIfError( aErrorCode );
       
   508     const TInt newLength = iContent.Length() + aBytes.Length();
       
   509     if ( iContent.MaxLength() < newLength )
       
   510         {
       
   511         iContent.ReAllocL( newLength );
       
   512         }
       
   513     iContent.Append( aBytes );
       
   514     }
       
   515 
       
   516 // -----------------------------------------------------------------------------
       
   517 // CUpnpContentHandlersController::ChunksMergingEndL
       
   518 // Method that is called when all chunks that contain current content
       
   519 // were received, so we can pass merged content to current content handler
       
   520 // as an argument of OnContentL method
       
   521 // -----------------------------------------------------------------------------
       
   522 //
       
   523 void CUpnpContentHandlersController::ChunksMergingEndL()
       
   524     {
       
   525     if ( iContent.Length() > 0 )
       
   526         {
       
   527         TLex8 lex(iContent);
       
   528         lex.SkipSpace();
       
   529         if ( !lex.Eos() ) 
       
   530             {
       
   531             iCurrentContentHandler->OnContentL( iContent );
       
   532             }
       
   533         iContent.Zero();
       
   534         }
       
   535     }
       
   536 
       
   537 // -----------------------------------------------------------------------------
       
   538 // CUpnpContentHandlersController::OnStartPrefixMappingL
       
   539 // This method is a notification of the beginning of the scope of a prefix-URI Namespace mapping.
       
   540 // This method is always called before the corresponding OnStartElementL method.
       
   541 // -----------------------------------------------------------------------------
       
   542 //
       
   543 void CUpnpContentHandlersController::OnStartPrefixMappingL(
       
   544     const RString& /*aPrefix*/, const RString& /*aUri*/, TInt aErrorCode )
       
   545     {
       
   546     User::LeaveIfError( aErrorCode );
       
   547     }
       
   548 
       
   549 // -----------------------------------------------------------------------------
       
   550 // CUpnpContentHandlersController::OnEndPrefixMappingL
       
   551 // This method is a notification of the end of the scope of a prefix-URI mapping.
       
   552 // This method is called after the corresponding DoEndElementL method.
       
   553 // -----------------------------------------------------------------------------
       
   554 //
       
   555 void CUpnpContentHandlersController::OnEndPrefixMappingL(
       
   556     const RString& /*aPrefix*/, TInt aErrorCode )
       
   557     {
       
   558     User::LeaveIfError( aErrorCode );
       
   559     }
       
   560 
       
   561 // -----------------------------------------------------------------------------
       
   562 // CUpnpContentHandlersController::OnIgnorableWhiteSpaceL
       
   563 // This method is a notification of ignorable whitespace in element content.
       
   564 // -----------------------------------------------------------------------------
       
   565 //
       
   566 void CUpnpContentHandlersController::OnIgnorableWhiteSpaceL(
       
   567     const TDesC8& /*aBytes*/, TInt aErrorCode )
       
   568     {
       
   569     User::LeaveIfError( aErrorCode );
       
   570     }
       
   571 
       
   572 // -----------------------------------------------------------------------------
       
   573 // CUpnpContentHandlersController::OnSkippedEntityL
       
   574 // This method is a notification of a skipped entity. If the parser encounters an
       
   575 // external entity it does not need to expand it - it can return the entity as aName
       
   576 // for the client to deal with.
       
   577 // -----------------------------------------------------------------------------
       
   578 //
       
   579 void CUpnpContentHandlersController::OnSkippedEntityL(
       
   580     const RString& /*aName*/, TInt aErrorCode )
       
   581     {
       
   582     User::LeaveIfError( aErrorCode );
       
   583     }
       
   584 
       
   585 // -----------------------------------------------------------------------------
       
   586 // CUpnpContentHandlersController::OnProcessingInstructionL
       
   587 // This method is a receive notification of a processing instruction.
       
   588 // -----------------------------------------------------------------------------
       
   589 //
       
   590 void CUpnpContentHandlersController::OnProcessingInstructionL(
       
   591     const TDesC8& /*aTarget*/, const TDesC8& /*aData*/, TInt aErrorCode )
       
   592     {
       
   593     User::LeaveIfError( aErrorCode );
       
   594     ChunksMergingEndL();
       
   595     }
       
   596 
       
   597 // -----------------------------------------------------------------------------
       
   598 // CUpnpContentHandlersController::OnError
       
   599 // This method indicates an error has occurred.
       
   600 // -----------------------------------------------------------------------------
       
   601 //
       
   602 void CUpnpContentHandlersController::OnError( TInt /*aErrorCode*/)
       
   603     {
       
   604     }
       
   605 
       
   606 // -----------------------------------------------------------------------------
       
   607 // CUpnpContentHandlersController::GetExtendedInterface
       
   608 // This method obtains the interface matching the specified uid.
       
   609 // -----------------------------------------------------------------------------
       
   610 //
       
   611 TAny* CUpnpContentHandlersController::GetExtendedInterface( const TInt32 /*aUid*/)
       
   612     {
       
   613     return 0;
       
   614     }
       
   615 
       
   616 // -----------------------------------------------------------------------------
       
   617 // CUpnpContentHandlersController::SetCurrentContentHandlerL
       
   618 // Sets ContentHandler argument as a current content handler, so it will
       
   619 // receive parsing events. Previous content handler will be push on stack
       
   620 // that it could be againt current content handler after calling of
       
   621 // SetPreviousContentHandler.
       
   622 // -----------------------------------------------------------------------------
       
   623 //
       
   624 void CUpnpContentHandlersController::SetCurrentContentHandlerL(
       
   625     CUpnpContentHandler* aNewContentHandler )
       
   626     {
       
   627     ASSERT( NULL != aNewContentHandler );
       
   628     iStack->PushL( aNewContentHandler );
       
   629     iCurrentContentHandler = aNewContentHandler;
       
   630     }
       
   631 
       
   632 // -----------------------------------------------------------------------------
       
   633 // CUpnpContentHandlersController::SetPreviousContentHandler
       
   634 // Deletes current content handler, and set previous content handler as current
       
   635 // contetnt handler.
       
   636 // -----------------------------------------------------------------------------
       
   637 //
       
   638 void CUpnpContentHandlersController::SetPreviousContentHandler()
       
   639     {
       
   640     ASSERT( iStack->Count() > 1 );
       
   641     delete iStack->Pop();
       
   642     iCurrentContentHandler = iStack->Head();
       
   643     }
       
   644 
       
   645 //  End of File