public void DeleteLinksFromAssociation(FolderAssociation association)
 {
     using (var query = Connection.Prepare($"delete from LinkStatus where AssociationId='{association.Id}'"))
     {
         query.Step();
     }
 }
Exemple #2
0
        private async Task CreateFolder(FolderAssociation association, BaseItem localItem, string name)
        {
            //adds the folder and if necessesary the parent folder
            var uri = new Uri(Configuration.ServerUrl);
            var remoteBaseFolder = uri.LocalPath;
            var path             = _BuildRemoteFolderPath(association, localItem.EntityId);

            path = WebUtility.UrlDecode(path.Replace(remoteBaseFolder, "").TrimEnd('/'));
            var folders = path.Split('/');

            if (localItem.IsCollection)
            {
                folders = (path + "/" + name).Split('/');
            }
            var currentFolder = remoteBaseFolder.TrimEnd('/');

            foreach (string f in folders)
            {
                string folderName = Uri.EscapeDataString(f);
                if (_existingFolders.Contains(currentFolder + '/' + folderName))//this should speed up the inital sync
                {
                    currentFolder += '/' + folderName;
                    continue;
                }
                //var folderContent = await _davClient.ListFolder(new Uri(currentFolder, UriKind.RelativeOrAbsolute));
                if (!await _davClient.Exists(new Uri(currentFolder + '/' + folderName, UriKind.RelativeOrAbsolute)))
                {
                    await _davClient.CreateFolder(new Uri(currentFolder + '/' + folderName, UriKind.RelativeOrAbsolute));
                }
                _existingFolders.Add(currentFolder + '/' + folderName);
                currentFolder += '/' + folderName;
            }
        }
        protected async Task _UpdateFileIndexes(FolderAssociation association, List <BaseItem> items)
        {
            await SetExecutionStatus(ExecutionStatus.UpdatingIndex);

            var itemTableModel = ItemTableModel.GetDefault();

            foreach (BaseItem t in items)
            {
                t.Association = association;
                var foundItem = itemTableModel.GetItem(t);
                if (foundItem == null)
                {
                    itemTableModel.InsertItem(t);
                    t.Id = itemTableModel.GetLastInsertItem().Id;
                }
                else
                {
                    if (foundItem.ChangeKey != t.ChangeKey)
                    {
                        t.ChangeNumber = foundItem.ChangeNumber + 1;
                        itemTableModel.UpdateItem(t, foundItem.Id);
                    }
                    t.Id = foundItem.Id;
                }
            }
            association.LastSync = DateTime.Now;
            FolderAssociationTableModel.GetDefault().UpdateItem(association, association.Id);
        }
        public override async Task <List <BaseItem> > GetDeletedItemsAsync(FolderAssociation association)
        {
            List <BaseItem> result = new List <BaseItem>();
            //get the storagefolder
            var           localFolderItem = GetAssociatedItem(association.LocalFolderId);
            StorageFolder sFolder         = await StorageFolder.GetFolderFromPathAsync(localFolderItem.EntityId);

            var sItems  = new List <IStorageItem>();
            var options = new QueryOptions();

            options.FolderDepth   = FolderDepth.Deep;
            options.IndexerOption = IndexerOption.UseIndexerWhenAvailable;
            var itemQuery = sFolder.CreateItemQueryWithOptions(options);
            var queryTask = itemQuery.GetItemsAsync();

            //get all the files and folders from the db that were inside the folder at the last time
            var existingItems = ItemTableModel.GetDefault().GetFilesForFolder(association, this.GetType());

            sItems.AddRange(await queryTask);

            var storageItems = new List <BaseItem>();

            foreach (var storageItem in sItems)
            {
                storageItems.Add(new BaseItem {
                    EntityId = storageItem.Path
                });
            }
            var missingItems = existingItems.Except(storageItems, new EnityIdComparer()).ToList();

            //var fixedPath = sFolder.Path.Replace("USERS", "Users");
            foreach (var missingItem in missingItems)
            {
                if (missingItem.EntityId == sFolder.Path)
                {
                    continue;
                }
                //additional check if the file really does not exist
                //for some reason the query seems to return wrong results sometimes
                if (!missingItem.IsCollection)
                {
                    FileInfo fInfo = new FileInfo(missingItem.EntityId);
                    if (!fInfo.Exists)
                    {
                        result.Add(missingItem);
                    }
                }
                else
                {
                    DirectoryInfo dInfo = new DirectoryInfo(missingItem.EntityId);
                    if (!dInfo.Exists)
                    {
                        result.Add(missingItem);
                    }
                }
            }
            return(result);
        }
