diff -r 000000000000 -r f979ecb2b13e pimappservices/calendar/server/src/agssess.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pimappservices/calendar/server/src/agssess.cpp Tue Feb 02 10:12:19 2010 +0200 @@ -0,0 +1,4310 @@ +// Copyright (c) 1997-2009 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: +// + +#include "agssess.h" + +#include "agmattachment.h" +#include "agscategoryindex.h" +#include "agscategorylist.h" +#include "agmentry.h" +#include "agsiterator.h" +#include "agsentrymodel.h" +#include "agmpanic.h" +#include "agmcategory.h" +#include "agmcontent.h" +#include "agmserv.h" +#include "agsfilemanager.h" +#include "agsmain.h" +#include "calcommonimpl.h" +#include "agmdebug.h" +#include "agmtzrules.h" +#include "agssortinstance.h" +#include "agsinstanceiterator.h" +#include "agmsortcriteria.h" +#include "agmdate.h" +#include "agssort.h" +#include "agmcalendarinfo.h" +#include "calsessionimpl.h" +#include "agmfilechangenotification.h" +#ifdef SYMBIAN_SYSTEM_STATE_MANAGEMENT +#include "agssystemstateobserver.h" +#endif + +#include +#include + +// +// CAgnServerSession +// + +const TInt KGranFilteredEntries = 20; +const TInt KMaxNumberOfBufferedNotifications = 50; +const TInt KGranNotificationBuffer = 64; + +const TInt KSlot0 = 0; +const TInt KSlot1 = 1; +const TInt KSlot2 = 2; +const TInt KSlot3 = 3; + +void CleanupCloseAgendaImmediately(TAny* aRef) + { + if (aRef) + { + static_cast(aRef)->CloseAgenda(ETrue); + } + } + +TAgnChangeFilter::TAgnChangeFilter(CAgnServerSession& aSession) : + iChangeBroadcastEnabled(ETrue), + iSession(aSession), + iStartTimeUtc(Time::NullTTime()), + iEndTimeUtc(Time::NullTTime()), + iPubSubChangeMadeDuringDisable(ENoChange), + iPubSubEnabled(ETrue) + { + } + +TBool TAgnChangeFilter::ChangeBroadcastEnabled() const + { + return iChangeBroadcastEnabled; + } + +const CAgnServerSession& TAgnChangeFilter::Session() const + { + return iSession; + } + +void TAgnChangeFilter::SetEnableChangeBroadcast(TBool aBool) + { + iChangeBroadcastEnabled = aBool; + } + +TBool TAgnChangeFilter::ChangeMadeWhileDisabled() const + { + return iChangeMadeWhileDisabled; + } + +void TAgnChangeFilter::SetChangeMadeWhileDisabled(TBool aBool) + { + iChangeMadeWhileDisabled = aBool; + } + +void TAgnChangeFilter::SetChangeParameter(const TTime& aStartTime, const TTime& aEndTime, MCalChangeCallBack2::TChangeEntryType aChangeType) + { + iStartTimeUtc = aStartTime; + iEndTimeUtc = aEndTime; + iEntryType = aChangeType; + } + +TBool TAgnChangeFilter::CheckChangeWithinRangeL(const CAgnRptDef* aRptDef, const TTime& aStartTime, const TTime& aEndTime) const + { + TBool entryInTimeRange = ETrue; + if (aRptDef) + { + TTime nudgedNextTimeUtc; + TBool nextDateExists = aRptDef->NudgeNextInstanceUtcL(iStartTimeUtc, nudgedNextTimeUtc); + if ( ! nextDateExists || nudgedNextTimeUtc > iEndTimeUtc) + { + entryInTimeRange = EFalse; + } + } + else + { + if (iStartTimeUtc > aEndTime || iEndTimeUtc < aStartTime) + { + entryInTimeRange = EFalse; + } + } + return entryInTimeRange; + } + +TBool TAgnChangeFilter::IsValidChangeL(const TAgnChange& aChange) const + { + if (aChange.iOperationType != MCalChangeCallBack2::EChangeUndefined) + { + if (iEntryType == MCalChangeCallBack2::EChangeEntryTodo && aChange.iEntryType != CCalEntry::ETodo) + { + return EFalse; + } + if (iEntryType == MCalChangeCallBack2::EChangeEntryEvent && aChange.iEntryType == CCalEntry::ETodo) + { + return EFalse; + } + + // Check the entry is within the time range specified by the filter + // aChange.iRepeatRule gives the repeat data for the newly stored entry. If this operation is an update, + // then aChange.iOriginalRepeatRule gives the repeat data for the old entry. + TBool entryInTimeRange = CheckChangeWithinRangeL(aChange.iRepeatRule, aChange.iStartTimeOfEntryUtc, aChange.iEndTimeOfEntryUtc); + TBool originalEntryInTimeRange = CheckChangeWithinRangeL(aChange.iOriginalRepeatRule, aChange.iOriginalStartTimeUtc, aChange.iOriginalEndTimeUtc); + + if (iEntryType != MCalChangeCallBack2::EChangeEntryEvent) + { + if (aChange.iEntryType == CCalEntry::ETodo && aChange.iStartTimeOfEntryUtc == Time::NullTTime() && aChange.iEndTimeOfEntryUtc == Time::NullTTime()) + { + return ETrue; + } + } + + if ( ! entryInTimeRange && ! originalEntryInTimeRange) + { + return EFalse; + } + } + return ETrue; + } + +TBool TAgnChangeFilter::PubSubEnabled() const + { + return iPubSubEnabled; + } + +void TAgnChangeFilter::SetPubSubChange(TPubSubChange aChange) + { + if(aChange==ENoChange) + {//clear all bits + iPubSubChangeMadeDuringDisable = ENoChange; // = 0 + } + else + { + iPubSubChangeMadeDuringDisable = iPubSubChangeMadeDuringDisable | aChange; + } + } + +TBool TAgnChangeFilter::TodoChanged() const + { + return iPubSubChangeMadeDuringDisable & ETodoChanged; + } + +void TAgnChangeFilter::SetEnablePubSubNotification(TBool aEnablePubSubNotification) + { + iPubSubEnabled = aEnablePubSubNotification; + } + +CAgnServerSession::CAgnServerSession(CAgnServer& aServer) + :iAgnServer(aServer), iSessionReady(ETrue) + { + iAgnServer.SessionAdded(); + } + +CAgnServerSession* CAgnServerSession::NewL(CAgnServer& aServer) + { + CAgnServerSession* self = new (ELeave) CAgnServerSession(aServer); + CleanupStack::PushL(self); + self->ConstrucL(); + CleanupStack::Pop(self); + return self; + } + +void CAgnServerSession::ConstrucL() + { + iAgnSessionFileManager = CAgnSessionFileManager::NewL(*this, *(iAgnServer.FileMgr())); + } + +void CAgnServerSession::ServiceL(const RMessage2 &aMessage) + { + TBool complete = ETrue; + TInt err = KErrNone; + iMessage = aMessage; + +#ifdef SYMBIAN_SYSTEM_STATE_MANAGEMENT + if (iAgnServer.SystemStateObserver().IsShutdownInProgress()) + { + //Shutdown in progress + err = IsReadOnlyOperation(); + complete = ETrue; + } +#endif + if (err == KErrNone) + { + TRAP(err,complete = DispatchMessageL()); + _DBGLOG_IPC(AgmDebug::DebugLogIPCL(aMessage.Function(), TInt(this), err);) + + if ( err != KErrNone ) + { + if (err == KErrNotReady && + aMessage.Function() != ETransferAttachmentFileToServer && + aMessage.Function() != ETransferFileToClientToWrite && + aMessage.Function() != ETransferAttachmentFileToClient&& + aMessage.Function() != EMoveFileToServer) + { + // If a function has failed with Not ready, then a drive must not be ready + // If it is not an attachment failure, then it must have happened on the drive containing + // the Calendar file. In this case, ensure the session always leaves with KErrNotReady + // until the session is closed and re-opened. + iSessionReady = EFalse; + } + delete iBuffer; + iBuffer = NULL; + } + } + + if (complete && err != KClientHasBeenPanicked) + { + aMessage.Complete(err); + } + } + +CAgnServerSession::~CAgnServerSession() + { + //This is required for robustness. Clients which are incorrectly + //written can make requests with MCalProgressCallBack callbacks could + //subsequently panic and cause the session to be destructed. + //The task which the client had initiated will be cancelled so it does not + //attempt to use the session again with further progress information. + + CancelAllTask(); + + // Cleanup any resources that have been allocated + delete iBuffer; + // Close the calendar file after a delay + CloseAgendas(); + iAgnServer.SessionClosed(); + delete iAgnSessionFileManager; + delete iInstanceIteratorMgr; + } + +/** +* Check to see if an operation can be performed due to backup\restore process +* @return ETrue, if the operation can not be performed, EFalse otherwise. +*/ +TBool CAgnServerSession::CheckBackupRestore() + { + if(iBackupRestoreLock + //All opeerations apart from the following ones are not allowed when Backup\Restore is in progress. + && iMessage.Function() != ECloseAgenda + && iMessage.Function() != ECancelChangeNotification + && iMessage.Function() != EDisableChangeBroadcast + && iMessage.Function() != ETransmitBuffer + && iMessage.Function() != ERequestChangeNotificationParameters + && iMessage.Function() != ERequestChangeNotification + && iMessage.Function() != EEnableChangeBroadcast + && iMessage.Function() != EGetChangesSinceLastNotification + && iMessage.Function() != ERequestProgress) + { + return ETrue; + } + + // Return false, if iBackupRestoreLock is false or operations are those above, CAgnServFile::IsLocked() + // will determine whether or not an operation can be performed. + return EFalse; + } + +TBool CAgnServerSession::DispatchMessageL() + { + TBool operationRequiresFileLock = EFalse; + TBool callIsAsynchronous = ETrue; + if(CheckBackupRestore()) + { + User::Leave(KErrLocked); + } + + switch (iMessage.Function()) + { + case EOpenAgenda: + { + OpenAgendaL(); + iSessionReady = ETrue; + } + break; + + case ECloseAgenda: + { + // Close the calendar file after a delay + CloseAgendaL(); + iSessionReady = ETrue; + } + break; + + case ERequestChangeNotificationParameters: + { + RequestChangeNotificationParametersL(); + } + break; + + case ERequestChangeNotification: + { + RequestChangeNotification(); + callIsAsynchronous = EFalse; + } + break; + + case ECancelChangeNotification: + { + CancelChangeNotification(); + } + break; + + case EDisableChangeBroadcast: + { + DisableChangeBroadcastL(); + } + break; + + case EEnableChangeBroadcast: + { + EnableChangeBroadcastL(); + } + break; + + case EAgnHeapSizeCount: + { + TInt allocSize; + User::Heap().AllocSize(allocSize); + TPckg HeapSize(allocSize); + iMessage.WriteL(KSlot0, HeapSize); + } + break; + + case EAgnResourceCount: + { + TPckg HeapCells(User::Heap().Count()); + iMessage.WriteL(KSlot0, HeapCells); + } + break; + + case EAgnSetHeapFailure: + { + User::__DbgSetAllocFail(RHeap::EUser,(RHeap::TAllocFail)iMessage.Int0(),iMessage.Int1()); + } + break; + + case ECreateAgendaFile: + { + CreateAgendaFileL(); + } + break; + + case EGetListFileNames: + { + ListAgendaFilesL(); + } + break; + + case EDeleteAgendaFile: + { + DeleteAgendaFileL(); + } + break; + + case ECancelTask: + { + CancelTaskL(); + } + break; + + case EAgendaFileExists: + { + AgendaFileExistsL(); + } + break; + + case ETransmitBuffer: + { + TransmitBufferL(); + } + break; + + case ESetUpdateAlarm: + { + SetUpdateAlarmL(); + } + break; + + case ESetEnablePubSubNotification: + { + SetEnablePubSubNotificationL(); + } + break; + + case ERequestProgress: + { + RequestProgressL(); + callIsAsynchronous = EFalse; + } + break; + + case EGetChangesSinceLastNotification: + { + GetChangesSinceLastNotificationL(); + } + break; + + case EStartBuildIndex: + { + //Asynchronous call + StartBuildIndex(); + callIsAsynchronous = EFalse; + } + break; + case ETzDbChangedTime: + { + TzRulesLastModifiedDateTimeL(); + } + break; + case ERollback: + { + RollbackL(); + } + break; + case EGetFileChangesSinceLastNotification: + { + GetFileChangesSinceLastNotificationL(); + } + break; + default: + { + operationRequiresFileLock = ETrue; + } + break; + } + + // Most commands are not permitted while the file is locked + + if ( operationRequiresFileLock ) + { + if ( ! iSessionReady) + { + User::Leave(KErrNotReady); + } + else + { + switch ( iMessage.Function() ) + { + case EFetchEntry: + { + FetchEntryL(); + } + break; + case EFetchEntryByUID: + { + FetchEntryByUIDL(); + } + break; + case EFetchSimpleEntry: + { + FetchSimpleEntryL(); + } + break; + case EFetchSimpleEntries: + { + FetchSimpleEntriesL(); + } + break; + case EUpdateEntry: + { + UpdateEntryL(); + } + break; + case EAddEntry: + { + AddEntryL(); + } + break; + case EDeleteEntry: + { + DeleteEntryL(); + } + break; + case EPreviousInstances: + { + PreviousInstancesL(); + } + break; + case ENextInstances: + { + NextInstancesL(); + } + break; + case ECreateEntryIterator: + { + CreateEntryIteratorL(); + } + break; + case EEntryIteratorNext: + { + EntryIteratorNextL(); + } + break; + case EEntryIteratorPosition: + { + EntryIteratorPositionL(); + } + break; + case ECommit: + { + CommitL(); + } + break; + case EGetEntryUidsSinceDate: + { + GetEntryUidsSinceDateL(); + } + break; + case ERestoreText: + { + RestoreTextL(); + } + break; + case ERestoreAlarmAction: + { + RestoreAlarmActionL(); + } + break; + case EGetCategoryListCount: + { + GetCategoryListCountL(); + } + break; + case EGetCategoryListItem: + { + GetCategoryListItemL(); + } + break; + case EAddCategoryToList: + { + AddCategoryToListL(); + } + break; + case ECategoryFilter: + { + FilterCategoryL(); + } + break; + case ETidyByDateReadParams: + { + TidyByDateReadParamsL(); + } + break; + case ETidyByDateStart: + { + TidyByDateStartL(); + callIsAsynchronous = EFalse; + } + break; + case ECategoryStart: + { + CategoryTaskStartL(); + } + break; + case ECategoryStartAsyn: + { + AsynchCategoryTaskStartL(); + callIsAsynchronous = EFalse; + } + break; + case EInstanceIteratorCreate: + { + CreateInstanceIteratorL(); + } + break; + case EInstanceIteratorDestroy: + { + DestroyInstanceIteratorL(); + } + break; + case EInstanceIteratorNext: + { + InstanceIteratorNextL(); + } + break; + case EInstanceIteratorPrevious: + { + InstanceIteratorPreviousL(); + } + break; + case EInstanceIteratorCount: + { + InstanceIteratorCountL(); + } + break; + case EInstanceIteratorLocateIndex: + { + InstanceIteratorLocateIndexL(); + } + break; + + // Group Scheduling + case EGetChangesSinceLastNotification: + { + GetChangesSinceLastNotificationL(); + } + break; + case EFetchEntryByGuid: + { + FetchEntryByGuidL(); + } + break; + case EFetchSimpleEntriesByGuid: + { + FetchSimpleEntriesByGuidL(); + } + break; + case EDeleteEntriesByLocalUid: + { + DeleteEntriesByLocalUidL(); + } + break; + case EDeleteEntryByGuid: + { + DeleteEntryByGuidL(); + } + break; + case EFindInstances: + { + FindInstancesL(); + } + break; + case ETransferAttachmentFileToServer: + { + TransferAttachmentFileToServerL(); + } + break; + case ETransferAttachmentFileToClient: + { + TransferAttachmentFileToClientL(); + callIsAsynchronous = EFalse; + } + break; + case ETransferFileToClientToWrite: + { + TransferFileToClientToWriteL(); + callIsAsynchronous = EFalse; + } + break; + case EFetchSortedAttachments: + { + FetchSortedAttachmentsL(); + } + break; + case EEntriesWithAttachment: + { + EntriesWithAttachmentL(); + } + break; + case EFetchAttachmentById: + { + FetchAttachmentByIdL(); + } + break; + case EMoveFileToServer: + { + MoveFileToServerL(); + } + break; + case EFetchSimpleEntryByUID: + { + FetchSimpleEntryByUIDL(); + } + break; + case ESetCalendarInfo: + { + SetCalendarInfoL(); + } + break; + case EGetCalendarInfo: + { + GetCalendarInfoL(); + } + break; + case EGetPropertyValue: + { + GetPropertyValueL(); + } + break; + default: + PanicClientL(EBadRequest); + return ETrue; + } + } + } + + // If the buffer size is greater than KInitialBufferSize, then the buffer cannot be + // transmitted now. A large enough buffer must first be created on the client side to + // hold this. + if ( iBuffer && iBuffer->Size() <= KInitialBufferSize && + iBuffer->Size() > 0 ) + { + TransmitBufferL(); + } + + return callIsAsynchronous; // complete normally + } + +void CAgnServerSession::SetUpdateAlarmL() + { + TBool updateAlarm = iMessage.Int0(); + CAgnServFile* file = GetFileL(KSlot1); + file->Model()->SetUpdateAlarmL(updateAlarm); + } + +void CAgnServerSession::SetEnablePubSubNotificationL() + { + TBool enablePubsub = iMessage.Int0(); + TPckgBuf fileId; + iMessage.ReadL(KSlot1, fileId); + + if(iAgnSessionFileManager) + { + CAgnSessionFile* client = NULL; + TRAPD(err, client = &(iAgnSessionFileManager->GetSessionFileL(fileId()))); + if(err == KErrNone && client) + { + client->SetEnablePubSubNotificationL(enablePubsub); + } + else if (err != KErrNotFound) + { + User::Leave(err); + } + } + } + +void CAgnServerSession::PanicClientL(TInt aPanic) const + { + _LIT(KAgendaServerPanic,"AgnServer"); + iMessage.Panic(KAgendaServerPanic,aPanic); + User::Leave(KClientHasBeenPanicked); + } + +// +// Utility Functions: + +HBufC* CAgnServerSession::ReadClientDesLC(TInt aDesNum) + { + const TInt KDesLength = iMessage.GetDesLength(aDesNum); + if (KDesLength == KErrArgument) + { + PanicClientL(EIndexError); + } + else if (KDesLength == KErrBadDescriptor) + { + PanicClientL(EBadDescriptor); + } + User::LeaveIfError(KDesLength); + + HBufC* readBuffer = HBufC::NewLC(KDesLength); + TPtr readPtr(readBuffer->Des()); + + TRAPD(ret, iMessage.ReadL(aDesNum, readPtr)); + if (ret != KErrNone) + { + PanicClientL(EBadDescriptor); + } + + return readBuffer; + } + + +HBufC8* CAgnServerSession::ReadClientDes8LC(TInt aDesNum) + { + const TInt KDesLength = iMessage.GetDesLength(aDesNum); + if (KDesLength == KErrArgument) + { + PanicClientL(EIndexError); + } + else if (KDesLength == KErrBadDescriptor) + { + PanicClientL(EBadDescriptor); + } + User::LeaveIfError(KDesLength); + + HBufC8* readBuffer = HBufC8::NewLC(KDesLength); + TPtr8 readPtr(readBuffer->Des()); + + TRAPD(ret, iMessage.ReadL(aDesNum, readPtr)); + if (ret != KErrNone) + { + PanicClientL(EBadDescriptor); + } + + return readBuffer; + } + +// +//Server Functions: +void CAgnServerSession::OpenAgendaL() + { + // Open a new file for this session + // Arguments: 0: Input - buffer contains name of file and session ID + // 1: Output - status + // 2: Output - file ID + // 3: Output - collection ID + // + + // Get descriptor for filename to open + const TInt KBufferSize = iMessage.GetDesLengthL(KSlot0); + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0, KBufferSize); + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot0, des); + RDesReadStream readStream(des); + HBufC* fileName = HBufC::NewLC(readStream, KMaxTInt); + TInt sessionId = readStream.ReadInt32L(); + CalCommon::TCalFileVersionSupport status; + + HBufC* nameWithPath = iAgnServer.FileMgr()->ParseFilenameLC(*fileName); + CAgnServFile* file = iAgnServer.FileMgr()->GetFile(*nameWithPath); + TInt err = KErrNone; + if(file) + { + if(IsOwnFileL(sessionId, *file)) + {//If this file has been opened by same CCalSession object + User::Leave(KErrAlreadyExists); + } + else if (FileHasBeenOpenedL(*file)) + {//If this file has been opened by a different CCalSession object + User::Leave(KErrArgument); + } + } + CleanupStack::PopAndDestroy(nameWithPath); + CloseAgendaL(sessionId);//Check if this CCalSession object has had opened a different file, if so, close it. + TRAP(err, file = &iAgnServer.FileMgr()->OpenAgendaL(*fileName, iAgnServer, status)); + CleanupStack::PopAndDestroy(fileName); + CleanupStack::PopAndDestroy(buffer); + User::LeaveIfError(err); + CleanupStack::PushL(TCleanupItem(CleanupCloseAgendaImmediately, file)); + TPckg theStatus(status); + iMessage.WriteL(KSlot1, theStatus); + + __ASSERT_ALWAYS(file, User::Leave(KErrCorrupt)); + TInt64 fileId = file->Model()->GetFileIdL(); + TCalCollectionId shortFileId = file->CollectionId(); + TPckg fileIdPackage(fileId); + iMessage.WriteL(KSlot2, fileIdPackage); + TPckg shortFileIdPackage(shortFileId); + iMessage.WriteL(KSlot3, shortFileIdPackage); + file->Model()->CategoryIndex().SetCategoryList(&(file->CategoryList())); + if(iAgnSessionFileManager->AddClientL(fileId, sessionId)) + { + file->Model()->CheckTzDbModificationL(); + } + + // This is the cleanup item to close agenda if anything fails + CleanupStack::Pop(); + } + +void CAgnServerSession::BackupReStoreChangedL(TInt64 aOldFileId, const CAgnServFile& aServFile, MCalChangeCallBack2::TChangeType aChangeType) + { + if(iAgnSessionFileManager) + { + TAgnChange change; + change.iOperationType = aChangeType; + + //reset model and file id if restore ends + if(aChangeType == MCalChangeCallBack2::ERestoreEnd) + { + iAgnSessionFileManager->ReSetModel(aOldFileId, aServFile); + change.iFileId = aServFile.Model()->GetFileIdL(); + } + else + { + change.iFileId = aOldFileId; + } + + iAgnSessionFileManager->AddChangeL(change); + } + + if(aChangeType == MCalChangeCallBack2::EBackupStart || aChangeType == MCalChangeCallBack2::ERestoreStart) + { + LockClient(ETrue); + } + else + { + LockClient(EFalse); + } + } + +void CAgnServerSession::LockClient(TBool aLock) + { + iBackupRestoreLock = aLock; + } + +/** +* Closes the calendar file in the current agenda server session immediately or after a delay. +* The delay is triggered using a timer owned by the calendar file. If a session then tries to access the same calendar file, the delay is cancelled and the file is not closed +* @param aCloseImmediately EFalse if a delay is required before the closure of the calendar file, ETrue if the calendar file is to be closed immediately +*/ +void CAgnServerSession::CloseAgendaL() + { + TInt sessionId = iMessage.Int0(); + CloseAgendaL(sessionId); + } + +void CAgnServerSession::CloseAgendaL(TInt aSessionId) + { + if(iAgnSessionFileManager) + { + TInt index = iAgnSessionFileManager->GetSessionFile(aSessionId); + CAgnServFile* file = NULL; + if(index >= 0) + { + TRAPD(err, file = iAgnServer.FileMgr()->GetFileL(iAgnSessionFileManager->GetSessionFileByIndex(index).FileId())); + if(file && err == KErrNone) + { + User::LeaveIfError(iAgnServer.FileMgr()->CloseAgenda(*file, EFalse)); + } + iAgnSessionFileManager->DeleteSessionFile(aSessionId); + } + } + } +void CAgnServerSession::FetchEntryL() + { + // Fetch an entry from the agenda file + // Arguments: 0 : Output - Data Buffer + // 1 : Input - Entry Id to fetch + // 2 : Output - Size of buffer + // 3 : Input - File Id + TPckgBuf entryId; + iMessage.ReadL(KSlot1, entryId); + + CAgnServFile* file = GetFileL(KSlot3); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + CAgnEntry* entry = file->Model()->FetchEntryL(entryId()); + + if ( entry ) + { + CleanupStack::PushL(entry); + + ExternalizeEntryToClientL(*entry, KSlot2); + + CleanupStack::PopAndDestroy(entry); + } + else + { + TPckg size(0); + iMessage.WriteL(KSlot2, size); + } + } + + +void CAgnServerSession::FetchEntryByUIDL() + { + // Fetch an entry from the agenda file + // Arguments: 0 : Output - Data Buffer + // 1 : Input - Unique Id to fetch + // 2 : Output - Size of buffer + // 3 : Input - File ID + + TPckgBuf uniqueId; + iMessage.ReadL(KSlot1, uniqueId); + + CAgnServFile* file = GetFileL(KSlot3); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + CAgnEntry* entry = file->Model()->FetchEntryL(uniqueId()); + + if ( entry ) + { + CleanupStack::PushL(entry); + + ExternalizeEntryToClientL(*entry, KSlot2); + + CleanupStack::PopAndDestroy(entry); + } + else + { + TPckg size(0); + iMessage.WriteL(KSlot2, size); + } + } + + +void CAgnServerSession::ExternalizeEntryToClientL(const CAgnEntry& aEntry, TInt aSlot) + { + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + bufStream.WriteUint32L( aEntry.Type() ); + aEntry.ExternalizeToBufferL(bufStream); + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(aSlot, size); + } + + +void CAgnServerSession::TransmitBufferL() + { + // Transmit the contents of the buffer stream to the client, + // then delete it + // Arguments: 0 : Output - Data Buffer + + if (!iBuffer) + { + PanicClientL(EBadRequest); + } + iMessage.WriteL(KSlot0, iBuffer->Ptr(0)); + + delete iBuffer; + iBuffer = NULL; + } + + +void CAgnServerSession::FetchSimpleEntryL() + { + // Fetch a lite-entry from the server + // (A lite entry consists of time information without any text) + // Arguments: 0 : Output - Data buffer + // 1 : Input - TAgnInstace + // 2 : Output - Size of buffer + const TInt KBufferSize = iMessage.GetDesLengthL(KSlot1); + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0, KBufferSize); + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot1, des); + RDesReadStream readStream(des); + TAgnEntryId entryId; + readStream >> entryId; + CleanupStack::PopAndDestroy(buffer); + + // Make sure this entry hasn't been deleted or updated TAgnInstanceId entryId = (*entryIds)[ii].iId; + TCalCollectionId collectionId = iMessage.Int3(); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(collectionId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + + const CAgnSimpleEntry* KEntry = file->Model()->GetSimpleEntryFromIndexes(entryId); + + if ( KEntry ) + { + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + // Write a bool to indicate if entry is available + bufStream.WriteUint8L(KEntry != NULL); + + bufStream.WriteUint32L(KEntry->Type()); + KEntry->ExternalizeL(bufStream, ETrue); + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot2, size); + } + else + { + TPckg emptyBuffer(0); + iMessage.WriteL(KSlot2, emptyBuffer); + } + } + +void CAgnServerSession::FetchSimpleEntryByUIDL() + { + // Fetch a lite-entry from the server + // (A lite entry is consists of time information without any text) + // Arguments: 0 : Output - Data buffer + // 1 : Input - TAgnInstace + // 2 : Output - Size of buffer + const TInt KBufferSize = iMessage.GetDesLengthL(KSlot1); + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0, KBufferSize); + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot1, des); + RDesReadStream readStream(des); + TUint32 entryId = readStream.ReadUint32L(); + CleanupStack::PopAndDestroy(buffer); + + TCalCollectionId collectionId = iMessage.Int3(); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(collectionId ); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + // Make sure this entry hasn't been deleted or updated + const CAgnSimpleEntry* KEntry = file->Model()->GetSimpleEntryFromIndexes(entryId); + + if ( KEntry ) + { + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + // Write a bool to indicate if entry is available + bufStream.WriteUint8L(KEntry != NULL); + + bufStream.WriteUint32L(KEntry->Type()); + KEntry->ExternalizeL(bufStream, ETrue); + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot2, size); + } + else + { + TPckg emptyBuffer(0); + iMessage.WriteL(KSlot2, emptyBuffer); + } + } + +void CAgnServerSession::EnsureStringsLoadedL(CAgnEntry& aEntry, TUint8 aShortFileId) + { + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(aShortFileId); + if (!aEntry.SummaryIsLoaded()) + { + HBufC* summary = file->Model()->RestoreTextL(aEntry.SummaryStreamId()); + aEntry.SetSummary(summary); + } + + if (!aEntry.DescriptionIsLoaded()) + { + HBufC* description = file->Model()->RestoreTextL(aEntry.DescriptionStreamId()); + aEntry.SetDescription(description); + } + } + +void CAgnServerSession::FetchSimpleEntriesL() + { + // Fetch an array of lite-entries from the server + // (A lite entry consists of time information without any text) + // Arguments: 0 : Output - Data buffer + // 1 : Input - TArray to fetch + // 2 : Output - Size of buffer + + CArrayFixSeg* instanceIds = new (ELeave) CArrayFixSeg(8); + CleanupStack::PushL(instanceIds); + + const TInt KDesLength = iMessage.GetDesLength(KSlot1); + if(KDesLength<0) + { + User::Leave(KErrArgument); + } + + CBufFlat* buffer = CBufFlat::NewL(KDesLength); + CleanupStack::PushL(buffer); + + buffer->ExpandL(0, KDesLength); + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot1, des); + + RBufReadStream readStream; + readStream.Open(*buffer); + CleanupClosePushL(readStream); + + const TInt KIdCount1 = readStream.ReadUint32L(); + + for ( TInt i = 0; i < KIdCount1; ++i ) + { + TAgnInstance instance; + instance.InternalizeL(readStream); + instanceIds->AppendL(instance); + } + + CleanupStack::PopAndDestroy(&readStream); // readStream.Close(); + + CleanupStack::PopAndDestroy(buffer); // buffer + + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + const TInt KIdCount2 = instanceIds->Count(); + + bufStream.WriteUint8L(KIdCount2); + + for ( TInt ii = 0; ii < KIdCount2 ; ++ii ) + { +#if defined (__CAL_VERBOSE_LOGGING__) || defined (__CAL_ENTRY_LOGGING__) + CAgnServFile* agnFile = iAgnServer.FileMgr()->GetFile((*instanceIds)[ii].iCollectionId); + CAgnEntry* fullEntry = agnFile->Model()->FetchEntryL((*instanceIds)[ii]); + CleanupStack::PushL(fullEntry); + AgmDebug::DebugLog("FetchSimpleEntriesL - Fetch entry with Id %d", (*instanceIds)[ii].Value()); + EnsureStringsLoadedL(*fullEntry, *entryIds[ii].iCollectionId); + AgmDebug::DebugLogEntryL(*fullEntry, EDumpEntryAll); + CleanupStack::PopAndDestroy(fullEntry); +#endif + TAgnInstanceId entryId = (*instanceIds)[ii].iId; + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL((*instanceIds)[ii].iCollectionId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + const CAgnSimpleEntry* KEntry = file->Model()->GetSimpleEntryFromIndexes(entryId); + + // Write a bool to indicate if entry is available + bufStream.WriteUint8L(KEntry != NULL); + + if ( KEntry ) + { + bufStream.WriteUint32L(KEntry->Type()); + KEntry->ExternalizeL(bufStream, ETrue); + bufStream.WriteUint8L((*instanceIds)[ii].iCollectionId); + } + } + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + + CleanupStack::PopAndDestroy(instanceIds); + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot2, size); + } + +void CAgnServerSession::UpdateEntryL() + { + // Updates an entry on the server + // Arguments: 0 : Input - Size of buffer + // 1 : Input - Data Buffer (containing entry data) + // 2 : Output - Entry Id of updated entry + // 3 : File ID + + // Restore length + const TInt KBufferSize = iMessage.Int0(); + + // Restore buffer + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + + buffer->ExpandL(0, KBufferSize); + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot1, des); + + // Internalize the data from the stream + RBufReadStream readStream; + readStream.Open(*buffer); + CleanupClosePushL(readStream); + + const CCalEntry::TType KEntryType = static_cast(readStream.ReadUint32L()); + + TBool deleteChildren = readStream.ReadUint8L(); + + CAgnEntry* entry = CAgnEntry::NewL(KEntryType); + CleanupStack::PushL(entry); + + entry->InternalizeFromBufferL(readStream); + + _DBGLOG_ENTRY(AgmDebug::DebugLog("Updating calendar file with entry");) + _DBGLOG_ENTRY(AgmDebug::DebugLogEntryL(*entry, EDumpEntryAll);) + + TCalCollectionId collectionId = iMessage.Int3(); + CAgnSessionFile& client = iAgnSessionFileManager->GetSessionFileL(collectionId); + client.UpdateEntryL(*entry, deleteChildren); + _DBGLOG_ENTRY(AgmDebug::DebugLog("Entry: Updated entry on file. Entry ID: %d",entry->EntryId().Value());) + + // Return entry id + TPckg entryPckg(entry->EntryId()); + iMessage.WriteL(KSlot2, entryPckg); + + CleanupStack::PopAndDestroy(entry); + CleanupStack::PopAndDestroy(&readStream); // readStream.Close(); + CleanupStack::PopAndDestroy(buffer); + } + +void CAgnServerSession::AddChangeL(const TAgnChange& aChange) + { + if(iAgnSessionFileManager) + { + iAgnSessionFileManager->AddChangeL(aChange); + } + } + +void CAgnServerSession::AddEntryL() + { + // Adds an entry to the server + // Arguments: 0 : Input - Size of buffer + // 1 : Input - Data Buffer (containing entry data) + // 2 : Output - Ids of updated entry + // 3 : Input - File Id + + + // Restore length + const TInt KBufferSize = iMessage.Int0(); + + // Restore buffer + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + + buffer->ExpandL(0, KBufferSize); + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot1, des); + + // Internalize the data from the stream + RBufReadStream readStream; + readStream.Open(*buffer); + CleanupClosePushL(readStream); + + const CCalEntry::TType KEntryType = (CCalEntry::TType) readStream.ReadUint32L(); + CAgnEntry* entry = CAgnEntry::NewL(KEntryType); + CleanupStack::PushL(entry); + + entry->InternalizeFromBufferL(readStream); + + TAgnEntryParameters params; + TPckgBuf fileId; + iMessage.ReadL(KSlot3, fileId); + CAgnSessionFile& client = iAgnSessionFileManager->GetSessionFileL(fileId()); + params.iEntryId = client.StoreEntryL(*entry); + params.iLocalId = entry->LocalUid(); + params.iRecurrenceId = entry->RecurrenceId().LocalL(); + params.iLastModifiedDateUtc = entry->LastModifiedDateUtc(); + params.iRecurrenceRange = entry->RecurrenceRange(); + + if (entry->TimeMode() != MAgnCalendarTimeMode::EFloating && entry->RptDef() != NULL ) + { + CAgnTzRules* tzRules = entry->RptDef()->AgnTzRules(); + if(tzRules != NULL) + { + params.iTzStreamId = (tzRules->TzZoneStreamId()); + params.iSystemTzRule = (tzRules->SystemTzRule()); + } + } + + // Set entry Id and unique Id + TPckg paramsPckg(params); + iMessage.WriteL(KSlot2, paramsPckg); + + CleanupStack::PopAndDestroy(entry); // entry + CleanupStack::PopAndDestroy(&readStream); // readStream.Close(); + CleanupStack::PopAndDestroy(buffer); // buffer + } + +/** +Called when a new attachment is stored with a file handle. +The file handle is transferred to the server side and the file is moved to the Calendar store. +*/ +void CAgnServerSession::TransferAttachmentFileToServerL() + { + // Arguments: 0 - Output : Attachment Data - local UID of entry and index of attachment on that entry + // 1 - Input : Attachment UID of new attachment + // 2,3 - FS : Used by file server to transfer file from client to agenda server + + RFile file; + CleanupClosePushL(file); + + User::LeaveIfError(file.AdoptFromClient(iMessage, KTransferAttachmentToSrvFsArgIndex, KTransferAttachmentToSrvFileArgIndex)); + + const TInt KBufferSize = iMessage.GetDesLengthL(KSlot0); + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0, KBufferSize); + + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot0, des); + + RDesReadStream readStream(des); + TCalLocalUid localUid = readStream.ReadUint32L(); + TInt attachmentIndex = readStream.ReadInt16L(); + TInt64 fileId; + readStream >> fileId; + + CAgnServFile* agnFile = iAgnServer.FileMgr()->GetFileL(fileId); + TPckg attachUid = agnFile->Model()->TransferAttachmentFileToServerL(file, localUid, attachmentIndex); + iMessage.WriteL(1, attachUid); + CleanupStack::PopAndDestroy(); + CleanupStack::PopAndDestroy(&file); // file.Close() + } + +void CAgnServerSession::MoveFileToServerL() + { + const TInt KBufferSize = iMessage.GetDesLengthL(KSlot0); + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0, KBufferSize); + + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot0, des); + + RDesReadStream readStream(des); + TCalLocalUid localUid = readStream.ReadUint32L(); + TInt attachmentIndex = readStream.ReadInt16L(); + TInt64 fileId; + readStream >> fileId; + + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId); + TPckg attachUid = file->Model()->MoveFileToServerL(localUid, attachmentIndex); + iMessage.WriteL(1, attachUid); + CleanupStack::PopAndDestroy(); + } +/** +Called when a file attachment is fetched from the client. +The file handle is opened on the server side then transferred to the client. +*/ +void CAgnServerSession::TransferAttachmentFileToClientL() + { + // Arguments: 0 - Output : Attachment UID of file attachment to send to client + // 1 - FS : Used by file server to transfer file from agenda server to client + // 2 - File Id : Long file id of the calendar file + TCalAttachmentUid attachmentUid = iMessage.Int0(); + + RFile file; + CleanupClosePushL(file); + + TPckgBuf fileId; + iMessage.ReadL(KSlot2, fileId); + CAgnServFile* agnServfile = iAgnServer.FileMgr()->GetFileL(fileId()); + agnServfile->Model()->OpenAttachmentFileL(file, attachmentUid); + + TPckg pckgSubSessionHandle(file.SubSessionHandle()); + iMessage.WriteL(KTransferAttachmentToCliFileArgIndex, pckgSubSessionHandle); + + User::LeaveIfError(file.TransferToClient(iMessage, KTransferAttachmentToCliFileArgIndex)); + + CleanupStack::PopAndDestroy(&file); // file.Close() + } + +/** +Called when a new attachment is stored with binary data. +The new file handle is opened on the server side, then transferred to the client side where the data is written directly onto the file. +This means that the binary data is not passed directly over IPC. +*/ +void CAgnServerSession::TransferFileToClientToWriteL() + { + // Arguments: 0 - Output : Attachment data of new file attachment to be created + // 1 - FS : Used by file server to transfer new file from agenda server to client + // 2 - Input : File Id + // 3 - Output : Size of attachment data that will be written to file handle on client side + TAttachmentData data; + TPckg pckgData(data); + iMessage.ReadL(0, pckgData); + TInt dataSize = iMessage.Int3(); + + RFile file; + CleanupClosePushL(file); + + TPckgBuf fileId; + iMessage.ReadL(KSlot2, fileId); + CAgnServFile* agnServFile = iAgnServer.FileMgr()->GetFileL(fileId()); + HBufC* fileName = agnServFile->Model()->GenerateRandomFilenameLC(data.iDrive); + agnServFile->Model()->CreateNewFileL(file, *fileName); + agnServFile->Model()->UpdateAttachmentDetailsL(data.iLocalUid, data.iAttachmentIndex, *fileName, dataSize); + CleanupStack::PopAndDestroy(fileName); + + TPckg pckgSubSessionHandle(file.SubSessionHandle()); + iMessage.WriteL(KTransferAttachmentToCliFileArgIndex, pckgSubSessionHandle); + User::LeaveIfError(file.TransferToClient(iMessage, KTransferAttachmentToCliFileArgIndex)); + + CleanupStack::PopAndDestroy(&file); // file.Close() + } + +/** +Fetches attachment UIDs of all file attachments in the order specified in CCalAttachmentManager::FetchAttachmentsL. +*/ +void CAgnServerSession::FetchSortedAttachmentsL() + { + // Arguments: 0 - Output : Data buffer (containing list of TCalLocalUid's of entries) + // 1 - Output : Size of data buffer + // 2 - Input : Sort order + // 3 - Input : File Id + + TUint32 sortOrder = iMessage.Int2(); + + RArray attachmentIds; + CleanupClosePushL(attachmentIds); + + TPckgBuf fileId; + iMessage.ReadL(KSlot3, fileId); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId()); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + + file->Model()->GetSortedAttachmentsL(attachmentIds, static_cast(sortOrder)); + + WriteIntArrayToBufferL(attachmentIds); + + CleanupStack::PopAndDestroy(&attachmentIds); // attachmentIds->Close() + + // Send it back to the client + TPckg listsize(iBuffer->Size()); + iMessage.WriteL(KSlot1, listsize); + } + +void CAgnServerSession::WriteIntArrayToBufferL(const RArray& aArray) + { + // Create a write stream for this buffer + const TInt KCount = aArray.Count(); + + // Buffer contains enough space for KCount integers and a count + const TInt KSizeOfBuffer = (KCount + 1) * sizeof(TUint32); + + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KSizeOfBuffer); + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + // Externalize the list + bufStream.WriteUint32L(KCount); + + for ( TInt ii = 0; ii < KCount; ++ii ) + { + bufStream << aArray[ii]; + } + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + } + +/** +Fetches all file attachments with the attachment specified by the UID. +This is called from CCalAttachmentManager::EntriesReferencingFileAttachmentL. +*/ +void CAgnServerSession::EntriesWithAttachmentL() + { + // Arguments: 0 - Output : Data buffer (containing list of TCalLocalUid's of entries) + // 1 - Output : Size of data buffer + // 2 - Input : attachment Uid + // 3 - Input : File Id + TCalAttachmentUid attachUid = iMessage.Int2(); + TPckgBuf fileId; + iMessage.ReadL(KSlot3, fileId); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId()); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + + const RArray* KUniqueIdList = file->Model()->GetEntriesWithAttachment(attachUid); + + WriteIntArrayToBufferL(*KUniqueIdList); + + // Send it back to the client + TPckg listsize(iBuffer->Size()); + iMessage.WriteL(KSlot1, listsize); + } + +/** +Fetches a file attachment by its UID. +Attachment UIDs are not exposed to the user. This function is used in the CCalAttachmentIterator. +*/ +void CAgnServerSession::FetchAttachmentByIdL() + { + // Get a list of file names held by the server + // currently setup extractor + // Arguments: 0 : Output - Data buffer + // 1 : Output - Size of buffer + // 2 : Input - attachment uid + // 3 : Input - File Id + + TCalAttachmentUid attachUid = iMessage.Int2(); + TPckgBuf fileId; + iMessage.ReadL(KSlot3, fileId); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId()); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + + CAgnAttachment* attachmentToWrite = file->Model()->FetchAttachmentByIdL(attachUid); + + if ( attachmentToWrite ) + { + CleanupStack::PushL(attachmentToWrite); + + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + attachmentToWrite->ExternalizeL(bufStream); + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + CleanupStack::PopAndDestroy(attachmentToWrite); + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot1, size); + } + else + { + TPckg emptyBuffer(0); + iMessage.WriteL(KSlot1, emptyBuffer); + } + } + +void CAgnServerSession::PreviousInstancesL() + { + // Gets the time of the previous instance to today + // Arguments: 0 : output data buffer + // 1 : size of output data buffer + // 2 : input data buffer + // 3 : size of input data buffer + + // Restore length + const TInt KBufferSize = iMessage.Int3(); + + const TInt KInstanceArrayGranularity = 16; + CArrayFixSeg* instances = new (ELeave) CArrayFixSeg(KInstanceArrayGranularity); + CleanupStack::PushL(instances); + + // Restore buffer + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0, KBufferSize); + + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot2, des); + + TFindInstanceParams parameters; + + RDesReadStream readStream(des); + + parameters.InternalizeL(readStream); + + TInt filecount = readStream.ReadInt16L(); + for(TInt ii=0;ii> fileId; + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + CAgnEntryModel* model = file->Model(); + model->PreviousPossibleInstancesL(*instances, parameters); + } + + CleanupStack::PopAndDestroy(buffer); + + const CAgnSimpleEntry* searchFromEntry = NULL; + if(parameters.iInstance.iCollectionId > 0) + {//If the iInstance.iFileId ==0, instances should be found from the start date of the searching range so there is no searchFromEntry + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(parameters.iInstance.iCollectionId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + searchFromEntry = file->Model()->GetSimpleEntryFromIndexes(parameters.iInstance.iId); + } + + TAgnSortInstance searchFromInstance(*searchFromEntry); + + if (searchFromEntry) + { + TAgnDaySortKey sortKey(AgnDateTime::MaxDate(), parameters.iUndatedTodoTimeLocal); + searchFromInstance.SetL(parameters.iInstance.iId.Date().LocalL(), parameters.iUndatedTodoTimeLocal); + const_cast(searchFromInstance.SimpleEntry()).SetCollectionId(parameters.iInstance.iCollectionId); + //the search from instance must match the filter settings + __ASSERT_ALWAYS(searchFromInstance.CheckStartAndEndDateOverlap(parameters), User::Leave(KErrNotFound)); + + // remove all instances before and including the searched from instance + TInt thisPosition(0); + User::LeaveIfError(instances->FindIsq(searchFromInstance, sortKey, thisPosition)); + instances->Delete(thisPosition, instances->Count() - thisPosition); + } + else if (!parameters.iInstance.iId.IsNullId()) + { + // The entry searched has been deleted or the entry id is wrong + User::Leave(KErrNotFound); + } + else + { + // we did not search from a specified instance + // so remove all instances that are after and including the start time + for (TInt i(instances->Count() - 1) ; i >= 0 && instances->At(i).InstanceDate() >= parameters.iInstance.iId.Date().LocalL() ; --i) + { + instances->Delete(i); + } + } + + // Truncate the list to the length of aSearchParams.iNumInstances by removeing instances from the end + if (instances->Count() > parameters.iNumInstances) + { + instances->Delete(0, instances->Count() - parameters.iNumInstances); + } + delete iBuffer; + iBuffer = NULL; + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + const TInt KInstanceCount(instances->Count()); + + bufStream.WriteUint32L(KInstanceCount); + + for (TInt i(0) ; i < KInstanceCount ; ++i) + { + TAgnInstance instance; + instance.iId = instances->At(i).InstanceIdL(); + instance.iCollectionId = (*instances)[i].SimpleEntry().CollectionId(); + bufStream << instance; + } + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + CleanupStack::PopAndDestroy(instances); + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot1, size); + } + +void CAgnServerSession::NextInstancesL() + { + // Gets the time of the next instance to today + // Arguments: 0 : output data buffer + // 1 : size of the output data buffer + // 2 : input data buffer + + // Restore length + const TInt KBufferSize = iMessage.GetDesLengthL(KSlot2); + + // Restore buffer + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0, KBufferSize); + + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot2, des); + + TFindInstanceParams parameters; + + RDesReadStream readStream(des); + + parameters.InternalizeL(readStream); + TInt filecount = readStream.ReadInt16L(); + const TInt KInstanceArrayGranularity = 16; + CArrayFixSeg* instances = new (ELeave) CArrayFixSeg(KInstanceArrayGranularity); + CleanupStack::PushL(instances); + + for(TInt ii=0;ii> fileId; + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + CAgnEntryModel* model = file->Model(); + model->NextPossibleInstancesL(*instances, parameters); + } + + const CAgnSimpleEntry* searchFromEntry = NULL; + if(parameters.iInstance.iCollectionId > 0) + { + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(parameters.iInstance.iCollectionId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + searchFromEntry = file->Model()->GetSimpleEntryFromIndexes(parameters.iInstance.iId); + } + + TAgnSortInstance searchFromInstance(*searchFromEntry); + if (searchFromEntry) + { + TAgnDaySortKey sortKey(AgnDateTime::MaxDate(), parameters.iUndatedTodoTimeLocal); + searchFromInstance.SetL(parameters.iInstance.iId.Date().LocalL(), parameters.iUndatedTodoTimeLocal); + const_cast(searchFromInstance.SimpleEntry()).SetCollectionId(parameters.iInstance.iCollectionId); + //the search from instance must match the filter settings + __ASSERT_ALWAYS(searchFromInstance.CheckStartAndEndDateOverlap(parameters), User::Leave(KErrNotFound)); + TInt thisPosition(0); + User::LeaveIfError(instances->FindIsq(searchFromInstance, sortKey, thisPosition)); + instances->Delete(0, thisPosition + 1); + } + else if (!parameters.iInstance.iId.IsNullId()) + { + // The entry searched has been deleted or the entry id is wrong + User::Leave(KErrNotFound); + } + + // Truncate the list to the length of aSearchParams.iNumInstances by removeing instances from the end + if (instances->Count() > parameters.iNumInstances) + { + instances->Delete(parameters.iNumInstances, instances->Count() - parameters.iNumInstances); + } + delete iBuffer; + iBuffer = NULL; + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + const TInt KInstanceCount(instances->Count()); + + bufStream.WriteUint32L(KInstanceCount); + + for (TInt i(0) ; i < KInstanceCount ; ++i) + { + TAgnInstance instance; + instance.iId = instances->At(i).InstanceIdL(); + instance.iCollectionId = (*instances)[i].SimpleEntry().CollectionId(); + bufStream << instance; + } + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + CleanupStack::PopAndDestroy(instances); + CleanupStack::PopAndDestroy(buffer); + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot1, size); + } + +void CAgnServerSession::CreateEntryIteratorL() + { + // Creates a server side entry iterator + // Used to iterate through all entries in the model e.g. for saving + // Arguments: 1 : Output - True if an entry is available + // 0 : Input - File Id + + TPckgBuf fileId; + iMessage.ReadL(KSlot0, fileId); + + TBool isEntry = EFalse; + if(iAgnSessionFileManager) + { + CAgnSessionFile& client = iAgnSessionFileManager->GetSessionFileL(fileId()); + isEntry = client.CreateEntryIterL(); + } + TPckg entryBuffer(isEntry); + iMessage.WriteL(KSlot1, entryBuffer); + } + +void CAgnServerSession::EntryIteratorNextL() + { + TPckgBuf fileId; + iMessage.ReadL(KSlot0, fileId); + + // Iterates to the next entry + // Arguments: 0 : Output - True if an entry is available + TBool isEntry = EFalse; + if(iAgnSessionFileManager) + { + CAgnSessionFile& client = iAgnSessionFileManager->GetSessionFileL(fileId()); + isEntry = client.IsEntryAvailableAtIteratorL(); + } + + TPckg boolBuffer(isEntry); + iMessage.WriteL(KSlot1, boolBuffer); + } + +void CAgnServerSession::EntryIteratorPositionL() + { + TPckgBuf fileId; + iMessage.ReadL(KSlot2, fileId); + + // Returns the entry ID of the current entry + // Arguments: 0 : Output - Entry ID + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId()); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + CAgnEntry* entry = NULL; + if(iAgnSessionFileManager) + { + CAgnSessionFile& client = iAgnSessionFileManager->GetSessionFileL(fileId()); + entry = client.FetchEntryAtIteratorL(); + } + + if ( entry ) + { + CleanupStack::PushL(entry); + + ExternalizeEntryToClientL(*entry, KSlot1); + + CleanupStack::PopAndDestroy(entry); + } + else + { + TPckg size(0); + iMessage.WriteL(KSlot1, size); + } + } + +void CAgnServerSession::GetEntryUidsSinceDateL() + { + // Selects entries with a last changed date greater than specified and that match filter + // Arguments: 0 - Output : Data buffer (containing list of TCalLocalUid's of entries) + // 1 - Output : Size of data buffer + // 2 - Input : Time + + TPckgBuf time; + iMessage.ReadL(KSlot2,time); + + RArray uniqueIdList; + CleanupClosePushL(uniqueIdList); + + CAgnServFile* file = GetFileL(KSlot3); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + file->Model()->GetEntryUidsSinceDateL(time(), uniqueIdList); + + WriteIntArrayToBufferL(uniqueIdList); + + CleanupStack::PopAndDestroy(&uniqueIdList); //uniqueIdList.Close(); + + // Send it back to the client + TPckg listsize(iBuffer->Size()); + iMessage.WriteL(KSlot1, listsize); + } + +void CAgnServerSession::RequestChangeNotification() + { + if(iAgnSessionFileManager) + { + iAgnSessionFileManager->RequestChangeNotification(iMessage); + } + } + +void CAgnSessionFileManager::RequestChangeNotification(const RMessage2 aMessage) + { + TInt sessionId = aMessage.Int0(); + TUint8 whichNotification = aMessage.Int1(); + + TInt index = GetSessionFile(sessionId); + if (index == KErrNotFound && whichNotification &EFileChange) + { + CAgnSessionFile* sessionFile = CAgnSessionFile::NewL(sessionId, iAgnServerSession); + CleanupStack::PushL(sessionFile); + iSessionFiles.AppendL(sessionFile); + CleanupStack::Pop(sessionFile); + sessionFile->RequestChangeNotification(aMessage); + } + else if(index >= 0) + { + iSessionFiles[index]->RequestChangeNotification(aMessage); + } + } + +void CAgnServerSession::CancelChangeNotification() + { + //get fileid + TInt sessionId = iMessage.Int0(); + TUint8 aNotificationType = iMessage.Int1(); + if(iAgnSessionFileManager) + { + TInt index = iAgnSessionFileManager->GetSessionFile(sessionId); + if (index >= 0) + { + iAgnSessionFileManager->GetSessionFileByIndex(index).CancelChangeNotification(aNotificationType); + } + } + } + +void CAgnServerSession::RequestChangeNotificationParametersL() + { + TPckgBuf start; + iMessage.ReadL(KSlot0, start); + + TPckgBuf end; + iMessage.ReadL(KSlot1, end); + + // Restore length + const TInt KBufferSize = iMessage.GetDesLength(KSlot2); + + // Restore buffer + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0, KBufferSize); + + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot2, des); + RDesReadStream readStream(des); + TInt16 type = readStream.ReadInt16L(); + TBool includeUndatedTodos = readStream.ReadInt16L(); + TInt64 fileid; + readStream >> fileid; + CleanupStack::PopAndDestroy(buffer); + if(iAgnSessionFileManager) + { + CAgnSessionFile& client = iAgnSessionFileManager->GetSessionFileL(fileid); + client.SetChangeNotificationParametersL(start(), end(), MCalChangeCallBack2::TChangeEntryType(type)); + } + } + +/** + * Gets the Notes Text writes it to a stream buffer and returns the size. + * Arguments: + * 0. Output - Buffer + * 1. Input - Stream Id + * 2. Output - Size of Notes Field + */ +void CAgnServerSession::RestoreTextL() + { + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + TPckgBuf textId; + iMessage.ReadL(KSlot1,textId); + + CAgnServFile* file = GetFileL(KSlot3); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + HBufC* text = file->Model()->RestoreTextL(textId()); + CleanupStack::PushL(text); + + bufStream.WriteUint32L(text->Length()); + bufStream << *text; + CleanupStack::PopAndDestroy(text); + + bufStream.CommitL(); + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + + // Send the size back to the client + TPckg sizeBuf(iBuffer->Size()); + iMessage.WriteL(KSlot2, sizeBuf); + } + +/** +Gets the Alarm Action writes it to a stream buffer and returns the size. +Arguments: + 0. Output - Buffer + 1. Input - Stream Id + 2. Output - Size of alarm action + 3. Input - File Id +*/ +void CAgnServerSession::RestoreAlarmActionL() + { + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + TPckgBuf id; + + iMessage.ReadL(KSlot1, id); + TPckgBuf fileId; + iMessage.ReadL(KSlot3, fileId); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId()); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + CAgnContent* alarmAction = file->Model()->RestoreAlarmActionL(id()); + CleanupStack::PushL(alarmAction); + alarmAction->ExternalizeL(bufStream); + CleanupStack::PopAndDestroy(alarmAction); + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + + // Send the size back to the client + TPckg sizeBuf(iBuffer->Size()); + iMessage.WriteL(KSlot2, sizeBuf); + } + +void CAgnServerSession::StartBuildIndex() + { + // if the calendar file is not opened, leave + TBool reportProgress = iMessage.Int0(); + TAgnMessageToComplete message(iMessage, reportProgress, *this); + + TUint8 fileId = iMessage.Int1(); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId); + file->StartBuildIndex(message); + } + +void CAgnServerSession::TidyByDateStartL() + { + TBool reportProgress = iMessage.Int0(); + TAgnMessageToComplete message(iMessage, reportProgress, *this); + TUint8 fileId = iMessage.Int1(); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + CAgnSessionFile& client = iAgnSessionFileManager->GetSessionFileL(fileId); + client.TidyByDateStartL(message, *file); + } + +void CAgnServerSession::RequestProgressL() + { + TAgnMessageToComplete message(iMessage, ETrue, *this); + TUint8 fileId = iMessage.Int0(); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId); + file->RequestProgressL(message); + } + +void CAgnServerSession::AsynchCategoryTaskStartL() + { + TBool reportProgress = iMessage.Int0(); + TAgnMessageToComplete message(iMessage, reportProgress, *this); + CCalAsyncTaskManager::TAsyncAction task = (CCalAsyncTaskManager::TAsyncAction)iMessage.Int1(); + TUint8 fileId = iMessage.Int2(); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + file->CategoryTaskStartL(message, task); + } + +void CAgnServerSession::GetCategoryListCountL() +// gets the number of categories in the list +// arguments: +// 0 - output, count +// 1 - input, file id + { + TPckgBuf fileId; + iMessage.ReadL(KSlot1, fileId); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId()); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + TInt count = file->CategoryList().CategoryCount(); + TPckg buf(count); + iMessage.WriteL(KSlot0, buf); + } + +void CAgnServerSession::GetCategoryListItemL() +// gets the category in the list at index passed in from the client +// arguments: +// 0 - output, data buffer +// 1 - input, index +// 2 - output, size of buffer +// 3 - input, file id + { + TInt index = iMessage.Int1(); + + TPckgBuf fileId; + iMessage.ReadL(KSlot3, fileId); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId()); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + if( index >= file->CategoryList().CategoryCount() ) + { + User::Leave(KErrNotFound); + } + + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + // Buffer contains one byte for category type and the string for the extended category name + file->CategoryList().Category(index).ExternalizeL(bufStream); + + bufStream.CommitL(); + + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot2, size); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close() + } + +void CAgnServerSession::AddCategoryToListL() +// adds a new category to the list; +// arguments: +// 0 - input, category name +// 1 - input, file id + { + + HBufC* bufptr = ReadClientDesLC(KSlot0); + TPtr categoryName = bufptr->Des(); + + TPckgBuf fileId; + iMessage.ReadL(KSlot1, fileId); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId()); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + file->CategoryList().AddCategoryL(categoryName); + + CleanupStack::PopAndDestroy(bufptr); + } + +void CAgnServerSession::CategoryTaskStartL() + { + // Arguments: 0 - Input : Data buffer (category and step size) + // 1 - Input : Size of data buffer + // 2 - Input : step of the task + // 3 - Input : File Id + const TInt KBufferSize = iMessage.Int1(); + // Restore buffer + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + + buffer->ExpandL(0, KBufferSize); + + TPtr8 buf(buffer->Ptr(0)); + iMessage.ReadL(KSlot0,buf); + // Internalize the data from the stream + TInt categoryIndex; + TUint8 shortFileId = iMessage.Int3(); + GetCategoryInfoL(*buffer,categoryIndex, shortFileId); + CleanupStack::PopAndDestroy(buffer); + + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(shortFileId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + TInt task = iMessage.Int2(); + file->Model()->CategoryIndex().PrepareStepTaskL(task,categoryIndex); + } + +void CAgnServerSession::FilterCategoryL() + { + // Arguments:0 - Input : Data Buffer (category and step size) + // 1 - Input : Size of data buffer + CArrayFixSeg* entryList = new (ELeave) CArrayFixSeg(KGranFilteredEntries); + CleanupStack::PushL(entryList); + + TPckgBuf fileId; + iMessage.ReadL(KSlot2, fileId); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId()); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + file->Model()->CategoryIndex().GetArrayFilterCategoryL(*entryList); + + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + const TInt KCount = entryList->Count(); + + bufStream.WriteInt16L(KCount); + + for( TInt ii = 0; ii < KCount; ++ii ) + { + entryList->At(ii).ExternalizeL(bufStream); + } + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + + CleanupStack::PopAndDestroy(entryList); + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot1, size); + } + +void CAgnServerSession::CancelTaskL() + { + TPckgBuf fileId; + iMessage.ReadL(KSlot0, fileId); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId()); + if(file) + { + file->DoTaskCompleteL(KErrCancel, this); + } + } + +void CAgnServerSession::CancelAllTask() + { + const TInt count = FileIdCount(); + for(TInt ii=0; iiGetFileL(FileId(ii))); + if(err == KErrNone) + { + TRAP_IGNORE(file->DoTaskCompleteL(KErrCancel, this)); + } + } + } + +void CAgnServerSession::BackupRestoreCancelTask() + { + const TInt count = FileIdCount(); + for(TInt ii=0; iiGetFileL(FileId(ii))); + if(err == KErrNone) + { + TRAP_IGNORE(file->CancelTaskL(this)); + } + } + } + +void CAgnServerSession::GetCategoryInfoL(const CBufFlat& aBufFlat,TInt& aCategoryIndex, TCalCollectionId aCollectionId) + { + RBufReadStream readStream; + readStream.Open(aBufFlat); + CleanupClosePushL(readStream); + + CAgnCategory* category = CAgnCategory::NewL(readStream); + + CleanupStack::PopAndDestroy(&readStream); // readStream.Close(); + + CleanupStack::PushL(category); + + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(aCollectionId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + aCategoryIndex = file->CategoryList().FindCategoryIndex(*category); + User::LeaveIfError(aCategoryIndex); + + CleanupStack::PopAndDestroy(category); + } + +/** Create a store with Agenda file */ +void CAgnServerSession::CreateAgendaFileL() + { + // Arguments: 0 : Input - size fo buffer + // 1 : Input - Data Buffer + // 2 : Input - file name + // 3 : Input - todo list name + + //Create a store + HBufC* filenameBuf = ReadClientDesLC(KSlot0); + CFileStore* store=iAgnServer.FileMgr()->CreateAgendaFileLC(*filenameBuf);//PUSH: store + store->SetTypeL(TUidType(KPermanentFileStoreLayoutUid, KUidAppDllDoc, KUidAgnApp)); + + CAgnEntryModel* model = CAgnEntryModel::NewL(NULL); + CleanupStack::PushL(model); //PUSH: model + TStreamId headstreamId = model->CreateL(*store); + + //Write dummy app id to the store + //Create the streamdictionary (effectively the root stream) + CStreamDictionary* streamDic=CStreamDictionary::NewLC();//PUSH: streamDic + if (streamDic->At(KUidAgnModel)!=headstreamId) + { + streamDic->AssignL(KUidAgnModel, headstreamId); + } + + // Stream dictionary (root) + TApaAppIdentifier dummyApp(KUidAgnModel, KNullDesC()); + CApaProcess::WriteRootStreamL(*store,*streamDic, dummyApp); + store->CommitL(); + CleanupStack::PopAndDestroy(3, store); + + //Convert the file name into standard format "c:filename + HBufC* parsedFilename = iAgnServer.FileMgr()->ParseFilenameLC(*filenameBuf);//full name include the parth + parsedFilename->Des().Fold(); + TParsePtrC parse(*parsedFilename); + HBufC* shortFileName = HBufC::NewLC(parsedFilename->Length()); + shortFileName->Des().Append(parse.Drive()); + shortFileName->Des().Append(parse.NameAndExt()); + CAgnFileChangeInfo* changeInfo = NULL; + changeInfo = CAgnFileChangeInfo::NewL(shortFileName, MCalFileChangeObserver::ECalendarFileCreated); + CleanupStack::Pop(shortFileName); + CleanupStack::PushL(changeInfo); + CalendarFileChangedL(*changeInfo);//add the change to the buffer + CleanupStack::PopAndDestroy(3, filenameBuf);//changeInfo, parsedFilename, filenameBuf + } + +TBool CAgnServerSession::IsOwnFileL(TInt aSessionId, const CAgnServFile& file) + { + TBool isOwnFile = EFalse; + //Check whether it is its own file + if(iAgnSessionFileManager) + { + TInt index = iAgnSessionFileManager->GetSessionFile(aSessionId); + if(index >= 0) + { + TCalFileId fileId = iAgnSessionFileManager->GetSessionFileByIndex(index).FileId(); + if(fileId == file.Model()->GetFileIdL()) + { + isOwnFile = ETrue; + } + } + } + return isOwnFile; + } + +TBool CAgnServerSession::FileCanBeDeletedL(TInt aSessionId, const CAgnServFile& file) + { + TBool fileCanBeDeleted = EFalse; + TBool isOwnFile = IsOwnFileL(aSessionId, file); + if(file.ReferenceCount() == 0 || (isOwnFile && file.ReferenceCount() == 1)) + { + fileCanBeDeleted = ETrue; + } + return fileCanBeDeleted; + } + +TBool CAgnServerSession::FileHasBeenOpenedL(const CAgnServFile& file) + { + TBool fileHasBeenOpened = EFalse; + if(iAgnSessionFileManager) + { + if(iAgnSessionFileManager->FindL(file.Model()->GetFileIdL()) != KErrNotFound) + { + fileHasBeenOpened = ETrue; + } + } + return fileHasBeenOpened; + } + +void CAgnServerSession::DeleteAgendaFileL() + { + // Delete a file held by the server + // 1: Input - Agenda file name + + // Get descriptor for filename to delete + HBufC* bufptr = ReadClientDesLC(KSlot0); + TPtr filename = bufptr->Des(); + + HBufC* fullFilename = iAgnServer.FileMgr()->ParseFilenameLC(filename); + TInt sessionId = iMessage.Int1(); + + CAgnServFile* file = NULL; + file = iAgnServer.FileMgr()->GetFile(*fullFilename); + if(file && !FileCanBeDeletedL(sessionId, *file)) + { + User::Leave(KErrInUse); + } + + TBool closeFile(EFalse); + TInt err = KErrNone; + if (!file) + { + // the file is not open so we must open it now + CalCommon::TCalFileVersionSupport status; + TRAP(err, file = &iAgnServer.FileMgr()->OpenAgendaL(filename, iAgnServer, status)); + if (err == KErrNone) + { + // Everything was fine when opening the file + closeFile = ETrue; + CleanupStack::PushL(TCleanupItem(CleanupCloseAgendaImmediately, file)); + } + } + if(!file) + { + iAgnServer.FileMgr()->DeleteAgendaFileL(filename); + } + else + { + TBool calInfoExist = file->IsCalendarInfoExistL(); + TBool deleteSessionFile = EFalse; + if (closeFile) + { + // This will call CloseAgenda(ETrue) + CleanupStack::PopAndDestroy(); + } + else if( IsOwnFileL(sessionId, *file) ) + { + // The client has requested to delete it's own calendar file + // so try to close it immediately + User::LeaveIfError(iAgnServer.FileMgr()->CloseAgenda(*file, ETrue)); + deleteSessionFile = ETrue; + iSessionReady = ETrue; + } + iAgnServer.FileMgr()->DeleteAgendaFileL(filename); + + TParsePtrC parse(*fullFilename); + HBufC* shortFileName = HBufC::NewLC(fullFilename->Length()); + shortFileName->Des().Append(parse.Drive()); + shortFileName->Des().Append(parse.NameAndExt()); + iAgnServer.AlarmServer().AlarmDeleteByCalendarFile(*shortFileName, EAllAlarms); + CAgnFileChangeInfo* changeInfo = NULL; + + if(calInfoExist) + { + HBufC* shortFileNameCopy = shortFileName->AllocLC(); + changeInfo = CAgnFileChangeInfo::NewL(shortFileNameCopy, MCalFileChangeObserver::ECalendarInfoDeleted); + CleanupStack::Pop(shortFileNameCopy); + CleanupStack::PushL(changeInfo); + CalendarFileChangedL(*changeInfo);//add the change to the buffer + CleanupStack::PopAndDestroy(changeInfo); + } + changeInfo = CAgnFileChangeInfo::NewL(shortFileName, MCalFileChangeObserver::ECalendarFileDeleted); + CleanupStack::Pop(shortFileName); + CleanupStack::PushL(changeInfo); + CalendarFileChangedL(*changeInfo); + CleanupStack::PopAndDestroy(changeInfo); + if(deleteSessionFile) + { + iAgnSessionFileManager->DeleteSessionFileIfFileNotificationNotRequired(sessionId); + } + } + + CleanupStack::PopAndDestroy(fullFilename); + CleanupStack::PopAndDestroy(bufptr); // buffer + } + +void CAgnServerSession::CalendarFileChangedL(CAgnFileChangeInfo& aFileChangeInfo) + { + RPointerArray sessions; + CleanupClosePushL(sessions); + iAgnServer.FetchSessionsL(sessions); + const TInt count = sessions.Count(); + for ( TInt i = 0; i < count; ++i ) + { + sessions[i]->AddFileChangeL(aFileChangeInfo, this); + } + CleanupStack::PopAndDestroy(&sessions); // sessions.Close() + } + +void CAgnServerSession::AddFileChangeL(CAgnFileChangeInfo& aFileChangeInfo, CAgnServerSession* aSession) + { + if(iAgnSessionFileManager && this != aSession) + { + iAgnSessionFileManager->AddFileChangeL(aFileChangeInfo); + } + } + +void CAgnSessionFileManager::AddFileChangeL(CAgnFileChangeInfo& aFileChangeInfo) + { + const TInt count = iSessionFiles.Count(); + for(TInt ii = 0; ii < count; ++ii) + { + iSessionFiles[ii]->AddFileChangeToBufferL(aFileChangeInfo); + } + } + +void CAgnServerSession::ListAgendaFilesL() + { + // Get a list of file names held by the server + // currently setup extractor + // Arguments: 0 : Output - Data buffer + // 1 : Output - Size of buffer + + //create the buffer + + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + CDesCArray* fileNames = iAgnServer.FileMgr()->ListAgendaFilesL(); + if( fileNames ) + { + CleanupStack::PushL(fileNames); + + const TInt KCount = fileNames->Count(); + + bufStream.WriteUint8L(KCount); + + for ( TInt ii = 0; ii < KCount; ++ii ) + { + const TInt KLength = (fileNames->MdcaPoint(ii)).Length(); + bufStream.WriteUint8L(KLength); + bufStream.WriteL(fileNames->MdcaPoint(ii), KLength); + } + + CleanupStack::PopAndDestroy(fileNames); + } + else + { + bufStream.WriteUint8L(0); + } + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot1, size); + } + +void CAgnServerSession::TidyByDateReadParamsL() + { + // Set up a tidy by date operation + // Arguments: 0 : Input - Buffer containing packaged tidy by date operation data + // 1 : Input - File Id + TUint8 fileId = iMessage.Int1(); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId); + __ASSERT_ALWAYS( file, Panic(EAgmErrTidyByDateNoFileOpen)); + // If the file already has a session associated with it, then it's busy + // for this delete operation. + if (file->IsLocked()) + { + return; + } + + const TInt KDesLength = iMessage.GetDesLength(KSlot0); + if(KDesLength<0) + { + User::Leave(KErrArgument); + } + CBufFlat* buffer = CBufFlat::NewL(KDesLength); + CleanupStack::PushL(buffer); + + buffer->ExpandL(0, KDesLength); + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot0, des); + + RBufReadStream readStream; + readStream.Open(*buffer); + CleanupClosePushL(readStream); + + TAgnFilter filter; + filter.InternalizeL(readStream); + TPckgBuf undatedTodosDatePckgBuf; + readStream.ReadL(undatedTodosDatePckgBuf); + TPckgBuf startDatePckgBuf; + readStream.ReadL(startDatePckgBuf); + TPckgBuf endDatePckgBuf; + readStream.ReadL(endDatePckgBuf); + + CleanupStack::PopAndDestroy(&readStream); // readStream.Close(); + + file->TidyByDateSetup(*this, + filter, + undatedTodosDatePckgBuf(), + startDatePckgBuf(), + endDatePckgBuf()); + + CleanupStack::PopAndDestroy(buffer); + } + +void CAgnServerSession::AgendaFileExistsL() + { + // Check if a Calendar file exists + // Arguments: 0 : Output - True if the file exists, otherwise False + // 1 : Input - Buffer containing calendar file name + HBufC* bufptr = ReadClientDesLC(KSlot1); + + TPckg isExists(iAgnServer.FileMgr()->AgendaFileExistsL(*bufptr)); + + CleanupStack::PopAndDestroy(bufptr); // bufptr + + iMessage.WriteL(KSlot0, isExists); + } + +void CAgnServerSession::BulkChangeCompletedL(TInt64 aFileId, TInt aErr) + { + CAgnSessionFile& client = iAgnSessionFileManager->GetSessionFileL(aFileId); + client.BulkChangeCompletedL(*this, aErr); + } + +void CAgnServerSession::EnableChangeBroadcastL() + { + //get fileid + TPckgBuf fileId; + iMessage.ReadL(KSlot0, fileId); + if(iAgnSessionFileManager) + { + CAgnSessionFile* client = NULL; + TRAPD(err, client = &(iAgnSessionFileManager->GetSessionFileL(fileId()))); + if(err == KErrNone && client) + { + client->EnableChangeBroadcastL(*this); + } + else if (err != KErrNotFound) + { + User::Leave(err); + } + } + } + +void CAgnServerSession::DisableChangeBroadcastL() + { + //get fileid + TPckgBuf fileId; + iMessage.ReadL(KSlot0, fileId); + if(iAgnSessionFileManager) + { + CAgnSessionFile* client = NULL; + TRAPD(err, client = &(iAgnSessionFileManager->GetSessionFileL(fileId()))); + if(err == KErrNone && client) + { + client->DisableChangeBroadcast(); + } + else if (err != KErrNotFound) + { + User::Leave(err); + } + } + } + +void CAgnServerSession::GetFileChangesSinceLastNotificationL() + { + // Get calendar change info + // Arguments: 0 : Output - Data buffer + // 1 : Output - Size of buffer + // 2 : Input - Session Id + + TInt sessionId = iMessage.Int2();; + delete iBuffer; + iBuffer = NULL; + TInt buffersize = 0; + if(iAgnSessionFileManager) + { + TInt index = iAgnSessionFileManager->GetSessionFile(sessionId); + if(index >= 0) + { + buffersize = iAgnSessionFileManager->GetSessionFileByIndex(index).GetFileChangesSinceLastNotificationL(iBuffer); + } + } + + TPckg size(buffersize); + iMessage.WriteL(KSlot1, size); + } + +void CAgnServerSession::GetChangesSinceLastNotificationL() + { + // Get changed entries from the log kept in the model + // Arguments: 0 : Output - Data buffer + // 1 : Input - Size of buffer + + TCalCollectionId collectionId = iMessage.Int2();; + delete iBuffer; + iBuffer = NULL; + TInt buffersize = 0; + TInt64 fileId = 0; + if(iAgnSessionFileManager) + { + CAgnSessionFile& client = iAgnSessionFileManager->GetSessionFileL(collectionId); + buffersize = client.GetChangesSinceLastNotificationL(iBuffer); + fileId = client.FileId(); + } + + TPckg size(buffersize); + iMessage.WriteL(KSlot1, size); + TPckg fileIdPackage(fileId); + iMessage.WriteL(KSlot3, fileIdPackage); + } + +void CAgnServerSession::FindInstancesL() + { + // Restore length + const TInt KBufferSize = iMessage.GetDesLengthL(KSlot2); + + // Restore buffer + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0, KBufferSize); + + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot2, des); + + TFindInstanceParams parameters; + + RDesReadStream readStream(des); + + parameters.InternalizeL(readStream); + TInt filecount = readStream.ReadInt16L(); + const TInt KInstanceArrayGranularity = 16; + CArrayFixSeg* instances = new (ELeave) CArrayFixSeg(KInstanceArrayGranularity); + CleanupStack::PushL(instances); + for(TInt ii=0;ii> fileId; + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + CAgnEntryModel* model = file->Model(); + model->FindInstancesL(*instances, parameters); + } + + TAgnDaySortKey sortKey(AgnDateTime::MaxDate(), parameters.iUndatedTodoTimeLocal); + instances->Sort(sortKey); + + // Now put the relevant info into a buffer + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + const TInt KCount = instances->Count(); + + bufStream.WriteUint32L(KCount); + + for ( TInt ii = 0; ii < KCount; ++ii ) + { + TAgnInstance instance; + instance.iId = (*instances)[ii].InstanceIdL(); + instance.iCollectionId = (*instances)[ii].SimpleEntry().CollectionId(); + bufStream << instance; + } + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + + CleanupStack::PopAndDestroy(instances); + CleanupStack::PopAndDestroy(buffer); + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot1, size); + } + +// CAgnInstanceInfo // + +CAgnInstanceInfo* CAgnInstanceInfo::NewL(const CAgnSimpleEntry& aSimpleEntry) + { + CAgnInstanceInfo* self = CAgnInstanceInfo::NewLC(aSimpleEntry); + CleanupStack::Pop(self); + return self; + } + + +CAgnInstanceInfo* CAgnInstanceInfo::NewLC(const CAgnSimpleEntry& aSimpleEntry) + { + CAgnInstanceInfo* self = new (ELeave) CAgnInstanceInfo(); + CleanupStack::PushL(self); + self->ConstructL(aSimpleEntry); + return self; + } + +void CAgnInstanceInfo::ConstructL(const CAgnSimpleEntry& aSimpleEntry) + { + iType = aSimpleEntry.Type(); + if ( aSimpleEntry.RptDef() ) + { + iRptDef = CAgnRptDef::NewL(aSimpleEntry); + iRptDef->CopyL(*aSimpleEntry.RptDef()); + } + else + { + iStartTimeUtc = aSimpleEntry.StartTime().UtcL(); + iEndTimeUtc = aSimpleEntry.EndTime().UtcL(); + } + } + +CAgnInstanceInfo::CAgnInstanceInfo() + { + } + +CCalEntry::TType CAgnInstanceInfo::Type() const + { + return iType; + } + +CAgnInstanceInfo::~CAgnInstanceInfo() + { + delete iRptDef; + } + +const CAgnRptDef* CAgnInstanceInfo::RptDef() const + { + return iRptDef; + } + +const TTime& CAgnInstanceInfo::StartTimeUtc() const + { + return iStartTimeUtc; + } + +const TTime& CAgnInstanceInfo::EndTimeUtc() const + { + return iEndTimeUtc; + } + +// TAgnMessageToComplete // + +TAgnMessageToComplete::TAgnMessageToComplete(RMessage2& aMessage, TBool aReportProgress, CAgnServerSession& aSession) + :iMessage(aMessage), iReportProgress(aReportProgress), iSession(aSession) + { + } + +RMessage2 TAgnMessageToComplete::Message() const + { + return iMessage; + } + +TBool TAgnMessageToComplete::ReportProgress() const + { + return iReportProgress; + } + +CAgnServerSession& TAgnMessageToComplete::Session() const + { + return iSession; + } + +/* +@capability WriteUserData +@capability ReadUserData +*/ +void CAgnServerSession::DeleteEntryByUIdL(TCalLocalUid aUniqueId, TCalCollectionId aCollectionId) + { + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(aCollectionId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + + CAgnEntry* entry = file->Model()->FetchEntryL(aUniqueId); + if (entry) + { + CleanupStack::PushL(entry); + DeleteEntryL(*entry, aCollectionId); + CleanupStack::PopAndDestroy(entry); + } + } + +void CAgnServerSession::DeleteEntryByIdL(TAgnEntryId aEntryId, TCalCollectionId aCollectionId) + { + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(aCollectionId); + __ASSERT_ALWAYS(file, User::Leave(KErrCorrupt)); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + CAgnEntry* entry = file->Model()->FetchEntryL(aEntryId); + if (entry) + { + CleanupStack::PushL(entry); + DeleteEntryL(*entry, aCollectionId); + CleanupStack::PopAndDestroy(entry); + } + } + +void CAgnServerSession::DeleteEntryL() + { + TPckgBuf entryId; + iMessage.ReadL(KSlot0,entryId); + TUint8 fileId = iMessage.Int1(); + DeleteEntryByIdL(entryId(), fileId); + } + +void CAgnServerSession::DeleteEntryL(CAgnEntry& aEntry, TCalCollectionId aCollectionId) + { + CAgnSessionFile& client = iAgnSessionFileManager->GetSessionFileL(aCollectionId); + client.DeleteEntryL(aEntry); + } + +void CAgnServerSession::FetchEntryByGuidL() + { + // Get a list of entries from the server with this GUID + // currently setup extractor + // Arguments: 0 : Output - Data buffer + // 1 : Output - Size of buffer + // 2 : Input - Guid + //create the buffer + + HBufC8* bufptr = ReadClientDes8LC(KSlot2); + TPtr8 guid = bufptr->Des(); + + RPointerArray list; + CleanupResetAndDestroyPushL(list); + CAgnServFile* file = GetFileL(KSlot3); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + + file->Model()->FetchEntriesL(guid, list); + + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + const TInt KCount = list.Count(); + + bufStream.WriteUint32L(KCount); + + for ( TInt ii = 0; ii < KCount; ++ii ) + { + CAgnEntry* entry = list[ii]; + + bufStream.WriteUint32L( entry->Type() ); + entry->ExternalizeToBufferL(bufStream); + } + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + CleanupStack::PopAndDestroy(&list); // list.Close() + CleanupStack::PopAndDestroy(bufptr); + + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot1, size); + } + +void CAgnServerSession::FetchSimpleEntriesByGuidL() + { + // Get a list of entries from the server with this GUID + // currently setup extractor + // Arguments: 0 : Output - Data buffer + // 1 : Output - Size of buffer + // 2 : Input - Guid + //create the buffer + + RPointerArray list; + CleanupResetAndDestroyPushL(list); + + const TInt KBufferSize = iMessage.GetDesLengthL(KSlot2); + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0, KBufferSize); + + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot2, des); + + RDesReadStream readStream(des); + TInt uidLen = readStream.ReadInt16L(); + HBufC8* uid = HBufC8::NewLC(uidLen); + TPtr8 guid = uid->Des(); + readStream.ReadL(guid, uidLen); + TInt filecount = readStream.ReadInt16L(); + TInt preEntryCount = 0;; + TInt entryCount = 0; + for(TInt ii=0;iiGetFileL(fileId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + file->Model()->FetchEntriesL(*uid, list); + entryCount = list.Count(); + for(TInt jj = preEntryCount; jjSetCollectionId(fileId); + } + preEntryCount = entryCount; + } + CleanupStack::PopAndDestroy(uid); + CleanupStack::PopAndDestroy(buffer); + + delete iBuffer; + iBuffer = NULL; + + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + // Create a write stream for this buffer + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + const TInt KCount = list.Count(); + + bufStream.WriteUint32L(KCount); + + for ( TInt ii = 0; ii < KCount; ++ii ) + { + CAgnEntry* entry = list[ii]; + + bufStream.WriteUint32L(entry->Type()); + // explictly use the simple entriy's ExternalizeL + entry->CAgnSimpleEntry::ExternalizeL(bufStream, ETrue); + bufStream.WriteUint8L(entry->CollectionId()); + } + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + CleanupStack::PopAndDestroy(&list); // list.Close() + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot1, size); + } + +void CAgnServerSession::DeleteEntriesByLocalUidL() + { + + // Delete entries by their local uids + // Arguments: 0 : Input - Size of data buffer + // 1 : Input - Data Buffer (containing filter) + const TInt KBufferSize = iMessage.Int0(); + + // Restore buffer + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + + buffer->ExpandL(0, KBufferSize); + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot1, des); + + // Internalize the data from the stream + RBufReadStream readStream; + readStream.Open(*buffer); + CleanupClosePushL(readStream); + + const TInt KCount = readStream.ReadUint32L(); + TUint8 fileId = iMessage.Int2(); + for ( TInt ii = 0; ii < KCount; ++ii ) + { + const TCalLocalUid KUniqueId = readStream.ReadUint32L(); + DeleteEntryByUIdL(KUniqueId, fileId); + } + + CleanupStack::PopAndDestroy(&readStream); // readStream.Close(); + + CleanupStack::PopAndDestroy(buffer); // buffer + } + +void CAgnServerSession::DeleteEntryByGuidL() + { + + HBufC8* guid = ReadClientDes8LC(KSlot0); + TBool commitAndNotify = iMessage.Int1(); + TPckgBuf fileId; + iMessage.ReadL(KSlot2, fileId); + CAgnSessionFile& client = iAgnSessionFileManager->GetSessionFileL(fileId()); + client.DeleteEntryByGuidL(*guid, commitAndNotify); + CleanupStack::PopAndDestroy(guid); + } + +void CAgnServerSession::CommitL() + { + TUint8 fileId = iMessage.Int0(); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId); + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + file->Model()->CommitL(); + } + +void CAgnServerSession::RollbackL() + { + TUint8 fileId = iMessage.Int0(); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId); + + //We cannot allow Rollback to happen if a file is locked. + //A change requested by one client if not committed, can be undone when another client requests a RollBack. + //This cannot be shifted to "RequiresFileLock" section as this operation can be allowed if session is not ready. + if(file->IsLocked()) + { + User::Leave(KErrLocked); + } + file->Model()->Rollback(); + } + +CAgnServFile* CAgnServerSession::GetFileL(TInt aSlot) + { + TPckgBuf fileId; + iMessage.ReadL(aSlot, fileId); + return iAgnServer.FileMgr()->GetFileL(fileId()); + } + +void CAgnServerSession::TzRulesLastModifiedDateTimeL() + { + TPckgBuf fileId; + iMessage.ReadL(KSlot1, fileId); + CAgnServFile* file = iAgnServer.FileMgr()->GetFileL(fileId()); + TPckgBuf time(file->Model()->TzRulesLastModifiedDateL()); + iMessage.WriteL(KSlot0, time); + } + +TInt CAgnServerSession::FileIdCount() + { + TInt count = 0; + if(iAgnSessionFileManager) + { + count = iAgnSessionFileManager->FileIdCount(); + } + return count; + } + +TInt64 CAgnServerSession::FileId(TInt aIndex) + { + TInt64 fileId = KNullFileId; + if(iAgnSessionFileManager) + { + fileId = iAgnSessionFileManager->FileId(aIndex); + } + return fileId; + } + +void CAgnServerSession::SetCalendarInfoL() + { + // Restore length + const TInt KBufferSize = iMessage.GetDesLength(KSlot1); + + // Restore buffer + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0, KBufferSize); + + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot1, des); + RDesReadStream readStream(des); + + CAgnCalendarInfo* info = CAgnCalendarInfo::NewL(); + CleanupStack::PushL(info); + info->IpcInternalizeL(readStream); + + // try to get the file if it is already open + HBufC* filename = ReadClientDesLC(KSlot0); + HBufC* parsedFilename = iAgnServer.FileMgr()->ParseFilenameLC(*filename); + parsedFilename->Des().Fold(); + CAgnServFile* file = iAgnServer.FileMgr()->GetFile(*parsedFilename); + + TBool closeFile(EFalse); + + if (!file) + { + // the file is not open so we must open it now + CalCommon::TCalFileVersionSupport status; + file = &iAgnServer.FileMgr()->OpenAgendaL(*filename, iAgnServer, status); + closeFile = ETrue; + CleanupStack::PushL(TCleanupItem(CleanupCloseAgendaImmediately, file)); + } + + // we have the file open, now set the file name on the info + // before saving the info in a stream in the file. + TParsePtrC parse(*parsedFilename); + HBufC* shortFileName = HBufC::NewLC(parsedFilename->Length()); + shortFileName->Des().Append(parse.Drive()); + shortFileName->Des().Append(parse.NameAndExt()); + info->SetFileNameL(*shortFileName); + TBool fileInfoExist = file->SetCalendarInfoL(*info); + + // set the file name to the correct format + CAgnFileChangeInfo* changeInfo = NULL; + if(fileInfoExist) + { + changeInfo = CAgnFileChangeInfo::NewL(shortFileName, MCalFileChangeObserver::ECalendarInfoUpdated); + } + else + { + changeInfo = CAgnFileChangeInfo::NewL(shortFileName, MCalFileChangeObserver::ECalendarInfoCreated); + } + CleanupStack::Pop(shortFileName); + CleanupStack::PushL(changeInfo); + CalendarFileChangedL(*changeInfo);//add the change to the buffer + CleanupStack::PopAndDestroy(changeInfo); + if (closeFile) + { + // This will call CloseAgenda(ETrue) + CleanupStack::PopAndDestroy(); + } + + CleanupStack::PopAndDestroy(parsedFilename); + CleanupStack::PopAndDestroy(filename); + CleanupStack::PopAndDestroy(info); + CleanupStack::PopAndDestroy(buffer); + } + + void CAgnServerSession::GetPropertyValueL() + { + // try to get the file if it is already open + HBufC* filename = ReadClientDesLC(KSlot2); + HBufC* parsedFilename = iAgnServer.FileMgr()->ParseFilenameLC(*filename); + parsedFilename->Des().Fold(); + CAgnServFile* file = iAgnServer.FileMgr()->GetFile(*parsedFilename); + + TBool closeFile(EFalse); + + if (!file) + { + // the file is not open so we must open it now + CalCommon::TCalFileVersionSupport status; + TRAPD(err, file = &iAgnServer.FileMgr()->OpenAgendaL(*filename, iAgnServer, status)); + + if (err == KErrNone) + { + // Everything was fine when opening the file + closeFile = ETrue; + CleanupStack::PushL(TCleanupItem(CleanupCloseAgendaImmediately, file)); + } + else if (err == KErrNoMemory || err == KErrNotFound) + { + // Leave if we ran out of memory or the file does not exist + // for other leave types we assume that the file is corrupt + // and we will return some invalid metadata later + User::Leave(err); + } + } + + HBufC8* value(NULL); + + if (file) + { + TPckgBuf streamId; + iMessage.ReadL(KSlot3, streamId); + value = file->GetPropertyValueLC(streamId()); + } + else + { + // We failed to open the file + value = KNullDesC8().AllocLC(); + } + + delete iBuffer; + iBuffer = NULL; + iBuffer = CBufFlat::NewL(1000); + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + // Externalize the calendar info + bufStream << *value; + + bufStream.CommitL(); + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + + CleanupStack::PopAndDestroy(value); + + if (closeFile) + { + // This will call CloseAgenda(ETrue) + CleanupStack::PopAndDestroy(); + } + + CleanupStack::PopAndDestroy(parsedFilename); + CleanupStack::PopAndDestroy(filename); + } + + void CAgnServerSession::GetCalendarInfoL() + { + // try to get the file if it is already open + HBufC* filename = ReadClientDesLC(KSlot2); + HBufC* parsedFilename = iAgnServer.FileMgr()->ParseFilenameLC(*filename); + parsedFilename->Des().Fold(); + CAgnServFile* file = iAgnServer.FileMgr()->GetFile(*parsedFilename); + + TBool closeFile(EFalse); + + if (!file) + { + // the file is not open so we must open it now + CalCommon::TCalFileVersionSupport status; + TRAPD(err, file = &iAgnServer.FileMgr()->OpenAgendaL(*filename, iAgnServer, status)); + + if (err == KErrNone) + { + // Everything was fine when opening the file + closeFile = ETrue; + CleanupStack::PushL(TCleanupItem(CleanupCloseAgendaImmediately, file)); + } + else if (err == KErrNoMemory || err == KErrNotFound) + { + // Leave if we ran out of memory or the file does not exist + // for other leave types we assume that the file is corrupt + // and we will return some invalid metadata later + User::Leave(err); + } + } + + CAgnCalendarInfo* info(NULL); + + if (file) + { + info = file->GetCalendarInfoLC(); + } + else + { + // We failed to open the file so send back some + // invalid calendar info + info = CAgnCalendarInfo::NewL(); + CleanupStack::PushL(info); + info->SetIsValid(EFalse); + + // set the file name to the correct format + TParsePtrC parse(*parsedFilename); + TFileName shortFileName(parse.Drive()); + shortFileName.Append(parse.NameAndExt()); + info->SetFileNameL(shortFileName); + } + + delete iBuffer; + iBuffer = NULL; + iBuffer = CBufFlat::NewL(1000); + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + // Externalize the calendar info + info->IpcExternalizeL(bufStream); + + bufStream.CommitL(); + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + + CleanupStack::PopAndDestroy(info); + + if (closeFile) + { + // This will call CloseAgenda(ETrue) + CleanupStack::PopAndDestroy(); + } + + CleanupStack::PopAndDestroy(parsedFilename); + CleanupStack::PopAndDestroy(filename); + } + +void CAgnServerSession::CloseAgendas() + { + const TInt count = FileIdCount(); + for (TInt ii =0; iiGetFileL(FileId(ii))); + if(servFile && err==KErrNone) + { + servFile->CloseAgenda(EFalse); + } + } + } + +//CAgnSessionFileManager +CAgnSessionFileManager::CAgnSessionFileManager(CAgnServerSession& aAgnServerSession, CAgnServFileMgr& aAgnServFileMgr) + :iAgnServerSession(aAgnServerSession),iAgnServFileMgr(aAgnServFileMgr) + { + } + +CAgnSessionFileManager* CAgnSessionFileManager::NewL(CAgnServerSession& aAgnServerSession, CAgnServFileMgr& aAgnServFileMgr) + { + return new(ELeave) CAgnSessionFileManager(aAgnServerSession, aAgnServFileMgr); + } + +CAgnSessionFileManager::~CAgnSessionFileManager() + { + iSessionFiles.ResetAndDestroy(); + } + +TBool CAgnSessionFileManager::AddClientL(TInt64 aFileId, TInt aSessionId) + {//return ETrue if an object of CAgnSessionFile has been added in the array iSessionFiles + TBool objectAdded = EFalse; + TInt index = GetSessionFile(aSessionId); + if(index < 0) + { + CAgnServFile* file = iAgnServFileMgr.GetFileL(aFileId); + CAgnSessionFile* SessionFile = CAgnSessionFile::NewL(aSessionId, aFileId, *(file->Model()), iAgnServerSession); + CleanupStack::PushL(SessionFile); + TLinearOrder order(CompareFileId); + User::LeaveIfError(iSessionFiles.InsertInOrder(SessionFile, order)); + CleanupStack::Pop(SessionFile); + objectAdded = ETrue; + } + else if (iSessionFiles[index]->FileId() == 0) + {//CAgnSessionFile was added when the client start to observ the file change but file may not opened yet. + CAgnServFile* file = iAgnServFileMgr.GetFileL(aFileId); + iSessionFiles[index]->ResetModel(*file);//set the model and file Id. + } + return objectAdded; + } + +TInt CAgnSessionFileManager::FileIdCount() + { + return iSessionFiles.Count(); + } + +TInt64 CAgnSessionFileManager::FileId(TInt aIndex) + { + return iSessionFiles[aIndex]->FileId(); + } + +TInt CAgnSessionFileManager::CompareFileId(const CAgnSessionFile& aLeft, const CAgnSessionFile& aRight) + { + TInt64 key =aLeft.FileId(); + return CompareFileId(&key, aRight); + } + +TInt CAgnSessionFileManager::CompareFileId(const TInt64* aKey, const CAgnSessionFile& aAgnSessionFile) + { + if (*aKey > aAgnSessionFile.FileId()) + { + return 1; + } + else if (*aKey < aAgnSessionFile.FileId()) + { + return -1; + } + + return 0; + } + +TInt CAgnSessionFileManager::FindL(TInt64 aFileId) const + { + return iSessionFiles.FindInOrder(aFileId, CompareFileId); + } + +void CAgnSessionFileManager::AddChangeL(const TAgnChange& aChange) + { + TInt index = FindL(aChange.iFileId); + if(index >= 0) + { + (*iSessionFiles[index]).AddChangeToBufferL(aChange, &iAgnServerSession); + } + } + +void CAgnSessionFileManager::DeleteSessionFile(TInt aSessionId) + { + TInt index = GetSessionFile(aSessionId); + if(index >= 0) + { + delete iSessionFiles[index]; + iSessionFiles.Remove(index); + } + } + +void CAgnSessionFileManager::DeleteSessionFileIfFileNotificationNotRequired(TInt aSessionId) + {//Delete the object ony if it doesn't request for file notification otherwise set its fileid = 0 which indicate the file is closed by this CCalSession object. + TInt index = GetSessionFile(aSessionId); + if(index >= 0) + { + if(!iSessionFiles[index]->FileNotificationIsReqested()) + { + delete iSessionFiles[index]; + iSessionFiles.Remove(index); + } + else + { + iSessionFiles[index]->SetFileId(KNullFileId); + } + } + } + +CAgnSessionFile& CAgnSessionFileManager::GetSessionFileL(TInt64 aFileId) + { + TInt index = FindL(aFileId); + if(index < 0) + { + User::Leave(KErrNotFound); + } + return *iSessionFiles[index]; + } + +TInt CAgnSessionFileManager::GetSessionFile(TInt aSessionId) + { + const TInt count = iSessionFiles.Count(); + for (TInt ii = 0; ii < count; ++ii) + { + if(iSessionFiles[ii]->SessionId() == aSessionId) + { + return ii; + } + } + + return KErrNotFound; + } + +CAgnSessionFile& CAgnSessionFileManager::GetSessionFileByIndex(TInt aIndex) + { + __ASSERT_ALWAYS(aIndex >= 0, User::Invariant()); + return *iSessionFiles[aIndex]; + } + +CAgnSessionFile& CAgnSessionFileManager::GetSessionFileL(TCalCollectionId aCollectionId) + { + TInt64 fileId = iAgnServFileMgr.GetLongFileIdL(aCollectionId); + return GetSessionFileL(fileId); + } + +void CAgnSessionFileManager::ReSetModel(TInt64 aFileId, const CAgnServFile& aServFile) + { + CAgnSessionFile& sessionFile = GetSessionFileL(aFileId); + sessionFile.ResetModel(aServFile); + } + +CAgnSessionFile::CAgnSessionFile(TInt aSessionId, TInt64 aFileId, CAgnEntryModel* aModel, CAgnServerSession& aAgnServerSession) + :iSessionId(aSessionId), + iFileId(aFileId), + iModel(aModel), + iChangeNotificationPending(ENotificationNotRequested), + iBulkChangeInProgress(EFalse), + iChangeFilter(aAgnServerSession), + iBufferedNotificationsCount(0), + iNotificationBufferFull(EFalse) + { + } + +TInt64 CAgnSessionFile::FileId() const + { + return iFileId; + } + +CAgnSessionFile* CAgnSessionFile::NewL(TInt aSessionId, TInt64 aFileId, CAgnEntryModel& aModel, CAgnServerSession& aAgnServerSession) + { + return new(ELeave) CAgnSessionFile(aSessionId, aFileId, &aModel, aAgnServerSession); + } + +CAgnSessionFile* CAgnSessionFile::NewL(TInt aSessionId, CAgnServerSession& aAgnServerSession) + { + return new(ELeave) CAgnSessionFile(aSessionId, 0, NULL, aAgnServerSession); + } + +CAgnSessionFile::~CAgnSessionFile() + { + iBufferedNotificationStream.Close(); + delete iBufferedNotification; + delete iEntryIter; + } + +void CAgnSessionFile::TidyByDateStartL(TAgnMessageToComplete& aMessageToComplete, CAgnServFile& aServerFile) + { + aServerFile.TidyByDateStartL(aMessageToComplete, iChangeFilter); + iBulkChangeInProgress = ETrue; + } + +void CAgnSessionFile::BulkChangeCompletedL(const CAgnServerSession& aSession, TInt aErr) + { + if ( iBulkChangeInProgress ) + { + if ( aErr == KErrNone ) + { + if ( iChangeFilter.ChangeBroadcastEnabled() ) + { + iModel->NotifyChangeL(aSession, NULL, MCalChangeCallBack2::EChangeUndefined, NULL); + iChangeFilter.SetChangeMadeWhileDisabled(EFalse); + } + else + { + iChangeFilter.SetChangeMadeWhileDisabled(ETrue); + } + + iModel->NotifyPublishAndSubscribeL(iChangeFilter); + } + + iBulkChangeInProgress = EFalse; + } + + iModel->SetUpdateAlarmL(ETrue); + } + +void CAgnSessionFile::SetEnablePubSubNotificationL(TBool aEnablePubSub) + { + iChangeFilter.SetEnablePubSubNotification(aEnablePubSub); + iModel->NotifyPublishAndSubscribeL(iChangeFilter); + } + +void CAgnSessionFile::EnableChangeBroadcastL(const CAgnServerSession& aAgnServerSession) + { + TBool changeMadeWhileDisabled = iChangeFilter.ChangeMadeWhileDisabled(); + iChangeFilter.SetEnableChangeBroadcast(ETrue); + if ( changeMadeWhileDisabled ) + { + iModel->NotifyChangeL(aAgnServerSession, NULL, MCalChangeCallBack2::EChangeUndefined, NULL); + iChangeFilter.SetChangeMadeWhileDisabled(EFalse); + } + } + +void CAgnSessionFile::DisableChangeBroadcast() + { + iChangeFilter.SetEnableChangeBroadcast(EFalse); + } + +void CAgnSessionFile::UpdateEntryL(CAgnEntry& aEntry, TBool aDeleteChildren) + { + if(iModel->AgnServFile().IsLocked()) + { + User::Leave(KErrLocked); + } + + iModel->UpdateEntryL(aEntry, &iChangeFilter, aDeleteChildren); + } + +TAgnEntryId CAgnSessionFile::StoreEntryL(CAgnEntry& aEntry) + { + if(iModel->AgnServFile().IsLocked()) + { + User::Leave(KErrLocked); + } + + return iModel->StoreL(aEntry, &iChangeFilter); + } + +void CAgnSessionFile::DeleteEntryL(CAgnEntry& aEntry) + { + if(iModel->AgnServFile().IsLocked()) + { + User::Leave(KErrLocked); + } + + iModel->DeleteEntryL(aEntry, ETrue, &iChangeFilter); + } + +void CAgnSessionFile::DeleteEntryByGuidL(const TDesC8& aGuid, TBool aCommit) + { + if(iModel->AgnServFile().IsLocked()) + { + User::Leave(KErrLocked); + } + + CAgnEntry* entry = iModel->FetchEntryL(aGuid); + + if( entry ) + { + CleanupStack::PushL(entry); + iModel->DeleteEntryL(*entry, ETrue, NULL); + if (aCommit) + { + iModel->CommitAndNotifyDeletesL(iChangeFilter); + } + CleanupStack::PopAndDestroy(entry); + } + else + { + User::Leave(KErrNotFound); + } + } + +void CAgnSessionFile::RequestChangeNotification(const RMessage2 aMessage) + { + iChangeNotificationMessage = aMessage; + iChangeNotificationPending = ENotificationRequested; + TUint8 whichNotification = aMessage.Int1(); + if(whichNotification&EEntryChangeInSameFile ) + { + RequestEntryChangeNotification(); + } + + if(whichNotification&EFileChange ) + { + RequestFileChangeNotification(); + } + } + +void CAgnSessionFile::RequestEntryChangeNotification() + { + iChangeIterested = iChangeIterested|EEntryChangeInSameFile; + if (iChangeNotificationPending == ENotificationRequested && iBufferedNotification && iBufferedNotification->Size() > 0 ) + { + iChangeNotificationMessage.Complete(EEntryChangeInSameFile); + iChangeNotificationPending = ENotificationAwaitingRequest; + } + } + +void CAgnSessionFile::RequestFileChangeNotification() + { + iChangeIterested = iChangeIterested|EFileChange; + if ( iChangeNotificationPending == ENotificationRequested && iFileBufferedNotification && iFileBufferedNotification->Size() > 0 ) + { + iChangeNotificationMessage.Complete(EFileChange); + iChangeNotificationPending = ENotificationAwaitingRequest; + } + } + +void CAgnSessionFile::CancelChangeNotification(TUint8 aNotificationType) + { + if (iChangeNotificationPending != ENotificationNotRequested) + { + if(aNotificationType&EEntryChangeInSameFile) + { + iChangeIterested =iChangeIterested&~EEntryChangeInSameFile; + } + if(aNotificationType&EFileChange) + { + iChangeIterested = iChangeIterested&~EFileChange; + } + if(iChangeIterested == 0) + { + iChangeNotificationPending = ENotificationNotRequested; + if ( ! iChangeNotificationMessage.IsNull()) + { + iChangeNotificationMessage.Complete(KErrCancel); + } + } + } + } + +void CAgnSessionFile::SetChangeNotificationParametersL(const TTime aStart, const TTime aEnd,MCalChangeCallBack2::TChangeEntryType aChangeType) + { + iChangeFilter.SetChangeParameter(aStart, aEnd, aChangeType); + } + +TInt CAgnSessionFile::GetChangesSinceLastNotificationL( CBufFlat*& aDataBuffer) + { + iBufferedNotificationStream.Close(); + + // Send it back to the client + TInt bufferSize = 0; + if (iBufferedNotification) + { + bufferSize = iBufferedNotification->Size(); + } + + aDataBuffer = iBufferedNotification ; + iBufferedNotification = NULL; + iBufferedNotificationsCount = 0; + iNotificationBufferFull = EFalse; + + return bufferSize; + } + +TInt CAgnSessionFile::GetFileChangesSinceLastNotificationL( CBufFlat*& aDataBuffer) + { + iFileBufferedNotificationStream.Close(); + + // Send it back to the client + TInt bufferSize = 0; + if (iFileBufferedNotification) + { + bufferSize = iFileBufferedNotification->Size(); + } + + aDataBuffer = iFileBufferedNotification ; + iFileBufferedNotification = NULL; + iFileBufferedNotificationsCount = 0; + return bufferSize; + } + +TBool CAgnSessionFile::ToNotifyL(const TAgnChange& aChange, CAgnServerSession* aAgnServerSession) + { + if(iChangeNotificationPending == ENotificationNotRequested || !(iChangeIterested &EEntryChangeInSameFile)) + { + //Notification is not required. + return EFalse; + } + + if(aChange.iOperationType == MCalChangeCallBack2::EChangeTzRules || + aChange.iOperationType == MCalChangeCallBack2::EBackupStart || + aChange.iOperationType == MCalChangeCallBack2::ERestoreStart || + aChange.iOperationType == MCalChangeCallBack2::EBackupEnd || + aChange.iOperationType == MCalChangeCallBack2::ERestoreEnd) + { + //Tz rule has been changed or backup-restore state has been changed. + return ETrue; + } + + if(aAgnServerSession == aChange.iSession) + { + //Calendar entry has been changed but the change came from the same session + return EFalse; + } + + // It is Calendar entry change come from another session + return iChangeFilter.IsValidChangeL(aChange); + } + +void CAgnSessionFile::AddChangeToBufferL(const TAgnChange& aChange, CAgnServerSession* aAgnServerSession) + { + if(iChangeNotificationPending == ENotificationRequested && aChange.iOperationType == MCalChangeCallBack2::ERestoredFileCanNotBeOpened) + { + iChangeNotificationMessage.Complete(KErrCorrupt); + iChangeNotificationPending = ENotificationAwaitingRequest; + } + else if (ToNotifyL(aChange, aAgnServerSession)) + { + // store the change in the notification buffer + if (!iBufferedNotification) + { + iBufferedNotification = CBufFlat::NewL(KGranNotificationBuffer); + iBufferedNotificationsCount = 0; + iNotificationBufferFull = EFalse; + iBufferedNotificationStream.Open(*iBufferedNotification); + } + + if (iBufferedNotificationsCount < KMaxNumberOfBufferedNotifications) + { + if(!iNotificationBufferFull) + { + iBufferedNotificationStream.WriteUint32L(aChange.iEntryId); + iBufferedNotificationStream.WriteInt8L(aChange.iOperationType); + iBufferedNotificationStream.WriteInt8L(aChange.iEntryType); + iBufferedNotificationStream.CommitL(); + + ++iBufferedNotificationsCount; + + // notify client that a change has occured + if (iChangeNotificationPending == ENotificationRequested) + { + iChangeNotificationMessage.Complete(EEntryChangeInSameFile); + iChangeNotificationPending = ENotificationAwaitingRequest; + } + } + } + else + { + iNotificationBufferFull = ETrue; + + // Clear all the notifications in the buffer + iBufferedNotification->Reset(); + iBufferedNotificationStream.Open(*iBufferedNotification); + + // Add a single 'Undefined Change' notification to the notification buffer + iBufferedNotificationStream.WriteUint32L(0); + iBufferedNotificationStream.WriteInt8L(MCalChangeCallBack2::EChangeUndefined); + iBufferedNotificationStream.WriteInt8L(MCalChangeCallBack2::EChangeEntryAll); + iBufferedNotificationStream.CommitL(); + + // Reset the count to 1 - Undefined Change + iBufferedNotificationsCount = 1; + } + } + } + +void CAgnSessionFile::AddFileChangeToBufferL(CAgnFileChangeInfo& aFileChangeInfo) + { + if(iChangeNotificationPending != ENotificationNotRequested && iChangeIterested &EFileChange) + { + // store the change in the notification buffer + if (!iFileBufferedNotification) + { + iFileBufferedNotification = CBufFlat::NewL(KGranNotificationBuffer); + iFileBufferedNotificationsCount = 0; + iFileBufferedNotificationStream.Open(*iFileBufferedNotification); + iFileBufferedNotificationStream.WriteInt32L(0); + } + MStreamBuf * streamBuf = iFileBufferedNotificationStream.Sink(); + TStreamPos posStart(0); + + if (iFileBufferedNotificationsCount < KMaxNumberOfBufferedNotifications) + { + aFileChangeInfo.ExternalizeL(iFileBufferedNotificationStream); + //bring the stream write position to the start + streamBuf->SeekL(MStreamBuf::EWrite, posStart); + iFileBufferedNotificationStream.WriteInt32L(++iFileBufferedNotificationsCount); + iFileBufferedNotificationStream.CommitL(); + } + else + { + // Clear all the notifications in the buffer + iFileBufferedNotification->Reset(); + iFileBufferedNotificationStream.Open(*iBufferedNotification); + + // Add a single 'Undefined Change' notification to the notification buffer + CAgnFileChangeInfo* fileChang = CAgnFileChangeInfo::NewL(NULL, MCalFileChangeObserver::ECalendarInfoUpdated); + CleanupStack::PushL(fileChang); + aFileChangeInfo.ExternalizeL(iFileBufferedNotificationStream); + //bring the stream write position to the start + streamBuf->SeekL(MStreamBuf::EWrite, posStart); + iFileBufferedNotificationStream.WriteInt32L(++iFileBufferedNotificationsCount); + iFileBufferedNotificationStream.CommitL(); + CleanupStack::PopAndDestroy(fileChang); + // Reset the count to 1 - Undefined Change + iFileBufferedNotificationsCount = 1; + } + // notify client that a change has occured + if (iChangeNotificationPending == ENotificationRequested) + { + iChangeNotificationMessage.Complete(EFileChange); + iChangeNotificationPending = ENotificationAwaitingRequest; + } + //bring the stream write position to the end + streamBuf->SeekL(MStreamBuf::EWrite, posStart + iFileBufferedNotification->Size()); + } + } + +TBool CAgnSessionFile::CreateEntryIterL() + { + if(iModel->AgnServFile().IsLocked()) + { + User::Leave(KErrLocked); + } + + if(!iEntryIter) + { + iEntryIter = iModel->CreateEntryIterL(); + } + return iEntryIter->SetToFirstL(); + } + +TBool CAgnSessionFile::IsEntryAvailableAtIteratorL() + { + if(iModel->AgnServFile().IsLocked()) + { + User::Leave(KErrLocked); + } + + __ASSERT_ALWAYS(iEntryIter, User::Leave(KErrCorrupt)); + return iEntryIter->NextL(); + } + +CAgnEntry* CAgnSessionFile::FetchEntryAtIteratorL() + { + __ASSERT_ALWAYS(iEntryIter, User::Leave(KErrCorrupt)); + return iModel->FetchEntryL(iEntryIter->At()); + } + +void CAgnSessionFile::ResetModel(const CAgnServFile& aServFile) + { + delete iEntryIter; + iEntryIter = NULL; + iModel = aServFile.Model(); + iFileId = iModel->GetFileIdL(); + } + +TInt CAgnSessionFile::SessionId() + { + return iSessionId; + } + +TBool CAgnSessionFile::FileNotificationIsReqested() + { + return iChangeIterested& EFileChange; + } + +void CAgnSessionFile::SetFileId(TCalFileId aFileId) + { + iFileId = aFileId; + } + +#ifdef SYMBIAN_SYSTEM_STATE_MANAGEMENT +TBool CAgnServerSession::IsReadOnlyOperation() + { + //Only operations that have read user data permissions are allowed once a shutdown notification + //is received. The Rollback operation is still allowed. + TInt operation = iMessage.Function(); + if (operation == ERollback || operation < KCapabilityWriteUserData) + { + return KErrNone; + } + else + { + return KErrLocked; + } + } +#endif + + +void CAgnServerSession::CreateInstanceIteratorL() + { + + //TFindInstanceParams buffer, CCalSortCriteria buffer, iteratorId + //Do this first, so it can be pushed off the cleanup stack last + CAgnSortCriteria* sortCriteria = CAgnSortCriteria::NewL(); + CleanupStack::PushL(sortCriteria); + + TFindInstanceParams* parameters = new (ELeave) TFindInstanceParams(); + CleanupStack::PushL(parameters); + + RArray fileIds; + CleanupClosePushL(fileIds); + + // Restore find instance parameter + const TInt KBufferSize = iMessage.GetDesLengthL(KSlot0); + CBufFlat* buffer = CBufFlat::NewL(KBufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0, KBufferSize); + + TPtr8 des(buffer->Ptr(0)); + iMessage.ReadL(KSlot0, des); + + RDesReadStream readStream(des); + parameters->InternalizeL(readStream); + + // Restore sort criteria + const TInt KSortCriteriaSize = iMessage.GetDesLengthL(KSlot1); + CBufFlat* sortCriteriaBuffer = CBufFlat::NewL(KSortCriteriaSize); + CleanupStack::PushL(sortCriteriaBuffer); + sortCriteriaBuffer->ExpandL(0, KSortCriteriaSize); + TPtr8 desSortCriteria(sortCriteriaBuffer->Ptr(0)); + iMessage.ReadL(KSlot1, desSortCriteria); + RBufReadStream sortCriteriaStream; + sortCriteriaStream.Open(*sortCriteriaBuffer); + sortCriteria->InternalizeL(sortCriteriaStream); + + //Create iterator with specified finding and sorting settings. + + if(iInstanceIteratorMgr == NULL) + { + //Do this to protect server from fuzzy attacks. + iInstanceIteratorMgr = CAgsInstanceIteratorMgr::NewL(); + } + + TInt filecount = sortCriteriaStream.ReadInt16L(); + for(TInt ii=0;ii> fileId; + fileIds.AppendL(fileId); + } + + CleanupStack::PopAndDestroy(sortCriteriaBuffer); + CleanupStack::PopAndDestroy(buffer); + + TInt iteratorId = iInstanceIteratorMgr->CreateIteratorL(parameters, sortCriteria, fileIds, *iAgnServer.FileMgr()); + //We are satisfied that the above line has taken ownership, so we can now pop these two + CleanupStack::PopAndDestroy(&fileIds);//doesn't destroy the content of the array + CleanupStack::Pop(parameters); + CleanupStack::Pop(sortCriteria); + + // Send the assigned iterator id back to the client + TPckg id(iteratorId); + iMessage.WriteL(KSlot2, id); + } + +void CAgnServerSession::DestroyInstanceIteratorL() + { + TInt iteratorId = iMessage.Int0(); + iInstanceIteratorMgr->DestroyIteratorL(iteratorId); + } + +void CAgnServerSession::InstanceIteratorNextL() + { + TInt iteratorId = iMessage.Int2(); + TInt startIndex = iMessage.Int3(); + + RArray instances; + CleanupClosePushL(instances); + iInstanceIteratorMgr->NextInstancesL(iteratorId, instances, startIndex); + + delete iBuffer; + iBuffer = NULL; + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + const TInt KCount = instances.Count(); + + bufStream.WriteUint32L(KCount); + + for ( TInt ii = 0; ii < KCount; ++ii ) + { + bufStream << instances[ii]; + } + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + CleanupStack::PopAndDestroy(&instances); + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot1, size); + } + +void CAgnServerSession::InstanceIteratorPreviousL() + { + TInt iteratorId = iMessage.Int2(); + TInt lastIndex = iMessage.Int3(); + + RArray instances; + CleanupClosePushL(instances); + iInstanceIteratorMgr->PreviousInstancesL(iteratorId, instances, lastIndex); + + delete iBuffer; + iBuffer = NULL; + iBuffer = CBufFlat::NewL(KInitialBufferSize); + + RBufWriteStream bufStream; + bufStream.Open(*iBuffer); + CleanupClosePushL(bufStream); + + const TInt KCount = instances.Count(); + + bufStream.WriteUint32L(KCount); + + for ( TInt ii = 0; ii < KCount; ++ii ) + { + bufStream << instances[ii]; + } + + bufStream.CommitL(); + + CleanupStack::PopAndDestroy(&bufStream); // bufStream.Close(); + CleanupStack::PopAndDestroy(&instances); + + // Send it back to the client + TPckg size(iBuffer->Size()); + iMessage.WriteL(KSlot1, size); + } + +void CAgnServerSession::InstanceIteratorCountL() + { + TInt iteratorId = iMessage.Int0(); + TInt count = iInstanceIteratorMgr->CountL(iteratorId); + TPckg size(count); + iMessage.WriteL(KSlot1, size); + } + +void CAgnServerSession::InstanceIteratorLocateIndexL() + { + TInt iteratorId = iMessage.Int0(); + TPckgBuf instanceId; + iMessage.ReadL(KSlot1,instanceId); + TInt index = iInstanceIteratorMgr->LocateIndexL(iteratorId, instanceId()); + TPckg size(index); + iMessage.WriteL(KSlot2, size); + } + + +