diff --git a/mdfinder.hashprovider/IHashProvider.cs b/mdfinder.hashprovider/IHashProvider.cs
new file mode 100644
index 0000000..72dfde4
--- /dev/null
+++ b/mdfinder.hashprovider/IHashProvider.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace mdfinder.hashprovider
+{
+ public interface IHashProvider
+ {
+ /// Gets the name of the hash provider.
+ /// The name of the hash provider.
+ string Name { get; }
+
+ /// Gets the description of the hash provider.
+ /// The description.
+ string Description { get; }
+
+ /// Gets a value indicating if this hash provider is valid to use.
+ /// The value indicating if the hash provider is valid.
+ /// This value can be used by hash providers to limit use of the provider. This can be used to create paid hash providers.
+ bool IsValid { get; }
+
+ /// Gets or sets the priority this provider has when multiple providers support the same extension.
+ /// The priority of the hash provider.
+ int Priority { get; set; }
+
+ /// Gets the file extensions that this hash provider can work with.
+ /// The file extensions the hash provider works with.
+ IEnumerable FileExtensions { get; }
+
+ /// Gets a hash from a file.
+ /// The file to hash.
+ /// The hash.
+ string GetHash(FileInfo file);
+ }
+}
diff --git a/mdfinder.hashprovider/Properties/AssemblyInfo.cs b/mdfinder.hashprovider/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ffe8708
--- /dev/null
+++ b/mdfinder.hashprovider/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("mdfinder.hashprovider")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("mdfinder.hashprovider")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f383e2d1-f62e-44cf-9e58-63542dcbd06e")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/mdfinder.hashprovider/mdfinder.hashprovider.csproj b/mdfinder.hashprovider/mdfinder.hashprovider.csproj
new file mode 100644
index 0000000..200e96f
--- /dev/null
+++ b/mdfinder.hashprovider/mdfinder.hashprovider.csproj
@@ -0,0 +1,48 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {F383E2D1-F62E-44CF-9E58-63542DCBD06E}
+ Library
+ Properties
+ mdfinder.hashprovider
+ mdfinder.hashprovider
+ v4.6.1
+ 512
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mdfinder.sln b/mdfinder.sln
index 4096ad4..7416fc6 100644
--- a/mdfinder.sln
+++ b/mdfinder.sln
@@ -5,6 +5,8 @@ VisualStudioVersion = 15.0.28307.168
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mdfinder", "mdfinder\mdfinder.csproj", "{E0F831FA-FCE1-471E-8767-D3FD7EDC7CCF}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mdfinder.hashprovider", "mdfinder.hashprovider\mdfinder.hashprovider.csproj", "{F383E2D1-F62E-44CF-9E58-63542DCBD06E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +17,10 @@ Global
{E0F831FA-FCE1-471E-8767-D3FD7EDC7CCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E0F831FA-FCE1-471E-8767-D3FD7EDC7CCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E0F831FA-FCE1-471E-8767-D3FD7EDC7CCF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F383E2D1-F62E-44CF-9E58-63542DCBD06E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F383E2D1-F62E-44CF-9E58-63542DCBD06E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F383E2D1-F62E-44CF-9E58-63542DCBD06E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F383E2D1-F62E-44CF-9E58-63542DCBD06E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/mdfinder/AboutWindow.xaml b/mdfinder/AboutWindow.xaml
new file mode 100644
index 0000000..9ae1466
--- /dev/null
+++ b/mdfinder/AboutWindow.xaml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Jordan Wages
+
+
+
+
+
+ Octokit
+ |
+ |
+
+
+ LiteDB
+ |
+ |
+
+
+
+
+
+
+
+
+
diff --git a/mdfinder/AboutWindow.xaml.cs b/mdfinder/AboutWindow.xaml.cs
new file mode 100644
index 0000000..7432ebe
--- /dev/null
+++ b/mdfinder/AboutWindow.xaml.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace mdfinder
+{
+ ///
+ /// Interaction logic for AboutWindow.xaml
+ ///
+ public partial class AboutWindow : Window
+ {
+ /// Default constructor.
+ public AboutWindow()
+ {
+ InitializeComponent();
+
+ this.txtVersion.Text = Assembly.GetExecutingAssembly().GetName().Version.ToString();
+ }
+
+ /// Event handler. Called by Hyperlink for request navigate events.
+ /// Source of the event.
+ /// Request navigate event information.
+ private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
+ {
+ Process.Start(e.Uri.AbsoluteUri);
+ e.Handled = true;
+ }
+
+ /// Event handler. Called by btnOK for click events.
+ /// Source of the event.
+ /// Routed event information.
+ private void btnOK_Click(object sender, RoutedEventArgs e)
+ {
+ this.Close();
+ }
+ }
+}
diff --git a/mdfinder/App.config b/mdfinder/App.config
index adba596..86c251c 100644
--- a/mdfinder/App.config
+++ b/mdfinder/App.config
@@ -27,6 +27,15 @@
25
+
+ True
+
+
+
+
+
+ en-US
+
\ No newline at end of file
diff --git a/mdfinder/DBHelper.cs b/mdfinder/DBHelper.cs
index e6b030a..f25c5a0 100644
--- a/mdfinder/DBHelper.cs
+++ b/mdfinder/DBHelper.cs
@@ -25,9 +25,9 @@ namespace mdfinder
/// The database.
private LiteDatabase Database { get; set; }
- /// Gets the file records.
- /// The file records.
- public LiteCollection FileRecords
+ /// Gets a collection of file records.
+ /// A collection of file records.
+ private LiteCollection FileRecordCollection
{
get
{
@@ -35,15 +35,6 @@ namespace mdfinder
}
}
- public IEnumerable ASDF
- {
- get
- {
- return this.FileRecords.FindAll();
- }
- }
-
-
#endregion
#region Constructors
@@ -72,8 +63,33 @@ namespace mdfinder
/// The hash provider.
public void InsertFileRecord(string path, long size, string hash, string hashProvider)
{
- this.FileRecords.Insert(new FileRecord() { Path = path, Size = size, Hash = hash, HashProvider = hashProvider });
- OnPropertyChanged("ASDF");
+ var fileRecord = new FileRecord() { Path = new Uri(path), Size = size, Hash = hash, HashProvider = hashProvider };
+ this.FileRecordCollection.Insert(fileRecord);
+ }
+
+ /// Gets the file records in this collection.
+ ///
+ /// An enumerator that allows foreach to be used to process the file records in this collection.
+ ///
+ public IEnumerable GetFileRecords()
+ {
+ return this.FileRecordCollection.FindAll();
+ }
+
+ /// Gets the file records in this collection.
+ /// The predicate.
+ ///
+ /// An enumerator that allows foreach to be used to process the file records in this collection.
+ ///
+ public IEnumerable GetFileRecords(Func predicate)
+ {
+ return this.FileRecordCollection.Find(fr => predicate(fr));
+ }
+
+ /// Clears the database to its blank/initial state.
+ public void Clear()
+ {
+ this.FileRecordCollection.Delete(Query.All());
}
#endregion
diff --git a/mdfinder/Extensions.cs b/mdfinder/Extensions.cs
index 89c0ce0..c36b0d6 100644
--- a/mdfinder/Extensions.cs
+++ b/mdfinder/Extensions.cs
@@ -27,5 +27,20 @@ namespace mdfinder
.GroupBy(a => a.i / binSize)
.Select(grp => grp.Select(a => a.x));
}
+
+ /// An IEnumerable extension method that returns the first item or a given default value if no items are in the collection.
+ /// Generic type parameter.
+ /// The items to act on.
+ /// The default.
+ /// A T.
+ public static T FirstOr(this IEnumerable items, T @default)
+ {
+ foreach(var t in items)
+ {
+ return t;
+ }
+
+ return @default;
+ }
}
}
diff --git a/mdfinder/FileRecord.cs b/mdfinder/FileRecord.cs
index 1bcb946..dcd14e8 100644
--- a/mdfinder/FileRecord.cs
+++ b/mdfinder/FileRecord.cs
@@ -16,7 +16,7 @@ namespace mdfinder
/// Gets or sets the full pathname of the file.
/// The full pathname of the file.
- public string Path { get; set; }
+ public Uri Path { get; set; }
/// Gets or sets the size.
/// The size.
diff --git a/mdfinder/Icon/icon.ico b/mdfinder/Icon/icon.ico
new file mode 100644
index 0000000..e353060
Binary files /dev/null and b/mdfinder/Icon/icon.ico differ
diff --git a/mdfinder/Icon/icon.png b/mdfinder/Icon/icon.png
new file mode 100644
index 0000000..31c8543
Binary files /dev/null and b/mdfinder/Icon/icon.png differ
diff --git a/mdfinder/Icon/icon.svg b/mdfinder/Icon/icon.svg
new file mode 100644
index 0000000..92a7db7
--- /dev/null
+++ b/mdfinder/Icon/icon.svg
@@ -0,0 +1,152 @@
+
+
+
+
diff --git a/mdfinder/Icons.xaml b/mdfinder/Icons.xaml
index d55ffda..184dd6d 100644
--- a/mdfinder/Icons.xaml
+++ b/mdfinder/Icons.xaml
@@ -1,13 +1,53 @@
-
+
-
-
-
-
-
+
@@ -85,4 +125,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mdfinder/Localization/Localization.Designer.cs b/mdfinder/Localization/Localization.Designer.cs
index 614a0ea..def609d 100644
--- a/mdfinder/Localization/Localization.Designer.cs
+++ b/mdfinder/Localization/Localization.Designer.cs
@@ -60,6 +60,51 @@ namespace mdfinder.Localization {
}
}
+ ///
+ /// Looks up a localized string similar to About mdfinder....
+ ///
+ public static string AboutMenu {
+ get {
+ return ResourceManager.GetString("AboutMenu", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to mdfinder is a file scanning and hashing application..
+ ///
+ public static string AboutWindowDescription {
+ get {
+ return ResourceManager.GetString("AboutWindowDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to github.
+ ///
+ public static string AboutWindowGithubLinkLabel {
+ get {
+ return ResourceManager.GetString("AboutWindowGithubLinkLabel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to license.
+ ///
+ public static string AboutWindowLicenseLinkLabel {
+ get {
+ return ResourceManager.GetString("AboutWindowLicenseLinkLabel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to About mdfinder.
+ ///
+ public static string AboutWindowTitle {
+ get {
+ return ResourceManager.GetString("AboutWindowTitle", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Actions.
///
@@ -105,6 +150,51 @@ namespace mdfinder.Localization {
}
}
+ ///
+ /// Looks up a localized string similar to Clear.
+ ///
+ public static string ClearLabel {
+ get {
+ return ResourceManager.GetString("ClearLabel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Hash.
+ ///
+ public static string ColumnHeadingHash {
+ get {
+ return ResourceManager.GetString("ColumnHeadingHash", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Hash Provider.
+ ///
+ public static string ColumnHeadingHashProvider {
+ get {
+ return ResourceManager.GetString("ColumnHeadingHashProvider", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Path.
+ ///
+ public static string ColumnHeadingPath {
+ get {
+ return ResourceManager.GetString("ColumnHeadingPath", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Size.
+ ///
+ public static string ColumnHeadingSize {
+ get {
+ return ResourceManager.GetString("ColumnHeadingSize", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to The current version is up to date with the github repository..
///
@@ -123,6 +213,33 @@ namespace mdfinder.Localization {
}
}
+ ///
+ /// Looks up a localized string similar to md5 hash provider. This provider creates a simple md5 hash given a file..
+ ///
+ public static string DefaultHashProviderDescription {
+ get {
+ return ResourceManager.GetString("DefaultHashProviderDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Default Provider.
+ ///
+ public static string DefaultHashProviderName {
+ get {
+ return ResourceManager.GetString("DefaultHashProviderName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Developers and Contributors.
+ ///
+ public static string DevelopersLabel {
+ get {
+ return ResourceManager.GetString("DevelopersLabel", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Edit.
///
@@ -132,6 +249,15 @@ namespace mdfinder.Localization {
}
}
+ ///
+ /// Looks up a localized string similar to File Processing Threshold.
+ ///
+ public static string FileAlertThresholdLabel {
+ get {
+ return ResourceManager.GetString("FileAlertThresholdLabel", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to File.
///
@@ -141,6 +267,33 @@ namespace mdfinder.Localization {
}
}
+ ///
+ /// Looks up a localized string similar to Filters.
+ ///
+ public static string FilterBarLabel {
+ get {
+ return ResourceManager.GetString("FilterBarLabel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Duplicates.
+ ///
+ public static string FilterDuplicatesLabel {
+ get {
+ return ResourceManager.GetString("FilterDuplicatesLabel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Show All.
+ ///
+ public static string FilterShowAllLabel {
+ get {
+ return ResourceManager.GetString("FilterShowAllLabel", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Help.
///
@@ -150,6 +303,42 @@ namespace mdfinder.Localization {
}
}
+ ///
+ /// Looks up a localized string similar to Files.
+ ///
+ public static string ItemsLabel {
+ get {
+ return ResourceManager.GetString("ItemsLabel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Language.
+ ///
+ public static string LanguageLabel {
+ get {
+ return ResourceManager.GetString("LanguageLabel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to The default MD5 hash provider should not have its priorty set..
+ ///
+ public static string MD5ProviderSetPriorityException {
+ get {
+ return ResourceManager.GetString("MD5ProviderSetPriorityException", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to OK.
+ ///
+ public static string OKLabel {
+ get {
+ return ResourceManager.GetString("OKLabel", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Open File Database....
///
@@ -159,6 +348,60 @@ namespace mdfinder.Localization {
}
}
+ ///
+ /// Looks up a localized string similar to Open Source Libraries.
+ ///
+ public static string OpenSourceCreditsLabel {
+ get {
+ return ResourceManager.GetString("OpenSourceCreditsLabel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Options....
+ ///
+ public static string OptionsMenu {
+ get {
+ return ResourceManager.GetString("OptionsMenu", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Note: Changing the user language will require a restart of the program..
+ ///
+ public static string OptionsWindowLanguageChangeNotice {
+ get {
+ return ResourceManager.GetString("OptionsWindowLanguageChangeNotice", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Options.
+ ///
+ public static string OptionsWindowTitle {
+ get {
+ return ResourceManager.GetString("OptionsWindowTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Provider Location.
+ ///
+ public static string ProviderFolderLabel {
+ get {
+ return ResourceManager.GetString("ProviderFolderLabel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Save.
+ ///
+ public static string SaveLabel {
+ get {
+ return ResourceManager.GetString("SaveLabel", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Save File Database....
///
@@ -195,6 +438,15 @@ namespace mdfinder.Localization {
}
}
+ ///
+ /// Looks up a localized string similar to Skip Empty Files.
+ ///
+ public static string SkipEmptyFilesLabel {
+ get {
+ return ResourceManager.GetString("SkipEmptyFilesLabel", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to mdfinder.
///
@@ -212,5 +464,14 @@ namespace mdfinder.Localization {
return ResourceManager.GetString("UnknownVersionStatusDescription", resourceCulture);
}
}
+
+ ///
+ /// Looks up a localized string similar to Version.
+ ///
+ public static string VersionLabel {
+ get {
+ return ResourceManager.GetString("VersionLabel", resourceCulture);
+ }
+ }
}
}
diff --git a/mdfinder/Localization/Localization.resx b/mdfinder/Localization/Localization.resx
index 573dcde..89b00bc 100644
--- a/mdfinder/Localization/Localization.resx
+++ b/mdfinder/Localization/Localization.resx
@@ -117,6 +117,21 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ About mdfinder...
+
+
+ mdfinder is a file scanning and hashing application.
+
+
+ github
+
+
+ license
+
+
+ About mdfinder
+
Actions
@@ -132,24 +147,90 @@
Cannot convert type to {0} from or to a boolean.
+
+ Clear
+
+
+ Hash
+
+
+ Hash Provider
+
+
+ Path
+
+
+ Size
+
The current version is up to date with the github repository.
The current version is ahead of the github repository, or is a custom version of butterflow-ui that cannot be compared to the github repository.
+
+ md5 hash provider. This provider creates a simple md5 hash given a file.
+
+
+ Default Provider
+
+
+ Developers and Contributors
+
Edit
+
+ File Processing Threshold
+
File
+
+ Filters
+
+
+ Duplicates
+
+
+ Show All
+
Help
+
+ Files
+
+
+ Language
+
+
+ The default MD5 hash provider should not have its priorty set.
+
+
+ OK
+
Open File Database...
+
+ Open Source Libraries
+
+
+ Options...
+
+
+ Note: Changing the user language will require a restart of the program.
+
+
+ Options
+
+
+ Provider Location
+
+
+ Save
+
Save File Database...
@@ -162,10 +243,16 @@
Scan the selected path
+
+ Skip Empty Files
+
mdfinder
Github failed to respond with the current version. This could be because of rate limits or a network failure.
+
+ Version
+
\ No newline at end of file
diff --git a/mdfinder/MainWindow.xaml b/mdfinder/MainWindow.xaml
index 7fd890d..ceeacac 100644
--- a/mdfinder/MainWindow.xaml
+++ b/mdfinder/MainWindow.xaml
@@ -11,6 +11,8 @@
+
+
@@ -52,24 +62,104 @@
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mdfinder/MainWindow.xaml.cs b/mdfinder/MainWindow.xaml.cs
index 7599019..9f16c2b 100644
--- a/mdfinder/MainWindow.xaml.cs
+++ b/mdfinder/MainWindow.xaml.cs
@@ -14,6 +14,10 @@ using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Forms;
using System.Threading;
+using mdfinder.hashprovider;
+using System.Diagnostics;
+using System.Reflection;
+using System.IO;
namespace mdfinder
{
@@ -24,10 +28,22 @@ namespace mdfinder
{
#region Properties
+ /// Gets or sets the database.
+ /// The database.
public DBHelper Database { get; set; }
+ /// Gets or sets the scanner.
+ /// The scanner.
public Scanner Scanner { get; set; }
+ /// Gets or sets the hash providers.
+ /// The hash providers.
+ public IEnumerable HashProviders { get; set; }
+
+ /// Gets or sets the default provider.
+ /// The default provider.
+ public IHashProvider DefaultProvider { get; set; }
+
#endregion
#region Constructors
@@ -37,13 +53,22 @@ namespace mdfinder
{
this.Database = new DBHelper();
this.Scanner = new Scanner();
+ this.DefaultProvider = new MD5HashProvider();
+ this.HashProviders = GetProviderPlugins();
- this.Scanner.DirectoryFound += (sender, args) => Dispatcher.Invoke(() => txtScanLocation.Text = args.Directory.Name);
- this.Scanner.FilesFound += (sender, args) =>
+ this.Scanner.DirectoryFound += (sender, args) => Dispatcher.Invoke(() => txtProgressLabel.Content = args.Directory.Name);
+ this.Scanner.FilesFound += (sender, args) =>
{
- foreach(var file in args.Files)
+ foreach (var file in args.Files)
{
- this.Database.InsertFileRecord(file.FullName, file.Length, Guid.NewGuid().ToString(), "test");
+ if (Properties.Settings.Default.SkipEmptyFiles && file.Length == 0)
+ {
+ break;
+ }
+
+ var provider = this.HashProviders.Where(hp => hp.FileExtensions.Contains(file.Extension.ToUpper())).OrderByDescending(hp => hp.Priority).FirstOr(this.DefaultProvider);
+ this.Database.InsertFileRecord(file.FullName, file.Length, provider.GetHash(file), provider.Name);
+ Dispatcher.Invoke(() => txtProgressLabel.Content = file.FullName);
}
};
this.Scanner.ReportProgress += (sender, args) => Dispatcher.Invoke(() => { if (args.Processed > 0) { this.progressBar.Value = args.Percentage * 100; } });
@@ -55,16 +80,40 @@ namespace mdfinder
#region Methods
+ /// Gets the provider plugins from a folder.
+ ///
+ /// An enumerator that allows foreach to be used to process the provider plugins in this
+ /// collection.
+ ///
+ private IEnumerable GetProviderPlugins()
+ {
+ var directory = new DirectoryInfo(Properties.Settings.Default.ProviderFolder);
+ foreach (var pluginFile in directory.GetFiles("*.dll"))
+ {
+ var assembly = Assembly.LoadFrom(pluginFile.FullName);
+ foreach (var type in assembly.GetTypes().Where(t => t.GetInterface("IHashProvider") != null))
+ {
+ yield return Activator.CreateInstance(type) as IHashProvider;
+ }
+ }
+ }
+
+ /// Event handler. Called by btnFilePicker for click events.
+ /// Source of the event.
+ /// Routed event information.
private void btnFilePicker_Click(object sender, RoutedEventArgs e)
{
var fbd = new FolderBrowserDialog();
- if(fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
+ if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
txtScanLocation.Text = fbd.SelectedPath;
}
}
+ /// Event handler. Called by btnScan for click events.
+ /// Source of the event.
+ /// Routed event information.
private void btnScan_Click(object sender, RoutedEventArgs e)
{
var location = txtScanLocation.Text;
@@ -73,10 +122,75 @@ namespace mdfinder
new Thread(() =>
{
this.Scanner.Scan(location);
+ this.Dispatcher.Invoke(() => txtProgressLabel.Content = string.Empty);
+ this.Dispatcher.Invoke(() => datagridFileRecords.ItemsSource = this.Database.GetFileRecords());
}).Start();
}
}
+ /// Event handler. Called by DatagridFileRecords for initialized events.
+ /// Source of the event.
+ /// Event information.
+ private void DatagridFileRecords_Initialized(object sender, EventArgs e)
+ {
+ this.datagridFileRecords.ItemsSource = this.Database.GetFileRecords();
+ }
+
+ /// Event handler. Called by BtnFilterDuplicates for click events.
+ /// Source of the event.
+ /// Routed event information.
+ private void BtnFilterDuplicates_Click(object sender, RoutedEventArgs e)
+ {
+ this.datagridFileRecords.ItemsSource = new ListCollectionView(this.Database.GetFileRecords().GroupBy(fr => fr.Hash).Where(g => g.Count() > 1).SelectMany(g => g).ToList());
+ ((ListCollectionView)this.datagridFileRecords.ItemsSource).GroupDescriptions.Add(new PropertyGroupDescription("Hash"));
+ }
+
+ /// Event handler. Called by BtnFilterShowAll for click events.
+ /// Source of the event.
+ /// Routed event information.
+ private void BtnFilterShowAll_Click(object sender, RoutedEventArgs e)
+ {
+ this.datagridFileRecords.ItemsSource = this.Database.GetFileRecords();
+ }
+
+ /// Event handler. Called by BtnClear for click events.
+ /// Source of the event.
+ /// Routed event information.
+ private void BtnClear_Click(object sender, RoutedEventArgs e)
+ {
+ this.Database.Clear();
+ this.datagridFileRecords.ItemsSource = Enumerable.Empty();
+ }
+
+ /// Event handler. Called by Hyperlink for click events.
+ /// Source of the event.
+ /// Routed event information.
+ private void Hyperlink_Click(object sender, RoutedEventArgs e)
+ {
+ Hyperlink link = (Hyperlink)e.OriginalSource;
+ Process.Start(link.NavigateUri.AbsoluteUri);
+ }
+
+ /// Event handler. Called by MenuOptions for click events.
+ /// Source of the event.
+ /// Routed event information.
+ private void MenuOptions_Click(object sender, RoutedEventArgs e)
+ {
+ var optionsWindow = new OptionsWindow();
+
+ optionsWindow.ShowDialog();
+
+ this.HashProviders = GetProviderPlugins();
+ }
+
+ private void MenuAbout_Click(object sender, RoutedEventArgs e)
+ {
+ var aboutWindow = new AboutWindow();
+
+ aboutWindow.Show();
+ }
#endregion
+
+
}
}
diff --git a/mdfinder/OptionsWindow.xaml b/mdfinder/OptionsWindow.xaml
new file mode 100644
index 0000000..fb16a2b
--- /dev/null
+++ b/mdfinder/OptionsWindow.xaml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mdfinder/OptionsWindow.xaml.cs b/mdfinder/OptionsWindow.xaml.cs
new file mode 100644
index 0000000..0375a06
--- /dev/null
+++ b/mdfinder/OptionsWindow.xaml.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Forms;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace mdfinder
+{
+ ///
+ /// Interaction logic for OptionsWindow.xaml
+ ///
+ public partial class OptionsWindow : Window
+ {
+ /// Gets or sets the supported languages.
+ /// The supported languages.
+ public List SupportedLanguages { get; set; } = new List(new[]
+ {
+ CultureInfo.CreateSpecificCulture("en-US"),
+ //CultureInfo.CreateSpecificCulture("es"),
+ //CultureInfo.CreateSpecificCulture("ar"),
+ //CultureInfo.CreateSpecificCulture("ja"),
+ //CultureInfo.CreateSpecificCulture("ru"),
+ //CultureInfo.CreateSpecificCulture("zh-CN"),
+ });
+
+ /// Default constructor.
+ public OptionsWindow()
+ {
+ InitializeComponent();
+ }
+
+ /// Event handler. Called by BtnSave for click events.
+ /// Source of the event.
+ /// Routed event information.
+ private void BtnSave_Click(object sender, RoutedEventArgs e)
+ {
+ Properties.Settings.Default.Save();
+
+ this.Close();
+ }
+
+ ///
+ /// Event handler. Called by BtnProviderLocationDirectory for click events.
+ ///
+ /// Source of the event.
+ /// Routed event information.
+ private void BtnProviderLocationDirectory_Click(object sender, RoutedEventArgs e)
+ {
+ var fbd = new FolderBrowserDialog();
+
+ if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
+ {
+ Properties.Settings.Default.ProviderFolder = fbd.SelectedPath;
+ }
+ }
+ }
+}
diff --git a/mdfinder/Properties/Settings.Designer.cs b/mdfinder/Properties/Settings.Designer.cs
index 39eaf3a..4ea131a 100644
--- a/mdfinder/Properties/Settings.Designer.cs
+++ b/mdfinder/Properties/Settings.Designer.cs
@@ -34,5 +34,41 @@ namespace mdfinder.Properties {
this["FilesFoundAlert"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool SkipEmptyFiles {
+ get {
+ return ((bool)(this["SkipEmptyFiles"]));
+ }
+ set {
+ this["SkipEmptyFiles"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("")]
+ public string ProviderFolder {
+ get {
+ return ((string)(this["ProviderFolder"]));
+ }
+ set {
+ this["ProviderFolder"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("en-US")]
+ public global::System.Globalization.CultureInfo Language {
+ get {
+ return ((global::System.Globalization.CultureInfo)(this["Language"]));
+ }
+ set {
+ this["Language"] = value;
+ }
+ }
}
}
diff --git a/mdfinder/Properties/Settings.settings b/mdfinder/Properties/Settings.settings
index e5a4c8e..c8c4bf7 100644
--- a/mdfinder/Properties/Settings.settings
+++ b/mdfinder/Properties/Settings.settings
@@ -5,5 +5,14 @@
25
+
+ True
+
+
+
+
+
+ en-US
+
\ No newline at end of file
diff --git a/mdfinder/Scanner.cs b/mdfinder/Scanner.cs
index 2f654f6..74fabbd 100644
--- a/mdfinder/Scanner.cs
+++ b/mdfinder/Scanner.cs
@@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace mdfinder
{
/// Scans directories, logging files and their attributes.
- public class Scanner
+ public class Scanner : PropertyChangedAlerter
{
#region Members
@@ -21,15 +21,54 @@ namespace mdfinder
/// Event queue for all listeners interested in ReportProgress events.
public event EventHandler ReportProgress;
+ private uint processed;
+
+ private uint total;
+
+ private bool isScanning;
+
#endregion
#region Properties
- public uint Processed { get; private set; }
+ public uint Processed
+ {
+ get
+ {
+ return this.processed;
+ }
+ private set
+ {
+ this.processed = value;
+ OnPropertyChanged();
+ }
+ }
- public uint Total { get; private set; }
+ public uint Total
+ {
+ get
+ {
+ return this.total;
+ }
+ private set
+ {
+ this.total = value;
+ OnPropertyChanged();
+ }
+ }
- public bool IsScanning { get; private set; }
+ public bool IsScanning
+ {
+ get
+ {
+ return this.isScanning;
+ }
+ private set
+ {
+ this.isScanning = value;
+ OnPropertyChanged();
+ }
+ }
#endregion
@@ -47,7 +86,7 @@ namespace mdfinder
Scan(scanPath);
}
}
-
+
private void Discover(DirectoryInfo directory)
{
try
@@ -63,6 +102,10 @@ namespace mdfinder
{
//Ignore and just continue.
}
+ catch (DirectoryNotFoundException directoryNotFoundException)
+ {
+ //Ignore and continue.
+ }
}
private void Scan(DirectoryInfo directory)
@@ -86,7 +129,7 @@ namespace mdfinder
OnReportProgress(this.Processed, this.Total);
}
}
- catch(UnauthorizedAccessException unauthorizedAccessException)
+ catch (UnauthorizedAccessException unauthorizedAccessException)
{
//Ignore and just continue.
}
diff --git a/mdfinder/SizeConverter.cs b/mdfinder/SizeConverter.cs
new file mode 100644
index 0000000..93a7e0f
--- /dev/null
+++ b/mdfinder/SizeConverter.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace mdfinder
+{
+ public class SizeConverter : IValueConverter
+ {
+ /// Suffix for size.
+ private static readonly string[] SUFFIX = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
+
+ /// Converts a value.
+ /// The value produced by the binding source.
+ /// The type of the binding target property.
+ /// The converter parameter to use.
+ /// The culture to use in the converter.
+ ///
+ /// A converted value. If the method returns , the valid null value is
+ /// used.
+ ///
+ ///
+ /// Thanks to user deepee1 on stackoverflow for the implementation.
+ /// https://stackoverflow.com/a/4975942/1210377.
+ ///
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (value != null)
+ {
+ var size = (long)value;
+
+ if (size == 0)
+ {
+ return "0" + SUFFIX[0];
+ }
+
+ int place = System.Convert.ToInt32(Math.Floor(Math.Log(size, 1024)));
+ double num = Math.Round(size / Math.Pow(1024, place), 1);
+ return (Math.Sign(size) * num).ToString() + SUFFIX[place];
+ }
+ else
+ {
+ return string.Empty;
+ }
+ }
+
+ /// Converts a value.
+ /// The value that is produced by the binding target.
+ /// The type to convert to.
+ /// The converter parameter to use.
+ /// The culture to use in the converter.
+ ///
+ /// A converted value. If the method returns , the valid null value is
+ /// used.
+ ///
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/mdfinder/URIConverter.cs b/mdfinder/URIConverter.cs
new file mode 100644
index 0000000..da47394
--- /dev/null
+++ b/mdfinder/URIConverter.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace mdfinder
+{
+ public class URIConverter : IValueConverter
+ {
+ /// Converts a value.
+ /// The value produced by the binding source.
+ /// The type of the binding target property.
+ /// The converter parameter to use.
+ /// The culture to use in the converter.
+ ///
+ /// A converted value. If the method returns , the valid null value is
+ /// used.
+ ///
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (value != null)
+ {
+ var uri = value as Uri;
+
+ return uri.LocalPath;
+ }
+ else
+ {
+ return string.Empty;
+ }
+ }
+
+ /// Converts a value.
+ /// The value that is produced by the binding target.
+ /// The type to convert to.
+ /// The converter parameter to use.
+ /// The culture to use in the converter.
+ ///
+ /// A converted value. If the method returns , the valid null value is
+ /// used.
+ ///
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ Uri uri = new Uri((string)value);
+ return uri;
+ }
+ }
+}
diff --git a/mdfinder/md5HashProvider.cs b/mdfinder/md5HashProvider.cs
new file mode 100644
index 0000000..c71748a
--- /dev/null
+++ b/mdfinder/md5HashProvider.cs
@@ -0,0 +1,103 @@
+using mdfinder.hashprovider;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace mdfinder
+{
+ public class MD5HashProvider : IHashProvider
+ {
+ /// The file extensions this hash provider works with.
+ private readonly string[] fileExtensions = new [] { "*" };
+
+ /// The MD5 instance.
+ private MD5 md5;
+
+ /// Gets the name of the hash provider.
+ /// The name of the hash provider.
+ public string Name
+ {
+ get
+ {
+ return Localization.Localization.DefaultHashProviderName;
+ }
+ }
+
+ /// Gets the description of the hash provider.
+ /// The description.
+ public string Description
+ {
+ get
+ {
+ return Localization.Localization.DefaultHashProviderDescription;
+ }
+ }
+
+ /// Gets a value indicating if this hash provider is valid to use.
+ ///
+ /// This value can be used by hash providers to limit use of the provider. This can be used to
+ /// create paid hash providers.
+ ///
+ /// The value indicating if the hash provider is valid.
+ public bool IsValid
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public IEnumerable FileExtensions
+ {
+ get
+ {
+ return this.fileExtensions;
+ }
+ }
+
+ ///
+ /// Gets or sets the priority this provider has when multiple providers support the same
+ /// extension.
+ ///
+ /// Thrown when the requested operation is not supported.
+ /// The priority of the hash provider.
+ public int Priority
+ {
+ get
+ {
+ return 1;
+ }
+ set
+ {
+ throw new NotSupportedException(Localization.Localization.MD5ProviderSetPriorityException);
+ }
+ }
+
+ /// Default constructor.
+ public MD5HashProvider()
+ {
+ this.md5 = MD5.Create();
+ }
+
+ /// Gets a hash from a file.
+ /// The file to hash.
+ /// The hash.
+ public string GetHash(FileInfo file)
+ {
+ try
+ {
+ return BitConverter.ToString(this.md5.ComputeHash(file.OpenRead()));
+ }
+ catch
+ {
+ //
+ }
+
+ return string.Empty;
+ }
+ }
+}
diff --git a/mdfinder/mdfinder.csproj b/mdfinder/mdfinder.csproj
index 8989580..a156230 100644
--- a/mdfinder/mdfinder.csproj
+++ b/mdfinder/mdfinder.csproj
@@ -46,9 +46,6 @@
..\packages\Octokit.0.32.0\lib\net45\Octokit.dll
-
- ..\packages\Standard.Licensing.1.1.5\lib\net45\Standard.Licensing.dll
-
@@ -73,6 +70,18 @@
MSBuild:Compile
Designer
+
+ AboutWindow.xaml
+
+
+ OptionsWindow.xaml
+
+
+
+
+ Designer
+ MSBuild:Compile
+
Designer
MSBuild:Compile
@@ -91,6 +100,7 @@
+
@@ -102,6 +112,10 @@
MainWindow.xaml
Code
+
+ Designer
+ MSBuild:Compile
+
@@ -135,11 +149,20 @@
-
-
-
+
+
+
+ {f383e2d1-f62e-44cf-9e58-63542dcbd06e}
+ mdfinder.hashprovider
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mdfinder/packages.config b/mdfinder/packages.config
index 4421dc4..6e60896 100644
--- a/mdfinder/packages.config
+++ b/mdfinder/packages.config
@@ -3,5 +3,4 @@
-
\ No newline at end of file