diff -r 000000000000 -r b497e44ab2fc syncmlfw/ds/syncagent/src/nsmldscmds.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/syncmlfw/ds/syncagent/src/nsmldscmds.cpp Thu Dec 17 09:07:52 2009 +0200 @@ -0,0 +1,4653 @@ +/* +* Copyright (c) 2005 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: DS Sync flow +* +*/ + +#define SYNCML_V3 +// INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include +// common includes with DM +#include "nsmlcliagconstants.h" +#include "NSmlCmdsBase.h" +#include "NSmlAgentBase.h" +#include "NSmlStatusContainer.h" +#include "NSmlResponseController.h" +#include "NSmlURI.h" +#include "WBXMLSyncMLGenerator.h" +#include "WBXMLSyncMLParser.h" +#include "WBXMLDevInfGenerator.h" +#include "WBXMLDevInfParser.h" +#include "WBXMLGeneratorError.h" +#include "WBXMLParser.h" +#include "WBXMLParserError.h" +#include "smldtd.h" +#include "smldef.h" +// DS specific includes +#include "nsmldsagconstants.h" +#include "NSmlDSCmds.h" +#include "nsmldscontent.h" +#include "NSmlDSAgent.h" +#include "nsmldserror.h" +#include "nsmlfilter.h" +#include "nsmldssettings.h" +#include "nsmldsbatchbuffer.h" +#include "nsmldshostclient.h" + + +#ifndef __WINS__ +// This lowers the unnecessary compiler warning (armv5) to remark. +// "Warning: #174-D: expression has no effect..." is caused by +// DBG_ARGS8 macro in no-debug builds. +#pragma diag_remark 174 +#endif + + +// CONSTANTS +_LIT8( KNSmlRoot, "/" ); + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::CNSmlDSCmds() +// C++ default constructor. +// ----------------------------------------------------------------------------- +// +CNSmlDSCmds::CNSmlDSCmds( CNSmlDSContent& aDSContent, MSyncMLProgressObserver& aDSObserver ) : iDSContent( aDSContent ), iDSObserver( aDSObserver ) + { + iAtomicModeOn = EFalse; + iAtomicId = 0; + iAtomicHasFailed = EFalse; + iItemOpened = EFalse; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ConstructL +// Symbian 2nd phase constructor. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ConstructL( CNSmlAgentBase* aAgent, const TDesC8& aSessionID, const TDesC8& aVerProto, const TInt aPublicId, const HBufC& aSyncMLUserName, CNSmlURI* aSyncServer, TBool aVersionCheck ) + { + CNSmlCmdsBase::ConstructL( aAgent, aSessionID, aVerProto, aPublicId, aSyncMLUserName, aSyncServer, aVersionCheck ); + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CNSmlDSCmds* CNSmlDSCmds::NewL( CNSmlAgentBase* aAgent, const TDesC8& aSessionID, const TDesC8& aVerProto, const TInt aPublicId, const HBufC& aSyncMLUserName, CNSmlURI* aSyncServer, CNSmlDSContent& aDSContent, MSyncMLProgressObserver& aDSObserver, TBool aVersionCheck ) + { + CNSmlDSCmds* self = new ( ELeave ) CNSmlDSCmds( aDSContent, aDSObserver ); + CleanupStack::PushL( self ); + self->ConstructL( aAgent, aSessionID, aVerProto, aPublicId, aSyncMLUserName, aSyncServer, aVersionCheck ); + CleanupStack::Pop(); // self + return self; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::~CNSmlDSCmds +// Destructor. +// ----------------------------------------------------------------------------- +// +CNSmlDSCmds::~CNSmlDSCmds() + { + delete iBatchBuffer; + delete iDSGetCmdId; + delete iDSGetMsgId; + delete iDSLargeObjectCmdName; + delete iDSDevGenerator; + delete iDSPreviousSyncTargetURI; + delete iDataBuffer; + delete iLargeUid; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::CommitBatchL +// Commits the batched commands and sets their statuses. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::CommitBatchL() + { + _DBG_FILE(_S8("CNSmlDSCmds::CommitBatchL : Begin")); + if ( !iDSContent.BatchModeOn() ) + { + return; + } + + RArray commitResults; + TInt resultCode; + + iDSContent.CommitBatchL( commitResults, resultCode ); + + // if the atomic mode is on and committing the batch fails then everyting will be rolled back + if ( iAtomicModeOn && resultCode != KErrNone ) + { + iAtomicHasFailed = ETrue; + commitResults.Close(); + iBatchModeOn = EFalse; + delete iBatchBuffer; + iBatchBuffer = NULL; + return; + } + + TInt commitIndex( 0 ); + + for ( TInt batchIndex = 0; batchIndex < iBatchBuffer->Count(); batchIndex++ ) + { + if ( resultCode != KErrNone ) + { + iDSContent.IncreaseServerItemsFailed(); + + iStatusToServer->SetStatusCodeL( iBatchBuffer->StatusEntryId( batchIndex ), TNSmlError::ESmlStatusCommandFailed ); + continue; + } + + TInt statusId( KErrNone ); + + for ( TInt i = 0; i < iBatchBuffer->NumberOfResults( batchIndex ); i++ ) + { + if ( commitResults[commitIndex] != KErrNone ) + { + statusId = commitResults[commitIndex]; + } + + ++commitIndex; + } + + // map the status code & set the command's status + MapStatusCodeL( batchIndex, statusId ); + + if ( statusId != KErrNone ) + { + iStatusToServer->SetStatusCodeL( iBatchBuffer->StatusEntryId( batchIndex ), iBatchBuffer->Status( batchIndex ) ); + } + } + + iBatchModeOn = EFalse; + delete iBatchBuffer; + iBatchBuffer = NULL; + _DBG_FILE(_S8("CNSmlDSCmds::CommitBatchL : End")); + commitResults.Close(); + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::MapStatusCode +// Performs mapping between datastore operation return values and SyncML error +// codes. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::MapStatusCodeL( const TInt aIndex, const TInt aStatus ) + { + TBool commandOk( EFalse ); + + if ( iBatchBuffer->Command( aIndex ) == KNSmlAgentAdd ) + { + switch ( aStatus ) + { + case KErrNone: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusItemAdded ); + iDSContent.IncreaseServerItemsAdded(); + commandOk = ETrue; + + if ( !iAtomicModeOn ) + { + iDSContent.CreateNewMapItemL( iBatchBuffer->Uid( aIndex ), iBatchBuffer->GUid( aIndex ), 0 ); + } + else + { + iDSContent.CreateNewMapItemL( iBatchBuffer->Uid( aIndex ), iBatchBuffer->GUid( aIndex ), iAtomicId ); + } + break; + + case KErrDiskFull: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusDeviceFull ); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlLowMemory, EFalse, EFalse ); + break; + + case KErrNotSupported: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + break; + + default: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusCommandFailed ); + break; + } + } + else if ( iBatchBuffer->Command( aIndex ) == KNSmlAgentReplace ) + { + switch ( aStatus ) + { + case KErrNone: + iDSContent.IncreaseServerItemsChanged(); + commandOk = ETrue; + break; + + case KErrNotFound: + { + TSmlDbItemUid newLUid; + + TInt retval = iDSContent.CreateItemL( newLUid, + iBatchBuffer->ItemData( aIndex ).Size(), + iBatchBuffer->MimeType( aIndex ), + iBatchBuffer->MimeVersion( aIndex ), + iBatchBuffer->Parent( aIndex ) ); + + if ( retval == KErrNone ) + { + TRAP( retval, iDSContent.WriteItemL( iBatchBuffer->ItemData( aIndex ) ) ); + } + + if ( retval == KErrNone ) + { + retval = iDSContent.CommitItemL(); + } + + switch( retval ) + { + case KErrNone: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusItemAdded ); + + iDSContent.IncreaseServerItemsAdded(); + commandOk = ETrue; + + if ( !iAtomicModeOn ) + { + iDSContent.CreateNewMapItemL( newLUid, iBatchBuffer->GUid( aIndex ), 0 ); + } + else + { + iDSContent.CreateNewMapItemL( newLUid, iBatchBuffer->GUid( aIndex ), iAtomicId ); + } + break; + + case KErrDiskFull: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusDeviceFull ); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlLowMemory, EFalse, EFalse ); + break; + + case KErrNotSupported: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + break; + + default: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusCommandFailed ); + break; + } + } + break; + + case KErrDiskFull: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusDeviceFull ); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlLowMemory, EFalse, EFalse ); + break; + + case KErrNotSupported: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + break; + + default: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusCommandFailed ); + break; + } + } + else if ( iBatchBuffer->Command( aIndex ) == KNSmlAgentDelete ) + { + switch ( aStatus ) + { + case KErrNone: + iDSContent.IncreaseServerItemsDeleted(); + commandOk = ETrue; + break; + + case KErrNotFound: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusItemIsNotDeleted ); + break; + + case KErrDiskFull: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusDeviceFull ); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlLowMemory, EFalse, EFalse ); + break; + + case KErrNotSupported: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + break; + + default: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusCommandFailed ); + break; + } + } + else if ( iBatchBuffer->Command( aIndex ) == KNSmlAgentMove ) + { + switch ( aStatus ) + { + case KErrNone: + iDSContent.IncreaseServerItemsMoved(); + commandOk = ETrue; + break; + + case KErrDiskFull: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusDeviceFull ); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlLowMemory, EFalse, EFalse ); + break; + + case KErrNotSupported: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + break; + + default: + iBatchBuffer->SetStatus( aIndex, TNSmlError::ESmlStatusMoveFailed ); + break; + } + } + + if ( !commandOk ) + { + iDSContent.IncreaseServerItemsFailed(); + } + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::DoAlertL +// Makes an Alert element and calls the parser to generate XML. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::DoAlertL( const TDesC8& aAlertCode, TTime* aLastSyncAnchor, TTime* aNextSyncAnchor ) + { + SmlAlert_t* alert = new ( ELeave ) SmlAlert_t; + CleanupStack::PushL( alert ); + + // element type + alert->elementType = SML_PE_ALERT; + + // CmdID element + DoCmdIdL( alert->cmdID ); + + // Alert code to Data element + PcdataNewL ( alert->data, aAlertCode ); + alert->itemList = new ( ELeave ) SmlItemList_t; + alert->itemList->item = new ( ELeave ) SmlItem_t; + + // Target and Source elements + if ( aAlertCode == KNSmlDSAgentResultAlert || aAlertCode == KNSmlDSAgentNextMessage || aAlertCode == KNSmlDSAgentNoEndOfData ) + { + DoTargetL( alert->itemList->item->target, iSentSyncHdrTarget->HostName() ); + DoSourceL( alert->itemList->item->source, iSentSyncHdrSource->HostName() ); + } + else + { + DoTargetWithFilterL( alert->itemList->item->target, iDSContent.RemoteDatabase()->Database() ); + DoSourceL( alert->itemList->item->source, iDSContent.LocalDatabase()->Database() ); + } + + // Anchor/Last and Anchor/Next in the Meta Element + if ( aLastSyncAnchor && aNextSyncAnchor ) + { + HBufC8* lastAnchor = HBufC8::NewLC( KNSmlDSAgentAnchorDateFormat.iTypeLength ); + HBufC8* nextAnchor = HBufC8::NewLC( KNSmlDSAgentAnchorDateFormat.iTypeLength ); + + if ( *aLastSyncAnchor != TTime( 0 ) ) + { + lastAnchor->Des().Format( KNSmlDSAgentAnchorDateFormat, + aLastSyncAnchor->DateTime().Year(), + aLastSyncAnchor->DateTime().Month() + 1, + aLastSyncAnchor->DateTime().Day() + 1, + aLastSyncAnchor->DateTime().Hour(), + aLastSyncAnchor->DateTime().Minute(), + aLastSyncAnchor->DateTime().Second() ); + } + + if ( *aNextSyncAnchor != TTime( 0 ) ) + { + nextAnchor->Des().Format( KNSmlDSAgentAnchorDateFormat, + aNextSyncAnchor->DateTime().Year(), + aNextSyncAnchor->DateTime().Month() + 1, + aNextSyncAnchor->DateTime().Day() + 1, + aNextSyncAnchor->DateTime().Hour(), + aNextSyncAnchor->DateTime().Minute(), + aNextSyncAnchor->DateTime().Second() ); + } + + if ( ( *aLastSyncAnchor != TTime( 0 ) ) || ( *aNextSyncAnchor != TTime( 0 ) ) ) + { + SmlMetInfMetInf_t* metInf; + DoMetInfLC( metInf ); + DoAnchorsL( *metInf, lastAnchor, nextAnchor ); + DoMetaL( alert->itemList->item->meta, metInf ); + CleanupStack::Pop(); // metInf + } + + CleanupStack::PopAndDestroy( 2 ); // lastAnchor, nextAnchor + } + + TInt ret( iGenerator->smlAlertCmd( alert) ); + + if ( ret != KWBXMLGeneratorOk ) + { + User::Leave( ret ); + } + + CleanupStack::PopAndDestroy(); // alert + + // save Status response information for response status controlling + TInt respID( CreateAndInitResponseItemL( KNSmlAgentAlert ) ); + + iResponseController->SetAppIndex( respID, iDSContent.CurrentIndex() ); + + if ( aAlertCode >= KNSmlDSTwoWay && aAlertCode <= KNSmlDSRefreshFromServerByServer ) + { + iResponseController->SetResponseDetail( respID, CNSmlResponseController::EResponseInitAlert ); + } + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::DoPutL +// Inserts DevInfo into Put element and calls the WBXML generator. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::DoPutL() + { + SmlPut_t* put = new ( ELeave )SmlPut_t; + CleanupStack::PushL( put ); + put->elementType = SML_PE_PUT; + + // CmdID element + DoCmdIdL( put->cmdID ); + + // Type element in Meta + SmlMetInfMetInf_t* metInf; + DoMetInfLC( metInf ); + PcdataNewL( metInf->type, KNSmlDSAgentDeviceInfoContentType ); + DoMetaL( put->meta, metInf ); + CleanupStack::Pop(); // metinf + + // Item element + put->itemList = new ( ELeave )SmlItemList_t; + put->itemList->item = new ( ELeave )SmlItem_t; + + // Item/Source element + if ( iVersionPublicId == KNSmlSyncMLPublicId ) + { + DoSourceL( put->itemList->item->source, KNSmlDSAgentDeviceInfo11URI ); + PcdataNewL( put->itemList->item->data, DoDeviceInfoL( ETrue ) ); + } + else if ( iVersionPublicId == KNSmlSyncMLPublicId12 ) + { + DoSourceL( put->itemList->item->source, KNSmlDSAgentDeviceInfo12URI ); + PcdataNewL( put->itemList->item->data, DoDeviceInfoL() ); + } + + // Device Info + FreeDeviceInfo(); + + TInt ret( iGenerator->smlPutCmd( put ) ); + + if ( ret != KWBXMLGeneratorOk ) + { + User::Leave( ret ); + } + + CleanupStack::PopAndDestroy(); // put + + //save Status response information for response status controlling + CreateAndInitResponseItemL( KNSmlAgentPut ); + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::DoResultsL +// Generate Device Info to Results element and calls the WBXML generator. +// ----------------------------------------------------------------------------- +// +CNSmlCmdsBase::TReturnValue CNSmlDSCmds::DoResultsL() + { + SmlResults_t* results = new ( ELeave ) SmlResults_t; + CleanupStack::PushL( results ); + results->elementType = SML_PE_RESULTS; + + // CmdID element + DoCmdIdL( results->cmdID ); + + // MsgRef element + if ( iDSGetMsgId ) + { + PcdataNewL ( results->msgRef, *iDSGetMsgId ); + } + + // CmdRef element + if ( iDSGetCmdId ) + { + PcdataNewL ( results->cmdRef, *iDSGetCmdId ); + } + + // Type element in Meta + SmlMetInfMetInf_t* metInf; + DoMetInfLC( metInf ); + PcdataNewL( metInf->type, KNSmlDSAgentDeviceInfoContentType ); + DoMetaL( results->meta, metInf ); + CleanupStack::Pop(); // metinf + + // Item element + results->itemList = new( ELeave ) SmlItemList_t; + results->itemList->item = new( ELeave ) SmlItem_t; + + // Item/source element + if ( iVersionPublicId == KNSmlSyncMLPublicId ) + { + DoSourceL( results->itemList->item->source, KNSmlDSAgentDeviceInfo11URI ); + PcdataNewL( results->itemList->item->data, DoDeviceInfoL(ETrue) ); + } + else if ( iVersionPublicId == KNSmlSyncMLPublicId12 ) + { + DoSourceL( results->itemList->item->source, KNSmlDSAgentDeviceInfo12URI ); + PcdataNewL( results->itemList->item->data, DoDeviceInfoL() ); + } + + // Device Info + results->itemList->next = NULL; + TInt ret( iGenerator->smlResultsCmd( results ) ); + FreeDeviceInfo(); + + if ( ret != KWBXMLGeneratorOk ) + { + User::Leave( ret ); + } + + CleanupStack::PopAndDestroy(); // results + + CreateAndInitResponseItemL( KNSmlAgentResults ); + + return CNSmlCmdsBase::EReturnOK; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::DoGetL +// Generates the Get element used to ask DevInfo from the server. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::DoGetL() + { + SmlGet_t* get = new( ELeave ) SmlGet_t; + CleanupStack::PushL( get ); + get->elementType = SML_PE_GET; + + // CmdID element + DoCmdIdL( get->cmdID ); + + // Type element in Meta + SmlMetInfMetInf_t* metInf; + DoMetInfLC( metInf ); + PcdataNewL( metInf->type, KNSmlDSAgentDeviceInfoContentType ); + DoMetaL( get->meta, metInf ); + CleanupStack::Pop(); // metinf + + // Item element + get->itemList = new( ELeave ) SmlItemList_t; + get->itemList->item = new( ELeave ) SmlItem_t; + + // Item/Target element + if ( iVersionPublicId == KNSmlSyncMLPublicId ) + { + DoTargetL( get->itemList->item->target, KNSmlDSAgentDeviceInfo11URI ); + } + else if ( iVersionPublicId == KNSmlSyncMLPublicId12 ) + { + DoTargetL( get->itemList->item->target, KNSmlDSAgentDeviceInfo12URI ); + } + + TInt ret( iGenerator->smlGetCmd( get ) ); + + if ( ret != KWBXMLGeneratorOk ) + { + User::Leave( ret ); + } + + CleanupStack::PopAndDestroy(); // get + + //save Status response information for response status controlling + CreateAndInitResponseItemL( KNSmlAgentGet ); + } + +// ----------------------------------------------------------------------------- +// CNSmlCmdsBase::DoStartSyncL +// Generates the Sync element. +// ----------------------------------------------------------------------------- +// +CNSmlCmdsBase::TReturnValue CNSmlDSCmds::DoStartSyncL() + { + // initialise SyncHdr + SmlSync_t* sync = new( ELeave ) SmlSync_t; + CleanupStack::PushL( sync ); + + // element type + sync->elementType = SML_PE_SYNC_START; + + // CmdID element + DoCmdIdL( sync->cmdID ); + + // Target element + DoTargetL( sync->target, iDSContent.RemoteDatabase()->Database() ); + + // Source element + DoSourceL( sync->source, iDSContent.LocalDatabase()->Database() ); + + // free memory and max object size in the Meta element + SmlMetInfMetInf_t* metInf; + DoMetInfLC( metInf ); + DoMaxObjSizeL( *metInf, iDSContent.MaxObjSizeL() ); + DoMetaL( sync->meta, metInf ); + CleanupStack::Pop(); // metInf + + // NumberOfChanges element + DoNumberOfChangesL( sync->noc ); + + TInt ret( iGenerator->smlStartSync( sync ) ); + CNSmlCmdsBase::TReturnValue returnValue( CNSmlCmdsBase::EReturnOK ); + + switch ( ret ) + { + case KWBXMLGeneratorOk: + break; + + case KWBXMLGeneratorBufferFull: + returnValue = CNSmlCmdsBase::EReturnBufferFull; + break; + + default: + User::Leave( ret ); + } + + CleanupStack::PopAndDestroy(); // sync + + // save Status response information for response status controlling + TInt respID( CreateAndInitResponseItemL( KNSmlAgentSync ) ); + + iResponseController->SetAppIndex( respID, iDSContent.CurrentIndex() ); + + return returnValue; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::DoEndSyncL +// Generates the end tag of the Sync element and calls the WBXML generator. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::DoEndSyncL() + { + TInt ret( iGenerator->smlEndSync() ); + + if ( ret != KWBXMLGeneratorOk ) + { + User::Leave( ret ); + } + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::DoAddOrReplaceOrDeleteL +// Generates Add, Replace, Delete and Move elements and calls the parser to +// generate xml. +// ----------------------------------------------------------------------------- +// +CNSmlCmdsBase::TReturnValue CNSmlDSCmds::DoAddOrReplaceOrDeleteL() + { + DBG_FILE(_S8("CNSmlCmdsBase::TReturnValue CNSmlDSCmds::DoAddOrReplaceOrDeleteL() begins")); + TInt ret( KErrNone ); + TSmlDbItemUid localUid; + TSmlDbItemUid parentUid( KNullDataItemId ); + TBuf8 cmdName; + CNSmlDbMeta* meta( NULL ); + MSyncMLProgressObserver::TSyncMLDataSyncModifications clientModifications = { 0, 0, 0, 0, 0 }; + MSyncMLProgressObserver::TSyncMLDataSyncModifications serverModifications = { 0, 0, 0, 0, 0 }; + + if ( iLargeData ) + { + DBG_FILE(_S8("CNSmlCmdsBase::TReturnValue CNSmlDSCmds::DoAddOrReplaceOrDeleteL() iLargeData TRUE")); + cmdName = *iDSLargeObjectCmdName; + delete iDSLargeObjectCmdName; + iDSLargeObjectCmdName = NULL; + iDSContent.CurrentUID( localUid ); + DBG_FILE(_S8("CNSmlCmdsBase::TReturnValue CNSmlDSCmds::DoAddOrReplaceOrDeleteL() iLargeData TRUE ends")); + } + else + { + if ( iDataBuffer ) + { + delete iDataBuffer; + iDataBuffer = 0; + } + + iDataBuffer = CBufFlat::NewL( 1 ); + + meta = CNSmlDbMeta::NewLC(); + DBG_FILE(_S8("before OpenNextItemL")); + ret = iDSContent.OpenNextItemL( localUid, parentUid, cmdName, iItemSizeInStream, *meta ); + + iBytesSent = 0; + + switch ( ret ) + { + case KErrNone: + iItemOpened = ETrue; + break; + + case KErrEof: + CleanupStack::PopAndDestroy(); // meta + return CNSmlCmdsBase::EReturnEndData; + + case KErrNotFound: + CleanupStack::PopAndDestroy(); // meta + iDSContent.SetCurrentItemWritten(); + serverModifications.iNumFailed = 1; + iDSObserver.OnSyncMLDataSyncModifications( iDSContent.TaskId(), clientModifications, serverModifications ); + return CNSmlCmdsBase::EReturnNotFound; + + default: + User::Leave( ret ); + } + + // check that item's data can be accepted by the server + TInt maxObjSize( iDSContent.MaxObjSizeInServer() ); + + if ( maxObjSize > 0 ) + { + if ( iItemSizeInStream > maxObjSize ) + { + CleanupStack::PopAndDestroy(); // meta + iDSContent.SetCurrentItemWritten(); + iDSContent.SetAsReceivedL( localUid ); + + if ( iItemOpened ) + { + iItemOpened = EFalse; + iDSContent.CloseItemL(); + } + + serverModifications.iNumFailed = 1; + iDSObserver.OnSyncMLDataSyncModifications( iDSContent.TaskId(), clientModifications, serverModifications ); + return CNSmlCmdsBase::EReturnSkipped; + } + } + } + + // begin to process the data + CNSmlCmdsBase::TReturnValue returnValue( CNSmlCmdsBase::EReturnOK ); + + // initialise command element + SmlGenericCmd_t* genericCmd = new ( ELeave ) SmlGenericCmd_t; + CleanupStack::PushL( genericCmd ); + + DBG_FILE(_S8("before DoCmdIdL")); + // CmdID element + DoCmdIdL( genericCmd->cmdID ); + + // Item element + genericCmd->itemList = new ( ELeave ) SmlItemList_t; + + // if in the middle of a large item then there's no need to recreate it + if ( (iLargeData) && (iLargeObjectItem) ) + { + DBG_FILE(_S8("LARGE")); + genericCmd->itemList->item = iLargeObjectItem; + iLargeObjectItem = NULL; + } + else + { + DBG_FILE(_S8("NO LARGE")); + genericCmd->itemList->item = new ( ELeave ) SmlItem_t; + + // Source element + TBuf<16> unicodeId; + unicodeId.Num( localUid ); + + DoSourceL( genericCmd->itemList->item->source, unicodeId ); + + if ( parentUid != KNullDataItemId ) + { + TBuf8<16> parentDes; + + if ( parentUid == KDbItemUidRoot ) + { + parentDes.Append( KNSmlRoot ); + } + else + { + parentDes.Num( parentUid ); + } + + genericCmd->itemList->item->sourceParent = new ( ELeave ) sml_source_or_target_parent_s; + PcdataNewL ( genericCmd->itemList->item->sourceParent->locURI, parentDes ); + } + + if ( cmdName == KNSmlAgentAdd || cmdName == KNSmlAgentReplace || cmdName == KNSmlAgentPartialReplace ) + { + if ( meta ) + { + SmlMetInfMetInf_t* metaInf = meta->MetInfL(); + + if ( metaInf ) + { + DoMetaL( genericCmd->itemList->item->meta, metaInf ); + } + } + } + } + + // generate command + if ( cmdName == KNSmlAgentAdd || cmdName == KNSmlAgentReplace || cmdName == KNSmlAgentPartialReplace ) + { + // set data + TPtr8 bufPtr( 0, 0 ); + TInt bufPos( iDataBuffer->Size() ); + + if ( iItemSizeInStream - iBytesSent > iMaxWorkspaceSize ) + { + iDataBuffer->ResizeL( iMaxWorkspaceSize ); + } + else + { + iDataBuffer->ResizeL( iItemSizeInStream - iBytesSent ); + } + + bufPtr.Set( iDataBuffer->Ptr( bufPos ) ); + bufPtr.SetLength( 0 ); + iDSContent.ReadItemL( bufPtr ); + + delete genericCmd->itemList->item->data; + genericCmd->itemList->item->data = NULL; + PcdataNewL( genericCmd->itemList->item->data, iDataBuffer->Ptr( 0 ) ); + + // fill in the correct element structure + DBG_FILE_CODE( genericCmd->itemList->item->data->length, _S8("length")); + if ( genericCmd->itemList->item->data->length >= KNSmlLargeObjectMinSize ) + { + DBG_FILE(_S8("iLargeData SET TRUE")); + DBG_FILE_CODE( genericCmd->itemList->item->data->length, _S8("length")); + iLargeData = ETrue; + iGenerator->SetContentLength( iItemSizeInStream ); + iGenerator->SetTruncate( ETrue ); + } + + if ( cmdName == KNSmlAgentAdd ) // Add + { + DBG_FILE(_S8("KNSmlAgentAdd")); + genericCmd->elementType = SML_PE_ADD; + ret = iGenerator->smlAddCmd( genericCmd ); + serverModifications.iNumAdded = 1; + } + else if ( cmdName == KNSmlAgentReplace ) // Replace + { + DBG_FILE(_S8("KNSmlAgentReplace")); + genericCmd->elementType = SML_PE_REPLACE; + ret = iGenerator->smlReplaceCmd( genericCmd ); + serverModifications.iNumReplaced = 1; + } + else if ( cmdName == KNSmlAgentPartialReplace ) // PartialReplace + { + DBG_FILE(_S8("KNSmlAgentPartialReplace")); + SmlMetInfMetInf_t* metInf; + DoMetInfLC( metInf ); + PcdataNewL( metInf->fieldLevel, KNullDesC8() ); + DoMetaL( genericCmd->meta, metInf ); + CleanupStack::Pop(); // metInf + genericCmd->elementType = SML_PE_REPLACE; + ret = iGenerator->smlReplaceCmd( genericCmd ); + serverModifications.iNumReplaced = 1; + } + } + else if ( cmdName == KNSmlAgentDelete ) // Delete + { + DBG_FILE(_S8("KNSmlAgentDelete")); + genericCmd->elementType = SML_PE_DELETE; + ret = iGenerator->smlDeleteCmd( genericCmd ); + serverModifications.iNumDeleted = 1; + } + else if ( cmdName == KNSmlAgentMove ) // Move + { + DBG_FILE(_S8("KNSmlAgentMove")); + genericCmd->elementType = SML_PE_MOVE; + ret = iGenerator->smlMoveCmd( genericCmd ); + serverModifications.iNumMoved = 1; + } + else // SoftDelete + { + DBG_FILE(_S8("SoftDelete")); + genericCmd->elementType = SML_PE_DELETE; + genericCmd->flags += SmlSftDel_f; + ret = iGenerator->smlDeleteCmd( genericCmd ); + serverModifications.iNumDeleted = 1; + } + DBG_FILE_CODE( ret, _S8("ret")); + + switch ( ret ) + { + case KWBXMLGeneratorOk: + if ( iGenerator->WasTruncated() ) + { + DBG_FILE(_S8("WasTruncated TRUE")); + if ( genericCmd->itemList->item->data->length < iGenerator->DataConsumed() ) + { + DBG_FILE_CODE( iBytesSent, _S8("iBytesSent")); + iBytesSent += genericCmd->itemList->item->data->length; + DBG_FILE_CODE( iBytesSent, _S8("iBytesSent")); + } + else + { + DBG_FILE_CODE( iBytesSent, _S8("iBytesSent")); + iBytesSent += iGenerator->DataConsumed(); + DBG_FILE_CODE( iBytesSent, _S8("iBytesSent")); + } + + // change item's ownership from struct to this class + iLargeObjectItem = genericCmd->itemList->item; + genericCmd->itemList->item = NULL; + + if ( iLargeData ) + { + delete iDSLargeObjectCmdName; + iDSLargeObjectCmdName = NULL; + iDSLargeObjectCmdName = cmdName.AllocL(); + } + + if ( iGenerator->DataConsumed() < iDataBuffer->Size() ) + { + iDataBuffer->Delete( 0, iGenerator->DataConsumed() ); + iDataBuffer->Compress(); + } + else + { + delete iDataBuffer; + iDataBuffer = NULL; + } + + returnValue = CNSmlCmdsBase::EReturnBufferFull; + } + else + { + DBG_FILE(_S8("WasTruncated FALSE")); + iDSContent.SetCurrentItemWritten(); + + if ( cmdName != KNSmlAgentDelete && cmdName != KNSmlAgentMove ) + { + iBytesSent += genericCmd->itemList->item->data->length; + DBG_FILE_CODE( genericCmd->itemList->item->data->length, _S8("length")); + DBG_FILE_CODE( iBytesSent, _S8("iBytesSent")); + if ( iBytesSent == iItemSizeInStream ) + { + DBG_FILE(_S8("iLargeData SET FALSE")); + iLargeData = EFalse; + } + } + + } + break; + + case KWBXMLGeneratorBufferFull: + DBG_FILE(_S8("KWBXMLGeneratorBufferFull")); + delete iDSLargeObjectCmdName; + iDSLargeObjectCmdName = NULL; + iDSLargeObjectCmdName = cmdName.AllocL(); + returnValue = CNSmlCmdsBase::EReturnBufferFull; + DBG_FILE(_S8("KWBXMLGeneratorBufferFull end")); + break; + + default: + DBG_FILE_CODE( ret, _S8("ret")); + User::Leave( ret ); + } + + DBG_FILE(_S8("before SetTruncate( EFalse )")); + iGenerator->SetTruncate( EFalse ); + + if ( ret == KWBXMLGeneratorOk ) + { + DBG_FILE(_S8("KWBXMLGeneratorOk")); + TInt respID( CreateAndInitResponseItemL( cmdName ) ); + TBuf8<16> localDes; + localDes.Num( localUid ); + iResponseController->SetLUIDL( respID, localDes ); + iResponseController->SetAppIndex( respID, iDSContent.CurrentIndex() ); + + if ( returnValue == CNSmlCmdsBase::EReturnBufferFull ) + { + DBG_FILE(_S8("iLargeData SET TRUE after EReturnBufferFull")); + iResponseController->SetMoreData( respID ); + iLargeData = ETrue; + } + } + + if ( !iLargeData ) + { + DBG_FILE(_S8("!iLargeData")); + iItemOpened = EFalse; + iDSContent.CloseItemL(); + } + + CleanupStack::PopAndDestroy(); // genericCmd + + if ( meta ) + { + CleanupStack::PopAndDestroy(); // meta + } + + if ( returnValue == CNSmlCmdsBase::EReturnOK ) + { + iDSObserver.OnSyncMLDataSyncModifications( iDSContent.TaskId(), clientModifications, serverModifications ); + } + + DBG_FILE_CODE( returnValue, _S8("returnValue")); + return returnValue; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::DoMapL +// Build a structure for the Map command. +// ----------------------------------------------------------------------------- +// +CNSmlCmdsBase::TReturnValue CNSmlDSCmds::DoMapL() + { + if ( !iDSContent.MapExists() ) + { + return EReturnEndData; + } + + SmlMap_t* map = new( ELeave ) SmlMap_t; + CleanupStack::PushL( map ); + map->elementType = SML_PE_MAP; + + // CmdID element + DoCmdIdL( map->cmdID ); + + // Target element + DoTargetL( map->target, iDSContent.RemoteDatabase()->Database() ); + + // Source element + DoSourceL( map->source, iDSContent.LocalDatabase()->Database() ); + + map->mapItemList = iDSContent.MapItemListL(); + + TInt ret( iGenerator->smlMapCmd( map ) ); + CNSmlCmdsBase::TReturnValue returnValue( CNSmlCmdsBase::EReturnOK ); + + switch ( ret ) + { + case KWBXMLGeneratorOk: + iDSContent.RemoveMap(); + break; + + case KWBXMLGeneratorBufferFull: + iDSContent.SetMapItemList( map->mapItemList ); //map item list is returned + map->mapItemList = NULL; //to the buffer + returnValue = CNSmlCmdsBase::EReturnBufferFull; + break; + + default: + User::Leave( ret ); + } + + CleanupStack::PopAndDestroy(); // map + + if ( returnValue != CNSmlCmdsBase::EReturnBufferFull ) + { + // save Status response information for response status controlling + TInt respID( CreateAndInitResponseItemL( KNSmlAgentMap ) ); + iResponseController->SetAppIndex( respID, iDSContent.CurrentIndex() ); + } + + return returnValue; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessResultsCmdL +// Processes DevInfo in the Results command that was received from the server. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessResultsCmdL( SmlResults_t* aResults ) + { + TInt statusID( iStatusToServer->CreateNewStatusElementL() ); + + iStatusToServer->SetCmdRefL( statusID, aResults->cmdID ); + iStatusToServer->SetCmdL( statusID, KNSmlAgentResults ); + + if ( iStatusToServerNoResponse ) + { + iStatusToServer->SetNoResponse( statusID, ETrue ); + } + else + { + iStatusToServer->SetNoResponse( statusID, EFalse ); + } + + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusOK ); + + // Is synchronisation already interrupted? + if ( iDSContent.AllDatabasesAreInterrupted() ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusCommandFailed ); + return; + } + + if ( aResults->cmdID->length == 0 ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlCmdIDMissing, EFalse, EFalse ); + return; + } + + // content type + if ( !IsDevInfoContentTypeOkL( aResults->meta, statusID ) ) + { + return; + } + + // source + if ( !SourceIsUnderItem( aResults->itemList ) ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlResultsItemSourceMissing, EFalse, EFalse ); + return; + } + + CNSmlURI* deviceInfoURI( CNSmlURI::NewLC() ); + + if ( iVersionPublicId == KNSmlSyncMLPublicId ) + { + deviceInfoURI->SetDatabaseL( KNSmlDSAgentDeviceInfo11URI ); + } + else if ( iVersionPublicId == KNSmlSyncMLPublicId12 ) + { + deviceInfoURI->SetDatabaseL( KNSmlDSAgentDeviceInfo12URI ); + } + + HBufC* resultsSource; + PCDATAToUnicodeLC( *aResults->itemList->item->source->locURI, resultsSource ); + resultsSource->Des().TrimRight(); + CNSmlURI* resultsSourceURI = CNSmlURI::NewLC(); + resultsSourceURI->SetDatabaseL( *resultsSource ); + + if ( !resultsSourceURI->IsEqualL( *deviceInfoURI ) ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlResultsItemSourceInvalid, EFalse, EFalse ); + CleanupStack::PopAndDestroy( 3 ); // resultsSourceURI, resultsSource, deviceInfoURI + return; + } + + CleanupStack::PopAndDestroy( 3 ); // resultsSourceURI, resultsSource, deviceInfoURI + + // Device Info in Data element + if ( !aResults->itemList->item->data ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlDSError::ESmlDSDeviceInfoMissing, EFalse, EFalse ); + return; + } + + if ( !aResults->itemList->item->data->content ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlDSError::ESmlDSDeviceInfoMissing, EFalse, EFalse ); + return; + } + + TPtrC8 deviceInfo( static_cast( aResults->itemList->item->data->content ), aResults->itemList->item->data->length ); + + ParseDeviceInfoL( statusID, deviceInfo ); + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessPutCmdL +// Handle the Put command from the server. DevInfo element in the command is +// processed. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessPutCmdL( SmlPut_t* aPut ) + { + TInt statusID( iStatusToServer->CreateNewStatusElementL() ); + + iStatusToServer->SetCmdRefL( statusID, aPut->cmdID ); + iStatusToServer->SetCmdL( statusID, KNSmlAgentPut ); + + if ( iStatusToServerNoResponse || IsFlagSet( aPut->flags, SmlNoResp_f ) ) + { + iStatusToServer->SetNoResponse( statusID, ETrue ); + } + else + { + iStatusToServer->SetNoResponse( statusID, EFalse ); + } + + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusOK ); + + // Is synchronisation already interrupted? + if ( iDSContent.AllDatabasesAreInterrupted() ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusCommandFailed ); + return; + } + + if ( aPut->cmdID->length == 0 ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlCmdIDMissing, EFalse, EFalse ); + return; + } + + // content type + if ( !IsDevInfoContentTypeOkL( aPut->meta, statusID ) ) + { + return; + } + + // source + if ( !SourceIsUnderItem( aPut->itemList ) ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlPutItemSourceMissing, EFalse, EFalse ); + return; + } + + CNSmlURI* deviceInfoURI( CNSmlURI::NewLC() ); + + if ( iVersionPublicId == KNSmlSyncMLPublicId ) + { + deviceInfoURI->SetDatabaseL( KNSmlDSAgentDeviceInfo11URI ); + } + else if ( iVersionPublicId == KNSmlSyncMLPublicId12 ) + { + deviceInfoURI->SetDatabaseL( KNSmlDSAgentDeviceInfo12URI ); + } + + HBufC* putSource; + PCDATAToUnicodeLC( *aPut->itemList->item->source->locURI, putSource ); + putSource->Des().TrimRight(); + CNSmlURI* putSourceURI = CNSmlURI::NewLC(); + putSourceURI->SetDatabaseL( *putSource ); + + if ( !putSourceURI->IsEqualL( *deviceInfoURI ) ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlPutItemSourceInvalid, EFalse, EFalse ); + CleanupStack::PopAndDestroy( 3 ); // putSourceURI, putSource, deviceInfoURI + return; + } + + CleanupStack::PopAndDestroy( 3 ); // putSourceURI, putSource, deviceInfoURI + + // Device Info in Data element + if ( !aPut->itemList->item->data ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlDSError::ESmlDSDeviceInfoMissing, EFalse, EFalse ); + return; + } + + if ( !aPut->itemList->item->data->content ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlDSError::ESmlDSDeviceInfoMissing, EFalse, EFalse ); + return; + } + + TPtrC8 deviceInfo( static_cast( aPut->itemList->item->data->content ), aPut->itemList->item->data->length ); + + ParseDeviceInfoL( statusID, deviceInfo ); + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessGetCmdL +// Handles the DevInfo request from the server in the Get command. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessGetCmdL( SmlGet_t* aGet ) + { + TInt statusID( iStatusToServer->CreateNewStatusElementL() ); + + iStatusToServer->SetCmdRefL( statusID, aGet->cmdID ); + iStatusToServer->SetCmdL( statusID, KNSmlAgentGet ); + + if ( iAtomicModeOn ) + { + iStatusToServer->SetAtomicOrSequenceId( statusID, iAtomicId ); + } + + if ( iStatusToServerNoResponse || IsFlagSet( aGet->flags, SmlNoResp_f ) ) + { + iStatusToServer->SetNoResponse( statusID, ETrue ); + } + else + { + iStatusToServer->SetNoResponse( statusID, EFalse ); + } + + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusOK ); + + // Is synchronisation already interrupted? + if ( iDSContent.AllDatabasesAreInterrupted() ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusCommandFailed ); + return; + } + + // cmdID + if ( aGet->cmdID->length == 0 ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlCmdIDMissing, EFalse, EFalse ); + return; + } + + // atomic command has failed + if ( iAtomicHasFailed ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusCommandFailed ); + return; + } + + TPtrC8 cmdID( static_cast( aGet->cmdID->content ), aGet->cmdID->length ); + + delete iDSGetCmdId; + iDSGetCmdId = NULL; + iDSGetCmdId = cmdID.AllocL(); + + delete iDSGetMsgId; + iDSGetMsgId = NULL; + iDSGetMsgId = iCurrServerMsgID->AllocL(); + + // content type + if ( !IsDevInfoContentTypeOkL( aGet->meta, statusID ) ) + { + return; + } + + // target + if ( !TargetIsUnderItem( aGet->itemList ) ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlGetItemTargetMissing, EFalse, EFalse ); + return; + } + + HBufC* getTarget; + PCDATAToUnicodeLC( *aGet->itemList->item->target->locURI, getTarget ); + getTarget->Des().TrimRight(); + CNSmlURI* deviceInfoURI = CNSmlURI::NewLC(); + + if ( iVersionPublicId == KNSmlSyncMLPublicId ) + { + deviceInfoURI->SetDatabaseL( KNSmlDSAgentDeviceInfo11URI ); + } + else if ( iVersionPublicId == KNSmlSyncMLPublicId12 ) + { + deviceInfoURI->SetDatabaseL( KNSmlDSAgentDeviceInfo12URI ); + } + + CNSmlURI* getTargetURI( CNSmlURI::NewLC() ); + + getTargetURI->SetDatabaseL( *getTarget ); + + if ( !getTargetURI->IsEqualL( *deviceInfoURI ) ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlGetItemTargetInvalid, EFalse, EFalse ); + CleanupStack::PopAndDestroy( 3 ); // getTargetURI, deviceInfoURI, getTarget + return; + } + + CleanupStack::PopAndDestroy( 3 ); // getTargetURI, deviceInfoURI, getTarget + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessAlertCmdL +// Handles the Alert command from a server. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessAlertCmdL( SmlAlert_t* aAlert, TBool aNextAlert, TBool aServerAlert, TBool aDisplayAlert ) + { + TBool databaseExists( EFalse ); + TBool initAlert( ETrue ); + + if ( aNextAlert || aServerAlert || aDisplayAlert ) + { + initAlert = EFalse; + } + + TInt statusID( iStatusToServer->CreateNewStatusElementL() ); + + iStatusToServer->SetCmdRefL( statusID, aAlert->cmdID ); + iStatusToServer->SetCmdL( statusID, KNSmlAgentAlert ); + + if ( iStatusToServerNoResponse || IsFlagSet( aAlert->flags, SmlNoResp_f ) ) + { + iStatusToServer->SetNoResponse( statusID, ETrue ); + } + else + { + iStatusToServer->SetNoResponse( statusID, EFalse ); + } + + if ( iAtomicHasFailed ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusCommandFailed ); + return; + } + + if ( aNextAlert && iDSContent.AllDatabasesAreInterrupted() ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusCommandFailed ); + return; + } + else + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusOK ); + } + + if ( aAlert->itemList ) + { + if ( aAlert->itemList->item ) + { + iStatusToServer->AddTargetRefL( statusID, aAlert->itemList->item->target ); + iStatusToServer->AddSourceRefL( statusID, aAlert->itemList->item->source ); + } + else + { + iStatusToServer->AddTargetRefL( statusID, NULL ); + iStatusToServer->AddSourceRefL( statusID, NULL ); + } + } + else + { + iStatusToServer->AddTargetRefL( statusID, NULL ); + iStatusToServer->AddSourceRefL( statusID, NULL ); + } + + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusOK ); + + // Next Sync anchor in Item/Meta element + if ( initAlert ) + { + if ( aAlert->itemList ) + { + if ( aAlert->itemList->item ) + { + if ( aAlert->itemList->item->meta ) + { + if ( aAlert->itemList->item->meta->content && aAlert->itemList->item->meta->contentType == SML_PCDATA_EXTENSION && aAlert->itemList->item->meta->extension == SML_EXT_METINF ) + { + SmlMetInfMetInf_t* metInf; + metInf = (SmlMetInfMetInf_t*) aAlert->itemList->item->meta->content; + if ( metInf->anchor ) + { + iStatusToServer->AddItemDataL( statusID, aAlert->itemList->item->meta ); + } + } + } + } + } + } + + TBool errorInCmdID( EFalse ); + + if ( aAlert->cmdID->length == 0 ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlCmdIDMissing, EFalse, EFalse ); + errorInCmdID = ETrue; + } + + if ( aServerAlert ) + { + databaseExists = MatchServerAlertL( aAlert, statusID ); + + if ( !databaseExists ) + { + return; + } + + iDSContent.SetAsServerAlerted(); + iDSContent.InitSyncLogEventL( *iAgent->SyncLog() ); + } + + // DisplayAlert + if( aDisplayAlert ) + { + if ( !aAlert->itemList ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlAlertInvalid, EFalse, EFalse ); + return; + } + if( !aAlert->itemList->item ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlAlertInvalid, EFalse, EFalse ); + return; + } + + //Read min and max times + // MINDT + TInt mindt = AlertParameter( aAlert->itemList->item->data, KNSmlDSAgentMINDT ); + // MAXDT + TInt maxdt = AlertParameter( aAlert->itemList->item->data, KNSmlDSAgentMAXDT ); + + HBufC* alertData = AlertDataLC( aAlert->itemList ); + + //Fill notifier params + TSyncMLDlgNotifParams params; + params.iNoteType = ESyncMLInfoNote; + params.iServerMsg = TBufC(alertData->Des()); + + CleanupStack::PopAndDestroy(); //alertData + + //Pack data and start notifier + RNotifier notifier; + User::LeaveIfError( notifier.Connect() ); + CleanupClosePushL(notifier); + + TPckgBuf resBuf; + + TRequestStatus status; + + TSyncMLDlgNotifParamsPckg data(params); + + notifier.StartNotifierAndGetResponse( status, KSyncMLDlgNotifierUid, data, resBuf ); + User::WaitForRequest(status); + + CleanupStack::PopAndDestroy(); //notifier, + + return; + } + + // Target element + if ( initAlert ) + { + if ( !TargetIsUnderItem( aAlert->itemList ) ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlAlertTargetLocURIMissing, EFalse, EFalse ); + } + else + { + HBufC* alertTarget; + PCDATAToUnicodeLC( *aAlert->itemList->item->target->locURI, alertTarget ); + alertTarget->Des().TrimRight(); + CNSmlURI* alertTargetURI = CNSmlURI::NewLC( iSentSyncHdrSource->HostName() ); + alertTargetURI->SetDatabaseL( *alertTarget ); + databaseExists = iDSContent.SetIndexByLocalDatabaseL( *alertTargetURI ); + CleanupStack::PopAndDestroy(); // alertTargetURI + + if ( !databaseExists ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusNotFound ); + } + + CleanupStack::PopAndDestroy(); // alertTarget + + if ( databaseExists && iDSContent.Interrupted() ) + { + if ( !errorInCmdID ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusCommandFailed ); + } + return; + } + } + if ( !databaseExists ) + { + return; + } + } + + // Alert Code in Data element + if ( !aAlert->data ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlAlertCodeMissing, EFalse, EFalse ); + } + else if ( !aAlert->data->content ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlAlertCodeMissing, EFalse, EFalse ); + } + else + { + TPtr8 alertCode( static_cast( aAlert->data->content ), aAlert->data->length, aAlert->data->length ); + + TrimRightSpaceAndNull( alertCode ); + + if ( alertCode.Length() == 0 ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlAlertCodeMissing, EFalse, EFalse ); + } + if ( aNextAlert ) + { + if ( alertCode != KNSmlDSAgentNextMessage ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusCommandFailed ); + iAgent->Interrupt( TNSmlError::ESmlAlertCodeInvalid, EFalse, EFalse ); + } + } + else + { + if ( ( alertCode != KNSmlDSTwoWay ) && ( alertCode != KNSmlDSSlowSync ) && ( alertCode != KNSmlDSTwoWayByServer ) ) + { + if ( !iDSContent.IsSupportedSyncTypeL( alertCode ) ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusOptFeatureNotSupported ); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlDSError::ESmlDSUnsupportedSyncType, EFalse, EFalse ); + } + } + //RD_SUSPEND_RESUME + if(iDSContent.GetSessionResumed()) + { + TNSmlPreviousSyncType prevalertcode=iDSContent.PreviousSyncTypeL(); + TBool refreshrequired=EFalse; + refreshrequired=iDSContent.GetRefreshRequired(); + //Checks if the Sync Type of the Resumed session and Suspened session is same + if(prevalertcode!=ETypeNotSet && alertCode.Compare(CNSmlDSAgent::MapAlertCode(prevalertcode))!=0) + { + //Sesion is interrupted if the Resumed command rejected by the Server with status code 508 &Sync Type other than 201 + //or if Resume command accepted by Server with 200 & Sync Type different than the Suspened session + if(refreshrequired && alertCode.Compare(KNSmlDSSlowSync)!=0 || !refreshrequired) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusCommandFailed); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlDSError::ESmlDSUnsupportedSyncType, EFalse, EFalse ); + } + //If the Resume session is rejected by the Server,Client modifications need to be sent in Pacakge#3 + else if(refreshrequired && alertCode.Compare(KNSmlDSSlowSync)==0) + { + iDSContent.SetSessionResumedL(EFalse); + } + } + } + //RD_SUSPEND_RESUME + + } + + if ( databaseExists ) + { + if ( !iDSContent.Interrupted() ) + { + if ( initAlert || aServerAlert ) + { + // MaxObjSize + TInt maxObjSize( ServerMaxObjSize( aAlert->itemList->item->meta ) ); + + if ( maxObjSize > 0 ) + { + iDSContent.SetMaxObjSizeInServer( maxObjSize ); + } + } + + // update content specific data + if ( initAlert ) + { + iDSContent.SetSyncTypeL( alertCode ); + iDSContent.SetInitAlertReceived(); + } + + if ( aServerAlert ) + { + SwitchAlertCode( alertCode ); + iDSContent.SetSyncTypeL( alertCode ); + } + } + } + } + + // status 406 is returned if is present BUT the session continues + if ( aAlert->itemList->item ) + { + if ( aAlert->itemList->item->target ) + { + if ( aAlert->itemList->item->target->filter ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusOptFeatureNotSupported ); + } + } + } + } + +// --------------------------------------------------------- +// CNSmlDSCmds::AlertParameter() +// +// --------------------------------------------------------- +TInt CNSmlDSCmds::AlertParameter( const SmlPcdata_t* aData, const TDesC8& aParamID ) const + { + TInt valueNum = 0; + if ( aData ) + { + if ( aData->content ) + { + TPtr8 parameters( (TUint8*) aData->content, aData->length, aData->length ); + TrimRightSpaceAndNull( parameters ); + TInt startPos = parameters.Find( aParamID ); + if ( startPos >= 0 ) + { + if ( parameters.Length() > startPos + aParamID.Length() ) + { + TPtrC8 strPart = parameters.Right( parameters.Length() - ( startPos + aParamID.Length() ) ); + TInt length = 0; + while ( length < strPart.Length() ) + { + TChar character = strPart[length]; + if ( character.IsDigit() ) + { + ++length; + } + else + { + break; + } + } + TPtrC8 valueStr = strPart.Left( length ); + TLex8 lexicalValue( valueStr ); + if ( lexicalValue.Val( valueNum ) != KErrNone ) + { + valueNum = 0; + } + } + } + } + } + return valueNum; + } +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessSyncL +// Handles the Sync command from a server. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessSyncL( SmlSync_t* aSync ) + { + TBool databaseExists( EFalse ); + TInt statusID( iStatusToServer->CreateNewStatusElementL() ); + + iBatchModeOn = EFalse; + + iStatusToServer->SetCmdRefL( statusID, aSync->cmdID ); + iStatusToServer->SetCmdL( statusID, KNSmlAgentSync ); + + if ( iStatusToServerNoResponse || IsFlagSet( aSync->flags, SmlNoResp_f ) ) + { + iStatusToServer->SetNoResponse( statusID, ETrue ); + } + else + { + iStatusToServer->SetNoResponse( statusID, EFalse ); + } + + iStatusToServer->AddTargetRefL( statusID, aSync->target ); + iStatusToServer->AddSourceRefL( statusID, aSync->source ); + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusOK ); + + if ( iAtomicModeOn ) + { + iStatusToServer->SetAtomicOrSequenceId( statusID, iAtomicId ); + } + + // cmdID + if ( aSync->cmdID->length == 0 ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlCmdIDMissing, EFalse, EFalse ); + } + + // Local Database in Target element + if ( !aSync->target ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlSyncTargetLocURIMissing, EFalse, EFalse ); + } + else + { + if ( !aSync->target->locURI ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlSyncTargetLocURIMissing, EFalse, EFalse ); + } + else + { + HBufC* syncTarget( NULL ); + + PCDATAToUnicodeLC( *aSync->target->locURI, syncTarget ); + syncTarget->Des().TrimRight(); + + if ( syncTarget->Length() == 0 ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlError::ESmlSyncTargetLocURIMissing, EFalse, EFalse ); + } + else + { + CNSmlURI* syncTargetURI = CNSmlURI::NewLC( iSentSyncHdrSource->HostName() ); + + syncTargetURI->SetDatabaseL( *syncTarget ); + databaseExists = iDSContent.SetIndexByLocalDatabaseL( *syncTargetURI ); + + if ( iMoreData ) + { + if ( !syncTargetURI->IsEqualL( *iDSPreviousSyncTargetURI ) ) + { + ResetLargeObjectBuffer(); + iAgent->SetEndOfDataAlertRequest(); + } + } + + delete iDSPreviousSyncTargetURI; + iDSPreviousSyncTargetURI = syncTargetURI; + CleanupStack::Pop(); // syncTargetURI + } + + CleanupStack::PopAndDestroy(); // syncTarget + } + } + + if ( !databaseExists ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusNotFound ); + iAgent->Interrupt( TNSmlError::ESmlSyncTargetLocURIInvalid, EFalse, EFalse ); + + if ( iAtomicModeOn ) + { + iAtomicHasFailed = ETrue; + } + } + + // Is synchronisation already interrupted? + // Is sync type one-way from client? + if ( databaseExists ) + { + if ( iDSContent.Interrupted() || iDSContent.SyncType() == KNSmlDSOneWayFromClient + || iDSContent.SyncType() == KNSmlDSRefreshFromClient + || iDSContent.SyncType() == KNSmlDSOneWayFromClientByServer + || iDSContent.SyncType() == KNSmlDSRefreshFromClientByServer ) + + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusCommandFailed ); + return; + } + } + + // ensure that transactions are supported if the atomic mode is on + if ( databaseExists && iAtomicModeOn ) + { + if ( !iDSContent.SupportsOperationL( KUidSmlSupportTransaction ) ) + { + iAtomicHasFailed = ETrue; + } + else + { + iDSContent.BeginTransActionL(); + } + } + + // Format + TPtrC8 format; + + if ( !IsChrFormat( aSync->meta, format ) ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + SmlPcdata_t* data( NULL ); + PcdataNewL( data, format ); + CleanupStack::PushL( data ); + iStatusToServer->AddItemDataL( statusID, data ); + CleanupStack::PopAndDestroy(); // data + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlFormatNotSupported, EFalse, EFalse ); + } + + // MaxObjSize + if ( databaseExists ) + { + TInt maxObjSize( ServerMaxObjSize( aSync->meta ) ); + + if ( maxObjSize > 0 ) + { + iDSContent.SetMaxObjSizeInServer( maxObjSize ); + } + } + + // NumberOfChanges + if ( databaseExists ) + { + TInt nocNum( -1 ); + TBool NocNumReceived( EFalse ); + if ( !iDSContent.ServerItemCountAsked() ) + { + // If new number of changes info is received + if ( aSync->noc ) + { + if ( aSync->noc->content ) + { + TPtr8 nocStr( static_cast( aSync->noc->content ), + aSync->noc->length, aSync->noc->length ); + TrimRightSpaceAndNull( nocStr ); + TLex8 lexicalValue( nocStr ); + + if ( lexicalValue.Val( nocNum ) == KErrNone ) + { + NocNumReceived = ETrue; + iDSContent.SetServerItemCount( nocNum ); + } + } + } + // else number of changes information is not received + if ( !NocNumReceived ) + { + iDSContent.SetServerItemCount( nocNum ); + } + iDSObserver.OnSyncMLSyncProgress( + MSyncMLProgressObserver::ESmlReceivingModificationsFromServer, + iDSContent.ServerItemCount(), 0 ); + } + + // If number of changes is more than batch limit then batch is used if + // plug in adapter supports batch mode + if ( iDSContent.ServerItemCount() >= KNSmlBatchLimit && !iMoreData ) + { + if ( iDSContent.SupportsOperationL( KUidSmlSupportBatch ) ) + { + iBatchModeOn = ETrue; + iDSContent.BeginBatchL(); + + if ( !iBatchBuffer ) + { + iBatchBuffer = new ( ELeave ) CNSmlDSBatchBuffer; + } + else + { + iBatchBuffer->Reset(); + } + } + } + } + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessEndSyncL +// Handles the end of the Sync command. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessEndSyncL() + { + if ( iDSContent.ContentIndexIsSet() ) + { + CommitBatchL(); + } + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessUpdatesL +// Processes received Add, Replace, Move and Delete commands. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessUpdatesL( const TDesC8& aCmd, SmlGenericCmd_t* aContent ) + { + // Is the sync previously interrupted? + TBool alreadyInterrupted ( EFalse ); + + if ( iDSContent.AllDatabasesAreInterrupted() ) + { + alreadyInterrupted = ETrue; + } + else + { + if ( !iDSContent.ContentIndexIsSet() ) + { + alreadyInterrupted = ETrue; + } + else + { + if ( iDSContent.Interrupted() ) + { + alreadyInterrupted = ETrue; + } + } + } + + if ( !aContent->itemList ) + { + return; + } + else + { + if ( !aContent->itemList->item ) + { + return; + } + } + + SmlItemList_t* itemList( aContent->itemList ); + SmlItem_t* item( aContent->itemList->item ); + + do + { + TBool processUpdate( EFalse ); + + if ( alreadyInterrupted ) + { + StatusDataToGenericCommandL( aCmd, aContent, item, TNSmlError::ESmlStatusCommandFailed ); + } + else if ( iAtomicHasFailed ) + { + StatusDataToGenericCommandL( aCmd, aContent, item, TNSmlError::ESmlStatusCommandFailed ); + } + else + { + TBool typeAndFormatOK( EFalse ); + + if ( iMoreData ) + { + typeAndFormatOK = ETrue; + } + else + { + if ( CheckAndSetReceivedMediaTypeL( aCmd, aContent, item ) ) + { + if ( IsFormatOkL( aCmd, aContent, item ) ) + { + typeAndFormatOK = ETrue; + } + } + } + + if ( typeAndFormatOK ) + { + TSmlDbItemUid parent; + TBool resumeBatchMode( EFalse ); + HBufC8* sourceParent( NULL ); + + processUpdate = ETrue; + + // check if SourceParent is received + if ( !IsParentOkL( item->targetParent, parent ) ) + { + if ( IsParentOkLC( item->sourceParent, sourceParent ) ) + { + if ( iBatchModeOn ) + { + CommitBatchL(); + resumeBatchMode = ETrue; + } + + if ( !iDSContent.MapSourceParent( *sourceParent, parent ) ) + { + TInt statusId; + + if ( aCmd == KNSmlAgentMove ) + { + statusId = StatusDataToGenericCommandL( aCmd, aContent, item, TNSmlError::ESmlStatusMoveFailed ); + } + else + { + statusId = StatusDataToGenericCommandL( aCmd, aContent, item, TNSmlError::ESmlStatusCommandFailed ); + } + + processUpdate = EFalse; + + if ( iAtomicModeOn ) + { + iStatusToServer->SetAtomicOrSequenceId( statusId, iAtomicId ); + iAtomicHasFailed = ETrue; + } + } + } + // Move MUST include either TargetParent or SourceParent + else if ( aCmd == KNSmlAgentMove ) + { + processUpdate = EFalse; + StatusDataToGenericCommandL( aCmd, aContent, item, TNSmlError::ESmlStatusIncompleteCommand ); + } + } + + if ( processUpdate ) + { + HBufC8* cmdLUID( NULL ); + HBufC8* cmdGUID( NULL ); + + if ( aCmd == KNSmlAgentReplace || aCmd == KNSmlAgentDelete || aCmd == KNSmlAgentMove ) + { + if ( IsLUIDOkLC( aCmd, aContent, item, cmdLUID ) ) + { + UpdateL( aCmd, aContent, item, *cmdLUID, parent ); + } + else + { + processUpdate = EFalse; + + if ( iAtomicModeOn ) + { + iAtomicHasFailed = ETrue; + } + } + } + else // Add + { + if ( IsGUIDOkLC( aCmd, aContent, item, cmdGUID ) ) + { + UpdateL( aCmd, aContent, item, *cmdGUID, parent ); + } + else + { + processUpdate = EFalse; + + if ( iAtomicModeOn ) + { + iAtomicHasFailed = ETrue; + } + } + } + + if ( cmdGUID ) + { + CleanupStack::PopAndDestroy(); // cmdGUID; + } + + if ( cmdLUID ) + { + CleanupStack::PopAndDestroy(); // cmdLUID; + } + } + + if ( sourceParent ) + { + CleanupStack::PopAndDestroy(); // sourceParent + } + + if ( resumeBatchMode ) + { + iDSContent.BeginBatchL(); + } + } + } + + // if no updates were done then the item has failed + if ( !processUpdate ) + { + MSyncMLProgressObserver::TSyncMLDataSyncModifications clientModifications = { 0, 0, 0, 0, 0 }; + MSyncMLProgressObserver::TSyncMLDataSyncModifications serverModifications = { 0, 0, 0, 0, 0 }; + + clientModifications.iNumFailed = 1; + iDSObserver.OnSyncMLDataSyncModifications( iDSContent.TaskId(), clientModifications, serverModifications ); + + if ( iDSContent.ContentIndexIsSet() ) + { + iDSContent.IncreaseServerItemsFailed(); + } + } + + // next item + item = NULL; + + if ( itemList->next ) + { + itemList = itemList->next; + + if ( itemList->item ) + { + item = itemList->item; + } + } + } while ( item ); + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessAtomicL +// Processes the Atomic command. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessAtomicL( SmlAtomic_t* aAtomic ) + { + TInt statusId( iStatusToServer->CreateNewStatusElementL() ); + + iStatusToServer->SetCmdRefL( statusId, aAtomic->cmdID ); + iStatusToServer->SetCmdL( statusId, KNSmlAgentAtomic ); + + if ( iStatusToServerNoResponse || IsFlagSet( aAtomic->flags, SmlNoResp_f ) ) + { + iStatusToServer->SetNoResponse( statusId, ETrue ); + } + else + { + iStatusToServer->SetNoResponse( statusId, EFalse ); + } + + if ( iDSContent.AllDatabasesAreInterrupted() ) + { + iStatusToServer->SetStatusCodeL( statusId, TNSmlError::ESmlStatusAtomicFailed ); + return; + } + + ++iAtomicId; + + if ( iDSContent.ContentIndexIsSet() ) + { + if ( iDSContent.SupportsOperationL( KUidSmlSupportTransaction) ) + { + iAtomicHasFailed = EFalse; + iDSContent.BeginTransActionL(); + iStatusToServer->SetStatusCodeL( statusId, TNSmlError::ESmlStatusOK ); + iStatusToServer->SetAtomicOrSequenceId( statusId, iAtomicId ); + } + else + { + iAtomicHasFailed = ETrue; + iStatusToServer->SetStatusCodeL( statusId, TNSmlError::ESmlStatusAtomicFailed ); + } + } + else + { + iAtomicHasFailed = EFalse; + iStatusToServer->SetStatusCodeL( statusId, TNSmlError::ESmlStatusOK ); + iStatusToServer->SetAtomicOrSequenceId( statusId, iAtomicId ); + } + + iAtomicModeOn = ETrue; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessEndAtomicL +// Handles the end of the Atomic command. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessEndAtomicL() + { + TInt resultCode; + + iDSContent.SaveCurrentIndex(); + iDSContent.SetToFirst(); + + do + { + if ( iDSContent.BatchModeOn() ) + { + CommitBatchL(); + } + } + while ( iDSContent.SetToNext() ); + + iDSContent.SetIndexToSaved(); + + if ( iAtomicHasFailed ) + { + iDSContent.SaveCurrentIndex(); + iDSContent.SetToFirst(); + + do + { + if ( iDSContent.AtomicModeOn() ) + { + iDSContent.RemoveFailedMappingsL( iAtomicId ); + iDSContent.RevertTransactionL( resultCode ); + } + } + while ( iDSContent.SetToNext() ); + + iDSContent.SetIndexToSaved(); + + iStatusToServer->SetStatusCodesInAtomicL( iAtomicId, TNSmlError::ESmlStatusRollBackOK, EFalse ); + iStatusToServer->SetStatusCodeToAtomicOrSequenceCmdL( iAtomicId, TNSmlError::ESmlStatusAtomicFailed, KNSmlAgentAtomic ); + } + else + { + TBool atomicSucceeded( ETrue ); + iDSContent.SaveCurrentIndex(); + iDSContent.SetToFirst(); + + do + { + if ( iDSContent.AtomicModeOn() ) + { + iDSContent.CommitTransactionL( resultCode ); + + if ( resultCode != KErrNone ) + { + atomicSucceeded = EFalse; + } + } + } + while ( iDSContent.SetToNext() ); + + iDSContent.SetIndexToSaved(); + + if ( !atomicSucceeded ) + { + iStatusToServer->SetStatusCodesInAtomicL( iAtomicId, TNSmlError::ESmlStatusRollBackOK, EFalse ); + iStatusToServer->SetStatusCodeToAtomicOrSequenceCmdL( iAtomicId, TNSmlError::ESmlStatusAtomicFailed, KNSmlAgentAtomic ); + } + } + + iAtomicModeOn = EFalse; + iAtomicHasFailed = EFalse; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessSequenceL +// Processes the Sequence command. Currently this command is not supported. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessSequenceL( SmlSequence_t* /*aSequence*/ ) + { + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessEndSequence +// Handles the end of the Sequence command. Currently this command is not +// supported. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessEndSequence() + { + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::DoEndMessageL +// Generates end tag of a SyncML element and possible final flag in SyncBody. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::DoEndMessageL( TBool aFinal ) + { + TInt ret; + + if ( aFinal ) + { + ret = iGenerator->smlEndMessage( ETrue ); + } + else + { + ret = iGenerator->smlEndMessage( EFalse ); + } + + if ( ret != KWBXMLGeneratorOk ) + { + User::Leave( ret ); + } + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::MatchServerAlertL +// Constructs URIs for local and remote databases received from a server. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::MatchServerAlertL( const SmlAlert_t* aAlert, TInt aStatusID ) + { + TBool databaseExists( EFalse ); + HBufC* imeiCode = HBufC::NewLC( 50 ); + HBufC* alertTarget; + TPtr imeiCodePtr( imeiCode->Des() ); + iPhoneInfo->PhoneDataL( CNSmlPhoneInfo::EPhoneSerialNumber, imeiCodePtr ); + CNSmlURI* localURI = CNSmlURI::NewLC( *imeiCode ); + + if ( !TargetIsUnderItem( aAlert->itemList ) ) + { + alertTarget = HBufC::NewLC( 0 ); + } + else + { + PCDATAToUnicodeLC( *aAlert->itemList->item->target->locURI, alertTarget ); + alertTarget->Des().TrimRight(); + } + + localURI->SetDatabaseL( *alertTarget ); + + HBufC* alertSource; + CNSmlURI* remoteURI = CNSmlURI::NewLC(); + + *remoteURI = *iSyncServer; + + if ( !SourceIsUnderItem( aAlert->itemList ) ) + { + alertSource = HBufC::NewLC( 0 ); + } + else + { + PCDATAToUnicodeLC( *aAlert->itemList->item->source->locURI, alertSource ); + alertSource->Des().TrimRight(); + } + + remoteURI->SetDatabaseL( *alertSource ); + + SmlMetInfMetInf_t* metInf; + TPtr8 mediaType( NULL, 0, 0 ); + + if ( aAlert->itemList->item->meta ) + { + if ( aAlert->itemList->item->meta->content && + aAlert->itemList->item->meta->contentType == SML_PCDATA_EXTENSION && + aAlert->itemList->item->meta->extension == SML_EXT_METINF ) + { + metInf = (SmlMetInfMetInf_t*) aAlert->itemList->item->meta->content; + + if ( metInf->type ) + { + mediaType.Set( static_cast( metInf->type->content ), metInf->type->length, metInf->type->length ); + TrimRightSpaceAndNull( mediaType ); + } + } + } + + if( iDSContent.SetIndexByRemoteDatabaseL( *remoteURI,ETrue ) ) + { + databaseExists = ETrue; + } + else + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusNotFound ); + } + + if ( iUnknownDevice && databaseExists ) + { + databaseExists = EFalse; + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusNotFound ); + } + CleanupStack::PopAndDestroy( 5 ); // alertSource, remoteURI, alertTarget, localURI, imeiCode + + return databaseExists; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::DoDeviceInfoL +// Builds DevInfo structure. +// ----------------------------------------------------------------------------- +// +TPtrC8 CNSmlDSCmds::DoDeviceInfoL( TBool aConvert ) + { + // create generator instance first + if ( !iDSDevGenerator ) + { + iDSDevGenerator = new( ELeave ) CWBXMLDevInfGenerator; + } + + // create workspace + iDSDevGenerator->CreateWorkspaceL(); + + //initialise DevInf + SmlDevInfDevInf_t* devInf = new( ELeave ) SmlDevInfDevInf_t; + CleanupStack::PushL( devInf ); + + // VerDTD element + PcdataNewL ( devInf->verdtd, KNSmlAgentVerDTD12 ); + + // Man element (manufacturer) + HBufC* manufacturer = HBufC::NewLC( 50 ); + TPtr manufacturerPtr( manufacturer->Des() ); + iPhoneInfo->PhoneDataL( CNSmlPhoneInfo::EPhoneManufacturer, manufacturerPtr ); + HBufC8* manufacturerInUTF8( NULL ); + NSmlUnicodeConverter::HBufC8InUTF8LC( *manufacturer, manufacturerInUTF8 ); + PcdataNewL ( devInf->man, *manufacturerInUTF8 ); + CleanupStack::PopAndDestroy( 2 ); // manufacturerInUTF8, manufacturer + + PcdataNewL ( devInf->fwv, KNullDesC8() ); + + // Mod element (model name) + HBufC* model = HBufC::NewLC( 50 ); + TPtr modelPtr = model->Des(); + iPhoneInfo->PhoneDataL( CNSmlPhoneInfo::EPhoneModelId, modelPtr ); + HBufC8* modelInUTF8 = NULL; + NSmlUnicodeConverter::HBufC8InUTF8LC( *model, modelInUTF8 ); + PcdataNewL ( devInf->mod, *modelInUTF8 ); + CleanupStack::PopAndDestroy( 2 ); // modelInUTF8, model + // SwV element (software version) + PcdataNewL ( devInf->swv, iPhoneInfo->SwVersionL() ); + + PcdataNewL ( devInf->hwv, KNullDesC8() ); + + // DevId element + HBufC* devId = HBufC::NewLC( 50 ); + TPtr devIdPtr( devId->Des() ); + iPhoneInfo->PhoneDataL( CNSmlPhoneInfo::EPhoneSerialNumber, devIdPtr ); + HBufC8* devIdInUTF8( NULL ); + NSmlUnicodeConverter::HBufC8InUTF8LC( *devId, devIdInUTF8 ); + PcdataNewL ( devInf->devid, *devIdInUTF8 ); + CleanupStack::PopAndDestroy( 2 ); // devIdInUTF8, devId + + // DevTyp element + _LIT8( KDevTyp, "phone" ); + PcdataNewL ( devInf->devtyp, KDevTyp ); + + // SupportLargeObjs element + devInf->flags += SmlSupportLargeObjects_f; + + // SupportNumberOfChanges element + devInf->flags += SmlSupportNumberOfChanges_f; + + // SupportUTC element + devInf->flags += SmlUTC_f; + + // DataStore elements + SmlDevInfDatastoreList_t** currDatastorePtr = &devInf->datastore; + + iDSContent.SetToFirst(); + + do + { + if ( iDSContent.Interrupted() ) + { + continue; + } + + CDesCArray* storeNames = iDSContent.StoreNamesL(); + CleanupStack::PushL( storeNames ); + + for ( TInt i = 0; i < storeNames->Count(); i++ ) + { + CNSmlDbCaps* dbCaps; + TInt result = iDSContent.DbCapabilitiesL( dbCaps ); + + if ( result != KErrNone ) + { + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlStatusCommandFailed, EFalse, EFalse ); + continue; + } + + CleanupStack::PushL( dbCaps ); + + // DataStore begins + *currDatastorePtr = new( ELeave ) SmlDevInfDatastoreList_t; + (*currDatastorePtr)->data = dbCaps->DatastoreL(); // ownership is changed + + CNSmlURI *databaseURI = CNSmlURI::NewLC(); + databaseURI->SetDatabaseL( (*storeNames)[i], ETrue ); + HBufC8* databaseURIInUTF8; + NSmlUnicodeConverter::HBufC8InUTF8LC( databaseURI->Database(), databaseURIInUTF8 ); + delete (*currDatastorePtr)->data->sourceref; + PcdataNewL ( (*currDatastorePtr)->data->sourceref,*databaseURIInUTF8 ); + CleanupStack::PopAndDestroy( 2 ); // databaseURI, databaseURIInUTF8 + + (*currDatastorePtr)->data->filtercap = dbCaps->FilterCaps(); + + // SourceRef element + // MaxGUIDSize + PcdataNewL ( (*currDatastorePtr)->data->maxguidsize, KNSmlDSAgentMaxGUIDSize ); + // RxPref, Rx, TxPref and Tx elements are already filled by an adpater + // SyncCap begins + (*currDatastorePtr)->data->synccap = new( ELeave ) SmlDevInfSyncCap_t; + (*currDatastorePtr)->data->synccap->synctype = new( ELeave ) SmlPcdataList_t; + SmlPcdataList_t** currSynctypePtr = &(*currDatastorePtr)->data->synccap->synctype; + // Sync Type elements + + TBuf8<1> stringSyncType; + + stringSyncType.Num( (TInt) CNSmlDbCaps::ETwoWaySync ); + PcdataNewL ( (*currSynctypePtr)->data, stringSyncType ); + (*currSynctypePtr)->next = new( ELeave ) SmlPcdataList_t; + currSynctypePtr = &(*currSynctypePtr)->next; + stringSyncType.Num( (TInt) CNSmlDbCaps::ESlowTwoWaySync ); + PcdataNewL ( (*currSynctypePtr)->data, stringSyncType ); + + if ( iDSContent.IsSupportedSyncTypeL( CNSmlDbCaps::EOneWaySyncFromClient ) ) + { + (*currSynctypePtr)->next = new( ELeave ) SmlPcdataList_t; + currSynctypePtr = &(*currSynctypePtr)->next; + stringSyncType.Num( (TInt) CNSmlDbCaps::EOneWaySyncFromClient ); + PcdataNewL ( (*currSynctypePtr)->data, stringSyncType ); + } + + if ( iDSContent.IsSupportedSyncTypeL( CNSmlDbCaps::ERefreshSyncFromClient ) ) + { + (*currSynctypePtr)->next = new( ELeave ) SmlPcdataList_t; + currSynctypePtr = &(*currSynctypePtr)->next; + stringSyncType.Num( (TInt) CNSmlDbCaps::ERefreshSyncFromClient ); + PcdataNewL ( (*currSynctypePtr)->data, stringSyncType ); + } + + if ( iDSContent.IsSupportedSyncTypeL( CNSmlDbCaps::EOneWaySyncFromServer ) ) + { + (*currSynctypePtr)->next = new( ELeave ) SmlPcdataList_t; + currSynctypePtr = &(*currSynctypePtr)->next; + stringSyncType.Num( (TInt) CNSmlDbCaps::EOneWaySyncFromServer ); + PcdataNewL ( (*currSynctypePtr)->data, stringSyncType ); + } + + if ( iDSContent.IsSupportedSyncTypeL( CNSmlDbCaps::ERefreshSyncFromServer ) ) + { + (*currSynctypePtr)->next = new( ELeave ) SmlPcdataList_t; + currSynctypePtr = &(*currSynctypePtr)->next; + stringSyncType.Num( (TInt) CNSmlDbCaps::ERefreshSyncFromServer ); + PcdataNewL ( (*currSynctypePtr)->data, stringSyncType ); + } + + (*currSynctypePtr)->next = new( ELeave ) SmlPcdataList_t; + currSynctypePtr = &(*currSynctypePtr)->next; + stringSyncType.Num( (TInt) CNSmlDbCaps::EServerAlertedSync ); + PcdataNewL ( (*currSynctypePtr)->data, stringSyncType ); + + // SyncCap ends + currDatastorePtr = &(*currDatastorePtr)->next; + + CleanupStack::PopAndDestroy(); // dbCaps + } + + CleanupStack::PopAndDestroy(); // storeNames + } while ( iDSContent.SetToNext() ); + + if ( aConvert ) + { + CNSmlDbCaps* dbcaps = CNSmlDbCaps::NewLC(); + dbcaps->ConvertDeviceInfoL( devInf ); + CleanupStack::PopAndDestroy(); // dbcaps + } + + TInt ret( iDSDevGenerator->smlDeviceInfo( devInf ) ); + + CleanupStack::PopAndDestroy(); // devInf + + if ( ret != KWBXMLGeneratorOk ) + { + User::Leave( ret ); + } + + return iDSDevGenerator->Document(); + } + +// ----------------------------------------------------------------------------- +// CNSmlCmdsBase::DoTargetWithFilterL +// Makes Source or Target element with Filter. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::DoTargetWithFilterL( sml_target_s*& aTarget, const TDesC& aLocURIData) const + { + DoTargetL( aTarget, aLocURIData ); + aTarget->locName = NULL; + + if ( !iDSContent.HasFilters() ) + { + return; + } + + CNSmlFilter* filter( CNSmlFilter::NewLC() ); + + TInt retval( iDSContent.GetFilterL( filter ) ); + + if ( retval == KErrNone ) + { + aTarget->filter = filter->FilterL(); + } + else if ( retval != KErrNotSupported ) + { + User::Leave( retval ); + } + + CleanupStack::PopAndDestroy(); // filter + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::FreeDeviceInfo +// Frees resources allocated by the DevInfo generator. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::FreeDeviceInfo() + { + delete iDSDevGenerator; + iDSDevGenerator = NULL; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ParseDeviceInfoL +// Parses the given DevInfo structure. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ParseDeviceInfoL( TInt aStatusID, const TPtrC8& aDeviceInfo ) + { + CWBXMLDevInfDocHandler* devDocHandler = CWBXMLDevInfDocHandler::NewL( this ); + CleanupStack::PushL( devDocHandler ); + + CWBXMLParser* devParser = CWBXMLParser::NewL(); + CleanupStack::PushL( devParser ); + + devParser->SetDocumentHandler( devDocHandler ); + devParser->SetExtensionHandler( devDocHandler ); + RDesReadStream devReadStream( aDeviceInfo ); + devParser->SetDocumentL( devReadStream ); + TWBXMLParserError ret( KWBXMLParserErrorOk ); + iDSDeviceInfoParsed = EFalse; + + do + { + ret = devParser->ParseL(); + + if ( ret != KWBXMLParserErrorOk && ret != KWBXMLParserErrorEof ) + { + iAgent->Interrupt( TNSmlDSError::ESmlDSDeviceInfoInvalid, EFalse, EFalse ); + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusCommandFailed ); + } + } while ( ret == KWBXMLParserErrorOk && iDSDeviceInfoParsed == EFalse ); + + CleanupStack::PopAndDestroy( 2 ); // devParser, devDocHandler + } + + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessDeviceInfoL +// Processes the DevInfo structure received from a server. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessDeviceInfoL( const SmlDevInfDevInf_t& aContent ) + { + iDSDeviceInfoParsed = ETrue; + TInt statusID( iStatusToServer->LastEntryID() ); + + // VerDTD + if ( iVersionCheck ) + { + if ( !IsVersionOkL( aContent, statusID ) ) + return; + } + + if ( iVersionPublicId == KNSmlSyncMLPublicId12 ) + { + if ( !UpdateServerIdInSettingsL( aContent, statusID ) ) + return; + } + + // DataStore + SmlDevInfDatastoreList_t* currDatastore( aContent.datastore ); + SmlDevInfCtCapList_t* currCtCapList( aContent.ctcap ); + + RPointerArray dbCapArray; + CleanupStack::PushL( TCleanupItem( DeleteRPointerArray, &dbCapArray ) ); + // check if all remote databases are present in devinf + SmlDevInfDatastoreList_t* tempDatastore = currDatastore; + RPointerArray srcRefArray; + TInt count = 0; + + while( tempDatastore ) + { + if ( !tempDatastore->data ) + { + tempDatastore = tempDatastore->next; + continue; + } + HBufC8* srcRef = tempDatastore->data->sourceref->Data().AllocLC(); + TPtr8 srcRefPtr( srcRef->Des() ); + TrimRightSpaceAndNull( srcRefPtr ); + CNSmlURI* srcRefURI = CNSmlURI::NewLC( iSyncServer->HostName() ); + count = count + 2; + + srcRefURI->SetDatabaseL( *srcRef ); + srcRefArray.Append( srcRefURI ); + tempDatastore = tempDatastore->next; + } + + TBool resp( EFalse ); + if ( iRespURI ) + { + resp = ETrue; + } + if( !iDSContent.CheckValidRemoteDbL( srcRefArray, resp )) + { + // interrupt sync session, Invalid remote database error shown + iAgent->Interrupt( TNSmlError::ESmlStatusNotFound, EFalse, EFalse ); + } + + CleanupStack::PopAndDestroy( count ); + while ( currDatastore ) + { + if ( !currDatastore->data ) + { + currDatastore = currDatastore->next; + continue; + } + + CNSmlDbCaps* dbcaps = CNSmlDbCaps::NewLC(); + // If device info from server is accordant with 1.1 standard, + // copy it under correct datastore (like in 1.2) + AppendCTCapsL( *dbcaps, currDatastore->data, currCtCapList ); + + dbCapArray.Append( dbcaps ); + CleanupStack::Pop(); // dbcaps + + // SourceRef + TBool databaseExists( EFalse ); + HBufC8* sourceRef = currDatastore->data->sourceref->Data().AllocLC(); + TPtr8 sourceRefPtr( sourceRef->Des() ); + TrimRightSpaceAndNull( sourceRefPtr ); + + if ( sourceRefPtr.Length() == 0 ) + { + iStatusToServer->SetStatusCodeL( statusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlDSError::ESmlDSDatastoreSourceRefMissing, EFalse, EFalse ); + CleanupStack::PopAndDestroy(); // sourceRef + break; + } + else + { + CNSmlURI* sourceRefURI = CNSmlURI::NewLC( iSyncServer->HostName() ); + sourceRefURI->SetDatabaseL( *sourceRef ); + TBool respURIExists( EFalse ); + + if ( iRespURI ) + { + respURIExists = ETrue; + } + + databaseExists = iDSContent.SetIndexByRemoteDatabaseL( *sourceRefURI, respURIExists ); + CleanupStack::PopAndDestroy(); // sourceRefURI + } + + CleanupStack::PopAndDestroy(); // sourceRef + + if ( !databaseExists ) + { + currDatastore = currDatastore->next; + continue; + } + + if ( !IsRxTxOkL( currDatastore, statusID, dbCapArray ) ) + { + // Something wrong with Rx or Tx + break; + } + + // Sync Types + CArrayFix* syncTypeArray = new( ELeave ) CArrayFixFlat(7); + CleanupStack::PushL( syncTypeArray ); + TInt pushed( 1 ); + SmlPcdataList_t* syncTypeList( NULL ); + + if ( currDatastore->data->synccap ) + { + syncTypeList = currDatastore->data->synccap->synctype; + } + + while ( syncTypeList ) + { + if ( syncTypeList->data ) + { + HBufC8* syncType = syncTypeList->data->Data().AllocLC(); + ++pushed; + TPtr8 syncTypePtr( syncType->Des() ); + TrimRightSpaceAndNull( syncTypePtr ); + syncTypeArray->AppendL( syncType ); + } + + syncTypeList = syncTypeList->next; + } + + iDSContent.UpdateSyncTypeL( *syncTypeArray ); + CleanupStack::PopAndDestroy( pushed ); // syncType, syncTypeArray + + // Support HierarchicalSync + TInt support( 0 ); + + if ( currDatastore->data->supportHierarchicalSync ) + { + support = 1; + } + + iDSContent.UpdateSupportHierarchicalSyncL( support ); + + // Filter-rx + iDSContent.RemoveFilterCapsL(); + + if ( currDatastore->data->filterrx ) + { + SmlDevInfXmitList_t* filterRxList( currDatastore->data->filterrx ); + + while ( filterRxList ) + { + if ( filterRxList->data ) + { + HBufC8* filterRxCTType = filterRxList->data->cttype->Data().AllocLC(); + TPtr8 filterRxCTTypePtr( filterRxCTType->Des() ); + TrimRightSpaceAndNull( filterRxCTTypePtr ); + ProcessFilterCapL ( *currDatastore->data->filtercap, *filterRxCTType ); + CleanupStack::PopAndDestroy(); // filterRxCTType + } + + filterRxList = filterRxList->next; + } + } + + currDatastore = currDatastore->next; + } + + CleanupStack::PopAndDestroy(); // dbCapArray + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::IsVersionOkL +// Checks the verDTD field in DevInfo. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::IsVersionOkL( const SmlDevInfDevInf_t& aContent, TInt aStatusID ) + { + TBool versionOK( ETrue ); + HBufC8* verDTD = aContent.verdtd->Data().AllocLC(); + TPtr8 verDTDPtr( verDTD->Des() ); + TrimRightSpaceAndNull( verDTDPtr ); + + if ( verDTDPtr.Length() == 0 || verDTDPtr != *iVerDTD ) + { + versionOK = EFalse; + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusVersionNotSupported ); + SmlPcdata_t* data( NULL ); + PcdataNewL( data, *iVerDTD ); + CleanupStack::PushL( data ); + + iStatusToServer->AddItemDataL( aStatusID, data ); + CleanupStack::PopAndDestroy(); // data + + if ( verDTDPtr.Length() == 0 ) + { + iAgent->Interrupt( TNSmlError::ESmlVerDTDMissing, EFalse, EFalse ); + } + else + { + iAgent->Interrupt( TNSmlError::ESmlVerDTDNotSupported, EFalse, EFalse ); + } + } + + CleanupStack::PopAndDestroy(); // verDTD + + return versionOK; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::UpdateServerIdInSettingsL +// ServerId is dragged out of device info because OMA settings are currently +// lacking ServerId. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::UpdateServerIdInSettingsL( const SmlDevInfDevInf_t& aContent, TInt aStatusID ) + { + TBool serverIdOK( ETrue ); + HBufC8* serverId = aContent.devid->Data().AllocLC(); + TPtr8 serverIdPtr( serverId->Des() ); + TrimRightSpaceAndNull( serverIdPtr ); + + if ( serverIdPtr.Length() == 0 ) + { + serverIdOK = EFalse; + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlDSError::ESmlDSDeviceInfoInvalid, EFalse, EFalse ); + } + else + { + TInt profileId( iAgent->ProfileId() ); + CNSmlDSProfile* profile = CNSmlDSSettings::NewLC()->ProfileL( profileId ); + + if ( !profile ) + { + User::Leave( TNSmlError::ESmlErrorInSettings ); + } + else + { + CleanupStack::PushL( profile ); + HBufC* unicode( NULL ); + NSmlUnicodeConverter::HBufC16InUnicodeLC( serverIdPtr, unicode ); + + // If this is a first sync with this server, there is a default + // ServerId (='None') in the AgentLog and Authentication tables. + // It must be updated. + TInt status = iDSContent.UpdateServerIdL( *unicode ); + + if ( status == KErrNone ) + { + profile->SetStrValue( EDSProfileServerId, *unicode ); + profile->SaveL(); + } + else + { + iAgent->Interrupt( status, EFalse, EFalse ); + serverIdOK = EFalse; + } + + CleanupStack::PopAndDestroy( 2 ); //profile, uniPtr + } + CleanupStack::PopAndDestroy(); + } + + CleanupStack::PopAndDestroy(); // serverId + + return serverIdOK; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::IsRxTxOkL +// Checks that the types proposed by the server in DevInfo are supported both +// for receiving and sending. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::IsRxTxOkL( SmlDevInfDatastoreList_t* aCurrDatastore, TInt aStatusID, RPointerArray& aDbCapArray ) + { + iDSContent.RemoveCtCapsL(); + + // RxPref + TBool clientCanTransmitType( EFalse ); + HBufC8* rxPrefCTType( NULL ); + + if ( aCurrDatastore->data->rxpref ) + { + if ( aCurrDatastore->data->rxpref->cttype ) + { + rxPrefCTType = aCurrDatastore->data->rxpref->cttype->Data().AllocLC(); + TPtr8 rxPrefCTTypePtr( rxPrefCTType->Des() ); + TrimRightSpaceAndNull( rxPrefCTTypePtr ); + + if ( rxPrefCTTypePtr.Length() == 0 ) + { + CleanupStack::PopAndDestroy(); // rxPrefCTType + rxPrefCTType = NULL; + } + } + } + + if ( !rxPrefCTType ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlDSError::ESmlDSDatastoreRxPrefCTTypeMissing, EFalse, EFalse ); + return EFalse; + } + + TInt status ( KErrNone ); + TRAPD( error, status = iDSContent.IsSupportedTxL( *rxPrefCTType ) ); + + if ( error != KErrNone ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusCommandFailed ); + iAgent->Interrupt( error, EFalse, EFalse ); + CleanupStack::PopAndDestroy(); // rxPrefCTType + return EFalse; + } + + if ( status ) + { + // if client supports RxPref it is used + clientCanTransmitType = ETrue; + } + + CleanupStack::PopAndDestroy(); // rxPrefCTType + + // Rx elements + // Read only when RxPref is not supported + if ( !clientCanTransmitType ) + { + SmlDevInfXmitList_t* rxList = aCurrDatastore->data->rx; + while ( rxList ) + { + HBufC8* rxCTType = rxList->data->cttype->Data().AllocLC(); + TPtr8 rxCTTypePtr( rxCTType->Des() ); + TrimRightSpaceAndNull( rxCTTypePtr ); + + TInt status (KErrNone ); + + TRAP( error, status = iDSContent.IsSupportedTxL( *rxCTType ) ); + if ( error != KErrNone ) + { + CleanupStack::PopAndDestroy(); // rxCTType + break; + } + + if ( status ) + { + clientCanTransmitType = ETrue; + CleanupStack::PopAndDestroy(); // rxCTType + break; + } + + CleanupStack::PopAndDestroy(); //rxCTType + rxList = rxList->next; + } + } + + if ( error != KErrNone ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusCommandFailed ); + iAgent->Interrupt( error, EFalse, EFalse ); + return EFalse; + } + else + if ( !clientCanTransmitType ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + iAgent->Interrupt( TNSmlDSError::ESmlDSDatastoreRxCTTypeNotMatching, EFalse, EFalse ); + return EFalse; + } + + //txPref + TBool clientCanReceiveType( EFalse ); + HBufC8* txPrefCTType( NULL ); + + if ( aCurrDatastore->data->txpref ) + { + if ( aCurrDatastore->data->txpref->cttype ) + { + txPrefCTType = aCurrDatastore->data->txpref->cttype->Data().AllocLC(); + TPtr8 txPrefCTTypePtr( txPrefCTType->Des() ); + TrimRightSpaceAndNull( txPrefCTTypePtr ); + + if ( txPrefCTTypePtr.Length() == 0 ) + { + CleanupStack::PopAndDestroy(); // txPrefCTType + txPrefCTType = NULL; + } + } + } + + if ( !txPrefCTType ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusIncompleteCommand ); + iAgent->Interrupt( TNSmlDSError::ESmlDSDatastoreTxPrefCTTypeMissing, EFalse, EFalse ); + return EFalse; // break the loop + } + + + TRAP( error, status = iDSContent.IsSupportedRxL( *txPrefCTType )); + if ( error != KErrNone ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusCommandFailed ); + iAgent->Interrupt( error, EFalse, EFalse ); + CleanupStack::PopAndDestroy(); // txPrefCTType + return EFalse; + } + else + if ( status ) + { + iDSContent.UpdateCtCapsL( aDbCapArray ); + clientCanReceiveType = ETrue; + } + + CleanupStack::PopAndDestroy(); // txPrefCTType + + + // Tx elements + if ( !clientCanReceiveType ) + { + SmlDevInfXmitList_t* txList = aCurrDatastore->data->tx; + while ( txList ) + { + if ( txList->data ) + { + HBufC8* txCTType = txList->data->cttype->Data().AllocLC(); + TPtr8 txCTTypePtr( txCTType->Des() ); + TrimRightSpaceAndNull( txCTTypePtr ); + + TInt status ( EFalse ); + TRAP( error, status = iDSContent.IsSupportedRxL( *txCTType )); + if ( error != KErrNone ) + { + CleanupStack::PopAndDestroy(); // txCTType + break; + } + else + if ( status ) + { + clientCanReceiveType = ETrue; + iDSContent.UpdateCtCapsL( aDbCapArray ); + CleanupStack::PopAndDestroy(); // txCTType + break; + } + + CleanupStack::PopAndDestroy(); // txCTType + } + + txList = txList->next; + } + } + + if ( error != KErrNone ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusCommandFailed ); + iAgent->Interrupt( error, EFalse, EFalse ); + return EFalse; + } + else + if ( !clientCanReceiveType ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + iAgent->Interrupt( TNSmlDSError::ESmlDSDatastoreTxCTTypeNotMatching, EFalse, EFalse ); + return EFalse; + } + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessCTCapL +// Reads CTCap elements and stores them to the Agent log. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessCTCapL( SmlDevInfCtCapList_t& aCapList, const TDesC8& aCTType ) const + { + CNSmlCtCapsHandler* ctCapsHandler = new(ELeave) CNSmlCtCapsHandler( &aCapList ); + CleanupStack::PushL( ctCapsHandler ); + CArrayFix* ctCapArray = new( ELeave ) CArrayFixFlat(8); + CleanupStack::PushL( ctCapArray ); + ctCapsHandler->GetCtCapsL( *ctCapArray, aCTType ); + + if ( ctCapArray->Count() > 0 ) + { + CArrayFix* currCtCapArray = new( ELeave ) CArrayFixFlat(8); + CleanupStack::PushL( currCtCapArray ); + + for ( TInt i = 0; i < currCtCapArray->Count(); i++ ) + { + if ( (*currCtCapArray)[i].iTag == TNSmlCtCapData::ECtType ) + { + if ( (*currCtCapArray)[i].iValue == aCTType ) + { + // CtCaps of the given content type are already stored + CleanupStack::PopAndDestroy( 3 ); // currCtCapArray, ctCapArray, ctCapsHandler + return; + } + } + } + + for ( TInt j = 0; j < ctCapArray->Count(); j++ ) + { + TNSmlCtCapData ctCapData( (*ctCapArray)[j].iTag, (*ctCapArray)[j].iValue ); + currCtCapArray->AppendL( ctCapData ); + } + + CleanupStack::PopAndDestroy(); // currCtCapArray + } + + CleanupStack::PopAndDestroy( 2 ); // ctCapArray, ctCapsHandler + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ProcessFilterCapL() +// Reads FilterCap elements and stores them to the Agent log. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::ProcessFilterCapL ( SmlDevInfFilterCapList_t& aFilterCapList, const TDesC8& aCTType ) const + { + CNSmlFilterCapsHandler* filterCapsHandler = new ( ELeave ) CNSmlFilterCapsHandler ( &aFilterCapList ); + CleanupStack::PushL( filterCapsHandler ); + CArrayFix* filterCapArray = new ( ELeave ) CArrayFixFlat(8); + CleanupStack::PushL( filterCapArray ); + filterCapsHandler->GetFilterCapsL( *filterCapArray, aCTType ); + + if ( filterCapArray->Count() > 0 ) + { + CArrayFix* currFilterCapArray = new ( ELeave ) CArrayFixFlat(8); + CleanupStack::PushL( currFilterCapArray ); + iDSContent.GetSavedFilterCapsL( currFilterCapArray ); + + for ( TInt i = 0; i < currFilterCapArray->Count(); i++ ) + { + if ( (*currFilterCapArray)[i].iTag == TNSmlFilterCapData::ECtType ) + { + if ( (*currFilterCapArray)[i].iValue == aCTType ) + { + // FilterCaps of given content type are already stored + CleanupStack::PopAndDestroy( 3 ); //currFilterCapArray, filtarCapArray, filterCapsHandler + return; + } + } + } + + for ( TInt j = 0; j < filterCapArray->Count(); j++ ) + { + TNSmlFilterCapData filterCapData ( (*filterCapArray)[j].iTag, (*filterCapArray)[j].iValue ); + currFilterCapArray->AppendL ( filterCapData ); + } + + iDSContent.UpdateFilterCapsL ( currFilterCapArray ); + + CleanupStack::PopAndDestroy( ); // currFilterCapArray + } + + CleanupStack::PopAndDestroy( 2 ); // filterCapArray, filterCapsHandler + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::DoNumberOfChangesL +// Generates the NumberOfChanges element. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::DoNumberOfChangesL( SmlPcdata_t*& aNoc ) const + { + HBufC8* stringNoc = HBufC8::NewLC( 16 ); + //RD_SUSPEND_RESUME - Code commented for Usability issue. + /*if(iDSContent.SuspendedState() == EStateServerModification && iDSContent.GetSessionResumed() ) + stringNoc->Des().Num( 0 ); + else*/ + //RD_SUSPEND_RESUME + stringNoc->Des().Num( iDSContent.ClientItemCount() ); + PcdataNewL ( aNoc, *stringNoc ); + CleanupStack::PopAndDestroy(); // stringNoc + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::GetChunkL +// Buffer the received item and handles large objects. +// ----------------------------------------------------------------------------- +// +TNSmlError::TNSmlSyncMLStatusCode CNSmlDSCmds::GetChunkL( const TDesC8& aUid, const SmlItem_t* aCurrentItem, const SmlPcdata_t* aMetaInCommand, CBufBase*& aBuffer ) + { + iItemSizeInStream = 0; + TNSmlError::TNSmlSyncMLStatusCode status( TNSmlError::ESmlStatusOK ); + iMoreData = IsFlagSet( aCurrentItem->flags, SmlMoreData_f ); + DBG_ARGS(_S("iMoreData flag (GetChunk): %d"), iMoreData); + // check that the previously received chunk belongs to the same item + if ( iAmountReceived != 0 ) + { + if ( aUid != *iLargeUid ) + { + iAgent->SetEndOfDataAlertRequest(); + delete iRecBuf; + iRecBuf = NULL; + delete iLargeUid; + iLargeUid = NULL; + iServerLargeObjectSize = 0; + } + } + + if ( iMoreData && ( iAmountReceived == 0 ) ) + { + iServerLargeObjectSize = ServerObjectSize( aCurrentItem->meta ); + + if ( iServerLargeObjectSize == 0 ) + { + iServerLargeObjectSize = ServerObjectSize( aMetaInCommand ); + } + + iItemSizeInStream = iServerLargeObjectSize; + delete iLargeUid; + iLargeUid = NULL; + iLargeUid = aUid.AllocL(); + } + + iRecBuf = CBufFlat::NewL( 1 ); + + // buffer data + if ( aCurrentItem->data ) + { + if ( iItemSizeInStream == 0 ) + { + iItemSizeInStream = aCurrentItem->data->length; + } + + if ( aCurrentItem->data->content ) + { + TPtr8 data( static_cast( aCurrentItem->data->content ), aCurrentItem->data->length, aCurrentItem->data->length ); + iRecBuf->InsertL( iRecBuf->Size(), data ); + } + } + else + { + aBuffer = iRecBuf; + iRecBuf = NULL; + return status; + } + + // last / only chunk + if ( !iMoreData ) + { + TBool notFirst( iAmountReceived != 0 ); + iAmountReceived += aCurrentItem->data->length; + + if ( notFirst && ( iAmountReceived != iServerLargeObjectSize ) ) + { + status = TNSmlError::ESmlStatusSizeMismatch; + delete iRecBuf; + iRecBuf = NULL; + } + aBuffer = iRecBuf; + iRecBuf = NULL; + iAmountReceived = 0; + } + // middle chunk + else + { + iAmountReceived += aCurrentItem->data->length; + aBuffer = iRecBuf; + status = TNSmlError::ESmlStatusItemAccepted; + } + + return status; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::UpdateL +// Performs updates to local databases. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::UpdateL( const TDesC8& aCmd, const SmlGenericCmd_t* aContent, const SmlItem_t* aItem, const TDesC8& aUID, const TSmlDbItemUid aParent ) + { + TInt returnCode( KErrNone ); + TInt statusId( -1 ); + TBool resumeBatchMode( EFalse ); + TBool backToBatchMode( EFalse ); + MSyncMLProgressObserver::TSyncMLDataSyncModifications clientModifications = { 0, 0, 0, 0, 0 }; + MSyncMLProgressObserver::TSyncMLDataSyncModifications serverModifications = { 0, 0, 0, 0, 0 }; + + if ( aCmd == KNSmlAgentAdd || aCmd == KNSmlAgentReplace ) + { + TPtr8 data( 0, 0 ); + CBufBase* dataBuffer( NULL ); + TBool canGo( EFalse ); + if ( iMoreData ) + { + backToBatchMode = ETrue; + } + TNSmlError::TNSmlSyncMLStatusCode statusCode( GetChunkL( aUID, aItem, aContent->meta, dataBuffer ) ); + if ( !iMoreData && backToBatchMode ) + { + resumeBatchMode = ETrue; + } + + if ( dataBuffer ) + { + data.Set( dataBuffer->Ptr( 0 ) ); + CleanupStack::PushL( dataBuffer ); + } + + // if size of large item does not match + if ( statusCode == TNSmlError::ESmlStatusSizeMismatch ) + { + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusSizeMismatch ); + } + // check that some data was actually received + else if ( data.Length() == 0 ) + { + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusIncompleteCommand ); + } + else + { + if ( statusCode == TNSmlError::ESmlStatusOK ) + { + canGo = ETrue; + } + else if ( statusCode == TNSmlError::ESmlStatusItemAccepted ) + { + // large items are not allowed during batch mode + if ( iBatchModeOn ) + { + CommitBatchL(); + resumeBatchMode = ETrue; + } + + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusItemAccepted ); + canGo = ETrue; + } + } + + if ( canGo ) + { + SmlMetInfMetInf_t* metInf( NULL ); + + if ( aItem->meta ) + { + if ( ( aItem->meta->content ) && ( aItem->meta->contentType == SML_PCDATA_EXTENSION ) && ( aItem->meta->extension == SML_EXT_METINF ) ) + { + if ( ((SmlMetInfMetInf_t*) aItem->meta->content)->type ) + { + metInf = (SmlMetInfMetInf_t*) aItem->meta->content; + } + } + } + + if ( !metInf ) + { + if ( (aContent->meta) && ( aContent->meta->content ) && ( aContent->meta->contentType == SML_PCDATA_EXTENSION ) && ( aContent->meta->extension == SML_EXT_METINF ) ) + { + metInf = (SmlMetInfMetInf_t*) aContent->meta->content; + } + } + + CNSmlDbMetaHandler* metaHandler; + + if ( !metInf ) + { + metaHandler = new ( ELeave ) CNSmlDbMetaHandler; + } + else + { + metaHandler = new ( ELeave ) CNSmlDbMetaHandler( metInf ); + } + + CleanupStack::PushL( metaHandler ); + + if ( aCmd == KNSmlAgentAdd ) + { + if ( !iItemOpened ) + { + iItemOpened = ETrue; + + if ( !iBatchModeOn && !iMoreData ) + { + returnCode = iDSContent.CreateItemL( iNewUid, data.Length(), metaHandler->Type(), metaHandler->Version(), aParent ); + } + else if ( !iBatchModeOn ) + { + returnCode = iDSContent.CreateItemL( iNewUid, iServerLargeObjectSize, metaHandler->Type(), metaHandler->Version(), aParent ); + } + else + { + iBatchBuffer->CreateNewItemL( aCmd ); + iBatchBuffer->SetGUidL( aUID ); + returnCode = iDSContent.CreateItemL( iBatchBuffer->Uid(), data.Length(), metaHandler->Type(), metaHandler->Version(), aParent ); + } + } + + if ( returnCode == KErrNone ) + { + TRAPD( error, iDSContent.WriteItemL( data ) ); + + if ( error != KErrNone ) + { + iMoreData = EFalse; + iItemOpened = EFalse; + } + + returnCode = error; + } + + // if this is the last or the only chunk then commit it + if ( !iMoreData ) + { + if ( returnCode == KErrNone ) + { + returnCode = iDSContent.CommitItemL(); + + if ( iBatchModeOn ) + { + iBatchBuffer->Increase(); + } + } + + iItemOpened = EFalse; + + switch ( returnCode ) + { + case KErrNone: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusItemAdded ); + + if ( !iBatchModeOn ) + { + iDSContent.IncreaseServerItemsAdded(); + clientModifications.iNumAdded = 1; + + if ( !iAtomicModeOn ) + { + iDSContent.CreateNewMapItemL( iNewUid, aUID, 0 ); + } + else + { + iDSContent.CreateNewMapItemL( iNewUid, aUID, iAtomicId ); + } + } + else + { + clientModifications.iNumAdded = 1; + iBatchBuffer->SetStatusEntryId( statusId ); + } + break; + + case KErrDiskFull: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusDeviceFull ); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlLowMemory, EFalse, EFalse ); + break; + + case KErrNotSupported: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + break; + + default: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusCommandFailed ); + break; + } + } + } + else // KNSmlAgentReplace + { + TBool partialUpdate( EFalse ); + iNewUid = KNullDataItemId; + + if ( (aContent->meta) && ( aContent->meta->content ) && ( aContent->meta->contentType == SML_PCDATA_EXTENSION ) && ( aContent->meta->extension == SML_EXT_METINF ) ) + { + SmlMetInfMetInf_t* metInfForPartial( (SmlMetInfMetInf_t*)aContent->meta->content ); + + if ( metInfForPartial->fieldLevel ) + { + partialUpdate = ETrue; + } + } + + if ( !iItemOpened ) + { + iItemOpened = ETrue; + + TSmlDbItemUid uid; + + returnCode = ConvertUid( aUID, uid ); + + if ( returnCode == KErrNone && !iMoreData ) + { + returnCode = iDSContent.ReplaceItemL( uid, data.Length(), aParent, partialUpdate ); + } + else if ( returnCode == KErrNone ) + { + returnCode = iDSContent.ReplaceItemL( uid, iServerLargeObjectSize, aParent, partialUpdate ); + } + + if ( returnCode == KErrNotFound ) + { + if ( iBatchModeOn ) + { + iBatchBuffer->CreateNewItemL( aCmd ); + iBatchBuffer->SetGUidL( aUID ); + returnCode = iDSContent.CreateItemL( iBatchBuffer->Uid(), data.Length(), metaHandler->Type(), metaHandler->Version(), aParent ); + } + else + { + if ( !iMoreData ) + { + returnCode = iDSContent.CreateItemL( iNewUid, data.Length(), metaHandler->Type(), metaHandler->Version(), aParent ); + } + else + { + returnCode = iDSContent.CreateItemL( iNewUid, iServerLargeObjectSize, metaHandler->Type(), metaHandler->Version(), aParent ); + } + } + } + else + { + if ( iBatchModeOn ) + { + iBatchBuffer->CreateNewItemL( aCmd ); + iBatchBuffer->SetGUidL( aUID ); + iBatchBuffer->StoreItemDataL( data ); + iBatchBuffer->SetMetaInformationL( metaHandler ); + iBatchBuffer->SetParent( aParent ); + } + } + } + + if ( returnCode == KErrNone ) + { + TRAPD( error, iDSContent.WriteItemL( data ) ); + + if ( error != KErrNone ) + { + iMoreData = EFalse; + iItemOpened = EFalse; + } + + returnCode = error; + } + + // if this is the last or the only chunk then commit it + if ( !iMoreData ) + { + if ( returnCode == KErrNone ) + { + returnCode = iDSContent.CommitItemL(); + + if ( iBatchModeOn ) + { + iBatchBuffer->Increase(); + } + } + + iItemOpened = EFalse; + + switch ( returnCode ) + { + case KErrNone: + if ( iNewUid == KNullDataItemId ) // item to be replaced was found + { + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusOK ); + + if ( !iBatchModeOn ) + { + iDSContent.IncreaseServerItemsChanged(); + clientModifications.iNumReplaced = 1; + } + else + { + clientModifications.iNumReplaced = 1; + iBatchBuffer->SetStatusEntryId( statusId ); + } + } + else // Replace was converted to Add + { + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusItemAdded ); + + if ( !iBatchModeOn ) + { + iDSContent.IncreaseServerItemsAdded(); + clientModifications.iNumAdded = 1; + + if ( !iAtomicModeOn ) + { + iDSContent.CreateNewMapItemL( iNewUid, aUID, 0 ); + } + else + { + iDSContent.CreateNewMapItemL( iNewUid, aUID, iAtomicId ); + } + } + else + { + clientModifications.iNumAdded = 1; + iBatchBuffer->SetStatusEntryId( statusId ); + } + } + + break; + + case KErrNotFound: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusNotFound ); + break; + + case KErrDiskFull: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusDeviceFull ); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlLowMemory, EFalse, EFalse ); + break; + + case KErrNotSupported: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + break; + + default: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusCommandFailed ); + break; + } + } + } + + CleanupStack::PopAndDestroy(); // metaHandler + } + + if ( dataBuffer ) + { + CleanupStack::PopAndDestroy(); // dataBuffer + iRecBuf = NULL; + } + + if ( statusCode != TNSmlError::ESmlStatusItemAccepted ) + { + iNewUid = KNullDataItemId; + } + } + else if ( aCmd == KNSmlAgentDelete ) + { + TSmlDbItemUid uid; + + returnCode = ConvertUid( aUID, uid ); + + if ( returnCode == KErrNone ) + { + returnCode = iDSContent.DeleteItemL( uid, IsFlagSet( aContent->flags, SmlSftDel_f ) ); + } + + switch ( returnCode ) + { + case KErrNone: + if ( !iBatchModeOn ) + { + iDSContent.IncreaseServerItemsDeleted(); + clientModifications.iNumDeleted = 1; + + if ( IsFlagSet( aContent->flags, SmlArchive_f ) ) + { + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusDeleteWithoutArchive ); + } + else + { + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusOK ); + } + } + else + { + iBatchBuffer->CreateNewItemL( aCmd ); + iBatchBuffer->Increase(); + clientModifications.iNumDeleted = 1; + if ( IsFlagSet( aContent->flags, SmlArchive_f ) ) + { + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusDeleteWithoutArchive ); + } + else + { + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusOK ); + } + + iBatchBuffer->SetStatusEntryId( statusId ); + } + break; + + case KErrNotFound: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusItemIsNotDeleted ); + break; + + case KErrDiskFull: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusDeviceFull ); + iAgent->InterruptL( iDSContent.CurrentIndex(), TNSmlError::ESmlLowMemory, EFalse, EFalse ); + break; + + case KErrNotSupported: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + break; + + default: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusCommandFailed ); + break; + } + } + else if ( aCmd == KNSmlAgentMove ) + { + TSmlDbItemUid uid; + + returnCode = ConvertUid( aUID, uid ); + + if ( returnCode == KErrNone ) + { + returnCode = iDSContent.MoveItemL( uid, aParent ); + } + + switch ( returnCode ) + { + case KErrNone: + if ( !iBatchModeOn ) + { + iDSContent.IncreaseServerItemsMoved(); + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusOK ); + clientModifications.iNumMoved = 1; + } + else + { + iBatchBuffer->CreateNewItemL( aCmd ); + iBatchBuffer->Increase(); + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusOK ); + iBatchBuffer->SetStatusEntryId( statusId ); + clientModifications.iNumMoved = 1; + } + break; + + case KErrNotSupported: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusCommandFailed ); + break; + + default: + statusId = StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusMoveFailed ); + break; + } + } + + if ( iDSContent.PartiallyUpdated() ) + { + iDSContent.SetSyncStatus( CNSmlDSAgent::EServerDataPartiallyUpdated ); + } + + if ( iAtomicModeOn ) + { + iStatusToServer->SetAtomicOrSequenceId( statusId, iAtomicId ); + + if ( returnCode != KErrNone ) + { + iAtomicHasFailed = ETrue; + } + } + + if ( !iMoreData ) + { + // build the modifications struct + TInt num( clientModifications.iNumAdded ); + num += clientModifications.iNumReplaced; + num += clientModifications.iNumMoved; + num += clientModifications.iNumDeleted; + + if ( num == 0 && !iBatchModeOn ) + { + // If items are handled in Batch mode then it never goes here + // Status of batch item is handled in CommitBatchL method + clientModifications.iNumFailed = 1; + iDSContent.IncreaseServerItemsFailed(); + } + + iDSObserver.OnSyncMLDataSyncModifications( iDSContent.TaskId(), clientModifications, serverModifications ); + iDSContent.SetServerItemCount( iDSContent.ServerItemCount() - 1 ); + } + + if ( resumeBatchMode && !iMoreData ) + { + if ( iDSContent.SupportsOperationL( KUidSmlSupportBatch ) ) + { + iBatchModeOn = ETrue; + if ( !iBatchBuffer ) + { + iBatchBuffer = new ( ELeave ) CNSmlDSBatchBuffer; + } + else + { + iBatchBuffer->Reset(); + } + + iDSContent.BeginBatchL(); + } + } + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::IsDevInfoContentTypeOkL +// Validates the content type in server's DevInfo. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::IsDevInfoContentTypeOkL( const SmlPcdata_t* aMeta, TInt aStatusID ) + { + if ( !aMeta ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + iAgent->Interrupt( TNSmlError::ESmlTypeInvalid, EFalse, EFalse ); + return EFalse; + } + + if ( ( !aMeta->content ) || ( aMeta->contentType != SML_PCDATA_EXTENSION ) || ( aMeta->extension != SML_EXT_METINF ) ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + iAgent->Interrupt( TNSmlError::ESmlTypeInvalid, EFalse, EFalse ); + return EFalse; + } + + SmlMetInfMetInf_t* metInf( static_cast( aMeta->content ) ); + + if ( !metInf->type ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + iAgent->Interrupt( TNSmlError::ESmlTypeInvalid, EFalse, EFalse ); + return EFalse; + } + + if ( !metInf->type->content ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + iAgent->Interrupt( TNSmlError::ESmlTypeInvalid, EFalse, EFalse ); + return EFalse; + } + + TPtr8 deviceInfoContentType( static_cast( metInf->type->content ), metInf->type->length, metInf->type->length ); + TrimRightSpaceAndNull( deviceInfoContentType ); + + if ( deviceInfoContentType.Length() == 0 ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + iAgent->Interrupt( TNSmlError::ESmlTypeInvalid, EFalse, EFalse ); + return EFalse; + } + + if ( deviceInfoContentType != KNSmlDSAgentDeviceInfoContentType ) + { + iStatusToServer->SetStatusCodeL( aStatusID, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat ); + iAgent->Interrupt( TNSmlError::ESmlTypeInvalid, EFalse, EFalse ); + return EFalse; + } + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::IsLUIDOkLC +// Checks that LUID is present in the Target element and returns it. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::IsLUIDOkLC( const TDesC8& aCmd, const SmlGenericCmd_t* aContent, const SmlItem_t* aItem, HBufC8*& aLUID ) + { + if ( !aItem->target ) + { + StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusIncompleteCommand ); + return EFalse; + } + + if ( !aItem->target->locURI ) + { + StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusIncompleteCommand ); + return EFalse; + } + + TPtr8 LUID( static_cast( aItem->target->locURI->content ), aItem->target->locURI->length, aItem->target->locURI->length ); + TrimRightSpaceAndNull( LUID ); + aLUID = LUID.AllocLC(); + + if ( aLUID->Length() == 0 ) + { + StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusIncompleteCommand ); + CleanupStack::PopAndDestroy(); // aLUID + return EFalse; + } + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::IsGUIDOkLC +// Checks that GUID is present in the Source element and returns it. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::IsGUIDOkLC( const TDesC8& aCmd, const SmlGenericCmd_t* aContent, const SmlItem_t* aItem, HBufC8*& aGUID ) + { + if ( !aItem->source ) + { + StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusIncompleteCommand ); + return EFalse; + } + + if ( !aItem->source->locURI ) + { + StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusIncompleteCommand ); + return EFalse; + } + + TPtr8 GUID( static_cast( aItem->source->locURI->content ), aItem->source->locURI->length, aItem->source->locURI->length ); + TrimRightSpaceAndNull( GUID ); + aGUID = GUID.AllocLC(); + + if ( aGUID->Length() == 0 ) + { + StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusIncompleteCommand ); + CleanupStack::PopAndDestroy(); // aGUID + return EFalse; + } + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::IsParentOkL +// Checks that GUID is present in the Parent element and returns GUID. If GUID +// is not present then KNullDataItemId is returned. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::IsParentOkL( const sml_source_or_target_parent_s* aParent, TSmlDbItemUid& aGUID ) + { + if ( !aParent ) + { + aGUID = KNullDataItemId; + return EFalse; + } + + if ( !aParent->locURI ) + { + aGUID = KNullDataItemId; + return EFalse; + } + + TPtr8 GUID( static_cast( aParent->locURI->content ), aParent->locURI->length, aParent->locURI->length ); + TrimRightSpaceAndNull( GUID ); + + if ( GUID == KNSmlRoot ) + { + aGUID = KDbItemUidRoot; + return ETrue; + } + + TLex8 lex( GUID ); + + if ( lex.Val( aGUID ) != KErrNone ) + { + aGUID = KNullDataItemId; + return EFalse; + } + + return ETrue ; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::IsParentOkLC +// Checks that GUID is present in the Parent element and returns GUID. If GUID +// is not present then an empty descriptor is returned. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::IsParentOkLC( const sml_source_or_target_parent_s* aParent, HBufC8*& aGUID ) + { + if ( !aParent ) + { + aGUID = KNullDesC8().AllocLC(); + return EFalse; + } + + if ( !aParent->locURI ) + { + aGUID = KNullDesC8().AllocLC(); + return EFalse; + } + + TPtr8 GUID( static_cast( aParent->locURI->content ), aParent->locURI->length, aParent->locURI->length ); + TrimRightSpaceAndNull( GUID ); + + aGUID = GUID.AllocLC(); + + return ETrue ; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::IsFormatOkL +// Validates the Format element received from the server. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::IsFormatOkL( const TDesC8& aCmd, const SmlGenericCmd_t* aContent, const SmlItem_t* aItem ) + { + TPtrC8 format; + + if ( ( !IsChrFormat( aContent->meta, format ) ) || ( !IsChrFormat( aItem->meta, format ) ) ) + { + StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat, &format ); + return EFalse; + } + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::IsChrFormat +// Checks if the Format elements value is chr. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::IsChrFormat( const SmlPcdata_t* aMeta, TPtrC8& aFormat ) const + { + if ( aMeta ) + { + if ( aMeta->content && aMeta->contentType == SML_PCDATA_EXTENSION && aMeta->extension == SML_EXT_METINF ) + { + SmlMetInfMetInf_t* metInf( static_cast( aMeta->content ) ); + + if ( metInf->format ) + { + if ( metInf->format->content ) + { + TPtr8 format( static_cast( metInf->format->content ), metInf->format->length, metInf->format->length ); + TrimRightSpaceAndNull( format ); + + if ( format.Length() > 0 ) + { + if ( format != KNSmlAgentChrFormat ) + { + aFormat.Set( format ); + return EFalse; + } + } + } + } + } + } + + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds:::CheckAndSetReceivedMediaTypeL +// Validates the received media (content) type. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::CheckAndSetReceivedMediaTypeL( const TDesC8& aCmd, const SmlGenericCmd_t* aContent, const SmlItem_t* aItem ) + { + if ( aCmd == KNSmlAgentDelete ) + { + return ETrue; + } + + TPtr8 mediaType( NULL, 0, 0 ); + TBool found( EFalse ); + + // first check item level media type + if ( MediaTypeSetOkL( aItem->meta, found, mediaType, aCmd ) ) + { + return ETrue; + } + + // check under command if item level media type was not found + if ( !found ) + { + if ( MediaTypeSetOkL( aContent->meta, found, mediaType,aCmd ) ) + { + return ETrue; + } + } + + if ( found ) + { + //mediatype found but does not suppport hierarchical sync (move) + StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusOptFeatureNotSupported ); + } + else + { + StatusDataToGenericCommandL( aCmd, aContent, aItem, TNSmlError::ESmlStatusUnsupportedMediaTypeOrFormat, &mediaType ); + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds:::MediaTypeSetOkL +// If the media (content) type is OK its devcaps are set to the corresponding +// DataStore. +// ----------------------------------------------------------------------------- +// +TBool CNSmlDSCmds::MediaTypeSetOkL( const SmlPcdata_t* aMeta, TBool& aFound, TPtr8& aMediaType,const TDesC8& aCmd ) const + { + aFound = EFalse; + + if ( aMeta ) + { + if ( aMeta->content && aMeta->contentType == SML_PCDATA_EXTENSION && aMeta->extension == SML_EXT_METINF ) + { + SmlMetInfMetInf_t* metInf( (SmlMetInfMetInf_t*)aMeta->content ); + + if ( metInf->type ) + { + aMediaType.Set( static_cast( metInf->type->content ), metInf->type->length, metInf->type->length ); + TrimRightSpaceAndNull( aMediaType ); + + if ( aMediaType.Length() > 0 ) + { + aFound = ETrue; + + if ( iDSContent.SetSavedPartnerDevCapsL() == KErrNone ) + { + TInt status( KErrNone ); + TRAPD( error, status = iDSContent.IsHierarchicalSyncSupportedL( aMediaType ) ); + + if ( error != KErrNone ) + { + return EFalse; + } + + if ( aCmd == KNSmlAgentMove && !status ) + { + return EFalse; + } + + return ETrue; + } + } + } + } + } + + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::smlDeviceInfoL +// Callback function used by the DevInfo parser. +// ----------------------------------------------------------------------------- +// +Ret_t CNSmlDSCmds::smlDeviceInfoL( SmlDevInfDevInfPtr_t aContent ) + { + ProcessDeviceInfoL( *aContent ); + return 0; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::AlertDataLC() +// +// ----------------------------------------------------------------------------- +// +HBufC* CNSmlDSCmds::AlertDataLC( const SmlItemList_t* aItemList ) const + { + HBufC* unicodeData( NULL ); + + if ( aItemList ) + { + if ( aItemList->item->data->content ) + { + TPtr8 data( static_cast( aItemList->item->data->content ), aItemList->item->data->length, aItemList->item->data->length ); + TrimRightSpaceAndNull( data ); + NSmlUnicodeConverter::HBufC16InUnicodeLC( data, unicodeData ); + } + } + + if ( !unicodeData ) + { + unicodeData = HBufC::NewLC( 0 ); + } + + return unicodeData; + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::AppendCTCapsL +// +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::AppendCTCapsL( CNSmlDbCaps& aDbCaps, const SmlDevInfDatastore_t* aDataStore, SmlDevInfCtCapList_t* aCtCapList ) const + { + if ( aDataStore->sourceref ) + { + aDbCaps.SetSourceRefL( aDataStore->sourceref->Data() ); + } + + if ( aDataStore->displayname ) + { + aDbCaps.SetDisplayNameL( aDataStore->displayname->Data() ); + } + + if ( aDataStore->maxguidsize ) + { + aDbCaps.SetMaxGuidSizeL( aDataStore->maxguidsize->Data() ); + } + + if ( aDataStore->rxpref ) + { + aDbCaps.SetRxPrefL( aDataStore->rxpref->cttype->Data(), aDataStore->rxpref->verct->Data() ); + } + + if ( aDataStore->rx ) + { + SmlDevInfXmitListPtr_t rx( aDataStore->rx ); + + while ( rx ) + { + aDbCaps.AddRxL( rx->data->cttype->Data(), rx->data->verct->Data() ); + rx = rx->next; + } + } + + if ( aDataStore->txpref ) + { + aDbCaps.SetTxPrefL( aDataStore->txpref->cttype->Data(), aDataStore->txpref->verct->Data() ); + } + + if ( aDataStore->tx ) + { + SmlDevInfXmitListPtr_t tx( aDataStore->tx ); + + while ( tx ) + { + aDbCaps.AddTxL( tx->data->cttype->Data(), tx->data->verct->Data() ); + tx = tx->next; + } + } + + if ( aDataStore->supportHierarchicalSync ) + { + aDbCaps.SetSupportHierarchicalSyncL(); + } + + if ( aDataStore->synccap ) + { + SmlPcdataListPtr_t syncType( aDataStore->synccap->synctype ); + + while ( syncType ) + { + TLex8 lex( syncType->data->Data() ); + TInt type; + lex.Val( type ); + aDbCaps.SetSyncType( (CNSmlDbCaps::ENSmlSyncTypes)type ); + syncType = syncType->next; + } + } + + TInt pc( 0 ); + SmlDevInfCtCapListPtr_t ctcap( NULL ); + + if ( iVersionPublicId == KNSmlSyncMLPublicId ) + { + ctcap = aCtCapList; + } + else if ( iVersionPublicId == KNSmlSyncMLPublicId12 ) + { + ctcap = aDataStore->ctcap; + } + + while ( ctcap ) + { + if ( ctcap->data ) + { + CNSmlCtCap* cap = aDbCaps.AddCtCapLC(); + ++pc; + + if ( ctcap->data->cttype ) + { + cap->SetCtTypeL( ctcap->data->cttype->Data() ); + } + + if ( ctcap->data->verct ) + { + cap->SetVerCtL( ctcap->data->verct->Data() ); + } + + if ( ctcap->data->fieldlevel ) + { + cap->SetFieldLevelL(); + } + + if ( iVersionPublicId == KNSmlSyncMLPublicId ) + { + if( ctcap->data->prop ) + { + SmlDevInfCTDataPropListPtr_t prop( ctcap->data->prop ); + + while ( prop ) + { + if( prop->data ) + { + CNSmlDevInfProp* pr( cap->AddDevInfPropLC( prop->data->prop->name->Data() ) ); + ++pc; + + if ( prop->data->prop->datatype ) + { + pr->SetDataTypeL( prop->data->prop->datatype->Data() ); + } + + if ( prop->data->prop->dname ) + { + pr->SetDisplayNameL( prop->data->prop->dname->Data() ); + } + + if ( prop->data->prop->size ) + { + pr->SetMaxSizeL( prop->data->prop->size->Data() ); + } + + if ( prop->data->prop->valenum ) + { + SmlPcdataListPtr_t propValEnum( prop->data->prop->valenum ); + + while ( propValEnum ) + { + if ( propValEnum->data ) + { + pr->AddValEnumL( propValEnum->data->Data() ); + } + + propValEnum = propValEnum->next; + } + } + + if ( prop->data->param ) + { + SmlDevInfCTDataListPtr_t param( prop->data->param ); + + while ( param ) + { + if ( param->data ) + { + CNSmlPropParam* par( pr->AddParamLC( param->data->name->Data() ) ); + ++pc; + + if ( param->data->datatype ) + { + par->SetDataTypeL( param->data->datatype->Data() ); + } + + if ( param->data->dname ) + { + par->SetDisplayNameL( param->data->dname->Data() ); + } + + if ( param->data->valenum ) + { + SmlPcdataListPtr_t valenum( param->data->valenum ); + + while (valenum) + { + if ( valenum->data ) + { + par->AddValEnumL( valenum->data->Data() ); + } + + valenum = valenum->next; + } + } + } + + param = param->next; + } + } + } + + prop = prop->next; + } + } + } + else if ( iVersionPublicId == KNSmlSyncMLPublicId12 ) + { + if ( ctcap->data->property ) + { + SmlDevInfPropertyListPtr_t prop( ctcap->data->property ); + + while ( prop ) + { + if ( prop->data ) + { + + if ( prop->data->propname == NULL ) + { + User::Leave( KErrArgument ); + } + + CNSmlDevInfProp* pr( cap->AddDevInfPropLC(prop->data->propname->Data() ) ); + ++pc; + + if ( prop->data->datatype ) + { + pr->SetDataTypeL( prop->data->datatype->Data() ); + } + + if ( prop->data->displayname ) + { + pr->SetDisplayNameL( prop->data->displayname->Data() ); + } + + if ( prop->data->maxoccur ) + { + pr->SetMaxOccurL( prop->data->maxoccur->Data() ); + } + + if ( prop->data->maxsize ) + { + pr->SetMaxSizeL( prop->data->maxsize->Data() ); + } + + if ( prop->data->notruncate ) + { + pr->SetNoTruncateL(); + } + + if ( prop->data->propparam ) + { + SmlDevInfPropParamListPtr_t param( prop->data->propparam ); + + while ( param ) + { + if ( param->data ) + { + CNSmlPropParam* par( pr->AddParamLC( param->data->paramname->Data() ) ); + ++pc; + + if ( param->data->datatype ) + { + par->SetDataTypeL( param->data->datatype->Data() ); + } + + if ( param->data->displayname ) + { + par->SetDisplayNameL( param->data->displayname->Data() ); + } + + if ( param->data->valenum ) + { + SmlPcdataListPtr_t valenum( param->data->valenum ); + + while ( valenum ) + { + if ( valenum->data ) + { + par->AddValEnumL( valenum->data->Data() ); + } + valenum = valenum->next; + } + } + } + + param = param->next; + } + } + } + + prop = prop->next; + } + } + } + } + + ctcap = ctcap->next; + } + + CleanupStack::PopAndDestroy( pc ); + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::SwitchAlertCodeL +// Does mapping between OMA DS 1.1 and 1.2 alert codes. +// ----------------------------------------------------------------------------- +// +void CNSmlDSCmds::SwitchAlertCode( TDes8& aAlertCode ) + { + if ( aAlertCode == KNSmlDSTwoWayByServer ) + { + aAlertCode = KNSmlDSTwoWay; + } + else if ( aAlertCode == KNSmlDSOneWayFromClientByServer ) + { + aAlertCode = KNSmlDSOneWayFromClient; + } + else if ( aAlertCode == KNSmlDSRefreshFromClientByServer ) + { + aAlertCode = KNSmlDSRefreshFromClient; + } + else if ( aAlertCode == KNSmlDSOneWayFromServerByServer ) + { + aAlertCode = KNSmlDSOneWayFromServer; + } + else if ( aAlertCode == KNSmlDSRefreshFromServerByServer ) + { + aAlertCode = KNSmlDSRefreshFromServer; + } + } + +// ----------------------------------------------------------------------------- +// CNSmlDSCmds::ConvertUid +// Converts UID from literal to numeric presentation. +// ----------------------------------------------------------------------------- +// +TInt CNSmlDSCmds::ConvertUid( const TDesC8& aLiteralUid, TSmlDbItemUid& aNumericUid ) + { + TLex8 lexer( aLiteralUid ); + + aNumericUid = KNullDataItemId; + + return lexer.Val( aNumericUid ); + } + +// End of File