private void ProcessRemoteFile(
            StorageFile remoteFile,
            List <StorageItem> localItems,
            EncryptedFolder folder,
            SyncConcurrentQueue queue,
            IStorage localStorage,
            string localFolderPath)
        {
            var encryptedFile = folder.Files.FirstOrDefault(f => f.EncryptedName == remoteFile.Name);

            if (encryptedFile == null)
            {
                // remote file does not exists in db, we can't recrypt it
                // todo add sync error
                return;
            }

            var localPath  = Path.Combine(localFolderPath, encryptedFile.Name);
            var localItem  = localItems.OfType <StorageFile>().FirstOrDefault(l => l.Name == encryptedFile.Name);
            var itemStatus = GetItemStatus(localItem, remoteFile, encryptedFile);

            if (itemStatus != null)
            {
                queue.Enqueue(
                    new QueueItem
                {
                    Status        = itemStatus.Value,
                    LocalStorage  = localStorage,
                    LocalPath     = localPath,
                    RemotePath    = remoteFile.FullPath,
                    RemoteStorage = this.remoteStorage,
                    EncryptedFile = encryptedFile
                });
            }
        }
示例#2
0
        public static async Task Main(string[] args)
        {
            using (var db = new DirDbContext("temp1.db", null))
            {
                db.Database.Migrate();
                var folder = new EncryptedFolder
                {
                    Name          = "First folder",
                    Created       = DateTime.Now,
                    EncryptedName = "First folder encrypted",
                    Files         = new List <EncryptedFile>
                    {
                        new EncryptedFile
                        {
                            Name = "First file"
                        },
                        new EncryptedFile
                        {
                            Name = "Second file"
                        }
                    }
                };
                db.Folders.Add(folder);
                await db.SaveChangesAsync();
            }

            Console.WriteLine("End");
            Console.ReadKey();
        }
示例#3
0
 public void TearDown()
 {
     this.dbContext?.Dispose();
     this.dbContext          = null;
     this.remoteStorageMock  = null;
     this.localStorageMock   = null;
     this.storageFactoryMock = null;
     this.rootFolder         = null;
 }
示例#4
0
        public static string GetRelativeEncryptedPath(this EncryptedFolder ecryptedFolder)
        {
            var path = ecryptedFolder.EncryptedName;

            while (ecryptedFolder.Parent != null)
            {
                ecryptedFolder = ecryptedFolder.Parent;
                path           = Path.Combine(ecryptedFolder.EncryptedName, path);
            }

            return(path);
        }
        private void ProcessLocalFile(
            StorageFile localFile,
            List <StorageItem> remoteItems,
            EncryptedFolder folder,
            SyncConcurrentQueue queue,
            IStorage localStorage,
            string remoteFolderPath)
        {
            var encryptedFile = folder.Files.FirstOrDefault(f => f.Name == localFile.Name);

            if (encryptedFile == null)
            {
                // file doesn't exists in remote
                encryptedFile = new EncryptedFile
                {
                    Name            = localFile.Name,
                    Created         = localFile.Modified,
                    Modified        = localFile.Modified,
                    EncryptedName   = Guid.NewGuid().ToString(),
                    UnencryptedSize = localFile.Size,
                    // todo Hash =
                    FolderId = folder.Id,
                    Folder   = folder
                };
                encryptedFile = this.db.Files.Add(encryptedFile).Entity;
                this.db.SaveChangesAsync();
            }
            else
            {
                var remoteExists = remoteItems.Any(x => x.Name == encryptedFile.EncryptedName);
                if (remoteExists)
                {
                    // already processed at remote processing
                    return;
                }
            }

            queue.Enqueue(
                new QueueItem
            {
                Status        = QueueItemStatus.WaitingForUpload,
                LocalStorage  = localStorage,
                LocalPath     = localFile.FullPath,
                RemotePath    = Path.Combine(remoteFolderPath, encryptedFile.EncryptedName),
                RemoteStorage = this.remoteStorage,
                EncryptedFile = encryptedFile
            });
        }
