예제 #1
0
        /// <summary>
        /// Recursively restores OriginalPath and the 'locked' icon.
        /// </summary>
        /// <param name="userFileSystemNewPath">Path in the user file system to start recursive processing.</param>
        private async Task MoveToCompletionRecursiveAsync(string userFileSystemNewPath)
        {
            if (FsPath.IsFolder(userFileSystemNewPath))
            {
                if (!new DirectoryInfo(userFileSystemNewPath).Attributes.HasFlag(System.IO.FileAttributes.Offline))
                {
                    //LogMessage("Folder offline, skipping:", userFileSystemFolderPath);

                    IEnumerable <string> userFileSystemChildren = Directory.EnumerateFileSystemEntries(userFileSystemNewPath, "*");

                    foreach (string userFileSystemChildPath in userFileSystemChildren)
                    {
                        try
                        {
                            await MoveToCompletionRecursiveAsync(userFileSystemChildPath);
                        }
                        catch (Exception ex)
                        {
                            logger.LogError("Failed to complete move", userFileSystemChildPath, null, ex);
                        }
                    }
                }
            }

            if (FsPath.Exists(userFileSystemNewPath) &&         // This check is just to avoid extra error in the log.
                !FsPath.IsRecycleBin(userFileSystemNewPath) &&  // When a file with content is deleted, it is moved to a Recycle Bin.
                !FsPath.AvoidAutoLock(userFileSystemNewPath))   // No need to update temp MS Office docs.
            {
                // Open file to prevent reads and changes between GetFileDataSizeInfo() call and SetInSync() call.
                using (WindowsFileSystemItem userFileSystemWinItem = WindowsFileSystemItem.OpenReadAttributes(userFileSystemNewPath, FileMode.Open, FileShare.None))
                {
                    // If a file with content is deleted it is moved to a recycle bin and converted
                    // to a regular file, so placeholder features are not available on it, checking if a file is a placeholder.
                    if (/*updateTargetOnSuccess &&*/ PlaceholderItem.IsPlaceholder(userFileSystemNewPath))
                    {
                        PlaceholderItem placeholderNew = PlaceholderItem.GetItem(userFileSystemNewPath);

                        await virtualDrive.GetUserFileSystemRawItem(userFileSystemNewPath, logger).ClearStateAsync();

                        // Update OriginalPath if the item is not new.
                        // Required for pptx and xlsx files Save As operation.
                        if (!placeholderNew.IsNew(virtualDrive))
                        {
                            // Update OriginalPath, so the item does not appear as moved.
                            logger.LogMessage("Setting Original Path", userFileSystemNewPath);
                            placeholderNew.SetOriginalPath(userFileSystemNewPath);
                        }

                        // Restore the 'locked' icon.
                        ServerLockInfo existingLock = await virtualDrive.LockManager(userFileSystemNewPath, logger).GetLockInfoAsync();

                        await virtualDrive.GetUserFileSystemRawItem(userFileSystemNewPath, logger).SetLockInfoAsync(existingLock);
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Compares two files contents.
        /// </summary>
        /// <param name="filePath1">File or folder 1 to compare.</param>
        /// <param name="filePath2">File or folder 2 to compare.</param>
        /// <returns>True if file is modified. False - otherwise.</returns>
        private static bool IsModified(string filePath1, string filePath2)
        {
            if (FsPath.IsFolder(filePath1) && FsPath.IsFolder(filePath2))
            {
                return(false);
            }

            try
            {
                if (new FileInfo(filePath1).Length == new FileInfo(filePath2).Length)
                {
                    byte[] hash1;
                    byte[] hash2;
                    using (var alg = System.Security.Cryptography.MD5.Create())
                    {
                        using (FileStream stream = new FileStream(filePath1, FileMode.Open, FileAccess.Read, FileShare.None))
                        {
                            hash1 = alg.ComputeHash(stream);
                        }
                        using (FileStream stream = new FileStream(filePath2, FileMode.Open, FileAccess.Read, FileShare.None))
                        {
                            hash2 = alg.ComputeHash(stream);
                        }
                    }

                    return(!hash1.SequenceEqual(hash2));
                }
            }
            catch (IOException)
            {
                // One of the files is blocked. Can not compare files and start sychronization.
                return(false);
            }

            return(true);
        }
예제 #3
0
        /// <summary>
        /// Recursively synchronizes all files and folders moved in user file system with the remote storage.
        /// Synchronizes only folders already loaded into the user file system.
        /// </summary>
        /// <param name="userFileSystemFolderPath">Folder path in user file system.</param>
        internal async Task SyncronizeMovedAsync(string userFileSystemFolderPath)
        {
            // In case of on-demand loading the user file system contains only a subset of the server files and folders.
            // Here we sync folder only if its content already loaded into user file system (folder is not offline).
            // The folder content is loaded inside IFolder.GetChildrenAsync() method.
            if (new DirectoryInfo(userFileSystemFolderPath).Attributes.HasFlag(System.IO.FileAttributes.Offline))
            {
                //LogMessage("Folder offline, skipping:", userFileSystemFolderPath);
                return;
            }

            IEnumerable <string> userFileSystemChildren = Directory.EnumerateFileSystemEntries(userFileSystemFolderPath, "*");

            //LogMessage("Synchronizing:", userFileSystemFolderPath);

            foreach (string userFileSystemPath in userFileSystemChildren)
            {
                string userFileSystemOldPath = null;
                try
                {
                    //$<PlaceholderItem.IsPlaceholder
                    if (!PlaceholderItem.IsPlaceholder(userFileSystemPath))
                    {
                        // Convert regular file/folder to placeholder.
                        // The file/folder was created or overwritten.
                        PlaceholderItem.ConvertToPlaceholder(userFileSystemPath, false);
                        LogMessage("Converted to placeholder", userFileSystemPath);
                    }
                    //$>

                    if (!FsPath.AvoidSync(userFileSystemPath))
                    {
                        PlaceholderItem userFileSystemItem = PlaceholderItem.GetItem(userFileSystemPath);
                        if (userFileSystemItem.IsMoved())
                        {
                            // Process items moved in user file system.
                            userFileSystemOldPath = userFileSystemItem.GetOriginalPath();
                            await new RemoteStorageRawItem(userFileSystemOldPath, this).MoveToAsync(userFileSystemPath);
                        }
                        else
                        {
                            // Restore Original Path and 'locked' icon that are lost during MS Office transactional save.
                            // We keep Original Path to process moved files when app was not running.
                            userFileSystemOldPath = userFileSystemItem.GetOriginalPath();
                            if (!userFileSystemItem.IsNew() && string.IsNullOrEmpty(userFileSystemOldPath))
                            {
                                // Restore Original Path.
                                LogMessage("Saving Original Path", userFileSystemItem.Path);
                                userFileSystemItem.SetOriginalPath(userFileSystemItem.Path);

                                // Restore the 'locked' icon.
                                bool isLocked = await Lock.IsLockedAsync(userFileSystemPath);

                                await new UserFileSystemRawItem(userFileSystemPath).SetLockIconAsync(isLocked);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogError("Move in remote storage failed", userFileSystemOldPath, userFileSystemPath, ex);
                }

                // Synchronize subfolders.
                try
                {
                    if (FsPath.IsFolder(userFileSystemPath))
                    {
                        await SyncronizeMovedAsync(userFileSystemPath);
                    }
                }
                catch (Exception ex)
                {
                    LogError("Folder move sync failed", userFileSystemPath, null, ex);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Recursively synchronizes all files and folders with the server.
        /// Synchronizes only folders already loaded into the user file system.
        /// </summary>
        /// <param name="userFileSystemFolderPath">Folder path in user file system.</param>
        private async Task SyncronizeFolderAsync(string userFileSystemFolderPath)
        {
            // In case of on-demand loading the user file system contains only a subset of the server files and folders.
            // Here we sync folder only if its content already loaded into user file system (folder is not offline).
            // The folder content is loaded inside IFolder.GetChildrenAsync() method.
            if (new DirectoryInfo(userFileSystemFolderPath).Attributes.HasFlag(System.IO.FileAttributes.Offline))
            {
                LogMessage("Folder offline, skipping:", userFileSystemFolderPath);
                return;
            }

            IEnumerable <string> userFileSystemChildren = Directory.EnumerateFileSystemEntries(userFileSystemFolderPath, "*");

            LogMessage("Synchronizing:", userFileSystemFolderPath);

            string remoteStorageFolderPath = Mapping.MapPath(userFileSystemFolderPath);
            IEnumerable <FileSystemInfo> remoteStorageChildrenItems = new DirectoryInfo(remoteStorageFolderPath).EnumerateFileSystemInfos("*");

            // Delete files/folders in user file system.
            foreach (string userFileSystemPath in userFileSystemChildren)
            {
                try
                {
                    string         remoteStoragePath = Mapping.MapPath(userFileSystemPath);
                    FileSystemInfo remoteStorageItem = remoteStorageChildrenItems.FirstOrDefault(x => x.FullName.Equals(remoteStoragePath, StringComparison.InvariantCultureIgnoreCase));
                    if (remoteStorageItem == null)
                    {
                        LogMessage("Deleting item:", userFileSystemPath);
                        await new UserFileSystemItem(userFileSystemPath).DeleteAsync();
                        LogMessage("Deleted succesefully:", userFileSystemPath);
                    }
                }
                catch (Exception ex)
                {
                    LogError("Delete failed:", userFileSystemPath, ex);
                }
            }

            // Create new files/folders in user file system.
            foreach (FileSystemInfo remoteStorageItem in remoteStorageChildrenItems)
            {
                try
                {
                    string userFileSystemPath = Mapping.ReverseMapPath(remoteStorageItem.FullName);
                    if (!FsPath.Exists(userFileSystemPath))
                    {
                        LogMessage("Creating new item:", userFileSystemPath);
                        await UserFileSystemItem.CreateAsync(userFileSystemFolderPath, remoteStorageItem);

                        LogMessage("Created succesefully:", userFileSystemPath);
                    }
                }
                catch (Exception ex)
                {
                    LogError("Creation failed:", remoteStorageItem.FullName, ex);
                }
            }

            // Update files/folders in user file system and sync subfolders.
            userFileSystemChildren = Directory.EnumerateFileSystemEntries(userFileSystemFolderPath, "*");
            foreach (string userFileSystemPath in userFileSystemChildren)
            {
                try
                {
                    string         remoteStoragePath = Mapping.MapPath(userFileSystemPath);
                    FileSystemInfo remoteStorageItem = remoteStorageChildrenItems.FirstOrDefault(x => x.FullName.Equals(remoteStoragePath, StringComparison.InvariantCultureIgnoreCase));

                    // The item was deleted or moved/renamed on the server, but it may still exists in the user file system.
                    // This is just to avoid extra exceptions in the log.
                    if (remoteStorageItem == null)
                    {
                        continue;
                    }

                    // Update existing files/folders info.
                    if (!await new UserFileSystemItem(userFileSystemPath).EqualsAsync(remoteStorageItem))
                    {
                        LogMessage("Item modified:", remoteStoragePath);
                        await new UserFileSystemItem(userFileSystemPath).UpdateAsync(remoteStorageItem);
                        LogMessage("Updated succesefully:", userFileSystemPath);
                    }

                    // Hydrate / dehydrate the file.
                    else
                    {
                        bool?hydrated = await new UserFileSystemItem(userFileSystemPath).UpdateHydrationAsync();
                        if (hydrated != null)
                        {
                            string hydrationDescrition = (bool)hydrated ? "Hydrated" : "Dehydrated";
                            LogMessage($"{hydrationDescrition} succesefully:", userFileSystemPath);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogError("Update failed:", userFileSystemPath, ex);
                }

                // Synchronize subfolders.
                try
                {
                    if (FsPath.IsFolder(userFileSystemPath))
                    {
                        await SyncronizeFolderAsync(userFileSystemPath);
                    }
                }
                catch (Exception ex)
                {
                    LogError("Folder sync failed:", userFileSystemPath, ex);
                }
            }
        }