Esempio n. 1
0
        public async Task <SyncCommandResult> Sync(string syncKey, string folderId, ExchangeChangeSet changeset)
        {
            if (string.IsNullOrEmpty(syncKey))
            {
                throw new ArgumentNullException(nameof(syncKey));
            }
            if (string.IsNullOrEmpty(folderId))
            {
                throw new ArgumentNullException(nameof(folderId));
            }
            if (changeset == null)
            {
                throw new ArgumentNullException(nameof(changeset));
            }

            LogService.Log("ActiveSyncServer", string.Format("Syncing key: {0} folder id: {1}", syncKey.TakeLast(5), folderId != null ? folderId.TakeLast(5) : "<none>"));

            SyncCommand command = new SyncCommand(new SyncCommandParameter(syncKey, folderId, changeset), this.settings);

            ResponseResult <SyncCommandResult> result = await command.Execute();

            if (ActiveSyncErrorHelper.IsStatusProvisioningError(result.Data?.Status, result?.Error))
            {
                await this.TryDoProvisioning();

                result = await command.Execute();
            }

            if (result.Error != null)
            {
                throw result.Error;
            }

            return(result.Data);
        }
Esempio n. 2
0
        public async Task Task_in_default_exchange_folder_have_no_category_in_exchange()
        {
            // add a single task without any category
            var changeSet = new ExchangeChangeSet();

            changeSet.AddedTasks.Add(new ExchangeTask {
                Subject = "task", Properties = ExchangeTaskProperties.Title
            });
            var result1 = await this.Provider.ExchangeService.ExecuteFirstSyncAsync(this.Runner.GetConnectionInfo(), changeSet);

            Assert.IsTrue(result1.AuthorizationResult.IsOperationSuccess);

            // perform a full sync, that will create the default Exchange folder
            await this.SyncFull();

            AssertEx.ContainsFolders(this.Workbook, this.Manager.ActiveProvider.DefaultFolderName);
            AssertEx.ContainsTasks(this.Workbook, "task");

            // create a new task in the default Exchange folder
            this.CreateTask("task 2", this.Workbook.Folders[0]);

            // send this new task in Exchange
            await this.SyncDelta();

            this.Workbook.RemoveAll();

            // fetch all tasks from Exchange, make sure both have no categories set
            var result2 = await this.Provider.ExchangeService.ExecuteFirstSyncAsync(this.Runner.GetConnectionInfo(), new ExchangeChangeSet());

            Assert.IsTrue(result2.AuthorizationResult.IsOperationSuccess);
            Assert.AreEqual(2, result2.ChangeSet.AddedTasks.Count);
            Assert.IsTrue(string.IsNullOrEmpty(result2.ChangeSet.AddedTasks[0].Category));
            Assert.IsTrue(string.IsNullOrEmpty(result2.ChangeSet.AddedTasks[1].Category));
        }
Esempio n. 3
0
        public async Task Task_renamed_in_exchange()
        {
            // add a single task without any category
            var changeSet = new ExchangeChangeSet();

            changeSet.AddedTasks.Add(new ExchangeTask {
                Subject = "task", Properties = ExchangeTaskProperties.Title
            });
            var result1 = await this.Provider.ExchangeService.ExecuteFirstSyncAsync(this.Runner.GetConnectionInfo(), changeSet);

            Assert.IsTrue(result1.AuthorizationResult.IsOperationSuccess);

            await this.SyncFull();

            AssertEx.ContainsTasks(this.Workbook, "task");
            var task = this.Workbook.Tasks[0];

            Assert.IsNotNull(task.SyncId);

            // rename the task in Exchange
            changeSet = new ExchangeChangeSet();
            changeSet.ModifiedTasks.Add(new ExchangeTask {
                Subject = "new subject", Id = task.SyncId, Properties = ExchangeTaskProperties.Title
            });
            await this.Provider.ExchangeService.ExecuteFirstSyncAsync(this.Runner.GetConnectionInfo(), changeSet);

            await this.SyncFull();

            AssertEx.ContainsTasks(this.Workbook, "new subject");
        }
