Example #1
0
        public async Task <IStorageHistory> RenameAsync(PathWithType source,
                                                        string newName,
                                                        NameCollisionOption collision,
                                                        IProgress <FilesystemErrorCode> errorCode,
                                                        CancellationToken cancellationToken)
        {
            if (Path.GetFileName(source.Path) == newName && collision == NameCollisionOption.FailIfExists)
            {
                errorCode?.Report(FilesystemErrorCode.ERROR_ALREADYEXIST);
                return(null);
            }

            if (!string.IsNullOrWhiteSpace(newName) &&
                !FilesystemHelpers.ContainsRestrictedCharacters(newName) &&
                !FilesystemHelpers.ContainsRestrictedFileName(newName))
            {
                try
                {
                    IStorageItem itemToRename = await source.Path.ToStorageItem();

                    await itemToRename.RenameAsync(newName, collision);

                    errorCode?.Report(FilesystemErrorCode.ERROR_SUCCESS);
                    return(new StorageHistory(FileOperationType.Rename, source, new PathWithType(itemToRename.Path, source.ItemType)));
                }
                catch (Exception e)
                {
                    errorCode?.Report(FilesystemTasks.GetErrorCode(e));
                    return(null);
                }
            }

            return(null);
        }
Example #2
0
        public async Task <ReturnResult> RenameAsync(PathWithType source, string newName, NameCollisionOption collision, bool registerHistory)
        {
            FilesystemErrorCode            returnCode = FilesystemErrorCode.ERROR_INPROGRESS;
            Progress <FilesystemErrorCode> errorCode  = new Progress <FilesystemErrorCode>();

            errorCode.ProgressChanged += (s, e) => returnCode = e;

            IStorageHistory history = await filesystemOperations.RenameAsync(source, newName, collision, errorCode, cancellationToken);

            if (registerHistory && !string.IsNullOrWhiteSpace(source.Path))
            {
                App.HistoryWrapper.AddHistory(history);
            }

            return(returnCode.ToStatus());
        }
Example #3
0
        public async Task <IStorageHistory> CreateAsync(PathWithType source, IProgress <FilesystemErrorCode> errorCode, CancellationToken cancellationToken)
        {
            try
            {
                switch (source.ItemType)
                {
                case FilesystemItemType.File:
                {
                    StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(Path.GetDirectoryName(source.Path));

                    await folder.CreateFileAsync(Path.GetFileName(source.Path));

                    break;
                }

                case FilesystemItemType.Directory:
                {
                    StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(Path.GetDirectoryName(source.Path));

                    await folder.CreateFolderAsync(Path.GetFileName(source.Path));

                    break;
                }

                case FilesystemItemType.Symlink:
                {
                    Debugger.Break();
                    throw new NotImplementedException();
                }

                default:
                    Debugger.Break();
                    break;
                }

                errorCode?.Report(FilesystemErrorCode.ERROR_SUCCESS);
                return(new StorageHistory(FileOperationType.CreateNew, source.CreateEnumerable(), null));
            }
            catch (Exception e)
            {
                errorCode?.Report(FilesystemTasks.GetErrorCode(e));
                return(null);
            }
        }
Example #4
0
        public async Task <ReturnResult> MoveItemAsync(PathWithType source, string destination, bool registerHistory)
        {
            PostedStatusBanner banner = associatedInstance.BottomStatusStripControl.OngoingTasksControl.PostBanner(
                string.Empty,
                associatedInstance.FilesystemViewModel.WorkingDirectory,
                0,
                ReturnResult.InProgress,
                FileOperationType.Move);

            ReturnResult returnStatus = ReturnResult.InProgress;

            banner.ErrorCode.ProgressChanged += (s, e) => returnStatus = e.ToStatus();

            Stopwatch sw = new Stopwatch();

            sw.Start();

            associatedInstance.ContentPage.ClearSelection();
            IStorageHistory history = await filesystemOperations.MoveAsync(source, destination, banner.Progress, banner.ErrorCode, cancellationToken);

            if (registerHistory && !string.IsNullOrWhiteSpace(source.Path))
            {
                App.HistoryWrapper.AddHistory(history);
            }

            banner.Remove();
            sw.Stop();

            if (sw.Elapsed.TotalSeconds >= 10)
            {
                associatedInstance.BottomStatusStripControl.OngoingTasksControl.PostBanner(
                    "Move Complete",
                    "The operation has completed.",
                    0,
                    ReturnResult.Success,
                    FileOperationType.Move);
            }

            return(returnStatus);
        }