Exemple #5
0
        public override async Task <List <BaseItem> > GetUpdatedItems(FolderAssociation association)
        {
            List <BaseItem> items  = new List <BaseItem>();
            var             folder = ItemTableModel.GetDefault().GetItem(association.RemoteFolderId);

            await _CheckRemoteFolderRecursive(folder, items);

            return(items);
        }
Exemple #6
0
        public override async Task <List <BaseItem> > GetDeletedItemsAsync(FolderAssociation association)
        {
            List <BaseItem> items         = new List <BaseItem>();
            var             folder        = ItemTableModel.GetDefault().GetItem(association.RemoteFolderId);
            var             existingItems = ItemTableModel.GetDefault().GetFilesForFolder(association, this.GetType()).ToList();

            await _GetDeletedItemsAsync(folder, existingItems, items);

            return(items);
        }
Exemple #7
0
        public override async Task <List <BaseItem> > GetUpdatedItems(FolderAssociation association)
        {
            List <BaseItem> items  = new List <BaseItem>();
            var             item   = GetAssociatedItem(association.LocalFolderId);
            StorageFolder   folder = await StorageFolder.GetFolderFromPathAsync(item.EntityId);

            await _GetChangesFromSearchIndex(folder, association.Id, items);

            //await _CheckLocalFolderRecursive(folder, association.Id, items);
            return(items);
        }
Exemple #8
0
        private string _BuildRemoteFilePath(FolderAssociation association, string path)
        {
            var    localFolder    = GetAssociatedItem(association.LocalFolderId);
            Uri    baseUri        = new Uri(localFolder.EntityId);
            Uri    fileUri        = new Uri(path);
            Uri    relativeUri    = baseUri.MakeRelativeUri(fileUri);
            string uri            = relativeUri.ToString();
            var    relativeString = uri.Substring(uri.IndexOf('/') + 1);
            var    remoteFolder   = GetAssociatedItem(association.RemoteFolderId);

            return(remoteFolder.EntityId + (relativeString));
        }
        public async Task <FolderAssociation> AddFolderToSyncAsync(StorageFolder folder, DavItem remoteFolderItem, bool allowInstantUpload = false)
        {
            StorageApplicationPermissions.FutureAccessList.Add(folder);
            var properties = await folder.Properties.RetrievePropertiesAsync(new List <string> {
                "System.DateModified"
            });

            FolderAssociation fa = new FolderAssociation
            {
                IsActive       = true,
                LocalFolderId  = 0,
                RemoteFolderId = 0,
                SyncDirection  = SyncDirection.FullSync,
                LastSync       = DateTime.MinValue
            };

            if (allowInstantUpload)
            {
                fa.SyncDirection         = SyncDirection.UploadOnly;
                fa.SupportsInstantUpload = true;
            }
            FolderAssociationTableModel.GetDefault().InsertItem(fa);
            fa = FolderAssociationTableModel.GetDefault().GetLastInsertItem();

            BaseItem li = new LocalItem
            {
                IsCollection = true,
                LastModified = ((DateTimeOffset)properties["System.DateModified"]).LocalDateTime,
                EntityId     = folder.Path,
                Association  = fa,
            };
            var testFolder = await StorageFolder.GetFolderFromPathAsync(folder.Path);

            if (testFolder.Path != folder.Path)
            {
                li.EntityId = testFolder.Path;
            }
            ItemTableModel.GetDefault().InsertItem(li);
            li = ItemTableModel.GetDefault().GetLastInsertItem();

            remoteFolderItem.Association = fa;
            ItemTableModel.GetDefault().InsertItem(remoteFolderItem);
            var ri = ItemTableModel.GetDefault().GetLastInsertItem();

            fa.RemoteFolderId = ri.Id;
            fa.LocalFolderId  = li.Id;
            FolderAssociationTableModel.GetDefault().UpdateItem(fa, fa.Id);
            var link = new LinkStatus(li, ri);

            LinkStatusTableModel.GetDefault().InsertItem(link);
            return(fa);
        }
Exemple #10
0
        public override async Task <List <BaseItem> > GetDeletedItemsAsync(FolderAssociation association)
        {
            if (Configuration.Configuration.DoNotUseSearchIndex)
            {
                var list = await GetDeletedItemsRecursiveAsync(association);

                return(list);
            }
            else
            {
                return(await GetDeletedItemsFromIndexAsync(association));
            }
        }