Esempio n. 4
0
        private async Task <List <EwsItemIdentifier> > ApplyRemoteChanges(ExchangeChangeSet changeSet, EwsSyncServer server, List <ExchangeMapId> mapId, EwsFolderIdentifier folderIdentifier, EwsItemType ewsItemType)
        {
            // enumerate remote content
            var remoteIdentifiers = await server.EnumerateFolderContentAsync(folderIdentifier, ewsItemType);

            var editedItems = new List <EwsItemIdentifier>();
            var newItems    = new List <EwsItemIdentifier>();

            // check for remote identifiers that have a new change key (ie. updated elements in Exchange)
            foreach (var task in this.workbook.Tasks.Where(t => t.SyncId != null))
            {
                // check if we can find this task that exists in the workbook in the remote identifiers
                var remoteId = remoteIdentifiers.FirstOrDefault(i => i.Id == task.SyncId.GetId());

                // we find this task in the remote identifiers, check if the change key has changed since last sync
                if (remoteId != null && remoteId.ChangeKey != task.SyncId.GetEwsItemIdentifier().ChangeKey)
                {
                    // local item found on server with a different ChangeKey because it was updated => update
                    editedItems.Add(new EwsItemIdentifier(remoteId.Id, remoteId.ChangeKey));
                }
            }

            // check for remote identifiers that we don't have in the workbook and that were not added during this sync operation
            foreach (var identifier in remoteIdentifiers.Where(i => mapId.All(id => id.ExchangeId != null && id.ExchangeId.GetId() != i.Id)))
            {
                var task = this.workbook.Tasks.Where(t => t.SyncId != null).FirstOrDefault(t => t.SyncId.GetId() == identifier.Id);
                if (task == null)
                {
                    // item found on server but not locally => new item
                    newItems.Add(identifier);
                }
            }

            var items = new List <EwsItemIdentifier>();

            items.AddRange(editedItems);
            items.AddRange(newItems);

            var ewsTasks = await server.DownloadFolderContentAsync(items, ewsItemType);

            foreach (var ewsTask in ewsTasks)
            {
                if (editedItems.Any(i => i.Id == ewsTask.Id))
                {
                    changeSet.ModifiedTasks.Add(ewsTask.BuildExchangeTask());
                }
                else if (newItems.Any(i => i.Id == ewsTask.Id))
                {
                    changeSet.AddedTasks.Add(ewsTask.BuildExchangeTask());
                }
                else
                {
                    throw new NotSupportedException();
                }
            }

            return(remoteIdentifiers);
        }
Esempio n. 5
0
        private ExchangeChangeSet GetChangeSet(IEnumerable <ExchangeTask> deleted)
        {
            var changeset = new ExchangeChangeSet();

            foreach (var exchangeTask in deleted)
            {
                changeset.DeletedTasks.Add(new ServerDeletedAsset(exchangeTask.Id));
            }
            return(changeset);
        }