Example #5
0
        public async Task <IStorageHistory> MoveAsync(PathWithType source,
                                                      string destination,
                                                      IProgress <float> progress,
                                                      IProgress <FilesystemErrorCode> errorCode,
                                                      CancellationToken cancellationToken)
        {
            IStorageHistory history = await CopyAsync(source, destination, progress, errorCode, cancellationToken);

            if (string.IsNullOrWhiteSpace(source.Path))
            {
                // Can't move (only copy) files from MTP devices because:
                // StorageItems returned in DataPackageView are read-only
                // The item.Path property will be empty and there's no way of retrieving a new StorageItem with R/W access
                errorCode?.Report(FilesystemErrorCode.ERROR_SUCCESS | FilesystemErrorCode.ERROR_INPROGRESS);
            }

            await DeleteAsync(source, progress, errorCode, true, cancellationToken);

            progress?.Report(100.0f);

            return(new StorageHistory(FileOperationType.Move, history.Source, history.Destination));
        }
Example #6
0
        public async Task <ReturnResult> DeleteItemAsync(PathWithType source, bool showDialog, bool permanently, bool registerHistory)
        {
            PostedStatusBanner banner;
            bool deleteFromRecycleBin = await recycleBinHelpers.IsRecycleBinItem(source.Path);

            if (deleteFromRecycleBin)
            {
                permanently = true;
            }

            if (permanently)
            {
                banner = associatedInstance.BottomStatusStripControl.OngoingTasksControl.PostBanner(string.Empty,
                                                                                                    associatedInstance.FilesystemViewModel.WorkingDirectory,
                                                                                                    0,
                                                                                                    ReturnResult.InProgress,
                                                                                                    FileOperationType.Delete);
            }
            else
            {
                banner = associatedInstance.BottomStatusStripControl.OngoingTasksControl.PostBanner(string.Empty,
                                                                                                    associatedInstance.FilesystemViewModel.WorkingDirectory,
                                                                                                    0,
                                                                                                    ReturnResult.InProgress,
                                                                                                    FileOperationType.Recycle);
            }

            ReturnResult returnStatus = ReturnResult.InProgress;

            banner.ErrorCode.ProgressChanged += (s, e) => returnStatus = e.ToStatus();

            if (App.AppSettings.ShowConfirmDeleteDialog && showDialog) // Check if the setting to show a confirmation dialog is on
            {
                ConfirmDeleteDialog dialog = new ConfirmDeleteDialog(
                    deleteFromRecycleBin,
                    permanently,
                    associatedInstance.ContentPage.SelectedItemsPropertiesViewModel);

                await dialog.ShowAsync();

                if (dialog.Result != DialogResult.Delete) // Delete selected item if the result is Yes
                {
                    return(ReturnResult.Cancelled);       // Return if the result isn't delete
                }

                permanently = dialog.PermanentlyDelete;
            }

            Stopwatch sw = new Stopwatch();

            sw.Start();

            IStorageHistory history = await filesystemOperations.DeleteAsync(source, banner.Progress, banner.ErrorCode, permanently, cancellationToken);

            if (!permanently && registerHistory)
            {
                App.HistoryWrapper.AddHistory(history);
            }

            banner.Remove();
            sw.Stop();

            PostBannerHelpers.PostBanner_Delete(returnStatus, permanently ? FileOperationType.Delete : FileOperationType.Recycle, sw, associatedInstance);

            return(returnStatus);
        }