Exemple #11
0
        private async Task <List <BaseItem> > GetDeletedItemsRecursiveAsync(FolderAssociation association, List <BaseItem> result = null, StorageFolder folder = null)
        {
            if (result is null)
            {
                result = new List <BaseItem>();
            }
            if (folder is null)
            {
                var localFolderItem = GetAssociatedItem(association.LocalFolderId);
                folder = await StorageFolder.GetFolderFromPathAsync(localFolderItem.EntityId);
            }
            var queryItems    = ItemTableModel.GetDefault().GetFilesForFolder(folder.Path + "\\");
            var dataBaseItems = new List <BaseItem>();

            //remove the items from subfolders
            foreach (var item in queryItems)
            {
                if (item.EntityId == folder.Path)
                {
                    continue;
                }
                var path = item.EntityId.Replace(folder.Path, "").Substring(1);
                if (!path.Contains('\\'))
                {
                    dataBaseItems.Add(item);
                }
            }

            var folderContent = await folder.GetItemsAsync();

            foreach (var item in folderContent)
            {
                if (item.IsOfType(StorageItemTypes.Folder) && item.Path != folder.Path)
                {
                    result = await GetDeletedItemsRecursiveAsync(association, result, item as StorageFolder);
                }
            }

            var folderItems = new List <BaseItem>();

            foreach (var storageItem in folderContent)
            {
                folderItems.Add(new BaseItem {
                    EntityId = storageItem.Path
                });
            }
            var missingItems = dataBaseItems.Except(folderItems, new EnityIdComparer()).ToList();

            result.AddRange(missingItems);
            return(result);
        }
        public ObservableCollection <LinkStatus> GetAllItems(FolderAssociation association)
        {
            var items = new ObservableCollection <LinkStatus>();

            using (var query = Connection.Prepare(GetSelectAllQuery() + " WHERE AssociationId = ?"))
            {
                query.Bind(1, association.Id);
                while (query.Step() == SQLiteResult.ROW)
                {
                    var item = CreateInstance(query);
                    items.Add(item);
                }
            }
            return(items);
        }