Esempio n. 6
0
        private async Task PushLocalChanges(ExchangeChangeSet changeSet, EwsSyncServer server, List <ExchangeMapId> mapId, EwsFolderIdentifier folder)
        {
            // send local add content
            if (changeSet.AddedTasks.Count > 0)
            {
                var ewsTasks         = changeSet.AddedTasks.Select(exchangeTask => exchangeTask.BuildEwsTask()).ToList();
                var createItemResult = await server.CreateItemAsync(ewsTasks, folder);

                if (changeSet.AddedTasks.Count == createItemResult.Identifiers.Count)
                {
                    for (int i = 0; i < createItemResult.Identifiers.Count; i++)
                    {
                        var identifier = createItemResult.Identifiers[i];
                        if (identifier.IsValid)
                        {
                            mapId.Add(new ExchangeMapId {
                                LocalId = changeSet.AddedTasks[i].LocalId, ExchangeId = identifier.GetFullId()
                            });
                        }
                        else
                        {
                            LogService.Log("EwsSyncService", "Error while creating task: " + changeSet.AddedTasks[i].Subject + " error: " + identifier.ErrorMessage);
                        }
                    }
                }
                else
                {
                    LogService.Log("EwsSyncService", string.Format("Request to create {0} items but result only has {1} items", changeSet.AddedTasks.Count, createItemResult.Identifiers.Count));
                }
            }

            // send local modification content
            if (changeSet.ModifiedTasks.Count > 0)
            {
                var ewsTasks         = changeSet.ModifiedTasks.Select(exchangeTask => exchangeTask.BuildEwsTask()).ToList();
                var updateItemResult = await server.UpdateItemsAsync(ewsTasks);

                // todo ews: we don't update change key here... not optimal because then we're going to ask
                // the server to enumerate items, we will find different change keys for update items and so
                // we're going to download them again from the server
            }

            // send local delete content
            if (changeSet.DeletedTasks.Count > 0)
            {
                var ewsIdentifiers = new List <EwsItemIdentifier>();
                foreach (var deletedAsset in changeSet.DeletedTasks)
                {
                    ewsIdentifiers.Add(deletedAsset.Id.GetEwsItemIdentifier());
                }

                await server.DeleteItemsAsync(ewsIdentifiers);
            }
        }
Esempio n. 7
0
        private async Task <ExchangeSyncResult> Sync(ExchangeConnectionInfo connectionInfo, ExchangeChangeSet changeSet = null)
        {
            if (changeSet == null)
            {
                changeSet = new ExchangeChangeSet();
            }

            var data = await this.service.ExecuteFirstSyncAsync(connectionInfo, changeSet);

            string message = string.Format("Operation success: {0} status: {1}", data.AuthorizationResult.IsOperationSuccess, data.AuthorizationResult.AuthorizationStatus);

            Assert.IsTrue(data.AuthorizationResult.IsOperationSuccess, message);
            Assert.AreEqual(ExchangeAuthorizationStatus.OK, data.AuthorizationResult.AuthorizationStatus, message);

            return(data);
        }
Esempio n. 8
0
        private ExchangeChangeSet BuildChangeSetFromMetadata()
        {
            var changeSet = new ExchangeChangeSet();

            foreach (var id in this.Metadata.AddedTasks)
            {
                var task = this.Workbook.Tasks.FirstOrDefault(t => t.Id == id);
                if (task != null)
                {
                    changeSet.AddedTasks.Add(this.CreateExchangeTask(task, TaskProperties.All));
                }
            }

            foreach (var deletedEntry in this.Metadata.DeletedTasks)
            {
                if (!string.IsNullOrEmpty(deletedEntry.SyncId))
                {
                    changeSet.DeletedTasks.Add(new ServerDeletedAsset(deletedEntry.SyncId));
                }
            }

            foreach (var editedEntry in this.Metadata.EditedTasks)
            {
                var task = this.Workbook.Tasks.FirstOrDefault(t => t.Id == editedEntry.Key);
                if (task != null)
                {
                    // the task is marked edited, make sure it has a sync id
                    if (!string.IsNullOrEmpty(task.SyncId))
                    {
                        changeSet.ModifiedTasks.Add(this.CreateExchangeTask(task, editedEntry.Value));
                    }
                    else
                    {
                        // otherwise, process it has an "added" task
                        changeSet.AddedTasks.Add(this.CreateExchangeTask(task, TaskProperties.All));
                    }
                }
            }

            LogService.LogFormat("ExchangeSync", "Performing sync, sending changeset with {0} added tasks {1} deleted tasks and {2} edited tasks",
                                 changeSet.AddedTasks.Count, changeSet.DeletedTasks.Count, changeSet.ModifiedTasks.Count);

            return(changeSet);
        }