Example #7
0
        public async Task <IStorageHistory> RestoreFromTrashAsync(PathWithType source,
                                                                  string destination,
                                                                  IProgress <float> progress,
                                                                  IProgress <FilesystemErrorCode> errorCode,
                                                                  CancellationToken cancellationToken)
        {
            FilesystemResult fsResult = FilesystemErrorCode.ERROR_INPROGRESS;

            errorCode?.Report(fsResult);

            if (source.ItemType == FilesystemItemType.Directory)
            {
                FilesystemResult <StorageFolder> sourceFolder = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(source.Path);

                FilesystemResult <StorageFolder> destinationFolder = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(Path.GetDirectoryName(destination));

                fsResult = sourceFolder.ErrorCode | destinationFolder.ErrorCode;
                errorCode?.Report(fsResult);

                if (sourceFolder && destinationFolder)
                {
                    fsResult = await FilesystemTasks.Wrap(() =>
                    {
                        return(FilesystemHelpers.MoveDirectoryAsync(sourceFolder.Result,
                                                                    destinationFolder.Result,
                                                                    Path.GetFileName(destination),
                                                                    CreationCollisionOption.FailIfExists));
                    }).OnSuccess(t => sourceFolder.Result.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask()); // TODO: we could use here FilesystemHelpers with registerHistory false?
                }
                errorCode?.Report(fsResult);
            }
            else
            {
                FilesystemResult <StorageFile> sourceFile = await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(source.Path);

                FilesystemResult <StorageFolder> destinationFolder = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(Path.GetDirectoryName(destination));

                fsResult = sourceFile.ErrorCode | destinationFolder.ErrorCode;
                errorCode?.Report(fsResult);

                if (sourceFile && destinationFolder)
                {
                    fsResult = await FilesystemTasks.Wrap(() =>
                    {
                        return(sourceFile.Result.MoveAsync(destinationFolder.Result,
                                                           Path.GetFileName(destination),
                                                           NameCollisionOption.GenerateUniqueName).AsTask());
                    });
                }
                errorCode?.Report(fsResult);
            }

            // Recycle bin also stores a file starting with $I for each item
            string iFilePath = Path.Combine(Path.GetDirectoryName(source.Path), Path.GetFileName(source.Path).Replace("$R", "$I"));
            await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(iFilePath)
            .OnSuccess(iFile => iFile.DeleteAsync().AsTask());

            errorCode?.Report(fsResult);
            if (fsResult != FilesystemErrorCode.ERROR_SUCCESS)
            {
                if (((FilesystemErrorCode)fsResult).HasFlag(FilesystemErrorCode.ERROR_UNAUTHORIZED))
                {
                    await DialogDisplayHelper.ShowDialogAsync("AccessDeniedDeleteDialog/Title".GetLocalized(), "AccessDeniedDeleteDialog/Text".GetLocalized());
                }
                else if (((FilesystemErrorCode)fsResult).HasFlag(FilesystemErrorCode.ERROR_UNAUTHORIZED))
                {
                    await DialogDisplayHelper.ShowDialogAsync("FileNotFoundDialog/Title".GetLocalized(), "FileNotFoundDialog/Text".GetLocalized());
                }
                else if (((FilesystemErrorCode)fsResult).HasFlag(FilesystemErrorCode.ERROR_ALREADYEXIST))
                {
                    await DialogDisplayHelper.ShowDialogAsync("ItemAlreadyExistsDialogTitle".GetLocalized(), "ItemAlreadyExistsDialogContent".GetLocalized());
                }
            }

            return(new StorageHistory(FileOperationType.Restore, source, new PathWithType(destination, source.ItemType)));
        }
Example #8
0
        public async Task <IStorageHistory> DeleteAsync(PathWithType source,
                                                        IProgress <float> progress,
                                                        IProgress <FilesystemErrorCode> errorCode,
                                                        bool permanently,
                                                        CancellationToken cancellationToken)
        {
            bool deleteFromRecycleBin = await recycleBinHelpers.IsRecycleBinItem(source.Path);

            FilesystemResult fsResult = FilesystemErrorCode.ERROR_INPROGRESS;

            errorCode?.Report(fsResult);
            progress?.Report(0.0f);

            if (source.ItemType == FilesystemItemType.File)
            {
                fsResult = await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(source.Path)
                           .OnSuccess((t) => t.DeleteAsync(permanently ? StorageDeleteOption.PermanentDelete : StorageDeleteOption.Default).AsTask());
            }
            else if (source.ItemType == FilesystemItemType.Directory)
            {
                fsResult = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(source.Path)
                           .OnSuccess((t) => t.DeleteAsync(permanently ? StorageDeleteOption.PermanentDelete : StorageDeleteOption.Default).AsTask());
            }

            errorCode?.Report(fsResult);

            if (fsResult == FilesystemErrorCode.ERROR_UNAUTHORIZED)
            {
                // Try again with fulltrust process
                if (associatedInstance.FilesystemViewModel.Connection != null)
                {
                    AppServiceResponse response = await associatedInstance.FilesystemViewModel.Connection.SendMessageAsync(new ValueSet()
                    {
                        { "Arguments", "FileOperation" },
                        { "fileop", "DeleteItem" },
                        { "filepath", source.Path },
                        { "permanently", permanently }
                    });

                    fsResult = (FilesystemResult)(response.Status == AppServiceResponseStatus.Success);
                }
            }
            else if (fsResult == FilesystemErrorCode.ERROR_INUSE)
            {
                // TODO: retry or show dialog
                await DialogDisplayHelper.ShowDialogAsync("FileInUseDeleteDialog/Title".GetLocalized(), "FileInUseDeleteDialog/Text".GetLocalized());
            }

            if (deleteFromRecycleBin)
            {
                // Recycle bin also stores a file starting with $I for each item
                string iFilePath = Path.Combine(Path.GetDirectoryName(source.Path), Path.GetFileName(source.Path).Replace("$R", "$I"));
                await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(iFilePath)
                .OnSuccess(t => t.DeleteAsync(StorageDeleteOption.PermanentDelete).AsTask());
            }
            errorCode?.Report(fsResult);
            progress?.Report(100.0f);

            if (fsResult)
            {
                await associatedInstance.FilesystemViewModel.RemoveFileOrFolderAsync(source.Path);

                if (!permanently)
                {
                    // Enumerate Recycle Bin
                    List <ShellFileItem> items = await recycleBinHelpers.EnumerateRecycleBin();

                    List <ShellFileItem> nameMatchItems;

                    // Get name matching files
                    if (Path.GetExtension(source.Path) == ".lnk" || Path.GetExtension(source.Path) == ".url") // We need to check if it is a shortcut file
                    {
                        nameMatchItems = items.Where((item) => item.FilePath == Path.Combine(Path.GetDirectoryName(source.Path), Path.GetFileNameWithoutExtension(source.Path))).ToList();
                    }
                    else
                    {
                        nameMatchItems = items.Where((item) => item.FilePath == source.Path).ToList();
                    }

                    // Get newest file
                    ShellFileItem item = nameMatchItems.Where((item) => item.RecycleDate != null).OrderBy((item) => item.RecycleDate).FirstOrDefault();

                    return(new StorageHistory(FileOperationType.Recycle, source, new PathWithType(item.RecyclePath, source.ItemType)));
                }

                return(new StorageHistory(FileOperationType.Delete, source, null));
            }
            else
            {
                // Stop at first error
                return(null);
            }
        }
