diff -r 000000000000 -r b497e44ab2fc syncmlfw/common/syncagent/src/nsmlstatuscontainer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syncmlfw/common/syncagent/src/nsmlstatuscontainer.cpp Thu Dec 17 09:07:52 2009 +0200 @@ -0,0 +1,634 @@ +/* +* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Client's Status command buffering +* +*/ + + + +//#include "nsmlcliagdefines.h" +#include "NSmlStatusContainer.h" +#include "nsmlcliagconstants.h" +#include "nsmlerror.h" +#include "smlmetinfdtd.h" + +// --------------------------------------------------------- +// CNSmlStatusContainer::CNSmlStatusContainer +// Constructor, nothing special in here. +// --------------------------------------------------------- +// +CNSmlStatusContainer::CNSmlStatusContainer() + { + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::ConstructL() +// Two-way construction. Constructor may leave in EPOC. +// --------------------------------------------------------- +// +void CNSmlStatusContainer::ConstructL(TBool aClearText) + { + iClearText = aClearText; + iStatusArray = new( ELeave ) CArrayFixFlat(KNSmlStatusArrayGranularity); + iArrayInd = -1; + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::~CNSmlStatusContainer() +// Destructor +// --------------------------------------------------------- +// + +CNSmlStatusContainer::~CNSmlStatusContainer() + { + delete iMsgRef; + if ( !iStatusArray ) + { + return; + } + TInt arrayCount = iStatusArray->Count(); + for ( TInt i = 0; i < arrayCount ; i++ ) + { + FreeResources( i ); + } + delete iStatusArray; + } +// --------------------------------------------------------- +// CNSmlStatusContainer::NewL() +// Creates new instance of CNSmlStatusContainer. +// Does not leave instance pointer to CleanupStack. +// --------------------------------------------------------- +// +CNSmlStatusContainer* CNSmlStatusContainer::NewL( TBool aClearText) + { + CNSmlStatusContainer* self = CNSmlStatusContainer::NewLC(aClearText); + CleanupStack::Pop(); + return( self ); + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::NewLC() +// Creates new instance of CNSmlStatusContainer +// Leaves instance pointer to CleanupStack. +// --------------------------------------------------------- +// +CNSmlStatusContainer* CNSmlStatusContainer::NewLC(TBool aClearText) + { + CNSmlStatusContainer* self = new (ELeave) CNSmlStatusContainer(); + CleanupStack::PushL( self ); + self->ConstructL(aClearText); + return( self ); + } +// --------------------------------------------------------- +// CNSmlStatusContainer::InitMsgRefL +// Creates new empty Status element and adds it to the array +// --------------------------------------------------------- +// +void CNSmlStatusContainer::InitMsgRefL( const SmlPcdata_t* aMsgRef ) + { + delete iMsgRef; + iMsgRef = NULL; + CopyPcdataL( aMsgRef, iMsgRef ); + } +// --------------------------------------------------------- +// CNSmlStatusContainer::CreateNewStatusElementL() +// Creates new empty Status element and adds it to the array +// --------------------------------------------------------- +// +EXPORT_C TInt CNSmlStatusContainer::CreateNewStatusElementL() + { + TStatusData statusData; + statusData.status = NULL; + statusData.noResponse = EFalse; + statusData.wasWritten = EFalse; + statusData.atomicOrSequenceID = 0; + statusData.performedInAtomic = EFalse; + statusData.statusIsFixed = EFalse; + iStatusArray->AppendL( statusData ); + TInt i = iStatusArray->Count() - 1; + (*iStatusArray)[i].status = new( ELeave ) SmlStatus_t; + (*iStatusArray)[i].status->elementType = SML_PE_STATUS; + CopyPcdataL( iMsgRef, (*iStatusArray)[i].status->msgRef ); + return iStatusArray->Count(); + } +// --------------------------------------------------------- +// CNSmlStatusContainer::SetCmdIDL() +// Sets CmdID element +// --------------------------------------------------------- +// +void CNSmlStatusContainer::SetCmdIDL( TInt aEntryID, const SmlPcdata_t* aCmdID ) + { + delete (*iStatusArray)[aEntryID-1].status->cmdID; + (*iStatusArray)[aEntryID-1].status->cmdID = NULL; + CopyPcdataL( aCmdID, (*iStatusArray)[aEntryID-1].status->cmdID ); + } +// --------------------------------------------------------- +// CNSmlStatusContainer::SetMsgRefL() +// Sets MsgRef element +// --------------------------------------------------------- +// +void CNSmlStatusContainer::SetMsgRefL( TInt aEntryID, const SmlPcdata_t* aMsgRef ) + { + delete (*iStatusArray)[aEntryID-1].status->msgRef; + (*iStatusArray)[aEntryID-1].status->msgRef = NULL; + CopyPcdataL( aMsgRef, (*iStatusArray)[aEntryID-1].status->msgRef ); + } +// --------------------------------------------------------- +// CNSmlStatusContainer::SetCmdRefL() +// Sets CmdRef element +// --------------------------------------------------------- +// +EXPORT_C void CNSmlStatusContainer::SetCmdRefL( TInt aEntryID, const SmlPcdata_t* aCmdRef ) + { + delete (*iStatusArray)[aEntryID-1].status->cmdRef; + (*iStatusArray)[aEntryID-1].status->cmdRef = NULL; + CopyPcdataL( aCmdRef, (*iStatusArray)[aEntryID-1].status->cmdRef ); + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::SetCmdL() +// Sets CmdRef element +// --------------------------------------------------------- +// +EXPORT_C void CNSmlStatusContainer::SetCmdL( TInt aEntryID, const TDesC8& aCmd ) + { + delete (*iStatusArray)[aEntryID-1].status->cmd; + (*iStatusArray)[aEntryID-1].status->cmd = NULL; + CreatePcdataL( (*iStatusArray)[aEntryID-1].status->cmd, aCmd ); + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::SetStatusCodeL() +// Sets Status code to Data element +// Created element is not pushed to Cleanup stack +// --------------------------------------------------------- +EXPORT_C void CNSmlStatusContainer::SetStatusCodeL( TInt aEntryID, TInt aStatusCode, TBool aFixStatus ) + { + //status code in data element + if ( !(*iStatusArray)[aEntryID-1].statusIsFixed ) + { + HBufC8* statusCode = HBufC8::NewLC( KNSmlAgentStatusCodeLength ); + statusCode->Des().Num( aStatusCode ); + if ( !(*iStatusArray)[aEntryID-1].status->data ) + { + CreatePcdataL( (*iStatusArray)[aEntryID-1].status->data, *statusCode ); + } + else + { + // Don't overwrite status 213 with 200, otherwise replace + // existing status + TInt existingStatus( TNSmlError::ESmlStatusOK ); + TBool ok = StatusCodeVal ( (*iStatusArray)[aEntryID-1].status->data, existingStatus ); + if ( !( ok && existingStatus == TNSmlError::ESmlStatusItemAccepted && + aStatusCode == TNSmlError::ESmlStatusOK ) ) + { + delete (*iStatusArray)[aEntryID-1].status->data; + (*iStatusArray)[aEntryID-1].status->data = NULL; + CreatePcdataL( (*iStatusArray)[aEntryID-1].status->data, *statusCode ); + } + } + if ( aFixStatus) + { + (*iStatusArray)[aEntryID-1].statusIsFixed = ETrue; + } + } + CleanupStack::PopAndDestroy(); //statusCode + } +// --------------------------------------------------------- +// CNSmlStatusContainer::SetChalL() +// Creates Chal element +// --------------------------------------------------------- +void CNSmlStatusContainer::SetChalL( TInt aEntryID, const TDesC8& aNonce ) + { + (*iStatusArray)[aEntryID-1].status->chal = new( ELeave ) SmlChal_t; + SmlMetInfMetInf_t* metInf = new( ELeave ) SmlMetInfMetInf_t; + CleanupStack::PushL( metInf ); + CreatePcdataL( metInf->type, KNSmlAgentAuthMD5 ); + CreatePcdataL( metInf->format, KNSmlAgentBase64Format ); + CreatePcdataL( metInf->nextnonce, aNonce ); + (*iStatusArray)[aEntryID-1].status->chal->meta = new( ELeave ) SmlPcdata_t; + (*iStatusArray)[aEntryID-1].status->chal->meta->length = 0; + (*iStatusArray)[aEntryID-1].status->chal->meta->content = ( TAny* ) metInf; + CleanupStack::Pop(); //metInf + (*iStatusArray)[aEntryID-1].status->chal->meta->contentType = SML_PCDATA_EXTENSION; + (*iStatusArray)[aEntryID-1].status->chal->meta->extension = SML_EXT_METINF; + } +// --------------------------------------------------------- +// CNSmlStatusContainer::SetNoResponse +// Sets NoResponse flag +// --------------------------------------------------------- +EXPORT_C void CNSmlStatusContainer::SetNoResponse( TInt aEntryID, TBool aNoResponse ) + { + (*iStatusArray)[aEntryID-1].noResponse = aNoResponse; + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::SetAtomicOrSequenceId +// Sets Atomic or Sequence Id +// --------------------------------------------------------- +EXPORT_C void CNSmlStatusContainer::SetAtomicOrSequenceId( TInt aEntryID, TInt aAtomicOrSequenceID ) + { + (*iStatusArray)[aEntryID-1].atomicOrSequenceID = aAtomicOrSequenceID; + } +// --------------------------------------------------------- +// CNSmlStatusContainer::SetPerformedInAtomic +// Mark an item be performed inside Atomic +// --------------------------------------------------------- +EXPORT_C void CNSmlStatusContainer::SetPerformedInAtomic( TInt aEntryID ) + { + (*iStatusArray)[aEntryID-1].performedInAtomic = ETrue; + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::SetStatusCodeToAtomicOrSequenceCmdL +// Change status code for Atomic command +// --------------------------------------------------------- +EXPORT_C void CNSmlStatusContainer::SetStatusCodeToAtomicOrSequenceCmdL( TInt aAtomicOrSequenceID, TInt aStatusCode, const TDesC8& aCmd ) + { + TInt arrayCount = iStatusArray->Count(); + for ( TInt i = 0; i < arrayCount; i++ ) + { + if ( (*iStatusArray)[i].atomicOrSequenceID == aAtomicOrSequenceID ) + { + if ( (*iStatusArray)[i].status->cmd ) + { + if ( (*iStatusArray)[i].status->cmd->content ) + { + TPtrC8 cmd( (TUint8*) (*iStatusArray)[i].status->cmd->content, (*iStatusArray)[i].status->cmd->length ); + if ( cmd == aCmd ) + { + SetStatusCodeL( i + 1, aStatusCode ); + break; + } + } + } + } + } + } +// --------------------------------------------------------- +// CNSmlStatusContainer::SetStatusCodesInAtomicL +// Change status code to all items in Atomic or to items which +// have been already performed +// --------------------------------------------------------- +EXPORT_C void CNSmlStatusContainer::SetStatusCodesInAtomicL( TInt aAtomicID, TInt aStatusCode, TBool aOnlyForPerformed ) + { + TInt arrayCount = iStatusArray->Count(); + for ( TInt i = 0; i < arrayCount; i++ ) + { + if ( !(*iStatusArray)[i].atomicOrSequenceID == aAtomicID ) + { + continue; + } + if ( (!aOnlyForPerformed) || ( aOnlyForPerformed && (*iStatusArray)[i].performedInAtomic ) ) + { + SetStatusCodeL( i + 1, aStatusCode ); + } + } + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::AddTargetRefL +// Adds TargetRef element +// --------------------------------------------------------- +EXPORT_C void CNSmlStatusContainer::AddTargetRefL( TInt aEntryID, const SmlTarget_t* aTarget ) + { + if ( !aTarget ) + { + return; + } + if ( !aTarget->locURI ) + { + return; + } + if ( !aTarget->locURI->content ) + { + return; + } + SmlTargetRefList_t** targetRefList; + targetRefList = &(*iStatusArray)[aEntryID-1].status->targetRefList; + while( *targetRefList ) + { + targetRefList = &(*targetRefList)->next; + } + *targetRefList = new( ELeave ) SmlTargetRefList_t; + CreateTargetRefL( aTarget, (*targetRefList)->targetRef ); + } +// --------------------------------------------------------- +// CNSmlStatusContainer::AddSourceRefL +// Adds SourceRef element +// --------------------------------------------------------- +EXPORT_C void CNSmlStatusContainer::AddSourceRefL( TInt aEntryID, const SmlSource_t* aSource ) + { + if ( !aSource ) + { + return; + } + if ( !aSource->locURI ) + { + return; + } + if ( !aSource->locURI->content ) + { + return; + } + SmlSourceRefList_t** sourceRefList; + sourceRefList = &(*iStatusArray)[aEntryID-1].status->sourceRefList; + while ( *sourceRefList ) + { + sourceRefList = &(*sourceRefList)->next; + } + *sourceRefList = new( ELeave ) SmlSourceRefList_t; + CreateSourceRefL( aSource, (*sourceRefList)->sourceRef ); + } +// --------------------------------------------------------- +// CNSmlStatusContainer::AddItemDataL +// Adds Item/Data element +// --------------------------------------------------------- +EXPORT_C void CNSmlStatusContainer::AddItemDataL (TInt aEntryID, const SmlPcdata_t* aData ) + { + SmlItemList_t* newItemList = new( ELeave ) SmlItemList_t; + CleanupStack::PushL( newItemList ); + newItemList->item = new( ELeave ) SmlItem_t; + CopyPcdataL( aData, newItemList->item->data ); + SmlItemList_t** itemList; + itemList = &(*iStatusArray)[aEntryID-1].status->itemList; + while ( *itemList ) + { + itemList = &(*itemList)->next; + } + *itemList = newItemList; + CleanupStack::Pop(); //newItemList + } +// --------------------------------------------------------- +// CNSmlStatusContainer::RemoveWritten() +// Marks Status command written in outgoing XML document +// --------------------------------------------------------- +void CNSmlStatusContainer::RemoveWritten( TInt aEntryID ) + { + (*iStatusArray)[aEntryID-1].wasWritten = ETrue; + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::Begin +// Sets index for reading to starting value +// --------------------------------------------------------- +EXPORT_C void CNSmlStatusContainer::Begin() + { + iArrayInd = -1; + } +// --------------------------------------------------------- +// CNSmlStatusContainer::NextStatusElement() +// Returns pointer to the next Status element +// --------------------------------------------------------- +EXPORT_C TBool CNSmlStatusContainer::NextStatusElement( SmlStatus_t*& aStatus, TBool aOnlyIfResponse ) + { + TBool moreElements( ETrue ); + while ( moreElements ) + { + iArrayInd++; + if ( iArrayInd > iStatusArray->Count() - 1 ) + { + RemoveAllWrittenOnes(); + iArrayInd = -1; + moreElements = EFalse; + } + else + { + if ( aOnlyIfResponse && (*iStatusArray)[iArrayInd].noResponse ) + { + } + else + if ( !(*iStatusArray)[iArrayInd].wasWritten ) + { + aStatus = (*iStatusArray)[iArrayInd].status; + return ETrue; + } + } + } + return moreElements; + } +// --------------------------------------------------------- +// CNSmlStatusContainer::CurrentEntryID() +// Returns current status ID +// --------------------------------------------------------- +TInt CNSmlStatusContainer::CurrentEntryID() const + { + return( iArrayInd + 1); + } +// --------------------------------------------------------- +// CNSmlStatusContainer::LastEntryID() +// Returns last status ID +// --------------------------------------------------------- +EXPORT_C TInt CNSmlStatusContainer::LastEntryID() const + { + return iStatusArray->Count(); + } +// --------------------------------------------------------- +// CNSmlStatusContainer::AnyOtherThanSyncHdrStatus() +// +// --------------------------------------------------------- +TBool CNSmlStatusContainer::AnyOtherThanOkSyncHdrStatus() const + { + TBool statusPresents = EFalse; + TInt arrayCount = iStatusArray->Count(); + for ( TInt i = 0; i < arrayCount; i++ ) + { + if ( !(*iStatusArray)[i].noResponse ) + { + if ( (*iStatusArray)[i].status->cmd ) + { + if ( (*iStatusArray)[i].status->cmd->content ) + { + TPtrC8 cmd( (TUint8*) (*iStatusArray)[i].status->cmd->content, (*iStatusArray)[i].status->cmd->length ); + if ( cmd == KNSmlAgentSyncHdr ) + { + if ( (*iStatusArray)[i].status->data ) + { + if ( (*iStatusArray)[i].status->data->content ) + { + TPtrC8 statusCode( (TUint8*) (*iStatusArray)[i].status->data->content, (*iStatusArray)[i].status->data->length ); + TLex8 lexicalValue( statusCode ); + TInt statusCodeNum; + if ( lexicalValue.Val( statusCodeNum ) != KErrNone ) + { + if ( statusCodeNum != TNSmlError::ESmlStatusOK && + statusCodeNum != TNSmlError::ESmlStatusAuthenticationAccepted ) + { + statusPresents = ETrue; + break; + } + } + } + } + } + else + { + statusPresents = ETrue; + break; + } + } + } + } + } + return statusPresents; + } +// --------------------------------------------------------- +// CNSmlStatusContainer::CreatePcdataL() +// Creates Pcdata +// Created element is not pushed to Cleanup stack +// --------------------------------------------------------- +void CNSmlStatusContainer::CreatePcdataL( SmlPcdata_t*& aPcdata, const TDesC8& aContent ) const + { + aPcdata = new( ELeave ) SmlPcdata_t; + aPcdata->SetDataL( aContent ); + aPcdata->contentType = SML_PCDATA_OPAQUE; + aPcdata->extension = SML_EXT_UNDEFINED; + } +// --------------------------------------------------------- +// CNSmlStatusContainer::CopyPcdataL() +// Deep copy to Pcdata element +// Copied element is not pushed to Cleanup stack +// --------------------------------------------------------- +// +void CNSmlStatusContainer::CopyPcdataL( const SmlPcdata_t* aFromPcdata, SmlPcdata_t*& aToPcdata ) const + { + aToPcdata = NULL; + if ( aFromPcdata ) + { + SmlPcdata_t* newPcdata = new( ELeave ) SmlPcdata_t; + CleanupStack::PushL( newPcdata ); + newPcdata->length = aFromPcdata->length; + if (iClearText) + { + newPcdata->contentType = SML_PCDATA_STRING; + } + else + { + newPcdata->contentType = SML_PCDATA_OPAQUE; + } + newPcdata->extension = SML_EXT_UNDEFINED; + if ( aFromPcdata->content ) + { + if ( aFromPcdata->contentType == SML_PCDATA_EXTENSION && aFromPcdata->extension == SML_EXT_METINF ) + { + newPcdata->contentType = SML_PCDATA_EXTENSION; + newPcdata->extension = aFromPcdata->extension; + newPcdata->length = 0; + CopyMetInfL( aFromPcdata->content, newPcdata->content ); + } + else + { + newPcdata->content = User::AllocL( newPcdata->length ); + TPtr8 fromPtr ( (TUint8*) aFromPcdata->content, aFromPcdata->length ); + fromPtr.SetLength( fromPtr.MaxLength() ); + TPtr8 toPtr ( (TUint8*) newPcdata->content, newPcdata->length ); + toPtr.SetLength( toPtr.MaxLength() ); + toPtr = fromPtr; + } + } + CleanupStack::Pop(); //newPcdata + aToPcdata = newPcdata; + } + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::CopyMetInfL() +// Deep copy to Meta Info +// --------------------------------------------------------- +void CNSmlStatusContainer::CopyMetInfL ( const void* aFromMetInf, void*& aToMetInf ) const + { + if ( aFromMetInf ) + { + SmlMetInfMetInf_t* fromMetInf = (SmlMetInfMetInf_t*) aFromMetInf; + SmlMetInfMetInf_t* toMetInf = new( ELeave ) SmlMetInfMetInf_t; + if ( fromMetInf->anchor ) + { + toMetInf->anchor = new( ELeave ) SmlMetInfAnchor_t; + CopyPcdataL( fromMetInf->anchor->next, toMetInf->anchor->next ); + } + aToMetInf = toMetInf; + } + } +// --------------------------------------------------------- +// CNSmlStatusContainer::CreateTargetOrSourceRefL() +// Creates TargetRef or SourceRef element +// --------------------------------------------------------- +void CNSmlStatusContainer::CreateSourceRefL( const SmlSource_t* aSource, SmlPcdata_t*& aSourceRef ) const + { + CopyPcdataL( aSource->locURI, aSourceRef ); + } + + +// --------------------------------------------------------- +// CNSmlStatusContainer::CreateTargetOrSourceRefL() +// Creates TargetRef or SourceRef element +// --------------------------------------------------------- +void CNSmlStatusContainer::CreateTargetRefL( const SmlTarget_t* aTarget, SmlPcdata_t*& aTargetRef ) const + { + CopyPcdataL( aTarget->locURI, aTargetRef ); + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::RemoveAllWrittenOnes() +// Removes all written Status elements +// --------------------------------------------------------- +void CNSmlStatusContainer::RemoveAllWrittenOnes() + { + for ( TInt i = iStatusArray->Count() - 1; i >= 0; i--) + { + if ( (*iStatusArray)[i].wasWritten ) + { + FreeResources( i ); + iStatusArray->Delete( i ); + } + } + iStatusArray->Compress(); + iArrayInd = -1; + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::FreeResources() +// Frees resources of an item +// --------------------------------------------------------- +void CNSmlStatusContainer::FreeResources( TInt aI ) + { + delete (*iStatusArray)[aI].status; + } + +// --------------------------------------------------------- +// CNSmlStatusContainer::StatusCodeVal() +// Converts status code to integer value +// --------------------------------------------------------- +TBool CNSmlStatusContainer::StatusCodeVal ( SmlPcdata_t*& aStatusCodeData, TInt& aVal ) const + { + TBool ret(EFalse); + if ( aStatusCodeData->content ) + { + TPtrC8 statusCode( (TUint8*) aStatusCodeData->content, aStatusCodeData->length ); + TLex8 lexicalValue( statusCode ); + TInt statusCodeNum( TNSmlError::ESmlStatusOK ); + if ( lexicalValue.Val( statusCodeNum ) == KErrNone ) + { + ret = ETrue; + aVal = statusCodeNum; + } + else + { + aVal = 0; + } + } + return ret; + } + +