Esempio n. 9
0
        private async Task FirstSync(ExchangeInfoBuild exchangeInfo)
        {
            this.OnSynchronizationProgressChanged(StringResources.SyncProgress_SyncInProgress);

            var changeSet = new ExchangeChangeSet();

            // start by sending an empty change set to get all existing task on the service
            LogService.LogFormat("ExchangeSync", "Performing first sync, step 1, sending empty changeset");
            var result = await this.SyncService.ExecuteFirstSyncAsync(exchangeInfo.ConnectionInfo, changeSet);

            var completedTasks = result.ChangeSet.AddedTasks.Where(t => t.Completed.HasValue).ToList();

            if (completedTasks.Count > 100)
            {
                // takes only 100 completed tasks, prevent bringing more in 2Day to prevent weird issue like having 3k tasks in the app
                var tasks = new List <ExchangeTask>();
                tasks.AddRange(result.ChangeSet.AddedTasks.Where(t => !t.Completed.HasValue));          // add all non completed tasks
                tasks.AddRange(result.ChangeSet.AddedTasks.Where(t => t.Completed.HasValue).Take(100)); // add first 100 completed tasks

                result.ChangeSet.AddedTasks.Clear();
                result.ChangeSet.AddedTasks.AddRange(tasks);
            }

            this.ProcessSyncResult(changeSet, result, sendCompletedNotification: false);
            this.OnSynchronizationProgressChanged(StringResources.SyncProgress_UpdatingTasks);

            // send a changeset for all tasks that does not have a sync id
            changeSet.AddedTasks.AddRange(this.Workbook.Tasks.Where(t => !t.IsCompleted && string.IsNullOrEmpty(t.SyncId)).Select(t => t.ToExchangeTask(setCategory: true, properties: TaskProperties.All)));
            LogService.LogFormat("ExchangeSync", "Performing first sync, step 2, sending changeset with {0} added tasks", changeSet.AddedTasks.Count);

            if (changeSet.AddedTasks.Count > 0)
            {
                result = await this.SyncService.ExecuteFirstSyncAsync(exchangeInfo.ConnectionInfo, changeSet);

                this.ProcessSyncResult(changeSet, result);
            }
            else
            {
                this.OnSynchronizationCompleted("Exchange");
            }

            this.FolderId = this.SyncService.TaskFolderId;
        }
Esempio n. 10
0
        private static void EncodingTest(string input, string output = null)
        {
            // setup
            var changeset = new ExchangeChangeSet();

            changeset.AddedTasks.Add(new ExchangeTask {
                Subject = input
            });

            // act
            var    parameter = new SyncCommandParameter("syncKey", "folderId", changeset);
            string xml       = parameter.BuildXml("command");

            // check
            const string subjectFormat = "<tasks:Subject>{0}</tasks:Subject>";
            string       subject       = string.Format(subjectFormat, output ?? input);

            Assert.IsTrue(xml.Contains(subject));
        }
Esempio n. 11
0
        private ExchangeChangeSet GetChangeSet(ExchangeTask added = null, ExchangeTask modified = null, IEnumerable <string> deleted = null)
        {
            var changeset = new ExchangeChangeSet();

            if (added != null)
            {
                changeset.AddedTasks.Add(added);
            }

            if (modified != null)
            {
                changeset.ModifiedTasks.Add(modified);
            }

            if (deleted != null)
            {
                deleted.ForEach(d => changeset.DeletedTasks.Add(new ServerDeletedAsset(d)));
            }

            return(changeset);
        }
Esempio n. 12
0
        public void Handle_special_character()
        {
            // setup
            var changeset = new ExchangeChangeSet();

            changeset.AddedTasks.Add(new ExchangeTask {
                Subject = "title /{ test"
            });
            changeset.AddedTasks.Add(new ExchangeTask {
                Subject = "title {} test"
            });
            changeset.AddedTasks.Add(new ExchangeTask {
                Subject = "title #d.3 test"
            });

            // act
            var    parameter = new SyncCommandParameter("syncKey", "folderId", changeset);
            string xml       = parameter.BuildXml("command");

            // check
            Assert.IsFalse(string.IsNullOrWhiteSpace(xml));
        }