示例#6
0
        public async Task SetUp()
        {
            this.remoteStorageMock = new Mock <IStorage>();
            this.localStorageMock  = new Mock <IStorage>();

            this.storageFactoryMock = new Mock <IStorageFactory>();
            this.storageFactoryMock.Setup(x => x.CreateLocalStorage(BasePath)).Returns(this.localStorageMock.Object);

            this.dbContext = new TestDbContext();
            var deviceRootFolder = new DeviceRootFolder
            {
                RootPath = BasePath,
                Folder   = new EncryptedFolder
                {
                    Name          = RootFolder,
                    EncryptedName = Guid.NewGuid().ToString(),
                    Created       = DateTime.UtcNow,
                    Modified      = DateTime.UtcNow,
                }
            };

            this.dbContext.Devices.Add(
                new Device
            {
                DeviceName        = DeviceName,
                DeviceRootFolders = new List <DeviceRootFolder>
                {
                    deviceRootFolder
                }
            });
            await this.dbContext.SaveChangesAsync();

            this.rootFolder = await this.dbContext.DeviceRootFolders
                              .Where(dr => dr.Device.DeviceName == DeviceName)
                              .Select(dr => dr.Folder)
                              .FirstOrDefaultAsync(f => f.Name == RootFolder);
        }
        private async Task SyncFolder(
            SyncConcurrentQueue queue,
            CancellationToken cancellationToken,
            EncryptedFolder folder,
            IStorage localStorage)
        {
            var remoteFolderPath = folder.GetRelativeEncryptedPath();
            var localFolderPath  = folder.GetRelativePath();
            var remoteItems      = await this.remoteStorage.GetFolderChilds(remoteFolderPath);

            var localItems = await localStorage.GetFolderChilds(localFolderPath);

            foreach (var remoteItem in remoteItems)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                switch (remoteItem)
                {
                case StorageFile remoteFile:
                    this.ProcessRemoteFile(
                        remoteFile,
                        localItems,
                        folder,
                        queue,
                        localStorage,
                        localFolderPath);
                    break;

                case StorageFolder remoteFolder:
                    var encryptedFolder = folder.Folders.FirstOrDefault(f => f.EncryptedName == remoteFolder.Name);
                    if (encryptedFolder == null)
                    {
                        // todo add sync error
                        continue;
                    }

                    await this.SyncFolder(queue, cancellationToken, encryptedFolder, localStorage);

                    break;

                default:
                    throw new NotImplementedException($"Failed to process emelent of type {remoteItem.GetType()}");
                }
            }

            foreach (var localItem in localItems)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                switch (localItem)
                {
                case StorageFile localFile:
                    this.ProcessLocalFile(
                        localFile,
                        remoteItems,
                        folder,
                        queue,
                        localStorage,
                        remoteFolderPath);
                    break;

                case StorageFolder localFolder:
                    var encryptedFolder = folder.Folders.FirstOrDefault(f => f.Name == localFolder.Name);
                    if (encryptedFolder == null)
                    {
                        // new local folder
                        encryptedFolder = new EncryptedFolder
                        {
                            Name          = localFolder.Name,
                            EncryptedName = Guid.NewGuid().ToString(),
                            RootId        = folder.RootId ?? folder.Id,
                            Root          = folder.Root ?? folder,
                            ParentId      = folder.Id,
                            Parent        = folder,
                            Created       = DateTime.UtcNow,
                            Modified      = DateTime.UtcNow
                        };
                        encryptedFolder = this.db.Add(encryptedFolder).Entity;
                        await this.db.SaveChangesAsync(cancellationToken);
                    }
                    else
                    {
                        var remoteFolderExists = remoteItems.OfType <StorageFolder>()
                                                 .Any(f => f.Name == encryptedFolder.EncryptedName);
                        if (remoteFolderExists)
                        {
                            // skip existing remote folders
                            continue;
                        }
                    }

                    await SyncFolder(queue, cancellationToken, encryptedFolder, localStorage);

                    break;

                default:
                    throw new NotImplementedException($"Failed to process emelent of type {localItem.GetType()}");
                }
            }
        }