diff --git a/RudeFox.FrontEnd/Models/FileSystemType.cs b/RudeFox.FrontEnd/Models/FileSystemType.cs
new file mode 100644
index 0000000..4741426
--- /dev/null
+++ b/RudeFox.FrontEnd/Models/FileSystemType.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace RudeFox.Models
+{
+ public enum FileSystemType
+ {
+ ///
+ /// New Technology File System.
+ ///
+ NTFS,
+ ///
+ /// File Allocation Table.
+ ///
+ FAT32,
+ ///
+ /// Unknown File System.
+ ///
+ Unknown,
+ ///
+ /// Used with ExpanDrive.
+ ///
+ EXFS
+ }
+}
diff --git a/RudeFox.FrontEnd/RudeFox.FrontEnd.csproj b/RudeFox.FrontEnd/RudeFox.FrontEnd.csproj
index 31fc425..c4e0c1a 100644
--- a/RudeFox.FrontEnd/RudeFox.FrontEnd.csproj
+++ b/RudeFox.FrontEnd/RudeFox.FrontEnd.csproj
@@ -68,6 +68,7 @@
Code
+
diff --git a/RudeFox.FrontEnd/Services/ShredderService.cs b/RudeFox.FrontEnd/Services/ShredderService.cs
index e244c86..600efd5 100644
--- a/RudeFox.FrontEnd/Services/ShredderService.cs
+++ b/RudeFox.FrontEnd/Services/ShredderService.cs
@@ -1,4 +1,5 @@
using RudeFox.Helpers;
+using RudeFox.Models;
using System;
using System.Collections.Generic;
using System.IO;
@@ -19,7 +20,8 @@ private ShredderService()
#endregion
#region Fields
- private const int MAX_BUFFER_SIZE = 1 * Constants.MEGABYTE;
+ private const int MAX_BUFFER_SIZE = Constants.MEGABYTE;
+ private const int OBFUSCATE_ROUNDS = 5;
Random _random = new Random();
#endregion
@@ -95,8 +97,7 @@ public async Task ShredFileAsync(FileInfo file, CancellationToken cancella
};
if (!file.Exists) return false;
-
- if (cancellationToken != null) cancellationToken.ThrowIfCancellationRequested();
+ file.IsReadOnly = false;
var result = await OverWriteFileAsync(file, cancellationToken, writeProgress).ConfigureAwait(false);
if (!result) return result;
@@ -110,6 +111,8 @@ await Task.Run(() =>
file.Delete();
}).ConfigureAwait(false);
+ await DestroyEntityMetaData(file);
+
if (progress != null) progress.Report(1.0);
return true;
@@ -160,15 +163,41 @@ public async Task ShredFolderAsync(DirectoryInfo folder, CancellationToken
if (percent == 1.0)
bytesComplete += length;
};
+
var result = await ShredFolderAsync(dir, cancellationToken, itemProgress).ConfigureAwait(false);
if (!result) return result;
}
}
+ // BUG: Don't know why this causes issues.
+ // await DestroyEntityMetaData(folder);
folder.Delete();
+
return true;
}
+ public bool IsFileLocked(FileInfo file)
+ {
+ FileStream stream = null;
+
+ try
+ {
+ stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
+ }
+ catch (IOException)
+ {
+ return true;
+ }
+ finally
+ {
+ if (stream != null) stream.Close();
+ }
+
+ return false;
+ }
+ #endregion
+
+ #region Private Methods
private async Task OverWriteFileAsync(FileInfo file, CancellationToken cancellationToken, IProgress progress)
{
if (!file.Exists) return false;
@@ -208,25 +237,44 @@ await Task.Run(() =>
return true;
}
-
- public bool IsFileLocked(FileInfo file)
+ private async Task DestroyEntityMetaData(FileSystemInfo entity, FileSystemType fileSystemType = FileSystemType.Unknown)
{
- FileStream stream = null;
+ if (!entity.Exists)
+ return false;
try
{
- stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
+ // prevent the indexing service from locking the file
+ entity.Attributes = FileAttributes.NotContentIndexed;
}
- catch (IOException)
+ catch (ArgumentException e)
{
- return true;
+ throw new UnauthorizedAccessException(e.Message, e);
}
- finally
+
+ await Task.Run(() =>
{
- if (stream != null) stream.Close();
- }
+ // rename the file a few times to remove it from the file system table.
+ for (var round = 0; round < OBFUSCATE_ROUNDS; round++)
+ {
+ var newPath = Path.Combine(Path.GetDirectoryName(entity.FullName), Path.GetRandomFileName());
- return false;
+ var file = entity as FileInfo;
+ var folder = entity as DirectoryInfo;
+
+ if (file != null)
+ file.MoveTo(newPath);
+ else
+ folder.MoveTo(newPath);
+ }
+
+ var newTime = new DateTime(1981, 1, 1, 0, 0, 1);
+ entity.LastAccessTime = newTime;
+ entity.LastWriteTime = newTime;
+ entity.CreationTime = newTime;
+ });
+
+ return true;
}
#endregion
}
diff --git a/RudeFox.FrontEnd/ViewModels/MainWindowVM.cs b/RudeFox.FrontEnd/ViewModels/MainWindowVM.cs
index 7dde8ef..da57bc6 100644
--- a/RudeFox.FrontEnd/ViewModels/MainWindowVM.cs
+++ b/RudeFox.FrontEnd/ViewModels/MainWindowVM.cs
@@ -47,7 +47,6 @@ public ObservableCollection WorkItems
#endregion
#region Drag and drop
-
void IDropTarget.DragOver(IDropInfo dropInfo)
{
var data = dropInfo.Data as IDataObject;
@@ -90,6 +89,7 @@ private async void DeleteItems(List paths)
join p in paths
on i.Path equals p
select p;
+
paths.RemoveAll(p => duplicates.Contains(p));
foreach (var path in paths)
@@ -126,8 +126,9 @@ on i.Path equals p
var tasks = newItems.Select(item =>
{
- return ShredderService.Instance.ShredItemAsync(item.Path, item.CancellationTokenSource.Token, item.TaskProgress);
- });
+ item.Task = ShredderService.Instance.ShredItemAsync(item.Path, item.CancellationTokenSource.Token, item.TaskProgress);
+ return item.Task;
+ }).ToList();
try
{
@@ -139,18 +140,40 @@ on i.Path equals p
}
catch (AggregateException exc)
{
- var msg = $"{exc.InnerExceptions.Count()} error(s) occured: ";
- foreach(var ex in exc.InnerExceptions)
+ var failedTasks = tasks.Where(t => t.IsFaulted);
+ tasks.RemoveAll(t => failedTasks.Contains(t));
+
+ var failedItems = WorkItems.Where(item => item.Task.IsFaulted || item.Task.IsCanceled);
+
+ for (int i = 0; i < WorkItems.Count; i++)
{
- msg += "\n---------------------------";
- msg += Environment.NewLine;
- msg += ex.ToString();
+ if (failedItems.Contains(WorkItems[i]))
+ {
+ WorkItems.RemoveAt(i);
+ i--;
+ }
}
- MessageBox.Show(msg);
+
+ var exception = exc.Flatten();
+ MessageBox.Show(exception.ToString());
+
}
catch( Exception exc)
{
- var failed = tasks.Where(t => t.IsFaulted);
+ var failedTasks = tasks.Where(t => t.IsFaulted);
+ tasks.RemoveAll(t => failedTasks.Contains(t));
+
+ var failedItems = WorkItems.Where(item => item.Task.IsFaulted || item.Task.IsCanceled);
+
+ for (int i = 0; i < WorkItems.Count; i++)
+ {
+ if (failedItems.Contains(WorkItems[i]))
+ {
+ WorkItems.RemoveAt(i);
+ i--;
+ }
+ }
+
MessageBox.Show(exc.ToString());
}
}
diff --git a/RudeFox.FrontEnd/ViewModels/WorkItemVM.cs b/RudeFox.FrontEnd/ViewModels/WorkItemVM.cs
index ebf6508..1822bac 100644
--- a/RudeFox.FrontEnd/ViewModels/WorkItemVM.cs
+++ b/RudeFox.FrontEnd/ViewModels/WorkItemVM.cs
@@ -63,13 +63,13 @@ public double Progress
}
}
- private long _length = -1;
+ private long _bytes = -1;
public long Bytes
{
- get { return _length; }
+ get { return _bytes; }
set
{
- if (SetProperty(ref _length, value))
+ if (SetProperty(ref _bytes, value))
RaisePropertyChanged(nameof(Size));
}
}
@@ -116,6 +116,13 @@ public string Size
}
}
+ private Task _task;
+ public Task Task
+ {
+ get { return _task; }
+ set { SetProperty(ref _task, value); }
+ }
+
public CancellationTokenSource CancellationTokenSource { get; set; }
public Progress TaskProgress { get; set; }
@@ -134,8 +141,10 @@ private async void CalculateBytes()
{
if (File.Exists(Path))
Bytes = new FileInfo(Path).Length;
- else
+ else if (Directory.Exists(Path))
Bytes = await ShredderService.Instance.GetFolderSize(new DirectoryInfo(Path));
+ else
+ Bytes = -1;
}
private void OnDeleteRequested(bool canceled = false)
{