Esempio n. 13
0
        public SyncCommandParameter(string syncKey, string folderId, ExchangeChangeSet changeset)
        {
            if (string.IsNullOrEmpty(syncKey))
            {
                throw new ArgumentNullException("syncKey");
            }
            if (string.IsNullOrEmpty(folderId))
            {
                throw new ArgumentNullException("folderId");
            }
            if (changeset == null)
            {
                throw new ArgumentNullException("changeset");
            }

            this.SyncKey  = syncKey;
            this.FolderId = folderId;

            this.AddedTasks    = changeset.AddedTasks;
            this.ModifiedTasks = changeset.ModifiedTasks;
            this.DeletedTasks  = changeset.DeletedTasks;
        }
Esempio n. 14
0
        public void Escape_invalid_xml_character()
        {
            // non-reg test for the following exception (Windows 8 only apparently)
            // ActiveSync: System.ArgumentException: ' ', hexadecimal value 0x0B, is an invalid character.
            // at System.Xml.XmlEncodedRawTextWriter.InvalidXmlChar(Int32 ch, Char* pDst, Boolean entitize)
            // ...
            // at Chartreuse.Today.Exchange.ActiveSync.Commands.SyncCommandParameter.CreateTaskXml(ExchangeTask task, StringBuilder builder, Boolean isAdd)
            // at Chartreuse.Today.Exchange.ActiveSync.Commands.SyncCommandParameter.AppendAddedTasks(StringBuilder xmlBuilder) at

            // setup
            var changeset = new ExchangeChangeSet();

            changeset.AddedTasks.Add(new ExchangeTask {
                Subject = "hello " + (char)0x0B + "world !"
            });

            // act
            var    parameter = new SyncCommandParameter("syncKey", "folderId", changeset);
            string xml       = parameter.BuildXml("command");

            // check
            Assert.IsFalse(string.IsNullOrWhiteSpace(xml));
            Assert.IsTrue(xml.Contains("hello world !"));
        }
Esempio n. 15
0
 public async Task <ExchangeSyncResult> ExecuteSyncAsync(ExchangeConnectionInfo connectionInfo, ExchangeChangeSet changeSet, string syncState, string folderId)
 {
     return(await this.ExecuteSyncAsync(connectionInfo, changeSet, syncState, folderId, false));
 }
Esempio n. 16
0
        public async Task <ExchangeSyncResult> ExecuteFirstSyncAsync(ExchangeConnectionInfo connectionInfo, ExchangeChangeSet changeSet)
        {
            ExchangeSyncResult loginResult = await this.EnsureLoginAsync(this.taskFolderId, connectionInfo);

            if (loginResult != null)
            {
                return(loginResult);
            }

            ActiveSyncServer server = CreateExchangeServer(connectionInfo);

            // Start sync with sync state = 0
            // In this case we only obtain a non ero syncKey to use with future queries
            SyncCommandResult syncCommandResult = await server.Sync(InitialSyncKey, this.taskFolderId, new ExchangeChangeSet());

            connectionInfo.PolicyKey = server.PolicyKey;

            if (syncCommandResult.Status != StatusOk)
            {
                var result = new ExchangeSyncResult
                {
                    AuthorizationResult = this.GetFailedAuthResult("ExecuteFirstSync", syncCommandResult)
                };

                return(result);
            }

            // As it is first sync, we have just picked a new SyncId
            // We have to re-sync with this new SyncId
            return(await this.ExecuteSyncAsync(connectionInfo, changeSet, syncCommandResult.SyncKey, this.taskFolderId, true));
        }