Example #9
0
        public async Task <IStorageHistory> CopyAsync(PathWithType source,
                                                      string destination,
                                                      IProgress <float> progress,
                                                      IProgress <FilesystemErrorCode> errorCode,
                                                      CancellationToken cancellationToken)
        {
            if (associatedInstance.FilesystemViewModel.WorkingDirectory.StartsWith(App.AppSettings.RecycleBinPath))
            {
                errorCode?.Report(FilesystemErrorCode.ERROR_UNAUTHORIZED);
                progress?.Report(100.0f);

                // Do not paste files and folders inside the recycle bin
                await DialogDisplayHelper.ShowDialogAsync(
                    "ErrorDialogThisActionCannotBeDone".GetLocalized(),
                    "ErrorDialogUnsupportedOperation".GetLocalized());

                return(null);
            }

            IStorageItem copiedItem = null;
            long         itemSize   = await FilesystemHelpers.GetItemSize(await source.Path.ToStorageItem());

            bool reportProgress = false; // TODO: The default value is false

            if (source.ItemType == FilesystemItemType.Directory)
            {
                if (string.IsNullOrWhiteSpace(source.Path) ||
                    Path.GetDirectoryName(destination).IsSubPathOf(source.Path)) // We check if user tried to copy anything above the source.ItemPath
                {
                    ImpossibleActionResponseTypes responseType = ImpossibleActionResponseTypes.Abort;

                    /*if (ShowDialog)
                     * {
                     *  /// Currently following implementation throws exception until it is resolved keep it disabled
                     *  Binding themeBind = new Binding();
                     *  themeBind.Source = ThemeHelper.RootTheme;
                     *  ContentDialog dialog = new ContentDialog()
                     *  {
                     *      Title = ResourceController.GetTranslation("ErrorDialogThisActionCannotBeDone"),
                     *      Content = ResourceController.GetTranslation("ErrorDialogTheDestinationFolder") + " (" + destinationPath.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries).Last() + ") " + ResourceController.GetTranslation("ErrorDialogIsASubfolder") + " (" + item.Name + ")",
                     *      PrimaryButtonText = ResourceController.GetTranslation("ErrorDialogSkip"),
                     *      CloseButtonText = ResourceController.GetTranslation("ErrorDialogCancel"),
                     *      PrimaryButtonCommand = new RelayCommand(() => { responseType = ImpossibleActionResponseTypes.Skip; }),
                     *      CloseButtonCommand = new RelayCommand(() => { responseType = ImpossibleActionResponseTypes.Abort; }),
                     *  };
                     *  BindingOperations.SetBinding(dialog, FrameworkElement.RequestedThemeProperty, themeBind);
                     *  await dialog.ShowAsync();
                     * }*/
                    if (responseType == ImpossibleActionResponseTypes.Skip)
                    {
                        progress?.Report(100.0f);
                        errorCode?.Report(FilesystemErrorCode.ERROR_SUCCESS | FilesystemErrorCode.ERROR_INPROGRESS);
                    }
                    else if (responseType == ImpossibleActionResponseTypes.Abort)
                    {
                        progress?.Report(100.0f);
                        errorCode?.Report(FilesystemErrorCode.ERROR_INPROGRESS | FilesystemErrorCode.ERROR_GENERIC);
                    }

                    return(null);
                }
                else
                {
                    if (reportProgress)
                    {
                        progress?.Report((float)(itemSize * 100.0f / itemSize));
                    }

                    FilesystemResult <StorageFolder> fsSourceFolderResult = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(Path.GetDirectoryName(source.Path));

                    FilesystemResult <StorageFolder> fsDestinationFolderResult = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(Path.GetDirectoryName(destination));

                    if (fsSourceFolderResult && fsDestinationFolderResult)
                    {
                        FilesystemResult fsCopyResult = await FilesystemTasks.Wrap(async() =>
                        {
                            return(await FilesystemHelpers.CloneDirectoryAsync(fsSourceFolderResult.Result, fsDestinationFolderResult.Result, Path.GetFileName(source.Path)));
                        })
                                                        .OnSuccess(t =>
                        {
                            if (associatedInstance.FilesystemViewModel.CheckFolderForHiddenAttribute(source.Path))
                            {
                                // The source folder was hidden, apply hidden attribute to destination
                                NativeFileOperationsHelper.SetFileAttribute(t.Path, FileAttributes.Hidden);
                            }
                            copiedItem = t;
                        });
                    }
                }
            }
            else if (source.ItemType == FilesystemItemType.File)
            {
                if (reportProgress)
                {
                    progress?.Report((float)(itemSize * 100.0f / itemSize));
                }

                FilesystemResult <StorageFolder> fsResult = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(Path.GetDirectoryName(destination));

                if (fsResult)
                {
                    StorageFile file = (StorageFile)await source.Path.ToStorageItem();

                    FilesystemResult <StorageFile> fsResultCopy = new FilesystemResult <StorageFile>(null, FilesystemErrorCode.ERROR_GENERIC);

                    if (file != null)
                    {
                        fsResultCopy = await FilesystemTasks.Wrap(() =>
                        {
                            return(file.CopyAsync(fsResult.Result, Path.GetFileName(source.Path), NameCollisionOption.GenerateUniqueName).AsTask());
                        });
                    }

                    if (fsResultCopy)
                    {
                        copiedItem = fsResultCopy.Result;
                    }
                    else if (fsResultCopy.ErrorCode == FilesystemErrorCode.ERROR_UNAUTHORIZED || fsResultCopy.ErrorCode == FilesystemErrorCode.ERROR_GENERIC)
                    {
                        // Try again with CopyFileFromApp
                        if (NativeFileOperationsHelper.CopyFileFromApp(source.Path, destination, true))
                        {
                            copiedItem = await source.Path.ToStorageItem(); // Dangerous - the provided item may be different than output result!
                        }
                        else
                        {
                            Debug.WriteLine(System.Runtime.InteropServices.Marshal.GetLastWin32Error());
                        }
                    }
                    else
                    {
                        errorCode?.Report(fsResultCopy.ErrorCode);
                    }
                }
            }

            if (Path.GetDirectoryName(destination) == associatedInstance.FilesystemViewModel.WorkingDirectory)
            {
                if (copiedItem != null)
                {
                    List <ListedItem> copiedListedItems = associatedInstance.FilesystemViewModel.FilesAndFolders
                                                          .Where(listedItem => copiedItem.Path.Contains(listedItem.ItemPath)).ToList();

                    if (copiedListedItems.Count > 0)
                    {
                        associatedInstance.ContentPage.AddSelectedItemsOnUi(copiedListedItems);
                        associatedInstance.ContentPage.FocusSelectedItems();
                    }
                }
            }

            progress?.Report(100.0f);

            var pathWithType = new PathWithType(
                copiedItem != null ? (!string.IsNullOrWhiteSpace(copiedItem.Path) ? copiedItem.Path : destination) : destination,
                source.ItemType);

            return(new StorageHistory(FileOperationType.Copy, source, pathWithType));
        }