Exemple #13
0
        //some users reported that the sync does not find any files
        //this workaround is used if the SearchIndexer does not yield any results, but it's quite slow
        private async Task _GetChangedFilesRecursive(StorageFolder folder, FolderAssociation association, List <BaseItem> result)
        {
            var items = await folder.GetItemsAsync();

            foreach (var storageItem in items)
            {
                Debug.WriteLine(storageItem.Path);
                BasicProperties propertyResult = null;
                if (storageItem.IsOfType(StorageItemTypes.File))
                {
                    propertyResult =
                        await((StorageFile)storageItem).GetBasicPropertiesAsync();
                }
                else if (storageItem.IsOfType(StorageItemTypes.Folder))
                {
                    propertyResult =
                        await((StorageFolder)storageItem).GetBasicPropertiesAsync();
                }

                var      existingItem = ItemTableModel.GetDefault().GetItemFromEntityId(storageItem.Path);
                DateTime date;
                if (existingItem != null && DateTime.TryParse(existingItem.ChangeKey, out date))
                {
                    int i = date.CompareTo(propertyResult.DateModified.UtcDateTime);
                    if (i <= 0)
                    {
                        if (propertyResult.Size != existingItem.Size)
                        {
                            var item = new LocalItem(association, storageItem, propertyResult);
                            result.Add(item);
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
                else if (existingItem == null)
                {
                    var item = new LocalItem(association, storageItem, propertyResult);
                    result.Add(item);
                }
                if (storageItem.IsOfType(StorageItemTypes.Folder))
                {
                    await _GetChangedFilesRecursive((StorageFolder)storageItem, association, result);
                }
            }
        }
Exemple #14
0
        private string _BuildRemoteFolderPath(FolderAssociation association, string path)
        {
            var localFolder = GetAssociatedItem(association.LocalFolderId);
            Uri baseUri     = new Uri(localFolder.EntityId);
            Uri fileUri     = new Uri(path);
            var relative    = fileUri.ToString().Replace(baseUri.ToString(), "");

            if (relative != "" && relative != "/")
            {
                relative = relative.Remove(relative.LastIndexOf('/')).TrimStart('/');
            }
            var remoteFolder = GetAssociatedItem(association.RemoteFolderId);
            var result       = remoteFolder.EntityId + (relative);

            return(result);
        }
Exemple #15
0
        public override async Task <List <BaseItem> > GetUpdatedItems(FolderAssociation association)
        {
            List <BaseItem> items  = new List <BaseItem>();
            var             item   = GetAssociatedItem(association.LocalFolderId);
            StorageFolder   folder = await StorageFolder.GetFolderFromPathAsync(item.EntityId);

            if (Configuration.Configuration.DoNotUseSearchIndex)
            {
                await _GetChangedFilesRecursive(folder, association, items);
            }
            else
            {
                await _GetChangesFromSearchIndex(folder, association.Id, items);
            }
            return(items);
        }
        public async Task <FolderAssociation> AddFolderToSyncAsync(StorageFolder folder, DavItem remoteFolderItem, SyncDirection direction = SyncDirection.FullSync)
        {
            StorageApplicationPermissions.FutureAccessList.Add(folder);
            var properties = await folder.Properties.RetrievePropertiesAsync(new List <string> {
                "System.DateModified"
            });

            FolderAssociation fa = new FolderAssociation
            {
                IsActive       = true,
                LocalFolderId  = 0,
                RemoteFolderId = 0,
                SyncDirection  = direction,
                LastSync       = DateTime.MinValue
            };

            FolderAssociationTableModel.GetDefault().InsertItem(fa);
            fa = FolderAssociationTableModel.GetDefault().GetLastInsertItem();
            var      path = folder.Path.Replace("\\USERS\\", "\\Users\\");
            BaseItem li   = new LocalItem
            {
                IsCollection = true,
                LastModified = ((DateTimeOffset)properties["System.DateModified"]).LocalDateTime,
                EntityId     = path,
                Association  = fa,
            };

            ItemTableModel.GetDefault().InsertItem(li);
            li = ItemTableModel.GetDefault().GetLastInsertItem();

            remoteFolderItem.Association = fa;
            ItemTableModel.GetDefault().InsertItem(remoteFolderItem);
            var ri = ItemTableModel.GetDefault().GetLastInsertItem();

            fa.RemoteFolderId = ri.Id;
            fa.LocalFolderId  = li.Id;
            FolderAssociationTableModel.GetDefault().UpdateItem(fa, fa.Id);
            var link = new LinkStatus(li, ri);

            LinkStatusTableModel.GetDefault().InsertItem(link);
            return(fa);
        }
 public void RemoveFromSyncedFolders(FolderAssociation association)
 {
     ItemTableModel.GetDefault().DeleteItemsFromAssociation(association);
     LinkStatusTableModel.GetDefault().DeleteLinksFromAssociation(association);
     FolderAssociationTableModel.GetDefault().DeleteItem(association.Id);
 }
Exemple #18
0
        public async Task <List <BaseItem> > GetChangesFromChangeTracker(KnownLibraryId libraryId, FolderAssociation association, List <StorageLibraryChangeType> supportedChangeTypes)
        {
            var result  = new List <BaseItem>();
            var library = await StorageLibrary.GetLibraryAsync(libraryId);

            library.ChangeTracker.Enable();
            _changeReader = library.ChangeTracker.GetChangeReader();
            var changes = await _changeReader.ReadBatchAsync();

            foreach (var change in changes)
            {
                if (change.ChangeType == StorageLibraryChangeType.ChangeTrackingLost)
                {
                    await LogHelper.Write($"Changetracking lost: {change.Path}");

                    library.ChangeTracker.Reset();
                    return(null);
                }
                try
                {
                    if (supportedChangeTypes.Contains(change.ChangeType))
                    {
                        Debug.WriteLine($"File: {change.Path} ChangeType: {change.ChangeType}");
                        if (change.Path.EndsWith("thumb"))
                        {
                            continue;
                        }
                        var file = await change.GetStorageItemAsync();

                        if (file == null && change.ChangeType == StorageLibraryChangeType.Deleted)
                        {
                            var localItem = new LocalItem();
                            localItem.Association = association;
                            localItem.EntityId    = change.Path;
                            result.Add(localItem);
                        }
                        else if (file == null || file.IsOfType(StorageItemTypes.Folder))
                        {
                            await LogHelper.Write($"Skipping {change.Path}");
                        }
                        else
                        {
                            try
                            {
                                //check if the file is currently in use, for example a video currently being recorded
                                var stream = await((StorageFile)file).OpenStreamForWriteAsync();
                                stream.Dispose();
                            }
                            catch (Exception)
                            {
                                continue;
                            }
                            var props = await file.GetBasicPropertiesAsync();

                            var item = new LocalItem(association, file, props);

                            if (change.ChangeType == StorageLibraryChangeType.ContentsChanged)
                            {
                                //for some reason something is writing to the files after the upload, but without making changes
                                var existingItem = ItemTableModel.GetDefault().GetItem(item);
                                if (existingItem?.Size == item.Size)
                                {
                                    continue;
                                }
                            }
                            result.Add(item);
                        }
                    }
                }
                catch (Exception e)
                {
                    await LogHelper.Write($"InstantUpload: {e.Message} File: {change.Path} ChangeType: {change.ChangeType}");

                    await LogHelper.Write(e.StackTrace);
                }
            }
            return(result);
        }