Esempio n. 17
0
 public async Task <ExchangeSyncResult> ExecuteFirstSyncAsync(ExchangeConnectionInfo connectionInfo, ExchangeChangeSet changeSet)
 {
     return(await this.ExecuteSyncAsync(connectionInfo, changeSet, null, null));
 }
Esempio n. 18
0
        public async Task <ExchangeSyncResult> ExecuteSyncAsync(ExchangeConnectionInfo connectionInfo, ExchangeChangeSet changeSet, string syncState, string folderId)
        {
            var syncRequest = new ExchangeSyncRequest
            {
                ConnectionInfo = connectionInfo,
                ChangeSet      = changeSet,
                SyncState      = syncState
            };
            var content = await this.requestBuilder.PostJsonAsync <ExchangeSyncRequest, ExchangeSyncResult>(this.serverUri + "/Api/Sync/Sync", syncRequest);

            this.taskFolderName = content.FolderName;

            return(content);
        }
Esempio n. 19
0
        private void ProcessSyncResult(ExchangeChangeSet sourceChangeSet, ExchangeSyncResult result, bool sendCompletedNotification = true)
        {
            if (this.isCanceled)
            {
                throw new OperationCanceledException();
            }

            if (result.AuthorizationResult.IsOperationSuccess)
            {
                this.Metadata.Reset();

                var changeSet = result.ChangeSet;

                this.Changes.WebAdd    = result.TaskAddedCount;
                this.Changes.WebEdit   = result.TaskEditedCount;
                this.Changes.WebDelete = result.TaskDeletedCount;

                // update task sent in the sourceChangeSet
                foreach (var exchangeTask in sourceChangeSet.AddedTasks)
                {
                    // find the task in the workbook
                    var task = this.Workbook.Tasks.FirstOrDefault(t => t.Id == exchangeTask.LocalId);
                    if (task != null)
                    {
                        var map = result.MapId.FirstOrDefault(m => m.LocalId == task.Id);
                        if (map != null)
                        {
                            this.PrepareTaskUpdate(task);

                            task.SyncId = map.ExchangeId;
                        }
                    }
                }

                LogService.LogFormat(
                    "ExchangeSync", "Processing result sent by server changeset with {0} added tasks {1} deleted tasks and {2} edited tasks",
                    changeSet.AddedTasks.Count, changeSet.DeletedTasks.Count, changeSet.ModifiedTasks.Count);

                foreach (var exchangeTask in changeSet.AddedTasks.Where(t => !string.IsNullOrEmpty(t.Subject)))
                {
                    // find the target folder by looking using its name
                    var folder = this.GetFolderForExchangeTask(exchangeTask);

                    var candidate = folder.Tasks.FirstOrDefault(t => t.SyncId == exchangeTask.Id);
                    if (candidate == null)
                    {
                        // check that we don't have already the "same" task
                        candidate = this.FindTask(folder.Tasks, exchangeTask.Subject, exchangeTask.Due);
                        if (candidate == null)
                        {
                            // create the task and add it to its folder
                            var task = exchangeTask.ToTask(this.Workbook);
                            this.AttachTaskToFolder(task, folder);

                            this.Changes.LocalAdd++;
                        }
                        else if (string.IsNullOrEmpty(candidate.SyncId))
                        {
                            candidate.SyncId = exchangeTask.Id;
                        }
                    }
                }

                foreach (var deletedAsset in changeSet.DeletedTasks)
                {
                    var task = this.Workbook.Tasks.FirstOrDefault(t => t.SyncId == deletedAsset.Id);
                    if (task != null)
                    {
                        this.DeleteTask(task);
                        this.Changes.LocalDelete++;
                    }
                }

                foreach (var exchangeTask in changeSet.ModifiedTasks)
                {
                    var task = this.Workbook.Tasks.FirstOrDefault(t => this.HaveSameId(t, exchangeTask));
                    if (task != null)
                    {
                        this.PrepareTaskUpdate(task);
                        task.UpdateFromExchange(exchangeTask);

                        var requiredFolder = this.GetFolderForExchangeTask(exchangeTask);
                        if (task.Folder != requiredFolder)
                        {
                            task.Folder = requiredFolder;
                        }

                        this.Changes.LocalEdit++;
                    }
                    else
                    {
                        LogService.LogFormat("ExchangeSync", "Task {0} has been modified on the server but cannot be found in the workbook", exchangeTask.Subject);
                    }
                }

                if (result.OperationResult.IsOperationSuccess)
                {
                    this.SyncState = result.SyncState;

                    if (sendCompletedNotification)
                    {
                        this.OnSynchronizationCompleted("Exchange");
                    }
                }
                else
                {
                    this.OnSynchronizationFailed(string.Format(ExchangeResources.Exchange_SyncErrorFormat, result.OperationResult.ErrorMessage));
                }
            }
            else
            {
                if (result.AuthorizationResult.Status != null && result.AuthorizationResult.Status.Equals("3", StringComparison.OrdinalIgnoreCase))
                {
                    this.OnSynchronizationFailed(StringResources.Exchange_InvalidSyncKeyWorkaround);
                }
                else
                {
                    this.OnSynchronizationFailed(string.Format(ExchangeResources.Exchange_AuthProblemFormat, result.AuthorizationResult.AuthorizationStatus, result.AuthorizationResult.ErrorMessage));
                }
            }
        }
