public static RopResult GetContentsTable(int serverId, int folderHandleIndex, DeleteFlags deleteFlags, out int rowCount) { // The construction conditions. Condition.IsTrue(connections.Count > 0); Condition.IsTrue(connections.Keys.Contains(serverId)); // Get current ConnectionData value. ConnectionData currentConnection = connections[serverId]; // Create a new currentDownloadContext. AbstractUploadInfo currentUploadContext = new AbstractUploadInfo(); rowCount = -1; // Find the current Upload Context foreach (AbstractUploadInfo tempUploadContext in currentConnection.UploadContextContainer) { if (tempUploadContext.RelatedFastTransferOperation == EnumFastTransferOperation.SynchronizationImportDeletes) { currentUploadContext = tempUploadContext; } } if (folderHandleIndex < 0) { rowCount = -1; // serverHandleIndex is Invalid Parameter. return RopResult.InvalidParameter; } else { if (deleteFlags == DeleteFlags.Initial) { rowCount = 0; return RopResult.Success; } else if (deleteFlags == DeleteFlags.HardDeleteCheck) { rowCount = 0; } else if (deleteFlags == DeleteFlags.SoftDeleteCheck) { rowCount = softDeleteMessageCount; if (priorOperation == MS_OXCFXICS.PriorOperation.RopSynchronizationImportMessageMove) { rowCount = 1; } } return RopResult.Success; } }
public static RopResult GetHierarchyTable(int serverId, int folderHandleIndex, DeleteFlags deleteFlags, out int rowCount) { // The construction conditions. Condition.IsTrue(connections.Count > 0); Condition.IsTrue(connections.Keys.Contains(serverId)); // Get current ConnectionData value. ConnectionData currentConnection = connections[serverId]; // Create a new currentDownloadContext. AbstractUploadInfo currentUploadContext = new AbstractUploadInfo(); // Initialize the rowCount value. rowCount = -1; // Find the current Upload Context foreach (AbstractUploadInfo tempUploadContext in currentConnection.UploadContextContainer) { if (tempUploadContext.RelatedFastTransferOperation == EnumFastTransferOperation.SynchronizationImportDeletes) { currentUploadContext = tempUploadContext; } } if (folderHandleIndex < 0) { rowCount = -1; // serverHandleIndex is Invalid Parameter. return RopResult.InvalidParameter; } else { if (deleteFlags == DeleteFlags.Initial) { rowCount = 0; return RopResult.Success; } else if (deleteFlags == DeleteFlags.HardDeleteCheck) { if (requirementContainer.ContainsKey(90205002) && !requirementContainer[90205002]) { rowCount = -1; } else { rowCount = 0; } } else if (deleteFlags == DeleteFlags.SoftDeleteCheck) { rowCount = softDeleteFolderCount; } return RopResult.Success; } }
public static RopResult SynchronizationUploadState(int serverId, int uploadContextHandleIndex, ICSStateProperties icsPropertyType, bool isPidTagIdsetGivenInputAsInter32, int icsStateIndex) { // The contractions conditions. Condition.IsTrue(connections.Count > 0); Condition.IsTrue(connections.Keys.Contains(serverId)); Condition.IsTrue(connections[serverId].DownloadContextContainer.Count > 0 || connections[serverId].UploadContextContainer.Count > 0); // Initialize the return value. RopResult result = RopResult.InvalidParameter; AbstractUploadInfo uploadInfo = new AbstractUploadInfo(); AbstractDownloadInfo downLoadInfo = new AbstractDownloadInfo(); // Get the current ConnectionData value. ConnectionData changeConnection = connections[serverId]; // Identify whether the DownloadContext or UploadContext is existent or not and record the index. bool isCurrentUploadinfoExist = false; int currentUploadIndex = 0; bool isCurrentDownLoadinfoExist = false; int currentDownLoadIndex = 0; foreach (AbstractUploadInfo tempUploadInfo in changeConnection.UploadContextContainer) { if (tempUploadInfo.UploadHandleIndex == uploadContextHandleIndex) { // Set the value to the related variable when the current upload context is existent. isCurrentUploadinfoExist = true; uploadInfo = tempUploadInfo; currentUploadIndex = changeConnection.UploadContextContainer.IndexOf(tempUploadInfo); break; } } if (!isCurrentUploadinfoExist) { foreach (AbstractDownloadInfo tempDownLoadInfo in changeConnection.DownloadContextContainer) { if (tempDownLoadInfo.DownloadHandleIndex == uploadContextHandleIndex) { // Set the value to the related variable when the current Download context is existent. isCurrentDownLoadinfoExist = true; downLoadInfo = tempDownLoadInfo; currentDownLoadIndex = changeConnection.DownloadContextContainer.IndexOf(tempDownLoadInfo); break; } } } if (isCurrentDownLoadinfoExist || isCurrentUploadinfoExist) { if (isCurrentUploadinfoExist) { if (icsStateIndex != 0) { AbstractFolder currentFolder = new AbstractFolder(); foreach (AbstractFolder tempFolder in changeConnection.FolderContainer) { if (tempFolder.FolderHandleIndex == uploadInfo.RelatedObjectHandleIndex) { // Set the value to the related variable when the current Folder is existent. currentFolder = tempFolder; Condition.IsTrue(currentFolder.ICSStateContainer.ContainsKey(icsStateIndex)); } } // Add ICS State to ICSStateContainer of current folder. AbstractUpdatedState updatedState = currentFolder.ICSStateContainer[icsStateIndex]; switch (icsPropertyType) { case ICSStateProperties.PidTagIdsetGiven: // Set IdsetGiven value uploadInfo.UpdatedState.IdsetGiven = updatedState.IdsetGiven; break; case ICSStateProperties.PidTagCnsetRead: // Set CnsetRead value uploadInfo.UpdatedState.CnsetRead = updatedState.CnsetRead; break; case ICSStateProperties.PidTagCnsetSeen: // Set CnsetSeen value uploadInfo.UpdatedState.CnsetSeen = updatedState.CnsetSeen; break; case ICSStateProperties.PidTagCnsetSeenFAI: // Set CnsetSeenFAI value uploadInfo.UpdatedState.CnsetSeenFAI = updatedState.CnsetSeenFAI; break; default: break; } // Update the UploadContextContainer context. changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Update(currentUploadIndex, uploadInfo); } } else { if (icsStateIndex != 0) { AbstractFolder currentFolder = new AbstractFolder(); foreach (AbstractFolder tempFolder in changeConnection.FolderContainer) { if (tempFolder.FolderHandleIndex == downLoadInfo.RelatedObjectHandleIndex) { // Set the value to the related variable when the current Folder is existent. currentFolder = tempFolder; // Identify ICS State whether exist index or not in ICSStateContainer Condition.IsTrue(currentFolder.ICSStateContainer.ContainsKey(icsStateIndex)); } } // Add update state to ICSStateContainer of current folder. AbstractUpdatedState updatedState = currentFolder.ICSStateContainer[icsStateIndex]; switch (icsPropertyType) { case ICSStateProperties.PidTagIdsetGiven: // Set IdsetGiven value. downLoadInfo.UpdatedState.IdsetGiven = updatedState.IdsetGiven; break; case ICSStateProperties.PidTagCnsetRead: // Set CnsetRead value. downLoadInfo.UpdatedState.CnsetRead = updatedState.CnsetRead; break; case ICSStateProperties.PidTagCnsetSeen: // Set CnsetSeen value. downLoadInfo.UpdatedState.CnsetSeen = updatedState.CnsetSeen; break; case ICSStateProperties.PidTagCnsetSeenFAI: // Set CnsetSeenFAI value. downLoadInfo.UpdatedState.CnsetSeenFAI = updatedState.CnsetSeenFAI; break; default: break; } // Update the DownloadContextContainer. changeConnection.DownloadContextContainer = changeConnection.DownloadContextContainer.Update(currentDownLoadIndex, downLoadInfo); } } connections[serverId] = changeConnection; if (isPidTagIdsetGivenInputAsInter32) { // Identify the property tag whether PtypInteger32 is or not. if (requirementContainer.Keys.Contains(2657) && requirementContainer[2657]) { result = RopResult.Success; ModelHelper.CaptureRequirement(2657, "[In Receiving the MetaTagIdsetGiven ICS State Property] Implementation does accept this MetaTagIdsetGiven property when the property tag identifies it as PtypInteger32. (Microsoft Exchange Server 2007 and above follow this behavior.)"); } else { return result; } } result = RopResult.Success; } return result; }
public static RopResult FastTransferDestinationConfigure(int serverId, int objHandleIndex, SourceOperation option, FastTransferDestinationConfigureCopyFlags copyFlag, out int uploadContextHandleIndex) { // The construction conditions. Condition.IsTrue(connections.Count > 0); Condition.IsTrue(connections.Keys.Contains(serverId)); // Initialize return value. RopResult result = RopResult.InvalidParameter; if (requirementContainer.ContainsKey(3492001)) { if ((copyFlag == FastTransferDestinationConfigureCopyFlags.Invalid) && requirementContainer[3492001] == true) { // FastTransferDestinationConfigureCopyFlags is invalid parameter and exchange server version is not ExchangeServer2007 . uploadContextHandleIndex = -1; ModelHelper.CaptureRequirement( 3492001, @"[In Appendix A: Product Behavior] If unknown flags in the CopyFlags field are set, implementation does fail the operation. <36> Section 3.2.5.8.2.1: Exchange 2010, Exchange 2013 and Exchange 2016 fail the ROP [RopFastTransferDestinationConfigure ROP] if unknown bit flags in the CopyFlags field are set."); return result; } } if (option == SourceOperation.CopyProperties || option == SourceOperation.CopyTo || option == SourceOperation.CopyFolder || option == SourceOperation.CopyMessages) { priorOperation = MS_OXCFXICS.PriorOperation.RopFastTransferDestinationConfigure; } sourOperation = option; // Create a new Upload context. AbstractUploadInfo uploadInfo = new AbstractUploadInfo(); // Set value for upload context. uploadContextHandleIndex = AdapterHelper.GetHandleIndex(); uploadInfo.UploadHandleIndex = uploadContextHandleIndex; ConnectionData changeConnection = connections[serverId]; connections.Remove(serverId); // Add the new Upload context to UploadContextContainer. changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Add(uploadInfo); connections.Add(serverId, changeConnection); result = RopResult.Success; ModelHelper.CaptureRequirement( 581, @"[In RopFastTransferDestinationConfigure ROP] The RopFastTransferDestinationConfigure ROP ([MS-OXCROPS] section 2.2.12.1) initializes a FastTransfer operation for uploading content encoded in a client-provided FastTransfer stream into a mailbox."); if (requirementContainer.ContainsKey(3492002)) { if ((copyFlag == FastTransferDestinationConfigureCopyFlags.Invalid) && requirementContainer[3492002] == true) { // Exchange 2007 ignore unknown values of the CopyFlags field. ModelHelper.CaptureRequirement( 3492002, @"[In Appendix A: Product Behavior] If unknown flags in the CopyFlags field are set, implementation does not fail the operation. <37> Section 3.2.5.8.2.1: Exchange 2007 ignore unknown values of the CopyFlags field."); return result; } } return result; }
public static RopResult SynchronizationImportMessageMove(int serverId, int synchronizationUploadContextHandleIndex, int sourceFolderIdIndex, int destinationFolderIdIndex, int sourceMessageIdIndex, int sourceFolderHandleIndex, int destinationFolderHandleIndex, bool inewerClientChange, out bool iolderversion, out bool icnpc) { // The contractions conditions. Condition.IsTrue(connections.Count > 0); Condition.IsTrue(connections.Keys.Contains(serverId)); Condition.IsTrue(connections[serverId].FolderContainer.Count > 1); // Initialize the return value. RopResult result = RopResult.InvalidParameter; iolderversion = false; icnpc = false; // Get the current ConnectionData value. ConnectionData changeConnection = connections[serverId]; // Identify whether Current Upload information is existent or not. bool isCurrentUploadinfoExist = false; // Record the current Upload information. int currentUploadIndex = 0; AbstractUploadInfo uploadInfo = new AbstractUploadInfo(); foreach (AbstractUploadInfo tempUploadInfo in changeConnection.UploadContextContainer) { if (tempUploadInfo.UploadHandleIndex == synchronizationUploadContextHandleIndex) { // Set the value for current upload information when current upload Information is existent. isCurrentUploadinfoExist = true; uploadInfo = tempUploadInfo; currentUploadIndex = changeConnection.UploadContextContainer.IndexOf(tempUploadInfo); } } // Create variable of relate to source Folder. AbstractFolder sourceFolder = new AbstractFolder(); bool isSourceFolderExist = false; int sourceFolderIndex = 0; // Create variable of relate to destination Folder. AbstractFolder destinationFolder = new AbstractFolder(); bool isdestinationFolderExist = false; int destinationFolderIndex = 0; // Create a new message. AbstractMessage movedMessage = new AbstractMessage(); // Identify whether the Moved Message is existent or not. bool isMovedMessageExist = false; int movedMessageIndex = 0; foreach (AbstractFolder tempFolder in changeConnection.FolderContainer) { if (tempFolder.FolderIdIndex == sourceFolderIdIndex && tempFolder.FolderHandleIndex == sourceFolderHandleIndex) { // Set the value to the variable when the source folder is existent. isSourceFolderExist = true; sourceFolder = tempFolder; sourceFolderIndex = changeConnection.FolderContainer.IndexOf(tempFolder); } } foreach (AbstractFolder tempFolder in changeConnection.FolderContainer) { if (tempFolder.FolderIdIndex == destinationFolderIdIndex && tempFolder.FolderHandleIndex == destinationFolderHandleIndex) { // Set the value to the related variable when the destination folder is existent. isdestinationFolderExist = true; destinationFolder = tempFolder; destinationFolderIndex = changeConnection.FolderContainer.IndexOf(tempFolder); } } foreach (AbstractMessage tempMessage in changeConnection.MessageContainer) { if (tempMessage.MessageIdIndex == sourceMessageIdIndex) { // Set the value to the related variable when the source Message is existent. isMovedMessageExist = true; movedMessage = tempMessage; movedMessageIndex = changeConnection.MessageContainer.IndexOf(tempMessage); } } if (isSourceFolderExist && isdestinationFolderExist && isMovedMessageExist && isCurrentUploadinfoExist) { // Set value for the new abstract message property. movedMessage.FolderIdIndex = destinationFolder.FolderIdIndex; movedMessage.FolderHandleIndex = destinationFolder.FolderHandleIndex; // Assigned a new change. movedMessage.ChangeNumberIndex = ModelHelper.GetChangeNumberIndex(); // Assigned a new message id. movedMessage.MessageIdIndex = AdapterHelper.GetObjectIdIndex(); // Update message Container. changeConnection.MessageContainer = changeConnection.MessageContainer.Update(movedMessageIndex, movedMessage); // Remove the current message id from MessageIds of source folder. sourceFolder.MessageIds = sourceFolder.MessageIds.Remove(movedMessage.MessageIdIndex); changeConnection.FolderContainer = changeConnection.FolderContainer.Update(sourceFolderIndex, sourceFolder); // Remove the current message id from MessageIds of destination Folder. destinationFolder.MessageIds = destinationFolder.MessageIds.Add(movedMessage.MessageIdIndex); changeConnection.FolderContainer = changeConnection.FolderContainer.Update(destinationFolderIndex, destinationFolder); // Add information of Upload context uploadInfo.IsnewerClientChange = inewerClientChange; uploadInfo.RelatedFastTransferOperation = EnumFastTransferOperation.SynchronizationImportMessageMove; // Update the upload context container changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Update(currentUploadIndex, uploadInfo); connections[serverId] = changeConnection; // Identify whether the IsnewerClientChange is true or false. if (uploadInfo.IsnewerClientChange == false) { result = RopResult.Success; ModelHelper.CaptureRequirement( 2449, @"[In Uploading Changes Using ICS] Value is Success indicates No error occurred, or a conflict has been resolved."); // Because if the result is success means the information about moving a message between two existing folders within the same mailbox imported ModelHelper.CaptureRequirement( 839, @"[In RopSynchronizationImportMessageMove ROP] The RopSynchronizationImportMessageMove ROP ([MS-OXCROPS] section 2.2.13.6) imports information about moving a message between two existing folders within the same mailbox."); } else { // Set out put parameter value iolderversion = true; ModelHelper.CaptureRequirement( 875, @"[In RopSynchronizationImportMessageMove ROP Response Buffer] [ Return value (4 bytes):] The following table[In section 2.2.3.2.4.4] contains additional return values[NewerClientChange] , if the ROP succeeded, but the server replica had an older version of a message than the local replica, the return value is 0x00040821."); icnpc = true; ModelHelper.CaptureRequirement( 876, @"[In RopSynchronizationImportMessageMove ROP Response Buffer] [ Return value (4 bytes):] The following table[In section 2.2.3.2.4.4] contains additional return values[NewerClientChange] , if the values of the ChangeNumber and PredecessorChangeList fields, specified in section 2.2.3.2.4.4.1, were not applied to the destination message, the return value is 0x00040821."); ModelHelper.CaptureRequirement( 1892, "[In Identifying Objects and Maintaining Change Numbers]Copying of messaging objects within a mailbox or moving messages between folders of the same mailbox translates into creation of new messaging objects and therefore, new internal identifiers MUST be assigned to new copies."); result = RopResult.NewerClientChange; } // Record RopSynchronizationImportMessageMove operation. priorUploadOperation = PriorOperation.RopSynchronizationImportMessageMove; } return result; }
public static RopResult SynchronizationGetTransferState(int serverId, int syncHandleIndex, out int downloadcontextHandleIndex) { // The contractions conditions. Condition.IsTrue(connections.Count > 0); Condition.IsTrue(connections.Keys.Contains(serverId)); Condition.IsTrue(connections[serverId].UploadContextContainer.Count > 0 || connections[serverId].DownloadContextContainer.Count > 0); // Initialize the return value. RopResult result = RopResult.InvalidParameter; downloadcontextHandleIndex = -1; // Get the current ConnectionData value. ConnectionData changeConnection = connections[serverId]; AbstractDownloadInfo downloadInfo = new AbstractDownloadInfo(); AbstractUploadInfo uploadInfo = new AbstractUploadInfo(); // Identify whether the Download context or Upload context is existent or not and record the index. bool isCurrentDownloadInfoExist = false; bool isCurrentUploadInfoExist = false; foreach (AbstractDownloadInfo temp in changeConnection.DownloadContextContainer) { if (temp.DownloadHandleIndex == syncHandleIndex) { // Set the value to the related variable when the current Download context is existent. isCurrentDownloadInfoExist = true; downloadInfo = temp; } } if (!isCurrentDownloadInfoExist) { foreach (AbstractUploadInfo tempInfo in changeConnection.UploadContextContainer) { if (tempInfo.UploadHandleIndex == syncHandleIndex) { // Set the value to the related variable when the current upload context is existent. isCurrentUploadInfoExist = true; uploadInfo = tempInfo; } } } if (isCurrentDownloadInfoExist || isCurrentUploadInfoExist) { // Create a new download context. AbstractDownloadInfo newDownloadInfo = new AbstractDownloadInfo { DownloadHandleIndex = AdapterHelper.GetHandleIndex() }; // Out the new downloadHandle. downloadcontextHandleIndex = newDownloadInfo.DownloadHandleIndex; ModelHelper.CaptureRequirement(765, "[In RopSynchronizationGetTransferState ROP Response Buffer]OutputServerObject: The value of this field MUST be the FastTransfer download context for the ICS state."); if (isCurrentDownloadInfoExist) { // Set the new Download context value newDownloadInfo.RelatedObjectHandleIndex = downloadInfo.RelatedObjectHandleIndex; newDownloadInfo.SynchronizationType = downloadInfo.SynchronizationType; newDownloadInfo.UpdatedState = downloadInfo.UpdatedState; priorDownloadOperation = PriorDownloadOperation.RopSynchronizationGetTransferState; } else { // Set the new Upload context value newDownloadInfo.RelatedObjectHandleIndex = uploadInfo.RelatedObjectHandleIndex; newDownloadInfo.SynchronizationType = uploadInfo.SynchronizationType; newDownloadInfo.UpdatedState = uploadInfo.UpdatedState; } // Set the abstractFastTransferStreamType for new Down loadContext value newDownloadInfo.AbstractFastTransferStreamType = FastTransferStreamType.state; newDownloadInfo.RelatedFastTransferOperation = EnumFastTransferOperation.SynchronizationGetTransferState; // Add new download context to DownloadContextContainer. changeConnection.DownloadContextContainer = changeConnection.DownloadContextContainer.Add(newDownloadInfo); connections[serverId] = changeConnection; result = RopResult.Success; // Because context created if the RopSynchronizationGetTransferState execute successful. ModelHelper.CaptureRequirement( 758, @"[In RopSynchronizationGetTransferState ROP] The RopSynchronizationGetTransferState ROP ([MS-OXCROPS] section 2.2.13.8) creates a FastTransfer download context for the checkpoint ICS state of the operation identified by the given synchronization download context or synchronization upload context at the current moment in time."); } return result; }
public static RopResult SynchronizationImportReadStateChanges(int serverId, int uploadContextHandleIndex, int messageHandleIndex, bool ireadstatus) { // The contractions conditions. Condition.IsTrue(connections.Count > 0); Condition.IsTrue(connections.Keys.Contains(serverId)); Condition.IsTrue(connections[serverId].MessageContainer.Count > 0); // Initialize the return value. RopResult result = RopResult.InvalidParameter; ConnectionData changeConnection = connections[serverId]; AbstractMessage currentMessage = new AbstractMessage(); AbstractUploadInfo uploadInfo = new AbstractUploadInfo(); // Identify whether the Message is existent or not and record the index. bool isCurrentMessageExist = false; int currentMessageindex = 0; // Identify whether the Upload information is existent or not and record the index. bool isCurrentUploadinfoExist = false; int currentUploadIndex = 0; foreach (AbstractUploadInfo tempUploadInfo in changeConnection.UploadContextContainer) { if (tempUploadInfo.UploadHandleIndex == uploadContextHandleIndex) { // Set the value to the variable when the upload context is existent. isCurrentUploadinfoExist = true; uploadInfo = tempUploadInfo; currentUploadIndex = changeConnection.UploadContextContainer.IndexOf(tempUploadInfo); } } foreach (AbstractMessage tempMessage in changeConnection.MessageContainer) { if (tempMessage.MessageHandleIndex == messageHandleIndex) { // Set the value to the variable when the Message is existent. isCurrentMessageExist = true; currentMessage = tempMessage; currentMessageindex = changeConnection.MessageContainer.IndexOf(tempMessage); } } if (isCurrentMessageExist) { // Find the parent folder of current message AbstractFolder parentfolder = new AbstractFolder(); int parentfolderIndex = 0; foreach (AbstractFolder tempFolder in changeConnection.FolderContainer) { if (tempFolder.FolderHandleIndex == currentMessage.FolderHandleIndex) { parentfolder = tempFolder; parentfolderIndex = changeConnection.FolderContainer.IndexOf(tempFolder); if (parentfolder.FolderPermission == PermissionLevels.None) { return result = RopResult.AccessDenied; } } } } if (isCurrentUploadinfoExist && isCurrentMessageExist) { // Set the message read status value. if (currentMessage.IsRead != ireadstatus) { currentMessage.IsRead = ireadstatus; // Get read State changeNumber. currentMessage.ReadStateChangeNumberIndex = ModelHelper.GetChangeNumberIndex(); ModelHelper.CaptureRequirement( 2260, @"[In Receiving a RopSynchronizationImportReadStateChanges Request]Upon successful completion of this ROP, the ICS state on the synchronization context MUST be updated by adding the new change number to the MetaTagCnsetRead property (section 2.2.1.1.4)."); } // Record the related Synchronization Operation. uploadInfo.RelatedFastTransferOperation = EnumFastTransferOperation.SynchronizationReadStateChanges; // Update the upload context container and message container. changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Update(currentUploadIndex, uploadInfo); changeConnection.MessageContainer = changeConnection.MessageContainer.Update(currentMessageindex, currentMessage); connections[serverId] = changeConnection; result = RopResult.Success; ModelHelper.CaptureRequirement( 2449, @"[In Uploading Changes Using ICS] Value is Success indicates No error occurred, or a conflict has been resolved."); // Because if the result is success means message read state changes is imported into the server replica. ModelHelper.CaptureRequirement( 905, @"[In RopSynchronizationImportReadStateChanges ROP] The RopSynchronizationImportReadStateChanges ROP ([MS-OXCROPS] section 2.2.13.3) imports message read state changes into the server replica."); } return result; }
public static RopResult SynchronizationImportMessageChange(int serverId, int uploadContextHandleIndex, int messageIdindex, ImportFlag importFlag, out int importMessageHandleIndex) { // The contractions conditions. Condition.IsTrue(connections.Count > 0); Condition.IsTrue(connections.Keys.Contains(serverId)); Condition.IsTrue(connections[serverId].UploadContextContainer.Count > 0 && connections[serverId].LogonHandleIndex > 0); // Initialize the return value. RopResult result = RopResult.InvalidParameter; importMessageHandleIndex = -1; if ((importFlag & ImportFlag.InvalidParameter) == ImportFlag.InvalidParameter && requirementContainer.ContainsKey(3509001) && requirementContainer[3509001]) { result = RopResult.InvalidParameter; ModelHelper.CaptureRequirement( 3509001, @"[In Appendix A: Product Behavior] If unknown flags are set, implementation does fail the operation. <40> Section 3.2.5.9.4.2: Exchange 2010, Exchange 2013 and Exchange 2016 fail the ROP [RopSynchronizationImportMessageChange] if unknown bit flags are set."); return result; } else if ((importFlag & ImportFlag.InvalidParameter) == ImportFlag.InvalidParameter && requirementContainer.ContainsKey(350900201) && requirementContainer[350900201]) { result = RopResult.Success; ModelHelper.CaptureRequirement( 350900201, @"[In Appendix A: Product Behavior] If unknown flags are set, implementation does not fail the operation. <41> Section 3.2.5.9.4.2: Exchange 2007 do not fail the ROP [RopSynchronizationImportMessageChange] if unknown bit flags are set."); } // Get ConnectionData value. ConnectionData changeConnection = connections[serverId]; AbstractUploadInfo uploadInfo = new AbstractUploadInfo(); // Identify whether the current Upload information is existent or not. bool isCurrentUploadinfoExist = false; // Record current Upload information. int currentUploadIndex = 0; foreach (AbstractUploadInfo tempUploadInfo in changeConnection.UploadContextContainer) { if (tempUploadInfo.UploadHandleIndex == uploadContextHandleIndex) { // Set the value to the current upload context variable when the current upload context is existent. isCurrentUploadinfoExist = true; uploadInfo = tempUploadInfo; currentUploadIndex = changeConnection.UploadContextContainer.IndexOf(tempUploadInfo); } } if (isCurrentUploadinfoExist) { // Create a new Message AbstractMessage currentMessage = new AbstractMessage(); // Identify whether the current message is existent or not. bool isMessageExist = false; // Record the current Message. int currentMessageIndex = 0; foreach (AbstractMessage tempMessage in changeConnection.MessageContainer) { if (tempMessage.MessageIdIndex == messageIdindex) { // Set the value to the variable when the message is existent. isMessageExist = true; currentMessage = tempMessage; currentMessageIndex = changeConnection.MessageContainer.IndexOf(tempMessage); } } if (isMessageExist) { // Set new change number currentMessage.ChangeNumberIndex = ModelHelper.GetChangeNumberIndex(); ModelHelper.CaptureRequirement(1898, "[In Identifying Objects and Maintaining Change Numbers]A new change number is assigned to a messaging object each time it is modified."); // Update the MessageContainer changeConnection.MessageContainer = changeConnection.MessageContainer.Update(currentMessageIndex, currentMessage); } else { // Set the new message handle currentMessage.MessageHandleIndex = AdapterHelper.GetHandleIndex(); // Set property value of abstract message object currentMessage.FolderHandleIndex = uploadInfo.RelatedObjectHandleIndex; currentMessage.FolderIdIndex = uploadInfo.RelatedObjectIdIndex; currentMessage.MessageProperties = new Sequence<string>(); currentMessage.IsRead = true; if ((importFlag & ImportFlag.Normal) == ImportFlag.Normal) { currentMessage.IsFAImessage = false; } if ((importFlag & ImportFlag.Associated) == ImportFlag.Associated) { currentMessage.IsFAImessage = true; // When the Associated is set and the message being imported is an FAI message this requirement is captured. ModelHelper.CaptureRequirement( 813, @"[In RopSynchronizationImportMessageChange ROP Request Buffer] [ImportFlag,when the name is Associated, the value is 0x10] If this flag is set, the message being imported is an FAI message."); } else { currentMessage.IsFAImessage = false; // When the Associated is not set and the message being imported is a normal message this requirement is captured. ModelHelper.CaptureRequirement( 814, @"[In RopSynchronizationImportMessageChange ROP Request Buffer] [ImportFlag,when the name is Associated, the value is 0x10] If this flag is not set, the message being imported is a normal message."); } // Out the new message handle importMessageHandleIndex = currentMessage.MessageHandleIndex; // Because this is out messageHandle so the OutputServerObject is a Message object. ModelHelper.CaptureRequirement(805, "[In RopSynchronizationImportMessageChange ROP Response Buffer]OutputServerObject: The value of this field MUST be the Message object into which the client will upload the rest of the message changes."); currentMessage.ChangeNumberIndex = ModelHelper.GetChangeNumberIndex(); ModelHelper.CaptureRequirement(1897, "[In Identifying Objects and Maintaining Change Numbers]When a new object is created, it is assigned a change number."); // Add new Message to MessageContainer changeConnection.MessageContainer = changeConnection.MessageContainer.Add(currentMessage); // Record the related FastTransferOperation for Upload Information. uploadInfo.RelatedFastTransferOperation = EnumFastTransferOperation.SynchronizationImportMessageChange; // Update the UploadContextContainer. changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Update(currentUploadIndex, uploadInfo); connections[serverId] = changeConnection; // Record RopSynchronizationImportMessageChange operation. priorOperation = PriorOperation.RopSynchronizationImportMessageChange; result = RopResult.Success; ModelHelper.CaptureRequirement( 2449, @"[In Uploading Changes Using ICS] Value is Success indicates No error occurred, or a conflict has been resolved."); // Because if the result is success means the messages or changes are imported. ModelHelper.CaptureRequirement( 782, @"[In RopSynchronizationImportMessageChange ROP] The RopSynchronizationImportMessageChange ROP ([MS-OXCROPS] section 2.2.13.2) is used to import new messages or changes to existing messages into the server replica."); } } return result; }
public static RopResult SynchronizationImportHierarchyChange(int serverId, int uploadContextHandleIndex, int parentFolderHandleIndex, Set<string> properties, int localFolderIdIndex, out int folderIdIndex) { // The contractions conditions. Condition.IsTrue(connections.Count > 0); Condition.IsTrue(connections.Keys.Contains(serverId)); Condition.IsTrue(connections[serverId].UploadContextContainer.Count > 0); // Initialize the return value. RopResult result = RopResult.InvalidParameter; folderIdIndex = -1; if (parentFolderHandleIndex == -1) { result = RopResult.NoParentFolder; ModelHelper.CaptureRequirement( 2450, @"[In Uploading Changes Using ICS] Value is NoParentFolder indicates An attempt is being made to upload a hierarchy change for a folder whose parent folder does not yet exist."); } else { // Get ConnectionData value. ConnectionData changeConnection = connections[serverId]; // Record current Upload Information. AbstractUploadInfo currentUploadInfo = new AbstractUploadInfo(); // Identify current Upload handle. bool isCurrentUploadHandleExist = false; foreach (AbstractUploadInfo tempUploadInfo in changeConnection.UploadContextContainer) { if (tempUploadInfo.UploadHandleIndex == uploadContextHandleIndex) { // Set the value to the variable when the current upload context is existent. isCurrentUploadHandleExist = true; currentUploadInfo = tempUploadInfo; } } if (isCurrentUploadHandleExist) { // Initialize the variable AbstractFolder parentfolder = new AbstractFolder(); bool isParentFolderExist = false; int parentfolderIndex = 0; AbstractFolder currentFolder = new AbstractFolder(); bool isFolderExist = false; int currentFolderIndex = 0; // Research the local folder Id. foreach (AbstractFolder tempFolder in changeConnection.FolderContainer) { if (tempFolder.FolderIdIndex == localFolderIdIndex) { // Set the value to the current Folder variable when the current folder is existent. isFolderExist = true; currentFolder = tempFolder; currentFolderIndex = changeConnection.FolderContainer.IndexOf(tempFolder); } if (tempFolder.FolderIdIndex == currentUploadInfo.RelatedObjectIdIndex) { // Set the value to the parent folder variable when the current parent folder is existent. isParentFolderExist = true; parentfolder = tempFolder; parentfolderIndex = changeConnection.FolderContainer.IndexOf(tempFolder); } } if (isFolderExist & isParentFolderExist) { foreach (string tempProperty in properties) { if (!currentFolder.FolderProperties.Contains(tempProperty)) { // Add Property for folder currentFolder.FolderProperties = currentFolder.FolderProperties.Add(tempProperty); } } // Get the new change Number currentFolder.ChangeNumberIndex = ModelHelper.GetChangeNumberIndex(); // Update the folder Container changeConnection.FolderContainer = changeConnection.FolderContainer.Update(currentFolderIndex, currentFolder); } else { // Create a new folder AbstractFolder newFolder = new AbstractFolder { FolderIdIndex = AdapterHelper.GetObjectIdIndex() }; // Set new folder Id folderIdIndex = newFolder.FolderIdIndex; // Set value for new folder newFolder.FolderProperties = properties; newFolder.ParentFolderHandleIndex = parentfolder.FolderHandleIndex; newFolder.ParentFolderIdIndex = parentfolder.FolderIdIndex; newFolder.SubFolderIds = new Set<int>(); newFolder.MessageIds = new Set<int>(); // Add the new folder to parent folder parentfolder.SubFolderIds = parentfolder.SubFolderIds.Add(newFolder.FolderIdIndex); newFolder.FolderPermission = PermissionLevels.FolderOwner; newFolder.ChangeNumberIndex = ModelHelper.GetChangeNumberIndex(); ModelHelper.CaptureRequirement(1897, "[In Identifying Objects and Maintaining Change Numbers]When a new object is created, it is assigned a change number."); // Update FolderContainer information changeConnection.FolderContainer = changeConnection.FolderContainer.Add(newFolder); changeConnection.FolderContainer = changeConnection.FolderContainer.Update(parentfolderIndex, parentfolder); } // Return Success connections[serverId] = changeConnection; // Record RopSynchronizationImportHierarchyChange operation. priorUploadOperation = PriorOperation.RopSynchronizationImportHierarchyChange; result = RopResult.Success; ModelHelper.CaptureRequirement( 2449, @"[In Uploading Changes Using ICS] Value is Success indicates No error occurred, or a conflict has been resolved."); // Because if the result is success means the folders or changes are imported. ModelHelper.CaptureRequirement( 816, @"[In RopSynchronizationImportHierarchyChange ROP] The RopSynchronizationImportHierarchyChange ROP ([MS-OXCROPS] section 2.2.13.4) is used to import new folders, or changes to existing folders, into the server replica."); } } return result; }
public static RopResult SynchronizationImportDeletes(int serverId, int uploadContextHandleIndex, Sequence<int> objIdIndexes, byte importDeleteFlag) { // The contractions conditions. Condition.IsTrue(connections.Count > 0); Condition.IsTrue(connections.Keys.Contains(serverId)); Condition.IsTrue(connections[serverId].FolderContainer.Count > 0); if (requirementContainer.ContainsKey(90205002) && requirementContainer[90205002]) { Condition.IsTrue(((ImportDeleteFlags)importDeleteFlag & ImportDeleteFlags.delete) == ImportDeleteFlags.delete); } // Initialize return value. RopResult result = RopResult.InvalidParameter; // When the ImportDeleteFlags flag is set HardDelete by Exchange 2007 then server return 0x80070057. if (importDeleteFlag == (byte)ImportDeleteFlags.HardDelete) { if (requirementContainer.ContainsKey(2593) && requirementContainer[2593]) { result = RopResult.NotSupported; ModelHelper.CaptureRequirement(2593, "[In Appendix A: Product Behavior] <16> Section 2.2.3.2.4.5.1: The HardDelete flag is not supported by Exchange 2003 or Exchange 2007."); return result; } } // When the ImportDeleteFlags flag is an invalid value (0x10) then server returns 0x80070057. if (importDeleteFlag == 0x10) { if (requirementContainer.ContainsKey(2254001) && requirementContainer[2254001]) { result = RopResult.NotSupported; } else { result = RopResult.InvalidParameter; } return result; } // Get ConnectionData value. ConnectionData changeConnection = connections[serverId]; // Create uploadInfo variable. AbstractUploadInfo uploadInfo = new AbstractUploadInfo(); // Identify whether the Current Upload information is existent or not. bool isCurrentUploadinfoExist = false; // Record the current uploadInfo index. int currentUploadIndex = 0; foreach (AbstractUploadInfo tempUploadInfo in changeConnection.UploadContextContainer) { if (tempUploadInfo.UploadHandleIndex == uploadContextHandleIndex) { // Set the value to the variable when the current upload context is existent. isCurrentUploadinfoExist = true; uploadInfo = tempUploadInfo; currentUploadIndex = changeConnection.UploadContextContainer.IndexOf(tempUploadInfo); } } if (isCurrentUploadinfoExist) { // Set the upload information. uploadInfo.ImportDeleteflags = importDeleteFlag; AbstractFolder currentFolder = new AbstractFolder(); // Record the current Folder Index int currentFolderIndex = 0; foreach (AbstractFolder tempFolder in changeConnection.FolderContainer) { if (tempFolder.FolderHandleIndex == uploadInfo.RelatedObjectHandleIndex) { // Set the value to the variable when the current Folder is existent. currentFolder = tempFolder; currentFolderIndex = changeConnection.FolderContainer.IndexOf(tempFolder); } } foreach (AbstractFolder tempFolder in changeConnection.FolderContainer) { if ((tempFolder.ParentFolderIdIndex == currentFolder.FolderIdIndex) && objIdIndexes.Contains(tempFolder.FolderIdIndex)) { // Remove current folder from FolderContainer and parent folder when the parent Folder is existent. changeConnection.FolderContainer = changeConnection.FolderContainer.Remove(tempFolder); currentFolder.SubFolderIds = currentFolder.SubFolderIds.Remove(tempFolder.FolderIdIndex); } if (importDeleteFlag == (byte)ImportDeleteFlags.Hierarchy) { softDeleteFolderCount += 1; } } foreach (AbstractMessage tempMessage in changeConnection.MessageContainer) { if ((tempMessage.FolderIdIndex == currentFolder.FolderIdIndex) && objIdIndexes.Contains(tempMessage.MessageIdIndex)) { // Remove current Message from MessageContainer and current folder when current Message is existent. changeConnection.MessageContainer = changeConnection.MessageContainer.Remove(tempMessage); currentFolder.MessageIds = currentFolder.MessageIds.Remove(tempMessage.MessageIdIndex); if (importDeleteFlag == (byte)ImportDeleteFlags.delete) { softDeleteMessageCount += 1; } } } // Update the FolderContainer. changeConnection.FolderContainer = changeConnection.FolderContainer.Update(currentFolderIndex, currentFolder); // Update the UploadContextContainer. changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Update(currentUploadIndex, uploadInfo); connections[serverId] = changeConnection; result = RopResult.Success; ModelHelper.CaptureRequirement( 2449, @"[In Uploading Changes Using ICS] Value is Success indicates No error occurred, or a conflict has been resolved."); // Because if the result is success means deletions of messages or folders into the server replica imported ModelHelper.CaptureRequirement( 884, @"[In RopSynchronizationImportDeletes ROP] The RopSynchronizationImportDeletes ROP ([MS-OXCROPS] section 2.2.13.5) imports deletions of messages or folders into the server replica."); return result; } return result; }
public static RopResult SynchronizationOpenCollector(int serverId, int folderHandleIndex, SynchronizationTypes synchronizationType, out int uploadContextHandleIndex) { // The contractions conditions. Condition.IsTrue(connections.Count > 0); Condition.IsTrue(connections.Keys.Contains(serverId)); Condition.IsTrue(connections[serverId].FolderContainer.Count > 0); // Initialize return value RopResult result = RopResult.InvalidParameter; uploadContextHandleIndex = -1; // Get ConnectionData value. ConnectionData changeConnection = connections[serverId]; AbstractFolder currentfolder = new AbstractFolder(); // Identify whether the CurrentFolder is existent or not. bool isCurrentFolderExist = false; // Identify whether the Current Folder is existent or not. foreach (AbstractFolder tempfolder in changeConnection.FolderContainer) { if (tempfolder.FolderHandleIndex == folderHandleIndex) { // Set the value to the variable when the current folder is existent. isCurrentFolderExist = true; currentfolder = tempfolder; } } if (isCurrentFolderExist) { // Initialize the upload information. AbstractUploadInfo abstractUploadInfo = new AbstractUploadInfo { UploadHandleIndex = AdapterHelper.GetHandleIndex() }; uploadContextHandleIndex = abstractUploadInfo.UploadHandleIndex; ModelHelper.CaptureRequirement(778, "[In RopSynchronizationOpenCollector ROP Response Buffer]OutputServerObject: The value of this field MUST be the synchronization upload context."); abstractUploadInfo.SynchronizationType = synchronizationType; abstractUploadInfo.RelatedObjectHandleIndex = folderHandleIndex; abstractUploadInfo.RelatedObjectIdIndex = currentfolder.FolderIdIndex; // Initialize the updatedState information. abstractUploadInfo.UpdatedState.IdsetGiven = new Set<int>(); abstractUploadInfo.UpdatedState.CnsetRead = new Set<int>(); abstractUploadInfo.UpdatedState.CnsetSeen = new Set<int>(); abstractUploadInfo.UpdatedState.CnsetSeenFAI = new Set<int>(); // Add the new value to UploadContextContainer. changeConnection.UploadContextContainer = changeConnection.UploadContextContainer.Add(abstractUploadInfo); connections[serverId] = changeConnection; // Record RopSynchronizationImportHierarchyChange operation. priorOperation = PriorOperation.RopSynchronizationOpenCollector; result = RopResult.Success; if (uploadContextHandleIndex != -1) { // Because if uploadContextHandleIndex doesn't equal -1 and the ROP return success, so only if this ROP success and return a valid handler this requirement will be verified. ModelHelper.CaptureRequirement( 769, @"[In RopSynchronizationOpenCollector ROP] The RopSynchronizationOpenCollector ROP ([MS-OXCROPS] section 2.2.13.7) configures the synchronization upload operation and returns a handle to a synchronization upload context."); } } return result; }