Beispiel #1
0
 public static IAsyncOperation <BaseStorageFolder> FromPathAsync(string path)
 {
     if (FtpHelpers.IsFtpPath(path) && FtpHelpers.VerifyFtpPath(path))
     {
         return(Task.FromResult <BaseStorageFolder>(new FtpStorageFolder(new StorageFolderWithPath(null, path))).AsAsyncOperation());
     }
     return(Task.FromResult <BaseStorageFolder>(null).AsAsyncOperation());
 }
 public virtual void CopyPathOfSelectedItem(RoutedEventArgs e)
 {
     try
     {
         if (SlimContentPage != null)
         {
             var path = SlimContentPage.SelectedItem != null ? SlimContentPage.SelectedItem.ItemPath : associatedInstance.FilesystemViewModel.WorkingDirectory;
             if (FtpHelpers.IsFtpPath(path))
             {
                 path = path.Replace("\\", "/", StringComparison.Ordinal);
             }
             DataPackage data = new DataPackage();
             data.SetText(path);
             Clipboard.SetContent(data);
             Clipboard.Flush();
         }
     }
     catch (Exception)
     {
         Debugger.Break();
     }
 }
Beispiel #3
0
 public static IAsyncOperation <BaseStorageFile> FromPathAsync(string path)
 => FtpHelpers.IsFtpPath(path) && FtpHelpers.VerifyFtpPath(path)
         ? Task.FromResult <BaseStorageFile>(new FtpStorageFile(new StorageFileWithPath(null, path))).AsAsyncOperation()
         : Task.FromResult <BaseStorageFile>(null).AsAsyncOperation();
        public async Task <IStorageHistory> CopyItemsAsync(IEnumerable <IStorageItemWithPath> source, IEnumerable <string> destination, IEnumerable <FileNameConflictResolveOptionType> collisions, IProgress <float> progress, IProgress <FileSystemStatusCode> errorCode, CancellationToken cancellationToken)
        {
            var connection = await AppServiceConnectionHelper.Instance;

            if (connection == null || source.Any(x => string.IsNullOrWhiteSpace(x.Path) || x.Path.StartsWith(@"\\?\", StringComparison.Ordinal)) || destination.Any(x => string.IsNullOrWhiteSpace(x) || x.StartsWith(@"\\?\", StringComparison.Ordinal) || FtpHelpers.IsFtpPath(x)))
            {
                // Fallback to builtin file operations
                return(await filesystemOperations.CopyItemsAsync(source, destination, collisions, progress, errorCode, cancellationToken));
            }

            source      = source.Where((src, index) => collisions.ElementAt(index) != FileNameConflictResolveOptionType.Skip).ToList();
            destination = destination.Where((src, index) => collisions.ElementAt(index) != FileNameConflictResolveOptionType.Skip).ToList();
            collisions  = collisions.Where(c => c != FileNameConflictResolveOptionType.Skip).ToList();

            var operationID = Guid.NewGuid().ToString();

            using var r = cancellationToken.Register(CancelOperation, operationID, false);

            EventHandler <Dictionary <string, object> > handler = (s, e) => OnProgressUpdated(s, e, operationID, progress);

            connection.RequestReceived += handler;

            var sourceReplace      = source.Where((src, index) => collisions.ElementAt(index) == FileNameConflictResolveOptionType.ReplaceExisting);
            var destinationReplace = destination.Where((src, index) => collisions.ElementAt(index) == FileNameConflictResolveOptionType.ReplaceExisting);
            var sourceRename       = source.Where((src, index) => collisions.ElementAt(index) != FileNameConflictResolveOptionType.ReplaceExisting);
            var destinationRename  = destination.Where((src, index) => collisions.ElementAt(index) != FileNameConflictResolveOptionType.ReplaceExisting);

            var result     = (FilesystemResult)true;
            var copyResult = new ShellOperationResult();

            if (sourceRename.Any())
            {
                var(status, response) = await connection.SendMessageForResponseAsync(new ValueSet()
                {
                    { "Arguments", "FileOperation" },
                    { "fileop", "CopyItem" },
                    { "operationID", operationID },
                    { "filepath", string.Join('|', sourceRename.Select(s => s.Path)) },
                    { "destpath", string.Join('|', destinationRename) },
                    { "overwrite", false },
                    { "HWND", NativeWinApiHelper.CoreWindowHandle.ToInt64() }
                });

                result &= (FilesystemResult)(status == AppServiceResponseStatus.Success &&
                                             response.Get("Success", false));
                var shellOpResult = JsonConvert.DeserializeObject <ShellOperationResult>(response.Get("Result", ""));
                copyResult.Items.AddRange(shellOpResult?.Items ?? Enumerable.Empty <ShellOperationItemResult>());
            }
            if (sourceReplace.Any())
            {
                var(status, response) = await connection.SendMessageForResponseAsync(new ValueSet()
                {
                    { "Arguments", "FileOperation" },
                    { "fileop", "CopyItem" },
                    { "operationID", operationID },
                    { "filepath", string.Join('|', sourceReplace.Select(s => s.Path)) },
                    { "destpath", string.Join('|', destinationReplace) },
                    { "overwrite", true },
                    { "HWND", NativeWinApiHelper.CoreWindowHandle.ToInt64() }
                });

                result &= (FilesystemResult)(status == AppServiceResponseStatus.Success &&
                                             response.Get("Success", false));
                var shellOpResult = JsonConvert.DeserializeObject <ShellOperationResult>(response.Get("Result", ""));
                copyResult.Items.AddRange(shellOpResult?.Items ?? Enumerable.Empty <ShellOperationItemResult>());
            }

            if (connection != null)
            {
                connection.RequestReceived -= handler;
            }

            result &= (FilesystemResult)copyResult.Items.All(x => x.Succeeded);

            if (result)
            {
                progress?.Report(100.0f);
                errorCode?.Report(FileSystemStatusCode.Success);
                var copiedSources = copyResult.Items.Where(x => sourceRename.Select(s => s.Path).Contains(x.Source)).Where(x => x.Succeeded && x.Destination != null && x.Source != x.Destination);
                if (copiedSources.Any())
                {
                    return(new StorageHistory(FileOperationType.Copy, copiedSources.Select(x => sourceRename.Single(s => s.Path == x.Source)),
                                              copiedSources.Select(item => StorageHelpers.FromPathAndType(item.Destination, sourceRename.Single(s => s.Path == item.Source).ItemType))));
                }
                return(null); // Cannot undo overwrite operation
            }
            else
            {
                // Retry failed operations
                var failedSources = copyResult.Items.Where(x => source.Select(s => s.Path).Contains(x.Source)).Where(x => !x.Succeeded);
                var copyZip       = source.Zip(destination, (src, dest) => new { src, dest }).Zip(collisions, (z1, coll) => new { z1.src, z1.dest, coll });
                return(await filesystemOperations.CopyItemsAsync(
                           failedSources.Select(x => copyZip.Single(s => s.src.Path == x.Source).src),
                           failedSources.Select(x => copyZip.Single(s => s.src.Path == x.Source).dest),
                           failedSources.Select(x => copyZip.Single(s => s.src.Path == x.Source).coll), progress, errorCode, cancellationToken));
            }
        }
        public async Task <IStorageHistory> RestoreFromTrashAsync(IStorageItemWithPath source, string destination, IProgress <float> progress, IProgress <FileSystemStatusCode> errorCode, CancellationToken cancellationToken)
        {
            var connection = await AppServiceConnectionHelper.Instance;

            if (connection == null || string.IsNullOrWhiteSpace(source.Path) || source.Path.StartsWith(@"\\?\", StringComparison.Ordinal) || string.IsNullOrWhiteSpace(destination) || destination.StartsWith(@"\\?\", StringComparison.Ordinal) || FtpHelpers.IsFtpPath(destination))
            {
                // Fallback to builtin file operations
                return(await filesystemOperations.RestoreFromTrashAsync(source, destination, progress, errorCode, cancellationToken));
            }

            var operationID = Guid.NewGuid().ToString();

            using var r = cancellationToken.Register(CancelOperation, operationID, false);

            EventHandler <Dictionary <string, object> > handler = (s, e) => OnProgressUpdated(s, e, operationID, progress);

            connection.RequestReceived += handler;

            var moveResult = new ShellOperationResult();

            var(status, response) = await connection.SendMessageForResponseAsync(new ValueSet()
            {
                { "Arguments", "FileOperation" },
                { "fileop", "MoveItem" },
                { "operationID", operationID },
                { "filepath", source.Path },
                { "destpath", destination },
                { "overwrite", false },
                { "HWND", NativeWinApiHelper.CoreWindowHandle.ToInt64() }
            });

            var result = (FilesystemResult)(status == AppServiceResponseStatus.Success &&
                                            response.Get("Success", false));
            var shellOpResult = JsonConvert.DeserializeObject <ShellOperationResult>(response.Get("Result", ""));

            moveResult.Items.AddRange(shellOpResult?.Items ?? Enumerable.Empty <ShellOperationItemResult>());

            if (connection != null)
            {
                connection.RequestReceived -= handler;
            }

            result &= (FilesystemResult)moveResult.Items.All(x => x.Succeeded);

            if (result)
            {
                progress?.Report(100.0f);
                errorCode?.Report(FileSystemStatusCode.Success);
                var movedSources = moveResult.Items.Where(x => new[] { source }.Select(s => s.Path).Contains(x.Source)).Where(x => x.Succeeded && x.Destination != null && x.Source != x.Destination);
                if (movedSources.Any())
                {
                    // Recycle bin also stores a file starting with $I for each item
                    await DeleteItemsAsync(movedSources.Select(src => StorageHelpers.FromPathAndType(
                                                                   Path.Combine(Path.GetDirectoryName(src.Source), Path.GetFileName(src.Source).Replace("$R", "$I", StringComparison.Ordinal)),
                                                                   new[] { source }.Single(s => s.Path == src.Source).ItemType)), null, null, true, cancellationToken);

                    return(new StorageHistory(FileOperationType.Restore, source,
                                              StorageHelpers.FromPathAndType(movedSources.Single().Destination, source.ItemType)));
                }
                return(null); // Cannot undo overwrite operation
            }
            else
            {
                // Retry failed operations
                return(await filesystemOperations.RestoreFromTrashAsync(source, destination, progress, errorCode, cancellationToken));
            }
        }
        public async Task <IStorageHistory> RenameAsync(IStorageItemWithPath source, string newName, NameCollisionOption collision, IProgress <FileSystemStatusCode> errorCode, CancellationToken cancellationToken)
        {
            var connection = await AppServiceConnectionHelper.Instance;

            if (connection == null || string.IsNullOrWhiteSpace(source.Path) || source.Path.StartsWith(@"\\?\", StringComparison.Ordinal) || FtpHelpers.IsFtpPath(source.Path))
            {
                // Fallback to builtin file operations
                return(await filesystemOperations.RenameAsync(source, newName, collision, errorCode, cancellationToken));
            }

            var renameResult = new ShellOperationResult();

            var(status, response) = await connection.SendMessageForResponseAsync(new ValueSet()
            {
                { "Arguments", "FileOperation" },
                { "fileop", "RenameItem" },
                { "operationID", Guid.NewGuid().ToString() },
                { "filepath", source.Path },
                { "newName", newName },
                { "overwrite", collision == NameCollisionOption.ReplaceExisting }
            });

            var result = (FilesystemResult)(status == AppServiceResponseStatus.Success &&
                                            response.Get("Success", false));
            var shellOpResult = JsonConvert.DeserializeObject <ShellOperationResult>(response.Get("Result", ""));

            renameResult.Items.AddRange(shellOpResult?.Items ?? Enumerable.Empty <ShellOperationItemResult>());

            result &= (FilesystemResult)renameResult.Items.All(x => x.Succeeded);

            if (result)
            {
                errorCode?.Report(FileSystemStatusCode.Success);
                var renamedSources = renameResult.Items.Where(x => new[] { source }.Select(s => s.Path).Contains(x.Source)).Where(x => x.Succeeded && x.Destination != null && x.Source != x.Destination);
                if (renamedSources.Any())
                {
                    return(new StorageHistory(FileOperationType.Rename, source,
                                              StorageHelpers.FromPathAndType(renamedSources.Single().Destination, source.ItemType)));
                }
                return(null); // Cannot undo overwrite operation
            }
            else
            {
                // Retry failed operations
                return(await filesystemOperations.RenameAsync(source, newName, collision, errorCode, cancellationToken));
            }
        }
        public async Task <IStorageHistory> DeleteItemsAsync(IEnumerable <IStorageItemWithPath> source, IProgress <float> progress, IProgress <FileSystemStatusCode> errorCode, bool permanently, CancellationToken cancellationToken)
        {
            var connection = await AppServiceConnectionHelper.Instance;

            if (connection == null || source.Any(x => string.IsNullOrWhiteSpace(x.Path) || x.Path.StartsWith(@"\\?\", StringComparison.Ordinal) || FtpHelpers.IsFtpPath(x.Path)))
            {
                // Fallback to builtin file operations
                return(await filesystemOperations.DeleteItemsAsync(source, progress, errorCode, permanently, cancellationToken));
            }

            source = source.DistinctBy(x => x.Path); // #5771
            var deleleFilePaths = source.Select(s => s.Path);

            var deleteFromRecycleBin = source.Any() ? recycleBinHelpers.IsPathUnderRecycleBin(source.ElementAt(0).Path) : false;

            permanently |= deleteFromRecycleBin;

            if (deleteFromRecycleBin)
            {
                // Recycle bin also stores a file starting with $I for each item
                deleleFilePaths = deleleFilePaths.Concat(source.Select(x => Path.Combine(Path.GetDirectoryName(x.Path), Path.GetFileName(x.Path).Replace("$R", "$I", StringComparison.Ordinal)))).Distinct();
            }

            var operationID = Guid.NewGuid().ToString();

            using var r = cancellationToken.Register(CancelOperation, operationID, false);

            EventHandler <Dictionary <string, object> > handler = (s, e) => OnProgressUpdated(s, e, operationID, progress);

            connection.RequestReceived += handler;

            var deleteResult = new ShellOperationResult();

            var(status, response) = await connection.SendMessageForResponseAsync(new ValueSet()
            {
                { "Arguments", "FileOperation" },
                { "fileop", "DeleteItem" },
                { "operationID", operationID },
                { "filepath", string.Join('|', deleleFilePaths) },
                { "permanently", permanently },
                { "HWND", NativeWinApiHelper.CoreWindowHandle.ToInt64() }
            });

            var result = (FilesystemResult)(status == AppServiceResponseStatus.Success &&
                                            response.Get("Success", false));
            var shellOpResult = JsonConvert.DeserializeObject <ShellOperationResult>(response.Get("Result", ""));

            deleteResult.Items.AddRange(shellOpResult?.Items ?? Enumerable.Empty <ShellOperationItemResult>());

            if (connection != null)
            {
                connection.RequestReceived -= handler;
            }

            result &= (FilesystemResult)deleteResult.Items.All(x => x.Succeeded);

            if (result)
            {
                progress?.Report(100.0f);
                errorCode?.Report(FileSystemStatusCode.Success);
                foreach (var item in deleteResult.Items)
                {
                    await associatedInstance.FilesystemViewModel.RemoveFileOrFolderAsync(item.Source);
                }
                var recycledSources = deleteResult.Items.Where(x => source.Select(s => s.Path).Contains(x.Source)).Where(x => x.Succeeded && x.Destination != null && x.Source != x.Destination);
                if (recycledSources.Any())
                {
                    return(new StorageHistory(FileOperationType.Recycle, recycledSources.Select(x => source.Single(s => s.Path == x.Source)),
                                              recycledSources.Select(item => StorageHelpers.FromPathAndType(item.Destination, source.Single(s => s.Path == item.Source).ItemType))));
                }
                return(new StorageHistory(FileOperationType.Delete, source, null));
            }
            else
            {
                // Retry failed operations
                var failedSources = deleteResult.Items.Where(x => source.Select(s => s.Path).Contains(x.Source))
                                    .Where(x => !x.Succeeded && x.HResult != HResult.COPYENGINE_E_USER_CANCELLED && x.HResult != HResult.COPYENGINE_E_RECYCLE_BIN_NOT_FOUND);
                return(await filesystemOperations.DeleteItemsAsync(
                           failedSources.Select(x => source.Single(s => s.Path == x.Source)), progress, errorCode, permanently, cancellationToken));
            }
        }