Esempio n. 20
0
        private async Task <ExchangeSyncResult> ExecuteSyncAsync(ExchangeConnectionInfo connectionInfo, ExchangeChangeSet changeSet, string syncState, string folderId, bool isFirstSync)
        {
            if (connectionInfo == null)
            {
                throw new ArgumentNullException("connectionInfo");
            }
            if (changeSet == null)
            {
                throw new ArgumentNullException("changeSet");
            }
            if (string.IsNullOrEmpty(syncState))
            {
                throw new ArgumentNullException("syncState");
            }

            if (string.IsNullOrEmpty(folderId) || connectionInfo.ServerUri == null || string.IsNullOrWhiteSpace(connectionInfo.ServerUri.ToString()))
            {
                ExchangeSyncResult loginResult = await this.EnsureLoginAsync(folderId, connectionInfo);

                if (loginResult != null)
                {
                    return(loginResult);
                }
            }
            else
            {
                this.taskFolderId = folderId;
            }

            ActiveSyncServer server = CreateExchangeServer(connectionInfo);

            ExchangeSyncResult returnValue = new ExchangeSyncResult
            {
                SyncState = syncState,
                ChangeSet = new ExchangeChangeSet()
            };

            bool mustSync = true;

            while (mustSync)
            {
                SyncCommandResult result = await server.Sync(returnValue.SyncState, this.taskFolderId, changeSet);

                if (result.Status != StatusOk)
                {
                    returnValue.AuthorizationResult = this.GetFailedAuthResult("Sync", result);
                    mustSync = false;
                }
                else
                {
                    returnValue.AuthorizationResult = new ExchangeAuthorizationResult
                    {
                        AuthorizationStatus = ExchangeAuthorizationStatus.OK,
                        IsOperationSuccess  = true,
                        ServerUri           = connectionInfo.ServerUri
                    };

                    if (result.SyncKey != null)
                    {
                        returnValue.SyncState = result.SyncKey;
                    }

                    connectionInfo.PolicyKey = server.PolicyKey;

                    // If we don't have any syncstate (nothing has changed) we return the old one
                    returnValue.OperationResult.IsOperationSuccess = true;

                    returnValue.ChangeSet.AddedTasks.AddRange(result.AddedTasks);
                    returnValue.ChangeSet.ModifiedTasks.AddRange(result.ModifiedTasks);
                    returnValue.ChangeSet.DeletedTasks.AddRange(result.DeletedTasks);
                    returnValue.TaskAddedCount  += result.ServerAddedTasks;
                    returnValue.TaskEditedCount += result.ServerModifiedTasks;

                    foreach (var map in result.ClientServerMapIds)
                    {
                        returnValue.AddMap(map.Key, map.Value);
                    }

                    returnValue.TaskDeletedCount += changeSet.DeletedTasks.Count;
                    mustSync = result.MoreAvailable;

                    changeSet = new ExchangeChangeSet(); // changeSet has been pushed to server, reset it !
                }
            }
            return(returnValue);
        }
