--- /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 <SyncMLObservers.h>
+#include <SyncMLNotifierParams.h>
+#include <SyncMLNotifier.h>
+#include <nsmlconstants.h>
+#include <nsmldebug.h>
+#include <nsmlphoneinfo.h>
+#include <nsmlunicodeconverter.h>
+// 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<TInt> 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<KNSmlMaxCmdNameLength> 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<TUint8*>( 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<TUint8*>( 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<TUint8*>( 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<KSyncMLMaxServerMsgLength>(alertData->Des());
+
+ CleanupStack::PopAndDestroy(); //alertData
+
+ //Pack data and start notifier
+ RNotifier notifier;
+ User::LeaveIfError( notifier.Connect() );
+ CleanupClosePushL(notifier);
+
+ TPckgBuf<TBool> 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<TUint8*>( 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 <Filter> 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<TUint8*>( 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<TUint8*>( 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<CNSmlDbCaps> dbCapArray;
+ CleanupStack::PushL( TCleanupItem( DeleteRPointerArray, &dbCapArray ) );
+ // check if all remote databases are present in devinf
+ SmlDevInfDatastoreList_t* tempDatastore = currDatastore;
+ RPointerArray<CNSmlURI> 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<HBufC8*>* syncTypeArray = new( ELeave ) CArrayFixFlat<HBufC8*>(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<CNSmlDbCaps>& 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<TNSmlCtCapData>* ctCapArray = new( ELeave ) CArrayFixFlat<TNSmlCtCapData>(8);
+ CleanupStack::PushL( ctCapArray );
+ ctCapsHandler->GetCtCapsL( *ctCapArray, aCTType );
+
+ if ( ctCapArray->Count() > 0 )
+ {
+ CArrayFix<TNSmlCtCapData>* currCtCapArray = new( ELeave ) CArrayFixFlat<TNSmlCtCapData>(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<TNSmlFilterCapData>* filterCapArray = new ( ELeave ) CArrayFixFlat<TNSmlFilterCapData>(8);
+ CleanupStack::PushL( filterCapArray );
+ filterCapsHandler->GetFilterCapsL( *filterCapArray, aCTType );
+
+ if ( filterCapArray->Count() > 0 )
+ {
+ CArrayFix<TNSmlFilterCapData>* currFilterCapArray = new ( ELeave ) CArrayFixFlat<TNSmlFilterCapData>(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<TUint8*>( 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<SmlMetInfMetInf_t*>( 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<TUint8*>( 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<TUint8*>( 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<TUint8*>( 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<TUint8*>( 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<TUint8*>( 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<SmlMetInfMetInf_t*>( aMeta->content ) );
+
+ if ( metInf->format )
+ {
+ if ( metInf->format->content )
+ {
+ TPtr8 format( static_cast<TUint8*>( 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<TUint8*>( 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<TUint8*>( 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