Esempio n. 21
0
        public async Task <ExchangeSyncResult> ExecuteSyncAsync(ExchangeConnectionInfo connectionInfo, ExchangeChangeSet changeSet, string syncState, string folderId)
        {
            if (connectionInfo == null)
            {
                throw new ArgumentNullException(nameof(connectionInfo));
            }
            if (changeSet == null)
            {
                throw new ArgumentNullException(nameof(changeSet));
            }

            var outChangeSet = new ExchangeChangeSet();

            var autoDiscoverResult = await this.EnsureAutoDiscover(connectionInfo);

            if (!IsExchangeSyncResultValid(autoDiscoverResult))
            {
                return(autoDiscoverResult);
            }

            var server = new EwsSyncServer(connectionInfo.CreateEwsSettings());

            var identifiers = await server.GetRootFolderIdentifiersAsync();

            //var subFolders = await server.GetSubFoldersAsync(identifiers.TaskFolderIdentifier);

            //var flaggedItemFolders = await this.EnsureSearchFolder(server);

            /*
             * var a = await server.EnumerateFolderContentAsync(flaggedItemFolders);
             * var d = await server.DownloadFolderContentAsync(a);
             */

            var mapId = new List <ExchangeMapId>();

            await this.PushLocalChanges(changeSet, server, mapId, identifiers.TaskFolderIdentifier);

            var remoteIdentifiers = await this.ApplyRemoteChanges(outChangeSet, server, mapId, identifiers.TaskFolderIdentifier, EwsItemType.Task);

            /*foreach (var subFolder in subFolders.Folders)
             * {
             *  await this.ApplyRemoteChanges(outChangeSet, server, mapId, subFolder);
             * }*/

            if (connectionInfo.SyncFlaggedItems)
            {
                try
                {
                    var identifier = await this.EnsureSearchFolderAsync(server);

                    var otherRemoteIdentifiers = await this.ApplyRemoteChanges(outChangeSet, server, mapId, identifier, EwsItemType.Item);

                    remoteIdentifiers.AddRange(otherRemoteIdentifiers);
                }
                catch (Exception ex)
                {
                    LogService.Log("EwsSyncService", $"Exception while syncing flagged items: {ex}");
                    TrackingManagerHelper.Exception(ex, "Exception while syncing flagged items");
                }
            }

            // check for deleted items
            foreach (var task in this.workbook.Tasks.Where(t => t.SyncId != null))
            {
                var remoteId = remoteIdentifiers.FirstOrDefault(i => i.Id == task.SyncId.GetId());
                if (remoteId == null)
                {
                    // local item not found on server because it was deleted => delete
                    outChangeSet.DeletedTasks.Add(new ServerDeletedAsset(task.SyncId));
                }
            }

            var result = new ExchangeSyncResult
            {
                AuthorizationResult = new ExchangeAuthorizationResult
                {
                    Status = "OK",
                    AuthorizationStatus = ExchangeAuthorizationStatus.OK,
                    IsOperationSuccess  = true,
                    ServerUri           = connectionInfo.ServerUri
                },
                ChangeSet       = outChangeSet,
                MapId           = mapId,
                SyncState       = identifiers.TaskFolderIdentifier.ChangeKey,
                OperationResult = new ServiceOperationResult
                {
                    IsOperationSuccess = true
                }
            };

            return(result);
        }