├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── .vs └── config │ └── applicationhost.config ├── CHANGELOG.md ├── FileMasta.Core ├── App.config ├── Data │ └── Bookmarks.cs ├── Extensions │ ├── DateTimeExtensions.cs │ ├── FileExtensions.cs │ ├── HttpExtensions.cs │ └── StringExtensions.cs ├── FileMasta.Core.csproj ├── IOdDatabase.cs ├── Models │ ├── DataItem.cs │ └── FileItem.cs ├── OdDatabase.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── FileMasta.sln ├── FileMasta ├── App.config ├── Configuration.cs ├── Controls │ ├── SplashScreen.Designer.cs │ ├── SplashScreen.cs │ └── SplashScreen.resx ├── Extensions │ ├── ControlExtensions.cs │ ├── DateTimeExtensions.cs │ ├── ExceptionExtensions.cs │ ├── LocalExtensions.cs │ └── StringExtensions.cs ├── FileMasta.csproj ├── Forms │ ├── AboutWindow.Designer.cs │ ├── AboutWindow.cs │ ├── AboutWindow.resx │ ├── BookmarksWindow.Designer.cs │ ├── BookmarksWindow.cs │ ├── BookmarksWindow.resx │ ├── DataViewWindow.Designer.cs │ ├── DataViewWindow.cs │ ├── DataViewWindow.resx │ ├── OptionsWindow.Designer.cs │ ├── OptionsWindow.cs │ └── OptionsWindow.resx ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── Models │ ├── Metadata.cs │ └── WebFile.cs ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ ├── book.png │ ├── dots-horizontal.png │ ├── download.png │ ├── filemasta-logo-v4.png │ ├── play-circle-outline.png │ ├── vlc.png │ └── windows.png ├── Utilities │ ├── ExternalEngine.cs │ └── Update.cs ├── app-logo.ico ├── log4net.config └── packages.config ├── LICENSE.md ├── README.md ├── References ├── CButtonLib.dll └── ChreneLib.dll ├── TERMSOFUSE.md ├── _config.yml └── screenshot1.png /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Description:** 2 | 3 | Provide a description of the feature request or bug here, the more details the better. 4 | Please also try to include the following if you are reporting a bug 5 | 6 | **Version:** 7 | 8 | **Logs:** 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.pch 68 | *.pdb 69 | *.pgc 70 | *.pgd 71 | *.rsp 72 | *.sbr 73 | *.tlb 74 | *.tli 75 | *.tlh 76 | *.tmp 77 | *.tmp_proj 78 | *.log 79 | *.vspscc 80 | *.vssscc 81 | .builds 82 | *.pidb 83 | *.svclog 84 | *.scc 85 | 86 | # Chutzpah Test files 87 | _Chutzpah* 88 | 89 | # Visual C++ cache files 90 | ipch/ 91 | *.aps 92 | *.ncb 93 | *.opendb 94 | *.opensdf 95 | *.sdf 96 | *.cachefile 97 | *.VC.db 98 | *.VC.VC.opendb 99 | 100 | # Visual Studio profiler 101 | *.psess 102 | *.vsp 103 | *.vspx 104 | *.sap 105 | 106 | # Visual Studio Trace Files 107 | *.e2e 108 | 109 | # TFS 2012 Local Workspace 110 | $tf/ 111 | 112 | # Guidance Automation Toolkit 113 | *.gpState 114 | 115 | # ReSharper is a .NET coding add-in 116 | _ReSharper*/ 117 | *.[Rr]e[Ss]harper 118 | *.DotSettings.user 119 | 120 | # JustCode is a .NET coding add-in 121 | .JustCode 122 | 123 | # TeamCity is a build add-in 124 | _TeamCity* 125 | 126 | # DotCover is a Code Coverage Tool 127 | *.dotCover 128 | 129 | # AxoCover is a Code Coverage Tool 130 | .axoCover/* 131 | !.axoCover/settings.json 132 | 133 | # Visual Studio code coverage results 134 | *.coverage 135 | *.coveragexml 136 | 137 | # NCrunch 138 | _NCrunch_* 139 | .*crunch*.local.xml 140 | nCrunchTemp_* 141 | 142 | # MightyMoose 143 | *.mm.* 144 | AutoTest.Net/ 145 | 146 | # Web workbench (sass) 147 | .sass-cache/ 148 | 149 | # Installshield output folder 150 | [Ee]xpress/ 151 | 152 | # DocProject is a documentation generator add-in 153 | DocProject/buildhelp/ 154 | DocProject/Help/*.HxT 155 | DocProject/Help/*.HxC 156 | DocProject/Help/*.hhc 157 | DocProject/Help/*.hhk 158 | DocProject/Help/*.hhp 159 | DocProject/Help/Html2 160 | DocProject/Help/html 161 | 162 | # Click-Once directory 163 | publish/ 164 | 165 | # Publish Web Output 166 | *.[Pp]ublish.xml 167 | *.azurePubxml 168 | # Note: Comment the next line if you want to checkin your web deploy settings, 169 | # but database connection strings (with potential passwords) will be unencrypted 170 | *.pubxml 171 | *.publishproj 172 | 173 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 174 | # checkin your Azure Web App publish settings, but sensitive information contained 175 | # in these scripts will be unencrypted 176 | PublishScripts/ 177 | 178 | # NuGet Packages 179 | *.nupkg 180 | # The packages folder can be ignored because of Package Restore 181 | **/[Pp]ackages/* 182 | # except build/, which is used as an MSBuild target. 183 | !**/[Pp]ackages/build/ 184 | # Uncomment if necessary however generally it will be regenerated when needed 185 | #!**/[Pp]ackages/repositories.config 186 | # NuGet v3's project.json files produces more ignorable files 187 | *.nuget.props 188 | *.nuget.targets 189 | 190 | # Microsoft Azure Build Output 191 | csx/ 192 | *.build.csdef 193 | 194 | # Microsoft Azure Emulator 195 | ecf/ 196 | rcf/ 197 | 198 | # Windows Store app package directories and files 199 | AppPackages/ 200 | BundleArtifacts/ 201 | Package.StoreAssociation.xml 202 | _pkginfo.txt 203 | *.appx 204 | 205 | # Visual Studio cache files 206 | # files ending in .cache can be ignored 207 | *.[Cc]ache 208 | # but keep track of directories ending in .cache 209 | !*.[Cc]ache/ 210 | 211 | # Others 212 | ClientBin/ 213 | ~$* 214 | *~ 215 | *.dbmdl 216 | *.dbproj.schemaview 217 | *.jfm 218 | *.pfx 219 | *.publishsettings 220 | orleans.codegen.cs 221 | 222 | # Including strong name files can present a security risk 223 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 224 | #*.snk 225 | 226 | # Since there are multiple workflows, uncomment next line to ignore bower_components 227 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 228 | #bower_components/ 229 | 230 | # RIA/Silverlight projects 231 | Generated_Code/ 232 | 233 | # Backup & report files from converting an old project file 234 | # to a newer Visual Studio version. Backup files are not needed, 235 | # because we have git ;-) 236 | _UpgradeReport_Files/ 237 | Backup*/ 238 | UpgradeLog*.XML 239 | UpgradeLog*.htm 240 | 241 | # SQL Server files 242 | *.mdf 243 | *.ldf 244 | *.ndf 245 | 246 | # Business Intelligence projects 247 | *.rdl.data 248 | *.bim.layout 249 | *.bim_*.settings 250 | 251 | # Microsoft Fakes 252 | FakesAssemblies/ 253 | 254 | # GhostDoc plugin setting file 255 | *.GhostDoc.xml 256 | 257 | # Node.js Tools for Visual Studio 258 | .ntvs_analysis.dat 259 | node_modules/ 260 | 261 | # TypeScript v1 declaration files 262 | typings/ 263 | 264 | # Visual Studio 6 build log 265 | *.plg 266 | 267 | # Visual Studio 6 workspace options file 268 | *.opt 269 | 270 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 271 | *.vbw 272 | 273 | # Visual Studio LightSwitch build output 274 | **/*.HTMLClient/GeneratedArtifacts 275 | **/*.DesktopClient/GeneratedArtifacts 276 | **/*.DesktopClient/ModelManifest.xml 277 | **/*.Server/GeneratedArtifacts 278 | **/*.Server/ModelManifest.xml 279 | _Pvt_Extensions 280 | 281 | # Paket dependency manager 282 | .paket/paket.exe 283 | paket-files/ 284 | 285 | # FAKE - F# Make 286 | .fake/ 287 | 288 | # JetBrains Rider 289 | .idea/ 290 | *.sln.iml 291 | 292 | # CodeRush 293 | .cr/ 294 | 295 | # Python Tools for Visual Studio (PTVS) 296 | __pycache__/ 297 | *.pyc 298 | 299 | # Cake - Uncomment if you are using it 300 | # tools/** 301 | # !tools/packages.config 302 | 303 | # Tabs Studio 304 | *.tss 305 | 306 | # Telerik's JustMock configuration file 307 | *.jmconfig 308 | 309 | # BizTalk build output 310 | *.btp.cs 311 | *.btm.cs 312 | *.odx.cs 313 | *.xsd.cs 314 | 315 | # OpenCover UI analysis results 316 | OpenCover/ 317 | 318 | # Azure Stream Analytics local run output 319 | ASALocalRun/ 320 | 321 | # MSBuild Binary and Structured Log 322 | *.binlog 323 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | ## [0.4.6] 2019-05-27 5 | * Created an od-database library 6 | * Added application configuration settings 7 | * Added FileHelpers to parse database 8 | * Added bookmarks extension (stored to csv file) 9 | * Added boomarked window 10 | * Added DateTime, Local and File Extensions 11 | * Search functions are asynchronous 12 | * Overall cleanup and optimization of project code 13 | 14 | ## [0.4.5] 2019-04-02 15 | * Hoping to fix most issues with loading data 16 | * Minor improvements to help efficiency 17 | 18 | ## [0.4.4] 2019-01-25 19 | * Data is now retrieved from od-database 20 | * Improved backend performance (#130) 21 | * Improved initial data processes 22 | * Improved saving files 23 | * Improved user interface 24 | * Removed remove data on close from settings 25 | 26 | ## [0.4.3] 2019-01-13 27 | * Improved local data storage stability 28 | * Improved efficiency by refactoring search (#128) 29 | * Improved the speed of buffering data 30 | * Improved the overall performance 31 | * Improved logging and status messages 32 | * Simplified user interface 33 | * Added ability to search minimum file size 34 | * Added ability to search start/end file modified date 35 | * Added ability to email file download links 36 | 37 | ## [0.4.2] 2018.11.05 38 | * Fixed issue with recent database changes (#116) 39 | * Clean up code and resources 40 | * Improved logging messages 41 | * Removed auto updater, now uses installer 42 | 43 | ## [0.4.1] 2018.08.24 44 | * Attempted to improve startup and search time (#114) 45 | * Enable custom location installer (#112) 46 | * Improved database error handling 47 | * Improved user interface 48 | * Added ability to search external engines 49 | 50 | ## [0.4.0] 2018.06.28 51 | * Updated database to use ftp file 52 | * Added support for more file extensions 53 | * User interface now uses default winform style 54 | * Added context menu to data table 55 | * Added menu and status tool strip -------------------------------------------------------------------------------- /FileMasta.Core/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /FileMasta.Core/Data/Bookmarks.cs: -------------------------------------------------------------------------------- 1 | using FileHelpers; 2 | using FileMasta.Core.Extensions; 3 | using FileMasta.Core.Models; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | 8 | namespace FileMasta.Core.Data 9 | { 10 | internal class Bookmarks 11 | { 12 | private readonly List files = new List(); 13 | 14 | /// 15 | /// Location of bookmarked files containing records 16 | /// 17 | public string FileLocation { get; private set; } 18 | 19 | /// 20 | /// Create a new users bookmarks instance 21 | /// 22 | public Bookmarks(string fileLocation) 23 | { 24 | if (File.Exists(fileLocation)) 25 | { 26 | FileHelperAsyncEngine engine = new FileHelperAsyncEngine(); 27 | engine.ErrorManager.ErrorMode = ErrorMode.IgnoreAndContinue; 28 | 29 | using (engine.BeginReadFile(fileLocation)) 30 | { 31 | foreach (DataItem file in engine) 32 | { 33 | files.Add(FileExtensions.DataItemToFile(file)); 34 | } 35 | } 36 | } 37 | 38 | FileLocation = fileLocation; 39 | } 40 | 41 | /// 42 | /// Get the list of bookmarked files 43 | /// 44 | public IList GetFiles => files; 45 | 46 | /// 47 | /// Search and retrieve a collection of files from the database with the specified properties 48 | /// 49 | /// String that contains the file name 50 | /// Type of file to return 51 | /// Minimum file size 52 | /// Minimum file modified time 53 | /// Maximum file modified time 54 | /// An enumerable collection of results with the specified parameters 55 | public IEnumerable Search(string name, string[] type, long minSize, DateTime minMTime, DateTime maxMTime) 56 | { 57 | FileHelperAsyncEngine engine = new FileHelperAsyncEngine(); 58 | engine.ErrorManager.ErrorMode = ErrorMode.IgnoreAndContinue; 59 | List results = new List(); 60 | 61 | using (engine.BeginReadFile(FileLocation)) 62 | { 63 | foreach (DataItem file in engine) 64 | { 65 | _ = double.TryParse(file.Mtime, out double fileTStampDbl); 66 | DateTime fileTimeStamp = DateTimeExtensions.ParseTimeStamp(fileTStampDbl); 67 | 68 | if (StringExtensions.ContainsAll(file.Name.ToLower(), StringExtensions.GetWords(name.ToLower())) && 69 | file.IsType(type) && 70 | long.Parse(file.Size) >= minSize && 71 | fileTimeStamp > minMTime && 72 | fileTimeStamp < maxMTime) 73 | results.Add(file); 74 | } 75 | } 76 | 77 | return results; 78 | } 79 | 80 | /// 81 | /// Add a file to users bookmarks 82 | /// 83 | /// URL to add 84 | public void Add(FileItem file) 85 | { 86 | files.Add(file); 87 | } 88 | 89 | /// 90 | /// Remove a file from users bookmarks 91 | /// 92 | /// URL to remove 93 | public void Remove(FileItem file) 94 | { 95 | files.Remove(file); 96 | } 97 | 98 | /// 99 | /// Check if file exists in the bookmarks 100 | /// 101 | /// URL of the File 102 | /// True if exists 103 | public bool IsBookmarked(FileItem file) 104 | { 105 | foreach (FileItem bookmark in files) 106 | if (bookmark.Url == file.Url) 107 | return true; 108 | return false; 109 | } 110 | 111 | /// 112 | /// Remove all items from users bookmarks 113 | /// 114 | public void RemoveAll() 115 | { 116 | files.Clear(); 117 | } 118 | 119 | /// 120 | /// Store and update users bookmarks file 121 | /// 122 | public void UpdateCache() 123 | { 124 | if (files.Count == 0) 125 | { 126 | DeleteCache(); 127 | return; 128 | } 129 | 130 | FileHelperAsyncEngine engine = new FileHelperAsyncEngine(); 131 | engine.ErrorManager.ErrorMode = ErrorMode.IgnoreAndContinue; 132 | 133 | using (engine.BeginWriteFile(FileLocation)) 134 | { 135 | foreach (FileItem file in files) 136 | { 137 | engine.WriteNext(FileExtensions.FileItemToData(file)); 138 | } 139 | } 140 | } 141 | 142 | /// 143 | /// Delete the bookmarks file 144 | /// 145 | public void DeleteCache() 146 | { 147 | if (File.Exists(FileLocation)) 148 | File.Delete(FileLocation); 149 | } 150 | } 151 | } -------------------------------------------------------------------------------- /FileMasta.Core/Extensions/DateTimeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FileMasta.Core.Extensions 4 | { 5 | internal abstract class DateTimeExtensions 6 | { 7 | /// 8 | /// Parse a Unix TimeStamp to DateTime 9 | /// 10 | /// TimeStamp in Seconds 11 | /// 12 | public static DateTime ParseTimeStamp(double timeStamp) 13 | { 14 | DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 15 | dt = dt.AddSeconds(timeStamp).ToLocalTime(); 16 | return dt; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /FileMasta.Core/Extensions/FileExtensions.cs: -------------------------------------------------------------------------------- 1 | using FileMasta.Core.Models; 2 | using System; 3 | using System.IO; 4 | 5 | namespace FileMasta.Core.Extensions 6 | { 7 | public abstract class FileExtensions 8 | { 9 | /// 10 | /// Converts a data record item to a file object with properties 11 | /// 12 | /// 13 | /// 14 | public static FileItem DataItemToFile(DataItem data) 15 | { 16 | if (data == null) return null; 17 | 18 | _ = double.TryParse( 19 | (data.Mtime ?? string.Empty).ToString(), 20 | out double unixTimestamp); 21 | _ = long.TryParse( 22 | (data.Size ?? string.Empty).ToString(), 23 | out long fileSize); 24 | 25 | return new FileItem( 26 | string.IsNullOrEmpty(data.Ext) 27 | ? data.Name 28 | : data.Name + "." + data.Ext, 29 | fileSize, 30 | DateTimeExtensions.ParseTimeStamp(unixTimestamp), 31 | string.IsNullOrEmpty(data.Ext) 32 | ? data.WebsiteUrl.Substring(0, data.WebsiteUrl.IndexOf('/', data.WebsiteUrl.IndexOf('/') + 2)) + "/" + data.Path + "/" + data.Name 33 | : data.WebsiteUrl.Substring(0, data.WebsiteUrl.IndexOf('/', data.WebsiteUrl.IndexOf('/') + 2)) + "/" + data.Path + "/" + data.Name + "." + data.Ext); 34 | 35 | } 36 | 37 | public static DataItem FileItemToData(FileItem file) 38 | { 39 | Uri fileUri = new Uri(file.Url); 40 | return new DataItem() 41 | { 42 | WebsiteId = "0", 43 | WebsiteUrl = fileUri.GetLeftPart(UriPartial.Authority) + "/", 44 | Path = Path.GetDirectoryName(fileUri.LocalPath).Replace(@"\", "/").TrimStart('/'), 45 | Name = Path.GetFileNameWithoutExtension(file.Name), 46 | Ext = file.GetExtension(), 47 | Size = file.Size.ToString(), 48 | Mtime = ((DateTimeOffset)file.Mtime).ToUnixTimeSeconds().ToString() 49 | }; 50 | } 51 | 52 | /// 53 | /// Creates a file object from the given link 54 | /// 55 | /// 56 | /// 57 | public static FileItem CreateFile(string url) 58 | { 59 | return new FileItem( 60 | Path.GetFileName(url), 61 | HttpExtensions.GetFileSize(new Uri(url)), 62 | HttpExtensions.GetFileLastModified(new Uri(url)), 63 | url); 64 | } 65 | 66 | public static FileItem CreateFile(long size, string url) 67 | { 68 | return new FileItem( 69 | Path.GetFileName(url), 70 | size, 71 | HttpExtensions.GetFileLastModified(new Uri(url)), 72 | url); 73 | } 74 | 75 | public static FileItem CreateFile(DateTime mTime, string url) 76 | { 77 | return new FileItem( 78 | Path.GetFileName(url), 79 | HttpExtensions.GetFileSize(new Uri(url)), 80 | mTime, 81 | url); 82 | } 83 | 84 | public static FileItem CreateFile(DateTime mTime, long size, string url) 85 | { 86 | return new FileItem( 87 | Path.GetFileName(url), 88 | size, 89 | mTime, 90 | url); 91 | } 92 | 93 | public static long CountLines(string fileName) 94 | { 95 | long count = -1; 96 | using (StreamReader sr = File.OpenText(fileName)) 97 | { 98 | string s = ""; 99 | while ((s = sr.ReadLine()) != null) 100 | { 101 | count++; 102 | } 103 | } 104 | return count; 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /FileMasta.Core/Extensions/HttpExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | 6 | namespace FileMasta.Core.Extensions 7 | { 8 | public abstract class HttpExtensions 9 | { 10 | /// 11 | /// Get the specified web file size in bytes 12 | /// 13 | /// File Url 14 | /// 15 | public static long GetFileSize(Uri uri) 16 | { 17 | WebRequest webRequest = WebRequest.Create(uri); 18 | webRequest.Method = "HEAD"; 19 | 20 | using (var webResponse = webRequest.GetResponse()) 21 | { 22 | var fileSize = webResponse.Headers.Get("Content-Length"); 23 | return Convert.ToInt64(fileSize); 24 | } 25 | } 26 | 27 | /// 28 | /// Get the specified web file last modified date 29 | /// 30 | /// File Url 31 | /// 32 | public static DateTime GetFileLastModified(Uri url) 33 | { 34 | try 35 | { 36 | return GetWebResponse(url.AbsoluteUri).LastModified; 37 | } 38 | catch 39 | { 40 | return DateTime.MinValue; 41 | } 42 | } 43 | 44 | /// 45 | /// Create new http web response 46 | /// 47 | /// URL to request 48 | /// Returns a web response from the URL 49 | private static HttpWebResponse GetWebResponse(string url) 50 | { 51 | WebRequest request = WebRequest.Create(url); 52 | request.Method = "HEAD"; 53 | request.Timeout = -1; 54 | return (HttpWebResponse)request.GetResponse(); 55 | } 56 | 57 | /// 58 | /// Get the file contents as an array of lines 59 | /// 60 | /// 61 | /// 62 | public static IEnumerable GetFileContents(string url) 63 | { 64 | List items = new List(); 65 | HttpWebRequest request = GetRequest(url); 66 | using (WebResponse webResponse = request.GetResponse()) 67 | using (StreamReader reader = new StreamReader(webResponse.GetResponseStream() ?? throw new InvalidOperationException("Error retrieving file contents"))) 68 | { 69 | string line; 70 | while ((line = reader.ReadLine()) != null) 71 | items.Add(line); 72 | } 73 | return items; 74 | } 75 | 76 | /// 77 | /// Initialize new http web request 78 | /// 79 | /// File URL 80 | /// Method for the request 81 | /// Whether request should follow redirection responses 82 | /// Sets content-type http header 83 | /// Returns a new HTTP Web Request to Get Response from file 84 | public static HttpWebRequest GetRequest(string requestUriString, string httpMethod = "GET", bool allowAutoRedirect = true, string contentType = "text/plain") 85 | { 86 | HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUriString); 87 | request.UserAgent = @"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"; 88 | request.ContentType = contentType; 89 | request.Timeout = Convert.ToInt32(new TimeSpan(0, 5, 0).TotalMilliseconds); 90 | request.AllowAutoRedirect = allowAutoRedirect; 91 | request.Method = httpMethod; 92 | return request; 93 | } 94 | 95 | public static Stream GetStream(string url) 96 | { 97 | return ((HttpWebResponse)GetRequest(url).GetResponse()).GetResponseStream(); 98 | } 99 | 100 | /// 101 | /// Download a web file using given URL to users local hard disk 102 | /// 103 | /// 104 | /// 105 | public static void DownloadFile(string url, string path) 106 | { 107 | using (WebClient wc = new WebClient()) 108 | { 109 | wc.Headers.Add("Accept: text/plain"); 110 | wc.Headers.Add("User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"); 111 | wc.DownloadFile(new Uri(url), path); 112 | } 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /FileMasta.Core/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text.RegularExpressions; 4 | 5 | namespace FileMasta.Core.Extensions 6 | { 7 | internal abstract class StringExtensions 8 | { 9 | /// 10 | /// Gets the file name from a given url 11 | /// 12 | /// File Url 13 | /// File Name 14 | public static string GetFileName(string url) 15 | { 16 | return Uri.EscapeDataString(url.Substring(url.LastIndexOf('/') + 1)); 17 | } 18 | 19 | /// 20 | /// Determines whether the string contains all the given sub strings 21 | /// 22 | /// 23 | /// 24 | /// 25 | public static bool ContainsAll(string source, params string[] values) 26 | { 27 | return values.All(x => source.ToLower().Contains(x)); 28 | } 29 | 30 | /// 31 | /// Get an array of words from the input 32 | /// 33 | /// 34 | /// Sub strings in string 35 | public static string[] GetWords(string value) 36 | { 37 | MatchCollection matches = Regex.Matches(value, @"\b[\w']*\b"); 38 | 39 | System.Collections.Generic.IEnumerable words = from m in matches.Cast() 40 | where !string.IsNullOrEmpty(m.Value) 41 | select TrimSuffix(m.Value); 42 | 43 | return words.ToArray(); 44 | } 45 | 46 | /// 47 | /// Removes the last occurance of the backslash 48 | /// 49 | /// 50 | /// 51 | private static string TrimSuffix(string value) 52 | { 53 | int backslashIndex = value.IndexOf('\''); 54 | if (backslashIndex != -1) 55 | value = value.Substring(0, backslashIndex); 56 | 57 | return value; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /FileMasta.Core/FileMasta.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2C534550-1884-4BDE-BD7B-B1348E53517B} 8 | Exe 9 | FileMasta.Core 10 | FileMasta.Core 11 | v4.6.1 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\packages\FileHelpers.3.4.0\lib\net45\FileHelpers.dll 38 | 39 | 40 | 41 | 42 | 43 | ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /FileMasta.Core/IOdDatabase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using FileMasta.Core.Models; 5 | 6 | namespace FileMasta.Core 7 | { 8 | internal interface IOdDatabase 9 | { 10 | Task> SearchRecords(string name, string[] type, long minSize, DateTime minMTime, DateTime maxMTime); 11 | 12 | Task> SearchBookmarked(string name, string[] type, long minSize, DateTime minMTime, DateTime maxMTime); 13 | 14 | long TotalFileCount { get; } 15 | 16 | long SizeTotal { get; } 17 | 18 | long DatabaseSize { get; } 19 | 20 | IList Bookmarked { get; } 21 | 22 | IEnumerable SearchKeywords { get; } 23 | 24 | void AddBookmark(FileItem file); 25 | 26 | void RemoveBookmark(FileItem file); 27 | 28 | bool IsBookmarked(FileItem file); 29 | 30 | void RemoveAll(); 31 | 32 | void UpdateBookmarks(); 33 | } 34 | } -------------------------------------------------------------------------------- /FileMasta.Core/Models/DataItem.cs: -------------------------------------------------------------------------------- 1 | using FileHelpers; 2 | using System.Linq; 3 | 4 | namespace FileMasta.Core.Models 5 | { 6 | [DelimitedRecord(",")] 7 | public class DataItem 8 | { 9 | public string WebsiteId { get; set; } 10 | public string WebsiteUrl { get; set; } 11 | public string Path { get; set; } 12 | public string Name { get; set; } 13 | public string Ext { get; set; } 14 | public string Size { get; set; } 15 | public string Mtime { get; set; } 16 | 17 | public bool IsType(string[] type) => type == FileType.All || type.Any(x => Ext.Contains(x.ToUpper())); 18 | } 19 | } -------------------------------------------------------------------------------- /FileMasta.Core/Models/FileItem.cs: -------------------------------------------------------------------------------- 1 | using FileMasta.Core.Data; 2 | using System; 3 | using System.IO; 4 | using System.Linq; 5 | 6 | namespace FileMasta.Core.Models 7 | { 8 | public partial class FileItem 9 | { 10 | public readonly string Name; 11 | public readonly long Size; 12 | public readonly DateTime Mtime; 13 | public readonly string Url; 14 | 15 | /// 16 | /// Create a web file object with specified properties 17 | /// 18 | /// 19 | /// 20 | /// 21 | /// 22 | public FileItem(string name, long size, DateTime mTime, string url) 23 | { 24 | Name = name; 25 | Size = size; 26 | Mtime = mTime; 27 | Url = url; 28 | } 29 | 30 | public string GetExtension() 31 | { 32 | return Path.GetExtension(Url)?.Replace(".", "").ToUpper(); 33 | } 34 | 35 | public bool IsType(string[] type) 36 | { 37 | return type == FileType.All || type.Any(x => GetExtension().Contains(x.ToUpper())); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /FileMasta.Core/OdDatabase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Threading.Tasks; 5 | using FileHelpers; 6 | using FileMasta.Core.Data; 7 | using FileMasta.Core.Extensions; 8 | using FileMasta.Core.Models; 9 | 10 | namespace FileMasta.Core 11 | { 12 | /// 13 | /// OD-Database Library 14 | /// 15 | public class OdDatabase : IOdDatabase 16 | { 17 | private string CacheLocation { get; set; } 18 | 19 | private Bookmarks Bookmarks { get; set; } 20 | 21 | /// 22 | /// Initialize the OD-Database instance 23 | /// 24 | /// 25 | /// 26 | /// 27 | public OdDatabase(string databaseUrl, string cacheLocation, string bookmarksLocation) 28 | { 29 | CacheLocation = cacheLocation; 30 | CacheDatabaseFile(databaseUrl, cacheLocation); 31 | Bookmarks = new Bookmarks(bookmarksLocation); 32 | } 33 | 34 | /// 35 | /// Cache the latest database file 36 | /// 37 | /// Url of the database 38 | /// Cache storage location 39 | private void CacheDatabaseFile(string databaseUrl, string cacheLocation) 40 | { 41 | long dbFileSize = HttpExtensions.GetFileSize(new Uri(databaseUrl)); 42 | DatabaseSize = dbFileSize; 43 | 44 | if (File.Exists(cacheLocation)) 45 | { 46 | if (dbFileSize != new FileInfo(cacheLocation).Length) 47 | { 48 | HttpExtensions.DownloadFile(databaseUrl, cacheLocation); 49 | } 50 | } 51 | else 52 | { 53 | HttpExtensions.DownloadFile(databaseUrl, cacheLocation); 54 | } 55 | 56 | TotalFileCount = FileExtensions.CountLines(cacheLocation); 57 | } 58 | 59 | /// 60 | /// Search and retrieve a collection of files from the database with the specified properties 61 | /// 62 | /// String that contains the file name 63 | /// Type of file to return 64 | /// Minimum file size 65 | /// Minimum file modified time 66 | /// Maximum file modified time 67 | /// An enumerable collection of results with the specified parameters 68 | public async Task> SearchRecords(string name, string[] type, long minSize, DateTime minMTime, DateTime maxMTime) 69 | { 70 | List results = new List(); 71 | 72 | using (FileHelperAsyncEngine engine = new FileHelperAsyncEngine()) 73 | { 74 | engine.ErrorManager.ErrorMode = ErrorMode.IgnoreAndContinue; 75 | 76 | using (engine.BeginReadFile(CacheLocation)) 77 | { 78 | await Task.Run(() => Parallel.ForEach(engine, file => 79 | { 80 | _ = double.TryParse(file.Mtime, out double fileTStampDbl); 81 | DateTime fileTimeStamp = DateTimeExtensions.ParseTimeStamp(fileTStampDbl); 82 | 83 | if (StringExtensions.ContainsAll(file.Name.ToLower(), StringExtensions.GetWords(name.ToLower())) && 84 | file.IsType(type) && 85 | long.Parse(file.Size) >= minSize && 86 | fileTimeStamp > minMTime && 87 | fileTimeStamp < maxMTime) 88 | results.Add(file); 89 | })); 90 | } 91 | } 92 | 93 | return results; 94 | } 95 | 96 | public async Task> SearchBookmarked(string name, string[] type, long minSize, DateTime minMTime, DateTime maxMTime) 97 | { 98 | List results = new List(); 99 | 100 | using (FileHelperAsyncEngine engine = new FileHelperAsyncEngine()) 101 | { 102 | engine.ErrorManager.ErrorMode = ErrorMode.IgnoreAndContinue; 103 | 104 | using (engine.BeginReadFile(Bookmarks.FileLocation)) 105 | { 106 | await Task.Run(() => Parallel.ForEach(engine, file => 107 | { 108 | _ = double.TryParse(file.Mtime, out double fileTStampDbl); 109 | DateTime fileTimeStamp = DateTimeExtensions.ParseTimeStamp(fileTStampDbl); 110 | 111 | if (StringExtensions.ContainsAll(file.Name.ToLower(), StringExtensions.GetWords(name.ToLower())) && 112 | file.IsType(type) && 113 | long.Parse(file.Size) >= minSize && 114 | fileTimeStamp > minMTime && 115 | fileTimeStamp < maxMTime) 116 | results.Add(file); 117 | })); 118 | } 119 | } 120 | 121 | return results; 122 | } 123 | 124 | /// 125 | /// Get the total size of indexed files 126 | /// 127 | /// Total size in bytes 128 | public long SizeTotal { get; private set; } 129 | 130 | /// 131 | /// Get the total number of files 132 | /// 133 | /// Total size in bytes 134 | public long TotalFileCount { get; private set; } 135 | 136 | /// 137 | /// Get the database file size 138 | /// 139 | /// Total size in bytes 140 | public long DatabaseSize { get; private set; } 141 | 142 | /// 143 | /// Get the list of the users bookmark files 144 | /// 145 | public IList Bookmarked => Bookmarks.GetFiles; 146 | 147 | /// 148 | /// Determines whether the file is bookmarked 149 | /// 150 | /// 151 | /// 152 | public bool IsBookmarked(FileItem file) => Bookmarks.IsBookmarked(file); 153 | 154 | /// 155 | /// Adds a file to bookmarks 156 | /// 157 | /// 158 | public void AddBookmark(FileItem file) => Bookmarks.Add(file); 159 | 160 | /// 161 | /// Removes a file from bookmarks 162 | /// 163 | /// 164 | public void RemoveBookmark(FileItem file) => Bookmarks.Remove(file); 165 | 166 | /// 167 | /// Removes all the file bookmarks 168 | /// 169 | public void RemoveAll() => Bookmarks.RemoveAll(); 170 | 171 | /// 172 | /// Updates the bookmarks collection to the users hard disk 173 | /// 174 | public void UpdateBookmarks() => Bookmarks.UpdateCache(); 175 | 176 | /// 177 | /// Fetches and returns the list of popular search keywords 178 | /// 179 | /// A collection of popular keywords 180 | public IEnumerable SearchKeywords => HttpExtensions.GetFileContents("https://dl.dropbox.com/s/4x2nypfiyuoyxjj/searches.txt?raw=true"); 181 | } 182 | 183 | /// 184 | /// Properties of files for sorting 185 | /// 186 | public enum Sort 187 | { 188 | Name, 189 | Size, 190 | Date 191 | } 192 | 193 | /// 194 | /// Categories for different types of files by their extension 195 | /// 196 | public abstract class FileType 197 | { 198 | public static string[] All { get; } = { }; 199 | public static string[] Audio { get; } = { "AAC", "AC3", "AIF", "AIFC", "AIFF", "AU", "CDA", "DTS", "FLA", "FLAC", "IT", "M1A", "M2A", "M3U", "M4A", "MID", "MIDI", "MKA", "MOD", "MP2", "MP3", "MPA", "OGG", "RA", "RMI", "SPC", "RMI", "SND", "UMX", "VOC", "WAV", "WMA", "XM" }; 200 | public static string[] Compressed { get; } = { "7Z", "ACE", "ARJ", "BZ2", "CAB", "GZ", "GZIP", "JAR", "R00", "R01", "R02", "R03", "R04", "R05", "R06", "R07", "R08", "R09", "R10", "R11", "R12", "R13", "R14", "R15", "R16", "R17", "R18", "R19", "R20", "R21", "R22", "R23", "R24", "R25", "R26", "R27", "R28", "R29", "RAR", "TAR", "TGZ", "Z", "ZIP" }; 201 | public static string[] Document { get; } = { "C", "CHM", "CPP", "CSV", "CXX", "DOC", "DOCM", "DOCX", "DOT", "DOTM", "DOTX", "H", "HPP", "HTM", "HTML", "HXX", "INI", "JAVA", "LUA", "MHT", "MHTML", "ODT", "PDF", "POTX", "POTM", "PPAM", "PPSM", "PPSX", "PPS", "PPT", "PPTM", "PPTX", "RTF", "SLDM", "SLDX", "THMX", "TXT", "VSD", "WPD", "WPS", "WRI", "XLAM", "XLS", "XLSB", "XLSM", "XLSX", "XLTM", "XLTX", "XML" }; 202 | public static string[] Executable { get; } = { "BAT", "CMD", "EXE", "MSI", "MSP", "SCR" }; 203 | public static string[] Picture { get; } = { "ANI", "BMP", "GIF", "ICO", "JPE", "JPEG", "JPG", "PCX", "PNG", "PSD", "TGA", "TIF", "TIFF", "WMF" }; 204 | public static string[] Video { get; } = { "3G2", "3GP", "3GP2", "3GPP", "AMR", "AMV", "ASF", "AVI", "BDMV", "BIK", "D2V", "DIVX", "DRC", "DSA", "DSM", "DSS", "DSV", "EVO", "F4V", "FLC", "FLI", "FLIC", "FLV", "HDMOV", "IFO", "IVF", "M1V", "M2P", "M2T", "M2TS", "M2V", "M4B", "M4P", "M4V", "MKV", "MP2V", "MP4", "MP4V", "MPE", "MPEG", "MPG", "MPLS", "MPV2", "MPV4", "MOV", "MTS", "OGM", "OGV", "PSS", "PVA", "QT", "RAM", "RATDVD", "RM", "RMM", "RMVB", "ROQ", "RPM", "SMIL", "SMK", "SWF", "TP", "TPR", "TS", "VOB", "VP6", "WEBM", "WM", "WMP", "WMV" }; 205 | } 206 | } -------------------------------------------------------------------------------- /FileMasta.Core/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FileMasta.Core 4 | { 5 | internal static class Program 6 | { 7 | /// 8 | /// The main entry point for the application. 9 | /// 10 | [STAThread] 11 | private static void Main() 12 | { 13 | 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /FileMasta.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("FileMasta.Core")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("HP Inc.")] 12 | [assembly: AssemblyProduct("FileMasta.Core")] 13 | [assembly: AssemblyCopyright("Copyright © HP Inc. 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("2c534550-1884-4bde-bd7b-b1348e53517b")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /FileMasta.Core/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /FileMasta.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2036 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileMasta", "FileMasta\FileMasta.csproj", "{75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}" 7 | ProjectSection(ProjectDependencies) = postProject 8 | {2C534550-1884-4BDE-BD7B-B1348E53517B} = {2C534550-1884-4BDE-BD7B-B1348E53517B} 9 | EndProjectSection 10 | EndProject 11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FileMasta.Core", "FileMasta.Core\FileMasta.Core.csproj", "{2C534550-1884-4BDE-BD7B-B1348E53517B}" 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Any CPU = Debug|Any CPU 16 | Debug|Win32 = Debug|Win32 17 | Debug|x64 = Debug|x64 18 | Debug|x86 = Debug|x86 19 | Release|Any CPU = Release|Any CPU 20 | Release|Win32 = Release|Win32 21 | Release|x64 = Release|x64 22 | Release|x86 = Release|x86 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Debug|Win32.ActiveCfg = Debug|Any CPU 28 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Debug|Win32.Build.0 = Debug|Any CPU 29 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Debug|x64.ActiveCfg = Debug|Any CPU 30 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Debug|x64.Build.0 = Debug|Any CPU 31 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Debug|x86.ActiveCfg = Debug|Any CPU 32 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Debug|x86.Build.0 = Debug|Any CPU 33 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Release|Win32.ActiveCfg = Release|Any CPU 36 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Release|Win32.Build.0 = Release|Any CPU 37 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Release|x64.ActiveCfg = Release|Any CPU 38 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Release|x64.Build.0 = Release|Any CPU 39 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Release|x86.ActiveCfg = Release|Any CPU 40 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA}.Release|x86.Build.0 = Release|Any CPU 41 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 42 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Debug|Any CPU.Build.0 = Debug|Any CPU 43 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Debug|Win32.ActiveCfg = Debug|Any CPU 44 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Debug|Win32.Build.0 = Debug|Any CPU 45 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Debug|x64.ActiveCfg = Debug|Any CPU 46 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Debug|x64.Build.0 = Debug|Any CPU 47 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Debug|x86.ActiveCfg = Debug|Any CPU 48 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Debug|x86.Build.0 = Debug|Any CPU 49 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Release|Any CPU.ActiveCfg = Release|Any CPU 50 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Release|Any CPU.Build.0 = Release|Any CPU 51 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Release|Win32.ActiveCfg = Release|Any CPU 52 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Release|Win32.Build.0 = Release|Any CPU 53 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Release|x64.ActiveCfg = Release|Any CPU 54 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Release|x64.Build.0 = Release|Any CPU 55 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Release|x86.ActiveCfg = Release|Any CPU 56 | {2C534550-1884-4BDE-BD7B-B1348E53517B}.Release|x86.Build.0 = Release|Any CPU 57 | EndGlobalSection 58 | GlobalSection(SolutionProperties) = preSolution 59 | HideSolutionNode = FALSE 60 | EndGlobalSection 61 | GlobalSection(ExtensibilityGlobals) = postSolution 62 | SolutionGuid = {688798EF-AA5D-4AA4-B35E-FF0B8A7D007E} 63 | EndGlobalSection 64 | EndGlobal 65 | -------------------------------------------------------------------------------- /FileMasta/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | False 16 | 17 | 18 | 19 | 20 | 21 | 0 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | False 31 | 32 | 33 | 34 | 35 | 37 | 39 | 41 | 43 | 45 | 47 | 48 | -------------------------------------------------------------------------------- /FileMasta/Configuration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using System.IO; 4 | 5 | namespace FileMasta 6 | { 7 | public abstract class Configuration 8 | { 9 | /// 10 | /// Application cache data directory, used for storing database and bookmarks 11 | /// 12 | public static string AppWorkingDirectory { get; } = Environment.CurrentDirectory; 13 | 14 | /// 15 | /// Url to project hosted on GitHub 16 | /// 17 | public static string ProjectUrl { get; } = ConfigurationManager.AppSettings["url.project"]; 18 | 19 | /// 20 | /// Url to the projects changelog file 21 | /// 22 | public static string ChangelogUrl { get; } = ConfigurationManager.AppSettings["fileUrl.changelog"]; 23 | 24 | /// 25 | /// Url to the latest application version 26 | /// 27 | public static string VersionUrl { get; } = ConfigurationManager.AppSettings["fileUrl.version"]; 28 | 29 | /// 30 | /// Url to the core database file 31 | /// 32 | public static string DatabaseUrl { get; } = ConfigurationManager.AppSettings["fileUrl.database"]; 33 | 34 | /// 35 | /// Database cache file path 36 | /// 37 | public static string DatabaseLocation { get; } = Path.Combine(AppWorkingDirectory, ConfigurationManager.AppSettings["fileName.database"]); 38 | /// 39 | /// Bookmarked file path 40 | /// 41 | public static string BookmarkedLocation { get; } = Path.Combine(AppWorkingDirectory, ConfigurationManager.AppSettings["fileName.bookmarked"]); 42 | } 43 | } -------------------------------------------------------------------------------- /FileMasta/Controls/SplashScreen.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FileMasta.Controls 2 | { 3 | partial class SplashScreen 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Component Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.LabelLoading = new System.Windows.Forms.Label(); 32 | this.ImageLogo = new System.Windows.Forms.PictureBox(); 33 | ((System.ComponentModel.ISupportInitialize)(this.ImageLogo)).BeginInit(); 34 | this.SuspendLayout(); 35 | // 36 | // LabelLoading 37 | // 38 | this.LabelLoading.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); 39 | this.LabelLoading.BackColor = System.Drawing.Color.Transparent; 40 | this.LabelLoading.Font = new System.Drawing.Font("Verdana", 10F); 41 | this.LabelLoading.Location = new System.Drawing.Point(4, 341); 42 | this.LabelLoading.Name = "LabelLoading"; 43 | this.LabelLoading.Size = new System.Drawing.Size(810, 29); 44 | this.LabelLoading.TabIndex = 0; 45 | this.LabelLoading.Text = "Initializing FileMasta, Please Wait..."; 46 | this.LabelLoading.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 47 | // 48 | // ImageLogo 49 | // 50 | this.ImageLogo.Anchor = System.Windows.Forms.AnchorStyles.None; 51 | this.ImageLogo.Image = global::FileMasta.Properties.Resources.app_logo; 52 | this.ImageLogo.Location = new System.Drawing.Point(314, 130); 53 | this.ImageLogo.Name = "ImageLogo"; 54 | this.ImageLogo.Size = new System.Drawing.Size(190, 190); 55 | this.ImageLogo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; 56 | this.ImageLogo.TabIndex = 3; 57 | this.ImageLogo.TabStop = false; 58 | // 59 | // SplashScreen 60 | // 61 | this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 17F); 62 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 63 | this.BackColor = System.Drawing.SystemColors.Control; 64 | this.Controls.Add(this.ImageLogo); 65 | this.Controls.Add(this.LabelLoading); 66 | this.DoubleBuffered = true; 67 | this.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 68 | this.Name = "SplashScreen"; 69 | this.Size = new System.Drawing.Size(818, 500); 70 | ((System.ComponentModel.ISupportInitialize)(this.ImageLogo)).EndInit(); 71 | this.ResumeLayout(false); 72 | 73 | } 74 | 75 | #endregion 76 | 77 | public System.Windows.Forms.Label LabelLoading; 78 | private System.Windows.Forms.PictureBox ImageLogo; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /FileMasta/Controls/SplashScreen.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace FileMasta.Controls 4 | { 5 | public partial class SplashScreen : UserControl 6 | { 7 | public SplashScreen() 8 | { 9 | InitializeComponent(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /FileMasta/Controls/SplashScreen.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 25 122 | 123 | -------------------------------------------------------------------------------- /FileMasta/Extensions/ControlExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.IO; 4 | using System.Windows.Forms; 5 | using FileMasta.Forms; 6 | 7 | namespace FileMasta.Extensions 8 | { 9 | internal abstract class ControlExtensions 10 | { 11 | /// 12 | /// Shows raw text from the specified URL in a window box 13 | /// 14 | /// Text to display in title 15 | /// Text to display in title 16 | /// URL to fetch string data from 17 | public static void ShowDataWindow(Form owner, string title, string url) 18 | { 19 | DataViewWindow frmInfo = new DataViewWindow { Text = title }; 20 | 21 | //using (var client = Program._webClient) 22 | using (Stream stream = Program.WebClient.OpenRead(url)) 23 | using (StreamReader reader = new StreamReader(stream ?? throw new InvalidOperationException("Unable to read data"))) 24 | frmInfo.labelData.Text = reader.ReadToEnd(); 25 | 26 | frmInfo.MaximumSize = new Size(frmInfo.MaximumSize.Width, owner.Height - 100); 27 | frmInfo.ShowDialog(owner); 28 | } 29 | 30 | /// 31 | /// Change button text and auto size 32 | /// 33 | /// Control to set text 34 | /// Text to set to control 35 | public static void SetControlTextWidth(Button ctrl, string text) 36 | { 37 | ctrl.Text = text; 38 | Font myFont = new Font(ctrl.Font.FontFamily, ctrl.Font.Size); 39 | SizeF mySize = ctrl.CreateGraphics().MeasureString(ctrl.Text, myFont); 40 | ctrl.Width = (int)Math.Round(mySize.Width, 0) + 22; 41 | ctrl.Refresh(); 42 | } 43 | 44 | /// 45 | /// Create a keyword label from template 46 | /// 47 | /// Most Search text/value 48 | /// Most Search text/value 49 | /// 50 | public static Label KeywordLabel(string text, EventHandler clickEvent) 51 | { 52 | Label a = new Label 53 | { 54 | Text = text, 55 | TextAlign = ContentAlignment.MiddleCenter, 56 | Font = new Font("Verdana", 8.25F, FontStyle.Regular | FontStyle.Underline), 57 | AutoSize = true, 58 | BackColor = Color.Transparent, 59 | ForeColor = Color.Black, 60 | Margin = new Padding(0, 0, 0, 1), 61 | Cursor = Cursors.Hand, 62 | Name = "LabelKeyword", 63 | }; 64 | 65 | // Click event performs a search in main form 66 | a.Click += clickEvent; 67 | 68 | return a; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /FileMasta/Extensions/DateTimeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FileMasta.Extensions 4 | { 5 | internal abstract class DateTimeExtensions 6 | { 7 | /// 8 | /// Parse a Unix TimeStamp to DateTime 9 | /// 10 | /// TimeStamp in Seconds 11 | /// 12 | public static DateTime ParseTimeStamp(double timeStamp) 13 | { 14 | DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 15 | dt = dt.AddSeconds(timeStamp).ToLocalTime(); 16 | return dt; 17 | } 18 | 19 | /// 20 | /// Get age from DateTime 21 | /// 22 | /// 23 | /// 24 | public static string TimeSpanAge(DateTime date) 25 | { 26 | const int second = 1; 27 | const int minute = 60 * second; 28 | const int hour = 60 * minute; 29 | const int day = 24 * hour; 30 | const int month = 30 * day; 31 | 32 | TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - date.Ticks); 33 | double delta = Math.Abs(ts.TotalSeconds); 34 | 35 | if (delta < 1 * minute) 36 | return ts.Seconds == 1 ? "1 second" : ts.Seconds + " seconds"; 37 | 38 | if (delta < 2 * minute) 39 | return "1 minute"; 40 | 41 | if (delta < 45 * minute) 42 | return ts.Minutes + " minutes"; 43 | 44 | if (delta < 90 * minute) 45 | return "1 hour"; 46 | 47 | if (delta < 24 * hour) 48 | return ts.Hours + " hours"; 49 | 50 | if (delta < 48 * hour) 51 | return "1 day"; 52 | 53 | if (delta < 30 * day) 54 | return ts.Days + " days"; 55 | 56 | if (delta < 12 * month) { 57 | int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30)); 58 | return months <= 1 ? "1 month" : months + " months"; 59 | } 60 | 61 | int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365)); 62 | return years <= 1 ? "1 year" : years + " years"; 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /FileMasta/Extensions/ExceptionExtensions.cs: -------------------------------------------------------------------------------- 1 | using FileMasta.Core.Extensions; 2 | using System; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using System.Windows.Forms; 8 | 9 | namespace FileMasta.Extensions 10 | { 11 | public static class ExceptionExtensions 12 | { 13 | private static Task RunLoop(StackTrace st) 14 | { 15 | StackFrame frame = st.GetFrame(4); 16 | for (int i = 0; i >= st.GetFrames().Length; i++) 17 | { 18 | if (st.GetFrame(i).GetFileLineNumber() <= 0) continue; 19 | frame = st.GetFrame(i); 20 | break; 21 | } 22 | return Task.Factory.StartNew(() => frame); 23 | } 24 | 25 | public static async void ApplicationThreadException(object sender, ThreadExceptionEventArgs e) 26 | { 27 | StackTrace st = new StackTrace(e.Exception, true); 28 | StackFrame frame = await RunLoop(st); 29 | 30 | string fileName = frame.GetFileName(); 31 | string methodName = frame.GetMethod().Name; 32 | int line = frame.GetFileLineNumber(); 33 | int col = frame.GetFileColumnNumber(); 34 | 35 | Program.Log.Error("Unexpected Error", e.Exception); 36 | 37 | if (MessageBox.Show(@"An error has occurred. Would you like to report this issue on GitHub? Your feedback helps us improve the quality of FileMasta, we appreciate that.", @"Error", MessageBoxButtons.YesNo) == DialogResult.Yes) 38 | { 39 | Process.Start($"{Configuration.ProjectUrl}issues/new?title=[Exception] {e.Exception.Message}&body=" + 40 | "*Please explain the problem, be clear and not vague.*%0A%0A" + 41 | "__Expected behavior__: %0A" + 42 | "__Actual behavior__: %0A" + 43 | "__Steps to reproduce the behavior__: %0A" + 44 | "%0A ----------------------- %0A" + 45 | "Version: " + Application.ProductVersion + 46 | "%0AFile Name: " + Path.GetFileName(fileName) + 47 | "%0AMethod Name: " + methodName + 48 | "%0ALine: " + line + 49 | "%0AColumn: " + col + 50 | "%0A ----------------------- %0A" + 51 | e.Exception); 52 | } 53 | } 54 | 55 | public static async void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) 56 | { 57 | StackTrace st = new StackTrace((Exception)e.ExceptionObject, true); 58 | StackFrame frame = await RunLoop(st); 59 | 60 | string fileName = frame.GetFileName(); 61 | string methodName = frame.GetMethod().Name; 62 | int line = frame.GetFileLineNumber(); 63 | int col = frame.GetFileColumnNumber(); 64 | 65 | Program.Log.Error("Unexpected Error", ((Exception)e.ExceptionObject)); 66 | 67 | if (MessageBox.Show(@"An error has occurred. Would you like to report this issue on GitHub? Your feedback helps us improve the quality of FileMasta, we appreciate that.", @"Error", MessageBoxButtons.YesNo) == DialogResult.Yes) 68 | { 69 | Process.Start($"{Configuration.ProjectUrl}issues/new?title=[Exception] {((Exception)e.ExceptionObject).Message}&body=" + 70 | "*Please explain the problem, be clear and not vague.*%0A%0A" + 71 | "__Expected behavior__: %0A" + 72 | "__Actual behavior__: %0A" + 73 | "__Steps to reproduce the behavior__: %0A" + 74 | "%0A ----------------------- %0A" + 75 | "Version: " + Application.ProductVersion + 76 | "%0AFile Name: " + Path.GetFileName(fileName) + 77 | "%0AMethod Name: " + methodName + 78 | "%0ALine: " + line + 79 | "%0AColumn: " + col + 80 | "%0A ----------------------- %0A" + 81 | (Exception)e.ExceptionObject); 82 | } 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /FileMasta/Extensions/LocalExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace FileMasta.Extensions 5 | { 6 | internal static class LocalExtensions 7 | { 8 | /// 9 | /// Supported media players 10 | /// 11 | public const string PathVlc = @"C:\Program Files (x86)\VideoLAN\VLC\vlc.exe"; 12 | public const string PathMpcCodec64 = @"C:\Program Files(x86)\K-Lite Codec Pack\MPC-HC64\mpc-hc64.exe"; 13 | public const string PathMpc64 = @"C:\Program Files\MPC-HC\mpc-hc64.exe"; 14 | public const string PathMpc86 = @"C:\Program Files (x86)\MPC-HC\mpc-hc.exe"; 15 | public const string PathKmPlayer = @"C:\KMPlayer\KMPlayer.exe"; 16 | public const string PathPotPlayer = @"C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe"; 17 | 18 | /// 19 | /// Supported PDF viewers 20 | /// 21 | public const string PathNitroReader = @"C:\Program Files\Nitro\Reader 5\NitroPDFReader.exe"; 22 | 23 | /// 24 | /// Supported download managers 25 | /// 26 | public const string PathIdm64 = @"C:\Program Files\Internet Download Manager\IDMan.exe"; 27 | public const string PathIdm86 = @"C:\Program Files (x86)\Internet Download Manager\IDMan.exe"; 28 | public const string PathFdm = @"C:\Program Files\FreeDownloadManager.ORG\Free Download Manager\fdm.exe"; 29 | public const string PathIda = @"C:\Program Files (x86)\IDA\ida.exe"; 30 | } 31 | 32 | /// 33 | /// Class containing methods to retrieve specific file system paths. 34 | /// 35 | public static class KnownFolders 36 | { 37 | private static readonly string[] KnownFoldersGuid = new string[] 38 | { 39 | "{56784854-C6CB-462B-8169-88E350ACB882}", // Contacts 40 | "{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}", // Desktop 41 | "{FDD39AD0-238F-46AF-ADB4-6C85480369C7}", // Documents 42 | "{374DE290-123F-4565-9164-39C4925E467B}", // Downloads 43 | "{1777F761-68AD-4D8A-87BD-30B759FA33DD}", // Favorites 44 | "{BFB9D5E0-C6A9-404C-B2B2-AE6DB6AF4968}", // Links 45 | "{4BD8D571-6D19-48D3-BE97-422220080E43}", // Music 46 | "{33E28130-4E1E-4676-835A-98395C3BC3BB}", // Pictures 47 | "{4C5C32FF-BB9D-43B0-B5B4-2D72E54EAAA4}", // SavedGames 48 | "{7D1D3A04-DEBB-4115-95CF-2F29DA2920DA}", // SavedSearches 49 | "{18989B1D-99B5-455B-841C-AB7C74E4DDFC}", // Videos 50 | }; 51 | 52 | /// 53 | /// Gets the current path to the specified known folder as currently configured. This does 54 | /// not require the folder to be existent. 55 | /// 56 | /// The known folder which current path will be returned. 57 | /// Specifies if the paths of the default user (user profile template) will be used. 58 | /// This requires administrative rights. 59 | /// The default path of the known folder. 60 | /// Thrown if the path could not be retrieved. 61 | public static string GetPath(KnownFolder knownFolder, bool defaultUser = false) 62 | { 63 | return GetPath(knownFolder, KnownFolderFlags.DoNotVerify, defaultUser); 64 | } 65 | 66 | private static string GetPath(KnownFolder knownFolder, KnownFolderFlags flags, 67 | bool defaultUser) 68 | { 69 | int result = SHGetKnownFolderPath(new Guid(KnownFoldersGuid[(int)knownFolder]), 70 | (uint)flags, new IntPtr(defaultUser ? -1 : 0), out IntPtr outPath); 71 | if (result >= 0) 72 | { 73 | return Marshal.PtrToStringUni(outPath); 74 | } 75 | else 76 | { 77 | throw new ExternalException("Unable to retrieve the known folder path. It may not " 78 | + "be available on this system.", result); 79 | } 80 | } 81 | 82 | [DllImport("Shell32.dll")] 83 | private static extern int SHGetKnownFolderPath( 84 | [MarshalAs(UnmanagedType.LPStruct)]Guid rfid, uint dwFlags, IntPtr hToken, 85 | out IntPtr pszPath); 86 | 87 | [Flags] 88 | private enum KnownFolderFlags : uint 89 | { 90 | SimpleIdList = 0x00000100, 91 | NotParentRelative = 0x00000200, 92 | DefaultPath = 0x00000400, 93 | Init = 0x00000800, 94 | NoAlias = 0x00001000, 95 | DoNotVerify = 0x00004000, 96 | Create = 0x00008000, 97 | NoAppContainerRedirection = 0x00010000, 98 | AliasOnly = 0x80000000 99 | } 100 | } 101 | 102 | /// 103 | /// Standard folders registered with the system. These folders are installed with Windows Vista 104 | /// and later operating systems, and a computer will have only folders appropriate to it installed. 105 | /// 106 | public enum KnownFolder 107 | { 108 | Contacts, 109 | Desktop, 110 | Documents, 111 | Downloads, 112 | Favorites, 113 | Links, 114 | Music, 115 | Pictures, 116 | SavedGames, 117 | SavedSearches, 118 | Videos 119 | } 120 | } -------------------------------------------------------------------------------- /FileMasta/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace FileMasta.Extensions 4 | { 5 | internal abstract class StringExtensions 6 | { 7 | /// 8 | /// Gets the file name from url 9 | /// 10 | /// File Url 11 | /// File Name 12 | public static string GetFileName(string url) 13 | { 14 | return Uri.EscapeDataString(url.Substring(url.LastIndexOf('/') + 1)); 15 | } 16 | 17 | /// 18 | /// Gets the file extension from url 19 | /// 20 | /// File Url 21 | /// File Name 22 | public static string GetFileExtension(string url) 23 | { 24 | return url.Substring(url.LastIndexOf('.') + 1); 25 | } 26 | 27 | /// 28 | /// Return the value represented as string with commas 29 | /// 30 | /// 31 | /// 32 | public static string FormatNumber(long value) 33 | { 34 | return $"{Convert.ToInt32(value):n0}"; 35 | } 36 | 37 | /// 38 | /// Size suffixes 39 | /// 40 | private static readonly string[] SizeSuffixes = { "Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; 41 | 42 | /// 43 | /// Return file size with suffix e.g. Bytes, MB, GB 44 | /// 45 | /// 46 | /// Bytes in string format 47 | public static string BytesToPrefix(long byteCount) 48 | { 49 | if (byteCount == 0) 50 | return "0" + " " + SizeSuffixes[0]; 51 | long bytes = Math.Abs(byteCount); 52 | int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024))); 53 | double num = Math.Round(bytes / Math.Pow(1024, place), 1); 54 | return (Math.Sign(byteCount) * num) + " " + SizeSuffixes[place]; 55 | } 56 | 57 | /// 58 | /// Return the total number of bytes from parsing the size prefix 59 | /// 60 | /// 61 | /// 62 | public static long ParseFileSize(string prefixSize) 63 | { 64 | // Remove leading and trailing spaces. 65 | prefixSize = prefixSize.Trim(); 66 | 67 | try 68 | { 69 | // Find the last non-alphabetic character. 70 | int extStart = 0; 71 | for (int i = prefixSize.Length - 1; i >= 0; i--) 72 | { 73 | // Stop if we find something other than a letter. 74 | if (char.IsLetter(prefixSize, i)) continue; 75 | extStart = i + 1; 76 | break; 77 | } 78 | 79 | // Get the numeric part. 80 | double number = double.Parse(prefixSize.Substring(0, extStart)); 81 | 82 | // Get the extension. 83 | string suffix; 84 | if (extStart < prefixSize.Length) 85 | { 86 | suffix = prefixSize.Substring(extStart).Trim(); 87 | if (suffix == "BYTES") suffix = "Bytes"; 88 | } 89 | else 90 | { 91 | suffix = "Bytes"; 92 | } 93 | 94 | // Find the extension in the list. 95 | int suffixIndex = -1; 96 | for (int i = 0; i < SizeSuffixes.Length; i++) 97 | { 98 | if (SizeSuffixes[i] != suffix) continue; 99 | suffixIndex = i; 100 | break; 101 | } 102 | if (suffixIndex < 0) 103 | throw new FormatException( 104 | "Unknown file size prefix " + suffix + "."); 105 | 106 | // Return the result. 107 | return (long)Math.Round(number * Math.Pow(1024, suffixIndex)); 108 | } 109 | catch (Exception ex) 110 | { 111 | throw new FormatException("Invalid file size format", ex); 112 | } 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /FileMasta/FileMasta.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {75A2CFC6-B0B1-42A6-B1F7-66B3C68A06CA} 8 | WinExe 9 | Properties 10 | FileMasta 11 | FileMasta 12 | v4.7.1 13 | 512 14 | true 15 | 16 | false 17 | 18 | 19 | publish\ 20 | true 21 | Disk 22 | false 23 | Foreground 24 | 7 25 | Days 26 | false 27 | false 28 | true 29 | 0 30 | 1.0.0.%2a 31 | false 32 | true 33 | 34 | 35 | AnyCPU 36 | true 37 | full 38 | false 39 | bin\Debug\ 40 | TRACE;DEBUG 41 | prompt 42 | 4 43 | false 44 | 45 | 46 | AnyCPU 47 | pdbonly 48 | true 49 | bin\Release\ 50 | TRACE;mono 51 | prompt 52 | 4 53 | 54 | 55 | app-logo.ico 56 | 57 | 58 | false 59 | 60 | 61 | FileMasta.Program 62 | 63 | 64 | 65 | ..\..\..\- Plugins\CButton\bin\Debug\CButtonLib.dll 66 | False 67 | 68 | 69 | ..\..\..\- Plugins\ChreneLib_DLL\ChreneLib.dll 70 | False 71 | 72 | 73 | ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | Form 101 | 102 | 103 | BookmarksWindow.cs 104 | 105 | 106 | 107 | 108 | Form 109 | 110 | 111 | AboutWindow.cs 112 | 113 | 114 | Form 115 | 116 | 117 | OptionsWindow.cs 118 | 119 | 120 | True 121 | True 122 | Resources.resx 123 | 124 | 125 | Form 126 | 127 | 128 | DataViewWindow.cs 129 | 130 | 131 | 132 | UserControl 133 | 134 | 135 | SplashScreen.cs 136 | 137 | 138 | Form 139 | 140 | 141 | MainForm.cs 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | AboutWindow.cs 151 | 152 | 153 | SplashScreen.cs 154 | 155 | 156 | BookmarksWindow.cs 157 | 158 | 159 | OptionsWindow.cs 160 | 161 | 162 | DataViewWindow.cs 163 | 164 | 165 | MainForm.cs 166 | 167 | 168 | ResXFileCodeGenerator 169 | Designer 170 | Resources.Designer.cs 171 | 172 | 173 | Always 174 | 175 | 176 | 177 | SettingsSingleFileGenerator 178 | Settings.Designer.cs 179 | 180 | 181 | True 182 | Settings.settings 183 | True 184 | 185 | 186 | 187 | 188 | Designer 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | False 199 | Microsoft .NET Framework 4.6.2 %28x86 and x64%29 200 | true 201 | 202 | 203 | False 204 | .NET Framework 3.5 SP1 205 | false 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | {2C534550-1884-4BDE-BD7B-B1348E53517B} 218 | FileMasta.Core 219 | 220 | 221 | 222 | 229 | -------------------------------------------------------------------------------- /FileMasta/Forms/AboutWindow.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FileMasta.Forms 2 | { 3 | partial class AboutWindow 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutWindow)); 32 | this.LabelDescription = new System.Windows.Forms.Label(); 33 | this.LabelVersion = new System.Windows.Forms.Label(); 34 | this.LabelCopyrightCredit = new System.Windows.Forms.Label(); 35 | this.ButtonOk = new System.Windows.Forms.Button(); 36 | this.PanelButtons = new System.Windows.Forms.Panel(); 37 | this.LinkProjectURL = new System.Windows.Forms.LinkLabel(); 38 | this.PanelButtons.SuspendLayout(); 39 | this.SuspendLayout(); 40 | // 41 | // LabelDescription 42 | // 43 | this.LabelDescription.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 44 | | System.Windows.Forms.AnchorStyles.Left) 45 | | System.Windows.Forms.AnchorStyles.Right))); 46 | this.LabelDescription.AutoEllipsis = true; 47 | this.LabelDescription.BackColor = System.Drawing.Color.Transparent; 48 | this.LabelDescription.ImeMode = System.Windows.Forms.ImeMode.NoControl; 49 | this.LabelDescription.Location = new System.Drawing.Point(12, 12); 50 | this.LabelDescription.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); 51 | this.LabelDescription.Name = "LabelDescription"; 52 | this.LabelDescription.Size = new System.Drawing.Size(375, 123); 53 | this.LabelDescription.TabIndex = 1; 54 | this.LabelDescription.Text = resources.GetString("LabelDescription.Text"); 55 | // 56 | // LabelVersion 57 | // 58 | this.LabelVersion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 59 | this.LabelVersion.AutoSize = true; 60 | this.LabelVersion.BackColor = System.Drawing.Color.Transparent; 61 | this.LabelVersion.Cursor = System.Windows.Forms.Cursors.Default; 62 | this.LabelVersion.ImeMode = System.Windows.Forms.ImeMode.NoControl; 63 | this.LabelVersion.Location = new System.Drawing.Point(12, 144); 64 | this.LabelVersion.Margin = new System.Windows.Forms.Padding(3, 5, 3, 5); 65 | this.LabelVersion.Name = "LabelVersion"; 66 | this.LabelVersion.Size = new System.Drawing.Size(93, 13); 67 | this.LabelVersion.TabIndex = 17; 68 | this.LabelVersion.Text = "Version 0.0.0.0"; 69 | // 70 | // LabelCopyrightCredit 71 | // 72 | this.LabelCopyrightCredit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 73 | this.LabelCopyrightCredit.AutoSize = true; 74 | this.LabelCopyrightCredit.BackColor = System.Drawing.Color.Transparent; 75 | this.LabelCopyrightCredit.Cursor = System.Windows.Forms.Cursors.Default; 76 | this.LabelCopyrightCredit.ImeMode = System.Windows.Forms.ImeMode.NoControl; 77 | this.LabelCopyrightCredit.Location = new System.Drawing.Point(12, 167); 78 | this.LabelCopyrightCredit.Margin = new System.Windows.Forms.Padding(3, 5, 3, 5); 79 | this.LabelCopyrightCredit.Name = "LabelCopyrightCredit"; 80 | this.LabelCopyrightCredit.Size = new System.Drawing.Size(242, 13); 81 | this.LabelCopyrightCredit.TabIndex = 21; 82 | this.LabelCopyrightCredit.Text = "Copyright © 2018 Ashley Davies (HerbL)"; 83 | // 84 | // ButtonOk 85 | // 86 | this.ButtonOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 87 | this.ButtonOk.DialogResult = System.Windows.Forms.DialogResult.OK; 88 | this.ButtonOk.Location = new System.Drawing.Point(332, 9); 89 | this.ButtonOk.Name = "ButtonOk"; 90 | this.ButtonOk.Size = new System.Drawing.Size(56, 24); 91 | this.ButtonOk.TabIndex = 0; 92 | this.ButtonOk.Text = "Ok"; 93 | this.ButtonOk.UseVisualStyleBackColor = true; 94 | // 95 | // PanelButtons 96 | // 97 | this.PanelButtons.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 98 | | System.Windows.Forms.AnchorStyles.Right))); 99 | this.PanelButtons.BackColor = System.Drawing.SystemColors.AppWorkspace; 100 | this.PanelButtons.Controls.Add(this.ButtonOk); 101 | this.PanelButtons.Location = new System.Drawing.Point(0, 219); 102 | this.PanelButtons.Margin = new System.Windows.Forms.Padding(0); 103 | this.PanelButtons.Name = "PanelButtons"; 104 | this.PanelButtons.Size = new System.Drawing.Size(399, 42); 105 | this.PanelButtons.TabIndex = 26; 106 | // 107 | // LinkProjectURL 108 | // 109 | this.LinkProjectURL.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 110 | this.LinkProjectURL.AutoSize = true; 111 | this.LinkProjectURL.Cursor = System.Windows.Forms.Cursors.Hand; 112 | this.LinkProjectURL.Location = new System.Drawing.Point(12, 190); 113 | this.LinkProjectURL.Margin = new System.Windows.Forms.Padding(3, 5, 3, 5); 114 | this.LinkProjectURL.Name = "LinkProjectURL"; 115 | this.LinkProjectURL.Size = new System.Drawing.Size(218, 13); 116 | this.LinkProjectURL.TabIndex = 2; 117 | this.LinkProjectURL.TabStop = true; 118 | this.LinkProjectURL.Text = "https://github.com/mostlyash/filemasta"; 119 | this.LinkProjectURL.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkProjectURL_LinkClicked); 120 | // 121 | // AboutWindow 122 | // 123 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 13F); 124 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 125 | this.ClientSize = new System.Drawing.Size(399, 261); 126 | this.Controls.Add(this.PanelButtons); 127 | this.Controls.Add(this.LabelCopyrightCredit); 128 | this.Controls.Add(this.LinkProjectURL); 129 | this.Controls.Add(this.LabelVersion); 130 | this.Controls.Add(this.LabelDescription); 131 | this.DoubleBuffered = true; 132 | this.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 133 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; 134 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 135 | this.MaximizeBox = false; 136 | this.MinimizeBox = false; 137 | this.Name = "AboutWindow"; 138 | this.ShowIcon = false; 139 | this.ShowInTaskbar = false; 140 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; 141 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 142 | this.Text = "About"; 143 | this.Load += new System.EventHandler(this.AboutWindow_Load); 144 | this.PanelButtons.ResumeLayout(false); 145 | this.ResumeLayout(false); 146 | this.PerformLayout(); 147 | 148 | } 149 | 150 | #endregion 151 | 152 | private System.Windows.Forms.Label LabelDescription; 153 | private System.Windows.Forms.Label LabelVersion; 154 | private System.Windows.Forms.Label LabelCopyrightCredit; 155 | private System.Windows.Forms.Button ButtonOk; 156 | private System.Windows.Forms.Panel PanelButtons; 157 | private System.Windows.Forms.LinkLabel LinkProjectURL; 158 | } 159 | } -------------------------------------------------------------------------------- /FileMasta/Forms/AboutWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Windows.Forms; 4 | 5 | namespace FileMasta.Forms 6 | { 7 | public partial class AboutWindow : Form 8 | { 9 | public AboutWindow() 10 | { 11 | InitializeComponent(); 12 | } 13 | 14 | /// 15 | /// Returns this process bit version 16 | /// 17 | /// 18 | public static string GetBitProcess() { if (Environment.Is64BitProcess) return "x64"; else return "x32"; } 19 | 20 | private void AboutWindow_Load(object sender, EventArgs e) 21 | { 22 | LabelVersion.Text = string.Format("Version {0} ({1})", Application.ProductVersion, GetBitProcess()); 23 | } 24 | 25 | private void LinkProjectURL_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 26 | { 27 | Process.Start(LinkProjectURL.Text); 28 | } 29 | 30 | /*************************************************************************/ 31 | /* Keyboard Shortcuts */ 32 | /*************************************************************************/ 33 | 34 | protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 35 | { 36 | switch (keyData) 37 | { 38 | // Close this instance 39 | case Keys.Escape: 40 | Close(); 41 | return true; 42 | } 43 | return base.ProcessCmdKey(ref msg, keyData); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /FileMasta/Forms/BookmarksWindow.cs: -------------------------------------------------------------------------------- 1 | using FileMasta.Core; 2 | using FileMasta.Core.Extensions; 3 | using FileMasta.Core.Models; 4 | using FileMasta.Extensions; 5 | using System; 6 | using System.Data; 7 | using System.Diagnostics; 8 | using System.IO; 9 | using System.Linq; 10 | using System.Windows.Forms; 11 | 12 | namespace FileMasta 13 | { 14 | public partial class BookmarksWindow : Form 15 | { 16 | public OdDatabase DataCache { get; set; } 17 | 18 | public BookmarksWindow() 19 | { 20 | InitializeComponent(); 21 | 22 | ListboxSearchType.SelectedIndex = 0; 23 | DropdownSearchSort.SelectedIndex = 0; 24 | DropdownSearchSizePrefix.SelectedIndex = 0; 25 | DateTimeMaxMTime.Value = DateTime.Now; 26 | } 27 | 28 | private void BookmarksWindow_Load(object sender, EventArgs e) 29 | { 30 | SetStatus("Loading bookmarked files"); 31 | Program.Log.InfoFormat("Loading bookmarked files"); 32 | EnableSearchControls(false); 33 | 34 | ListboxSearchType.SelectedIndex = 0; 35 | DropdownSearchSort.SelectedIndex = 0; 36 | DropdownSearchSizePrefix.SelectedIndex = 0; 37 | DateTimeMaxMTime.Value = DateTime.Now; 38 | 39 | DataGridFiles.Rows.Clear(); 40 | foreach (FileItem file in MainForm.Form.DataCache.Bookmarked) 41 | { 42 | _ = DataGridFiles.Rows.Add(file.Name, StringExtensions.BytesToPrefix(file.Size), file.Mtime.ToLocalTime(), file.Url); 43 | } 44 | 45 | StatusStripDatabaseInfo.Text = string.Format(StatusStripDatabaseInfo.Text, MainForm.Form.DataCache.Bookmarked); 46 | SetStatus("Loaded bookmarked files"); 47 | EnableSearchControls(true); 48 | } 49 | 50 | /// 51 | /// Search preference: Type 52 | /// 53 | private string[] SearchFileType { get; set; } = FileType.All.ToArray(); 54 | 55 | /// 56 | /// Search preference: Type 57 | /// 58 | private string SearchSizePrefix { get; set; } = "Bytes"; 59 | 60 | /// 61 | /// Search preference: Sort 62 | /// 63 | private Sort SearchSortBy { get; set; } = Sort.Name; 64 | 65 | private void TextboxSearchName_KeyDown(object sender, KeyEventArgs e) 66 | { 67 | if (e.KeyCode != Keys.Enter) return; 68 | PerformSearchAsync(); 69 | } 70 | 71 | private void ButtonSearch_Click(object sender, EventArgs e) 72 | { 73 | PerformSearchAsync(); 74 | } 75 | 76 | private void ListboxSearchType_SelectedIndexChanged(object sender, EventArgs e) 77 | { 78 | switch (ListboxSearchType.SelectedIndex) 79 | { 80 | case 0: 81 | SearchFileType = FileType.All; 82 | break; 83 | case 1: 84 | SearchFileType = FileType.Audio; 85 | break; 86 | case 2: 87 | SearchFileType = FileType.Compressed; 88 | break; 89 | case 3: 90 | SearchFileType = FileType.Document; 91 | break; 92 | case 4: 93 | SearchFileType = FileType.Executable; 94 | break; 95 | case 5: 96 | SearchFileType = FileType.Picture; 97 | break; 98 | case 6: 99 | SearchFileType = FileType.Video; 100 | break; 101 | } 102 | } 103 | 104 | private void DropdownSearchSizePrefix_SelectedIndexChanged(object sender, EventArgs e) 105 | { 106 | SearchSizePrefix = DropdownSearchSizePrefix.GetItemText(DropdownSearchSizePrefix.SelectedItem); 107 | } 108 | 109 | private void DropdownSearchSort_SelectedIndexChanged(object sender, EventArgs e) 110 | { 111 | switch (DropdownSearchSort.SelectedIndex) 112 | { 113 | case 0: 114 | SearchSortBy = Sort.Name; 115 | break; 116 | case 1: 117 | SearchSortBy = Sort.Size; 118 | break; 119 | case 2: 120 | SearchSortBy = Sort.Date; 121 | break; 122 | } 123 | } 124 | 125 | private async void PerformSearchAsync() 126 | { 127 | SetStatus("Searching..."); 128 | 129 | Program.Log.InfoFormat( 130 | "Searching bookmarks with the following filters: Name: {0}, Sort: {1}, Type: {2}, Size : {3}, Last Modified : {4} to {5}", 131 | TextboxSearchName.Text, 132 | SearchSortBy.ToString(), 133 | SearchFileType.ToArray(), 134 | NumericSearchGreaterThan.Value, 135 | DateTimeMinMTime.Value, 136 | DateTimeMaxMTime.Value); 137 | 138 | EnableSearchControls(false); 139 | DataGridFiles.Rows.Clear(); 140 | var timer = new Stopwatch(); 141 | timer.Start(); 142 | 143 | foreach (FileItem file in 144 | from DataItem bookmark in 145 | await DataCache.SearchBookmarked( 146 | TextboxSearchName.Text, 147 | SearchFileType, 148 | StringExtensions.ParseFileSize($"{NumericSearchGreaterThan.Value} {SearchSizePrefix}"), 149 | DateTimeMinMTime.Value, 150 | DateTimeMaxMTime.Value) 151 | let file = FileExtensions.DataItemToFile(bookmark) 152 | select file) 153 | { 154 | _ = DataGridFiles.Rows.Add(file.Name, 155 | StringExtensions.BytesToPrefix(file.Size), 156 | file.Mtime.ToLocalTime(), 157 | file.Url); 158 | } 159 | 160 | timer.Stop(); 161 | SetStatus($"{StringExtensions.FormatNumber(DataGridFiles.Rows.Count)} Results ({timer.Elapsed.TotalSeconds:0.000} seconds)"); 162 | timer.Reset(); 163 | EnableSearchControls(true); 164 | } 165 | 166 | private void DataGridFiles_SelectionChanged(object sender, EventArgs e) 167 | { 168 | PanelFileDetails.Enabled = DataGridFiles.SelectedRows.Count != 0; 169 | 170 | if (DataGridFiles.CurrentRow == null) return; 171 | SelectedFile = FileExtensions.CreateFile(DateTime.Parse(DataGridFiles.CurrentRow.Cells[2].Value.ToString()), StringExtensions.ParseFileSize(DataGridFiles.CurrentRow.Cells[1].Value.ToString()), DataGridFiles.CurrentRow.Cells[3].Value.ToString()); 172 | DisplayFileDetails(SelectedFile); 173 | } 174 | 175 | private void DataGridFiles_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e) 176 | { 177 | e.PaintParts &= DataGridViewPaintParts.All & ~DataGridViewPaintParts.Focus; 178 | } 179 | 180 | private void DataGridFiles_CellDoubleClick(object sender, DataGridViewCellEventArgs e) 181 | { 182 | if (e.RowIndex != -1) 183 | DisplayFileDetails(SelectedFile); 184 | } 185 | 186 | private void DataGridFiles_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) 187 | { 188 | e.Paint(e.CellBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.Focus); 189 | e.Handled = true; 190 | } 191 | 192 | private void ButtonFileRequestSize_Click(object sender, EventArgs e) 193 | { 194 | ButtonRequestSize.Visible = false; 195 | LabelFileValueSize.Text = StringExtensions.BytesToPrefix(SelectedFile.Size); 196 | } 197 | 198 | private void ButtonFileDownload_Click(object sender, EventArgs e) 199 | { 200 | try 201 | { 202 | Process.Start(SelectedFile.Url); 203 | } 204 | catch (Exception ex) 205 | { 206 | SetStatus("There was an issue downloading the file. " + ex.Message); 207 | } 208 | } 209 | 210 | private void ButtonFileOpenWith_Click(object sender, EventArgs e) 211 | { 212 | ContextFileOpenWith.Show(ButtonOpenWith, ButtonOpenWith.PointToClient(Cursor.Position)); 213 | } 214 | 215 | private void ButtonFileSave_Click(object sender, EventArgs e) 216 | { 217 | if (DataCache.IsBookmarked(SelectedFile)) 218 | { 219 | DataCache.RemoveBookmark(SelectedFile); 220 | ControlExtensions.SetControlTextWidth(ButtonBookmark, "Bookmark"); 221 | } 222 | else 223 | { 224 | DataCache.AddBookmark(SelectedFile); 225 | ControlExtensions.SetControlTextWidth(ButtonBookmark, "Unbookmark"); 226 | } 227 | } 228 | 229 | private FileItem SelectedFile { get; set; } 230 | 231 | /// 232 | /// Display selected file information in the details pane 233 | /// 234 | /// WebFile object 235 | private void DisplayFileDetails(FileItem file) 236 | { 237 | Program.Log.Info("Selected file " + file.Url); 238 | 239 | SelectedFile = file; 240 | LabelFileValueName.Text = Path.GetFileNameWithoutExtension(file.Name); 241 | LabelFileValueSize.Text = StringExtensions.BytesToPrefix(file.Size); 242 | LabelFileValueDomain.Text = new Uri(file.Url).Host; 243 | LabelFileValueModified.Text = file.Mtime.ToShortTimeString(); 244 | LabelFileValueAge.Text = DateTimeExtensions.TimeSpanAge(file.Mtime); 245 | LabelFileValueExtension.Text = file.GetExtension().ToUpper(); 246 | LabelFileValueURL.Text = Uri.UnescapeDataString(file.Url); 247 | LabelFileUrlBG.Height = LabelFileValueURL.Height + 17; 248 | 249 | foreach (ToolStripMenuItem item in ContextFileOpenWith.Items) 250 | item.Visible = false; 251 | 252 | if (FileType.Document.Contains(StringExtensions.GetFileExtension(file.Url))) 253 | { 254 | NitroReaderToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathNitroReader); 255 | } 256 | 257 | if (FileType.Video.Contains(StringExtensions.GetFileExtension(file.Url)) || FileType.Audio.Contains(file.GetExtension())) 258 | { 259 | WMPToolStripMenuItem.Visible = true; 260 | VLCToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathVlc); 261 | MPCToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathMpcCodec64) || File.Exists(LocalExtensions.PathMpc64) || File.Exists(LocalExtensions.PathMpc86); 262 | KMPlayerToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathKmPlayer); 263 | PotPlayerToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathPotPlayer); 264 | } 265 | 266 | IDMToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathIdm64) || File.Exists(LocalExtensions.PathIdm86); 267 | IDAToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathIda); 268 | FDMToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathFdm); 269 | 270 | ControlExtensions.SetControlTextWidth(ButtonBookmark, DataCache.IsBookmarked(file) ? "Unbookmark" : "Bookmark"); 271 | 272 | ButtonRequestSize.Visible = file.Size.ToString() == "0"; 273 | ButtonOpenWith.Visible = ContextFileOpenWith.Items.Count > 0; 274 | } 275 | 276 | private void NitroReaderToolStripMenuItem_Click(object sender, EventArgs e) 277 | { 278 | // Open file in Nitro Reader 279 | Process NitroReader = new Process(); 280 | NitroReader.StartInfo.FileName = LocalExtensions.PathNitroReader; 281 | NitroReader.StartInfo.Arguments = (SelectedFile.Url); 282 | NitroReader.Start(); 283 | } 284 | 285 | private void VLCToolStripMenuItem_Click(object sender, EventArgs e) 286 | { 287 | // Open file in VLC player, with subtitles (if found) 288 | using (Process VLC = new Process()) 289 | { 290 | VLC.StartInfo.FileName = LocalExtensions.PathVlc; 291 | VLC.StartInfo.Arguments = ("-vvv " + SelectedFile.Url); 292 | VLC.Start(); 293 | } 294 | } 295 | 296 | private void WMPToolStripMenuItem_Click(object sender, EventArgs e) 297 | { 298 | // Open file in Windows Media Player 299 | Process.Start("wmplayer.exe", SelectedFile.Url); 300 | } 301 | 302 | private void MPCToolStripMenuItem_Click(object sender, EventArgs e) 303 | { 304 | // Open file in Media Player Classic 305 | using (Process MPC = new Process()) 306 | { 307 | if (File.Exists(LocalExtensions.PathMpcCodec64)) 308 | MPC.StartInfo.FileName = LocalExtensions.PathMpcCodec64; 309 | else if (File.Exists(LocalExtensions.PathMpc64)) 310 | MPC.StartInfo.FileName = LocalExtensions.PathMpc64; 311 | else 312 | MPC.StartInfo.FileName = LocalExtensions.PathMpc86; 313 | MPC.StartInfo.Arguments = (SelectedFile.Url); 314 | MPC.Start(); 315 | } 316 | } 317 | 318 | private void KMPlayerToolStripMenuItem_Click(object sender, EventArgs e) 319 | { 320 | // Open file in KM Player 321 | using (Process KMP = new Process()) 322 | { 323 | KMP.StartInfo.FileName = LocalExtensions.PathKmPlayer; 324 | KMP.StartInfo.Arguments = (SelectedFile.Url); 325 | KMP.Start(); 326 | } 327 | } 328 | 329 | private void PotPlayerToolStripMenuItem_Click(object sender, EventArgs e) 330 | { 331 | // Open file in Pot Player 332 | using (Process PP = new Process()) 333 | { 334 | PP.StartInfo.FileName = LocalExtensions.PathPotPlayer; 335 | PP.StartInfo.Arguments = (SelectedFile.Url); 336 | PP.Start(); 337 | } 338 | } 339 | 340 | private void IDMToolStripMenuItem_Click(object sender, EventArgs e) 341 | { 342 | // Open file in Internet Download Manager 343 | using (Process IDM = new Process()) 344 | { 345 | if (File.Exists(LocalExtensions.PathIdm64)) 346 | IDM.StartInfo.FileName = LocalExtensions.PathIdm64; 347 | else 348 | IDM.StartInfo.FileName = LocalExtensions.PathIdm86; 349 | IDM.StartInfo.Arguments = ("-d " + SelectedFile.Url); 350 | IDM.Start(); 351 | } 352 | } 353 | 354 | private void IDAToolStripMenuItem_Click(object sender, EventArgs e) 355 | { 356 | // Open file in Internet Download Accelerator 357 | using (Process FDM = new Process()) 358 | { 359 | FDM.StartInfo.FileName = LocalExtensions.PathIda; 360 | FDM.StartInfo.Arguments = (SelectedFile.Url); 361 | FDM.Start(); 362 | } 363 | } 364 | 365 | private void FDMToolStripMenuItem_Click(object sender, EventArgs e) 366 | { 367 | // Open file in Free Download Manger 368 | using (Process FDM = new Process()) 369 | { 370 | FDM.StartInfo.FileName = LocalExtensions.PathFdm; 371 | FDM.StartInfo.Arguments = (SelectedFile.Url); 372 | FDM.Start(); 373 | } 374 | } 375 | 376 | /// 377 | /// Enable/Disable search controls, to prevent another search process which causes a crash 378 | /// 379 | /// Enable/Disable Controls 380 | private void EnableSearchControls(bool isEnabled) 381 | { 382 | TextboxSearchName.Enabled = isEnabled; 383 | ListboxSearchType.Enabled = isEnabled; 384 | ButtonSearch.Enabled = isEnabled; 385 | NumericSearchGreaterThan.Enabled = isEnabled; 386 | DropdownSearchSizePrefix.Enabled = isEnabled; 387 | DateTimeMinMTime.Enabled = isEnabled; 388 | DateTimeMaxMTime.Enabled = isEnabled; 389 | DropdownSearchSort.Enabled = isEnabled; 390 | } 391 | 392 | /// 393 | /// Set the current status of the application 394 | /// 395 | /// Message/status to be displayed 396 | private void SetStatus(string message) 397 | { 398 | StatusStripStatus.Text = message; 399 | } 400 | 401 | /*************************************************************************/ 402 | /* Keyboard Shortcuts */ 403 | /*************************************************************************/ 404 | 405 | protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 406 | { 407 | switch (keyData) 408 | { 409 | // Focus on Search Box 410 | case Keys.Control | Keys.F: 411 | TextboxSearchName.Focus(); 412 | return true; 413 | // Close application 414 | case Keys.Control | Keys.W: 415 | Application.Exit(); 416 | return true; 417 | } 418 | 419 | return base.ProcessCmdKey(ref msg, keyData); 420 | } 421 | 422 | private void MenuFileViewDetails_Click(object sender, EventArgs e) 423 | { 424 | if (DataGridFiles.SelectedRows.Count > 0) 425 | DisplayFileDetails(SelectedFile); 426 | } 427 | 428 | private void MenuFileBookmark_Click(object sender, EventArgs e) 429 | { 430 | if (DataCache.IsBookmarked(SelectedFile)) 431 | { 432 | DataCache.RemoveBookmark(SelectedFile); 433 | ControlExtensions.SetControlTextWidth(ButtonBookmark, "Bookmark"); 434 | } 435 | else 436 | { 437 | DataCache.AddBookmark(SelectedFile); 438 | ControlExtensions.SetControlTextWidth(ButtonBookmark, "Unbookmark"); 439 | } 440 | } 441 | 442 | private void MenuFileOpen_Click(object sender, EventArgs e) 443 | { 444 | if (DataGridFiles.SelectedRows.Count > 0) 445 | Process.Start(SelectedFile.Url); 446 | } 447 | 448 | private void MenuFileCopyURL_Click(object sender, EventArgs e) 449 | { 450 | if (DataGridFiles.SelectedRows.Count <= 0) return; 451 | Clipboard.SetText(SelectedFile.Url); 452 | SetStatus("Copied File URL to Clipboard"); 453 | } 454 | 455 | private void MenuFileEmail_Click(object sender, EventArgs e) 456 | { 457 | Process.Start("mailto:" + 458 | $"?body=File Report ({ListboxSearchType.SelectedItem})" + 459 | $"&subject=" + 460 | $"Name: {StringExtensions.GetFileName(SelectedFile.Url)} ({ListboxSearchType.SelectedItem})\n\n" + 461 | $"Direct URL: {SelectedFile}\n\n\n\n" + 462 | "Auto-generated by FileMasta: " + Configuration.ProjectUrl); 463 | } 464 | } 465 | } -------------------------------------------------------------------------------- /FileMasta/Forms/DataViewWindow.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FileMasta.Forms 2 | { 3 | partial class DataViewWindow 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DataViewWindow)); 32 | this.panelItems = new System.Windows.Forms.FlowLayoutPanel(); 33 | this.labelData = new System.Windows.Forms.Label(); 34 | this.panelItems.SuspendLayout(); 35 | this.SuspendLayout(); 36 | // 37 | // panelItems 38 | // 39 | this.panelItems.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 40 | | System.Windows.Forms.AnchorStyles.Right))); 41 | this.panelItems.AutoSize = true; 42 | this.panelItems.Controls.Add(this.labelData); 43 | this.panelItems.Font = new System.Drawing.Font("Segoe UI", 9.25F); 44 | this.panelItems.Location = new System.Drawing.Point(14, 12); 45 | this.panelItems.Name = "panelItems"; 46 | this.panelItems.Size = new System.Drawing.Size(436, 56); 47 | this.panelItems.TabIndex = 0; 48 | // 49 | // labelData 50 | // 51 | this.labelData.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 52 | | System.Windows.Forms.AnchorStyles.Left) 53 | | System.Windows.Forms.AnchorStyles.Right))); 54 | this.labelData.AutoSize = true; 55 | this.labelData.BackColor = System.Drawing.Color.Transparent; 56 | this.labelData.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 57 | this.labelData.ForeColor = System.Drawing.Color.Black; 58 | this.labelData.ImeMode = System.Windows.Forms.ImeMode.NoControl; 59 | this.labelData.Location = new System.Drawing.Point(0, 0); 60 | this.labelData.Margin = new System.Windows.Forms.Padding(0); 61 | this.labelData.Name = "labelData"; 62 | this.labelData.Size = new System.Drawing.Size(35, 14); 63 | this.labelData.TabIndex = 0; 64 | this.labelData.Text = "Text"; 65 | // 66 | // DataWindow 67 | // 68 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 13F); 69 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 70 | this.AutoScroll = true; 71 | this.AutoScrollMargin = new System.Drawing.Size(0, 12); 72 | this.AutoSize = true; 73 | this.ClientSize = new System.Drawing.Size(464, 81); 74 | this.Controls.Add(this.panelItems); 75 | this.DoubleBuffered = true; 76 | this.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 77 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 78 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 79 | this.MaximizeBox = false; 80 | this.MaximumSize = new System.Drawing.Size(480, 650); 81 | this.MinimizeBox = false; 82 | this.MinimumSize = new System.Drawing.Size(480, 40); 83 | this.Name = "DataWindow"; 84 | this.ShowIcon = false; 85 | this.ShowInTaskbar = false; 86 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 87 | this.Text = "Title"; 88 | this.Scroll += new System.Windows.Forms.ScrollEventHandler(this.DataDialog_Scroll); 89 | this.panelItems.ResumeLayout(false); 90 | this.panelItems.PerformLayout(); 91 | this.ResumeLayout(false); 92 | this.PerformLayout(); 93 | 94 | } 95 | 96 | #endregion 97 | 98 | private System.Windows.Forms.FlowLayoutPanel panelItems; 99 | public System.Windows.Forms.Label labelData; 100 | } 101 | } -------------------------------------------------------------------------------- /FileMasta/Forms/DataViewWindow.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace FileMasta.Forms 4 | { 5 | public partial class DataViewWindow : Form 6 | { 7 | public DataViewWindow() 8 | { 9 | InitializeComponent(); 10 | } 11 | 12 | private void DataDialog_Scroll(object sender, ScrollEventArgs e) 13 | { 14 | panelItems.Update(); // Stops 'Lag/Bad Drawing' when scrolling 15 | } 16 | 17 | 18 | /*************************************************************************/ 19 | /* Keyboard Shortcuts */ 20 | /*************************************************************************/ 21 | 22 | protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 23 | { 24 | switch (keyData) 25 | { 26 | // Close this instance 27 | case Keys.Escape: 28 | Close(); 29 | return true; 30 | } 31 | return base.ProcessCmdKey(ref msg, keyData); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /FileMasta/Forms/OptionsWindow.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace FileMasta.Forms 2 | { 3 | partial class OptionsWindow 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(OptionsWindow)); 32 | this.textBoxConnectionPassword = new ChreneLib.Controls.TextBoxes.CTextBox(); 33 | this.label4 = new System.Windows.Forms.Label(); 34 | this.textBoxConnectionUsername = new ChreneLib.Controls.TextBoxes.CTextBox(); 35 | this.label3 = new System.Windows.Forms.Label(); 36 | this.textBoxConnectionPort = new ChreneLib.Controls.TextBoxes.CTextBox(); 37 | this.label2 = new System.Windows.Forms.Label(); 38 | this.textBoxConnectionAddress = new ChreneLib.Controls.TextBoxes.CTextBox(); 39 | this.labelConnectionAddress = new System.Windows.Forms.Label(); 40 | this.labelTitleSettings = new System.Windows.Forms.Label(); 41 | this.labelConnectionDefault = new System.Windows.Forms.Label(); 42 | this.checkBoxConnectionDefault = new System.Windows.Forms.CheckBox(); 43 | this.labelTitleGeneral = new System.Windows.Forms.Label(); 44 | this.LabelWorkInProgress = new System.Windows.Forms.Label(); 45 | this.buttonSave = new System.Windows.Forms.Button(); 46 | this.buttonRestore = new System.Windows.Forms.Button(); 47 | this.SuspendLayout(); 48 | // 49 | // textBoxConnectionPassword 50 | // 51 | this.textBoxConnectionPassword.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 52 | this.textBoxConnectionPassword.BackColor = System.Drawing.SystemColors.Control; 53 | this.textBoxConnectionPassword.Font = new System.Drawing.Font("Verdana", 8.25F); 54 | this.textBoxConnectionPassword.ForeColor = System.Drawing.Color.Black; 55 | this.textBoxConnectionPassword.Location = new System.Drawing.Point(262, 219); 56 | this.textBoxConnectionPassword.Name = "textBoxConnectionPassword"; 57 | this.textBoxConnectionPassword.Size = new System.Drawing.Size(266, 21); 58 | this.textBoxConnectionPassword.TabIndex = 38; 59 | this.textBoxConnectionPassword.WaterMark = "Password"; 60 | this.textBoxConnectionPassword.WaterMarkActiveForeColor = System.Drawing.Color.White; 61 | this.textBoxConnectionPassword.WaterMarkFont = new System.Drawing.Font("Segoe UI", 9.25F); 62 | this.textBoxConnectionPassword.WaterMarkForeColor = System.Drawing.SystemColors.WindowFrame; 63 | // 64 | // label4 65 | // 66 | this.label4.AutoSize = true; 67 | this.label4.BackColor = System.Drawing.Color.Transparent; 68 | this.label4.Font = new System.Drawing.Font("Verdana", 8.25F); 69 | this.label4.ImeMode = System.Windows.Forms.ImeMode.NoControl; 70 | this.label4.Location = new System.Drawing.Point(14, 222); 71 | this.label4.Margin = new System.Windows.Forms.Padding(3, 6, 3, 6); 72 | this.label4.Name = "label4"; 73 | this.label4.Size = new System.Drawing.Size(66, 13); 74 | this.label4.TabIndex = 37; 75 | this.label4.Text = "Password:"; 76 | // 77 | // textBoxConnectionUsername 78 | // 79 | this.textBoxConnectionUsername.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 80 | this.textBoxConnectionUsername.BackColor = System.Drawing.SystemColors.Control; 81 | this.textBoxConnectionUsername.Font = new System.Drawing.Font("Verdana", 8.25F); 82 | this.textBoxConnectionUsername.ForeColor = System.Drawing.Color.Black; 83 | this.textBoxConnectionUsername.Location = new System.Drawing.Point(262, 190); 84 | this.textBoxConnectionUsername.Name = "textBoxConnectionUsername"; 85 | this.textBoxConnectionUsername.Size = new System.Drawing.Size(266, 21); 86 | this.textBoxConnectionUsername.TabIndex = 35; 87 | this.textBoxConnectionUsername.WaterMark = "Username"; 88 | this.textBoxConnectionUsername.WaterMarkActiveForeColor = System.Drawing.Color.White; 89 | this.textBoxConnectionUsername.WaterMarkFont = new System.Drawing.Font("Segoe UI", 9.25F); 90 | this.textBoxConnectionUsername.WaterMarkForeColor = System.Drawing.SystemColors.WindowFrame; 91 | // 92 | // label3 93 | // 94 | this.label3.AutoSize = true; 95 | this.label3.BackColor = System.Drawing.Color.Transparent; 96 | this.label3.Font = new System.Drawing.Font("Verdana", 8.25F); 97 | this.label3.ImeMode = System.Windows.Forms.ImeMode.NoControl; 98 | this.label3.Location = new System.Drawing.Point(14, 193); 99 | this.label3.Margin = new System.Windows.Forms.Padding(3, 6, 3, 6); 100 | this.label3.Name = "label3"; 101 | this.label3.Size = new System.Drawing.Size(58, 13); 102 | this.label3.TabIndex = 34; 103 | this.label3.Text = "Address:"; 104 | // 105 | // textBoxConnectionPort 106 | // 107 | this.textBoxConnectionPort.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 108 | this.textBoxConnectionPort.BackColor = System.Drawing.SystemColors.Control; 109 | this.textBoxConnectionPort.Font = new System.Drawing.Font("Verdana", 8.25F); 110 | this.textBoxConnectionPort.ForeColor = System.Drawing.Color.Black; 111 | this.textBoxConnectionPort.Location = new System.Drawing.Point(262, 161); 112 | this.textBoxConnectionPort.Name = "textBoxConnectionPort"; 113 | this.textBoxConnectionPort.Size = new System.Drawing.Size(266, 21); 114 | this.textBoxConnectionPort.TabIndex = 32; 115 | this.textBoxConnectionPort.WaterMark = "Port"; 116 | this.textBoxConnectionPort.WaterMarkActiveForeColor = System.Drawing.Color.White; 117 | this.textBoxConnectionPort.WaterMarkFont = new System.Drawing.Font("Segoe UI", 9.25F); 118 | this.textBoxConnectionPort.WaterMarkForeColor = System.Drawing.SystemColors.WindowFrame; 119 | // 120 | // label2 121 | // 122 | this.label2.AutoSize = true; 123 | this.label2.BackColor = System.Drawing.Color.Transparent; 124 | this.label2.Font = new System.Drawing.Font("Verdana", 8.25F); 125 | this.label2.ImeMode = System.Windows.Forms.ImeMode.NoControl; 126 | this.label2.Location = new System.Drawing.Point(14, 166); 127 | this.label2.Margin = new System.Windows.Forms.Padding(3, 6, 3, 6); 128 | this.label2.Name = "label2"; 129 | this.label2.Size = new System.Drawing.Size(35, 13); 130 | this.label2.TabIndex = 31; 131 | this.label2.Text = "Port:"; 132 | // 133 | // textBoxConnectionAddress 134 | // 135 | this.textBoxConnectionAddress.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 136 | this.textBoxConnectionAddress.BackColor = System.Drawing.SystemColors.Control; 137 | this.textBoxConnectionAddress.Font = new System.Drawing.Font("Verdana", 8.25F); 138 | this.textBoxConnectionAddress.ForeColor = System.Drawing.Color.Black; 139 | this.textBoxConnectionAddress.Location = new System.Drawing.Point(262, 132); 140 | this.textBoxConnectionAddress.Name = "textBoxConnectionAddress"; 141 | this.textBoxConnectionAddress.Size = new System.Drawing.Size(266, 21); 142 | this.textBoxConnectionAddress.TabIndex = 29; 143 | this.textBoxConnectionAddress.WaterMark = "Address"; 144 | this.textBoxConnectionAddress.WaterMarkActiveForeColor = System.Drawing.Color.White; 145 | this.textBoxConnectionAddress.WaterMarkFont = new System.Drawing.Font("Segoe UI", 9.25F); 146 | this.textBoxConnectionAddress.WaterMarkForeColor = System.Drawing.SystemColors.WindowFrame; 147 | // 148 | // labelConnectionAddress 149 | // 150 | this.labelConnectionAddress.AutoSize = true; 151 | this.labelConnectionAddress.BackColor = System.Drawing.Color.Transparent; 152 | this.labelConnectionAddress.Font = new System.Drawing.Font("Verdana", 8.25F); 153 | this.labelConnectionAddress.ImeMode = System.Windows.Forms.ImeMode.NoControl; 154 | this.labelConnectionAddress.Location = new System.Drawing.Point(14, 139); 155 | this.labelConnectionAddress.Margin = new System.Windows.Forms.Padding(3, 6, 3, 6); 156 | this.labelConnectionAddress.Name = "labelConnectionAddress"; 157 | this.labelConnectionAddress.Size = new System.Drawing.Size(58, 13); 158 | this.labelConnectionAddress.TabIndex = 28; 159 | this.labelConnectionAddress.Text = "Address:"; 160 | // 161 | // labelTitleSettings 162 | // 163 | this.labelTitleSettings.AutoSize = true; 164 | this.labelTitleSettings.BackColor = System.Drawing.Color.Transparent; 165 | this.labelTitleSettings.Font = new System.Drawing.Font("Verdana", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 166 | this.labelTitleSettings.ImeMode = System.Windows.Forms.ImeMode.NoControl; 167 | this.labelTitleSettings.Location = new System.Drawing.Point(13, 78); 168 | this.labelTitleSettings.Margin = new System.Windows.Forms.Padding(2, 8, 3, 8); 169 | this.labelTitleSettings.Name = "labelTitleSettings"; 170 | this.labelTitleSettings.Size = new System.Drawing.Size(80, 14); 171 | this.labelTitleSettings.TabIndex = 25; 172 | this.labelTitleSettings.Text = "Connection"; 173 | // 174 | // labelConnectionDefault 175 | // 176 | this.labelConnectionDefault.AutoSize = true; 177 | this.labelConnectionDefault.BackColor = System.Drawing.Color.Transparent; 178 | this.labelConnectionDefault.Font = new System.Drawing.Font("Verdana", 8.25F); 179 | this.labelConnectionDefault.ImeMode = System.Windows.Forms.ImeMode.NoControl; 180 | this.labelConnectionDefault.Location = new System.Drawing.Point(14, 110); 181 | this.labelConnectionDefault.Margin = new System.Windows.Forms.Padding(3, 6, 3, 6); 182 | this.labelConnectionDefault.Name = "labelConnectionDefault"; 183 | this.labelConnectionDefault.Size = new System.Drawing.Size(56, 13); 184 | this.labelConnectionDefault.TabIndex = 26; 185 | this.labelConnectionDefault.Text = "Custom:"; 186 | // 187 | // checkBoxConnectionDefault 188 | // 189 | this.checkBoxConnectionDefault.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 190 | this.checkBoxConnectionDefault.AutoSize = true; 191 | this.checkBoxConnectionDefault.BackColor = System.Drawing.Color.Transparent; 192 | this.checkBoxConnectionDefault.Font = new System.Drawing.Font("Verdana", 8.25F); 193 | this.checkBoxConnectionDefault.ImeMode = System.Windows.Forms.ImeMode.NoControl; 194 | this.checkBoxConnectionDefault.Location = new System.Drawing.Point(266, 110); 195 | this.checkBoxConnectionDefault.Name = "checkBoxConnectionDefault"; 196 | this.checkBoxConnectionDefault.Size = new System.Drawing.Size(15, 14); 197 | this.checkBoxConnectionDefault.TabIndex = 27; 198 | this.checkBoxConnectionDefault.UseVisualStyleBackColor = false; 199 | this.checkBoxConnectionDefault.CheckedChanged += new System.EventHandler(this.CheckBoxConnectionDefault_CheckedChanged); 200 | // 201 | // labelTitleGeneral 202 | // 203 | this.labelTitleGeneral.AutoSize = true; 204 | this.labelTitleGeneral.BackColor = System.Drawing.Color.Transparent; 205 | this.labelTitleGeneral.Font = new System.Drawing.Font("Verdana", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 206 | this.labelTitleGeneral.ImeMode = System.Windows.Forms.ImeMode.NoControl; 207 | this.labelTitleGeneral.Location = new System.Drawing.Point(13, 15); 208 | this.labelTitleGeneral.Margin = new System.Windows.Forms.Padding(2, 6, 3, 8); 209 | this.labelTitleGeneral.Name = "labelTitleGeneral"; 210 | this.labelTitleGeneral.Size = new System.Drawing.Size(59, 14); 211 | this.labelTitleGeneral.TabIndex = 20; 212 | this.labelTitleGeneral.Text = "General"; 213 | // 214 | // LabelWorkInProgress 215 | // 216 | this.LabelWorkInProgress.AutoSize = true; 217 | this.LabelWorkInProgress.BackColor = System.Drawing.Color.Transparent; 218 | this.LabelWorkInProgress.Font = new System.Drawing.Font("Verdana", 8.25F); 219 | this.LabelWorkInProgress.ImeMode = System.Windows.Forms.ImeMode.NoControl; 220 | this.LabelWorkInProgress.Location = new System.Drawing.Point(14, 47); 221 | this.LabelWorkInProgress.Margin = new System.Windows.Forms.Padding(3, 6, 3, 6); 222 | this.LabelWorkInProgress.Name = "LabelWorkInProgress"; 223 | this.LabelWorkInProgress.Size = new System.Drawing.Size(110, 13); 224 | this.LabelWorkInProgress.TabIndex = 21; 225 | this.LabelWorkInProgress.Text = "*work in progress"; 226 | // 227 | // buttonSave 228 | // 229 | this.buttonSave.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 230 | this.buttonSave.Font = new System.Drawing.Font("Verdana", 8.25F); 231 | this.buttonSave.Location = new System.Drawing.Point(474, 256); 232 | this.buttonSave.Name = "buttonSave"; 233 | this.buttonSave.Size = new System.Drawing.Size(56, 23); 234 | this.buttonSave.TabIndex = 40; 235 | this.buttonSave.Text = "Save"; 236 | this.buttonSave.UseVisualStyleBackColor = true; 237 | this.buttonSave.Click += new System.EventHandler(this.ButtonSave_Click); 238 | // 239 | // buttonRestore 240 | // 241 | this.buttonRestore.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 242 | this.buttonRestore.Font = new System.Drawing.Font("Verdana", 8.25F); 243 | this.buttonRestore.Location = new System.Drawing.Point(396, 256); 244 | this.buttonRestore.Name = "buttonRestore"; 245 | this.buttonRestore.Size = new System.Drawing.Size(72, 23); 246 | this.buttonRestore.TabIndex = 41; 247 | this.buttonRestore.Text = "Restore"; 248 | this.buttonRestore.UseVisualStyleBackColor = true; 249 | this.buttonRestore.Click += new System.EventHandler(this.ButtonRestore_Click); 250 | // 251 | // OptionsDialog 252 | // 253 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 13F); 254 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 255 | this.ClientSize = new System.Drawing.Size(544, 291); 256 | this.Controls.Add(this.buttonRestore); 257 | this.Controls.Add(this.buttonSave); 258 | this.Controls.Add(this.textBoxConnectionPassword); 259 | this.Controls.Add(this.label4); 260 | this.Controls.Add(this.textBoxConnectionUsername); 261 | this.Controls.Add(this.label3); 262 | this.Controls.Add(this.textBoxConnectionPort); 263 | this.Controls.Add(this.label2); 264 | this.Controls.Add(this.textBoxConnectionAddress); 265 | this.Controls.Add(this.labelConnectionAddress); 266 | this.Controls.Add(this.labelTitleSettings); 267 | this.Controls.Add(this.labelConnectionDefault); 268 | this.Controls.Add(this.checkBoxConnectionDefault); 269 | this.Controls.Add(this.labelTitleGeneral); 270 | this.Controls.Add(this.LabelWorkInProgress); 271 | this.DoubleBuffered = true; 272 | this.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 273 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 274 | this.MaximizeBox = false; 275 | this.MinimizeBox = false; 276 | this.Name = "OptionsDialog"; 277 | this.ShowIcon = false; 278 | this.ShowInTaskbar = false; 279 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide; 280 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 281 | this.Text = "Options"; 282 | this.Load += new System.EventHandler(this.Options_Load); 283 | this.ResumeLayout(false); 284 | this.PerformLayout(); 285 | 286 | } 287 | 288 | #endregion 289 | 290 | public ChreneLib.Controls.TextBoxes.CTextBox textBoxConnectionPassword; 291 | private System.Windows.Forms.Label label4; 292 | public ChreneLib.Controls.TextBoxes.CTextBox textBoxConnectionUsername; 293 | private System.Windows.Forms.Label label3; 294 | public ChreneLib.Controls.TextBoxes.CTextBox textBoxConnectionPort; 295 | private System.Windows.Forms.Label label2; 296 | public ChreneLib.Controls.TextBoxes.CTextBox textBoxConnectionAddress; 297 | private System.Windows.Forms.Label labelConnectionAddress; 298 | private System.Windows.Forms.Label labelTitleSettings; 299 | private System.Windows.Forms.Label labelConnectionDefault; 300 | private System.Windows.Forms.CheckBox checkBoxConnectionDefault; 301 | private System.Windows.Forms.Label labelTitleGeneral; 302 | private System.Windows.Forms.Label LabelWorkInProgress; 303 | private System.Windows.Forms.Button buttonSave; 304 | private System.Windows.Forms.Button buttonRestore; 305 | } 306 | } -------------------------------------------------------------------------------- /FileMasta/Forms/OptionsWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Threading; 4 | using System.Windows.Forms; 5 | 6 | namespace FileMasta.Forms 7 | { 8 | public partial class OptionsWindow : Form 9 | { 10 | public OptionsWindow() 11 | { 12 | InitializeComponent(); 13 | } 14 | 15 | private void Options_Load(object sender, EventArgs e) 16 | { 17 | LoadSettings(); 18 | } 19 | 20 | /// 21 | /// Enables/Disables Proxy Settings 22 | /// 23 | private void CheckBoxConnectionDefault_CheckedChanged(object sender, EventArgs e) 24 | { 25 | // Connection (Enabled/Disabled) 26 | textBoxConnectionAddress.Enabled = Properties.Settings.Default.proxyUseCustom; 27 | textBoxConnectionPort.Enabled = Properties.Settings.Default.proxyUseCustom; 28 | textBoxConnectionUsername.Enabled = Properties.Settings.Default.proxyUseCustom; 29 | textBoxConnectionPassword.Enabled = Properties.Settings.Default.proxyUseCustom; 30 | } 31 | 32 | /// 33 | /// Set UI/Web Properties 34 | /// 35 | private void LoadSettings() 36 | { 37 | // General 38 | // todo 39 | 40 | // Connection (Enabled/Disabled) 41 | textBoxConnectionAddress.Enabled = Properties.Settings.Default.proxyUseCustom; 42 | textBoxConnectionPort.Enabled = Properties.Settings.Default.proxyUseCustom; 43 | textBoxConnectionUsername.Enabled = Properties.Settings.Default.proxyUseCustom; 44 | textBoxConnectionPassword.Enabled = Properties.Settings.Default.proxyUseCustom; 45 | 46 | // Connection 47 | checkBoxConnectionDefault.Checked = Properties.Settings.Default.proxyUseCustom; 48 | textBoxConnectionAddress.Text = Properties.Settings.Default.proxyAddress; 49 | textBoxConnectionPort.Text = Convert.ToString(Properties.Settings.Default.proxyPort); 50 | textBoxConnectionUsername.Text = Properties.Settings.Default.proxyUsername; 51 | textBoxConnectionPassword.Text = Properties.Settings.Default.proxyPassword; 52 | 53 | // Set Proxy Settings 54 | if (Properties.Settings.Default.proxyUseCustom) 55 | { 56 | if (Uri.TryCreate(Properties.Settings.Default.proxyAddress + ":" + Properties.Settings.Default.proxyPort, UriKind.RelativeOrAbsolute, out Uri result)) 57 | { 58 | Program.WebClient.Proxy = new WebProxy(result); 59 | 60 | if (Properties.Settings.Default.proxyUsername == "" && Properties.Settings.Default.proxyPassword == "") 61 | Program.WebClient.UseDefaultCredentials = true; 62 | else 63 | { 64 | Program.WebClient.UseDefaultCredentials = false; 65 | Program.WebClient.Credentials = new NetworkCredential(Properties.Settings.Default.proxyUsername, Properties.Settings.Default.proxyPassword); 66 | } 67 | } 68 | else 69 | MessageBox.Show(this, @"Invalid Address/Port"); 70 | } 71 | else 72 | { 73 | Program.WebClient.UseDefaultCredentials = true; 74 | Program.WebClient.Proxy = new WebProxy( /* can't present value of type System.Net.WebProxy */); 75 | Program.WebClient.Credentials = CredentialCache.DefaultCredentials; 76 | } 77 | } 78 | 79 | private void ButtonRestore_Click(object sender, EventArgs e) 80 | { 81 | Properties.Settings.Default.Reset(); 82 | 83 | Thread.Sleep(500); 84 | LoadSettings(); 85 | MessageBox.Show(@"Settings restored to default."); 86 | Program.Log.Info("Restored user settings"); 87 | } 88 | 89 | private void ButtonSave_Click(object sender, EventArgs e) 90 | { 91 | // General 92 | // todo 93 | 94 | // Connection 95 | Properties.Settings.Default.proxyUseCustom = checkBoxConnectionDefault.Checked; 96 | Properties.Settings.Default.proxyAddress = textBoxConnectionAddress.Text; 97 | Properties.Settings.Default.proxyPort = Convert.ToInt32(textBoxConnectionPort.Text); 98 | Properties.Settings.Default.proxyUsername = textBoxConnectionUsername.Text; 99 | Properties.Settings.Default.proxyPassword = textBoxConnectionPassword.Text; 100 | 101 | Thread.Sleep(500); 102 | Properties.Settings.Default.Save(); 103 | LoadSettings(); 104 | MessageBox.Show(@"Settings Saved."); 105 | Program.Log.Info("Saved user settings"); 106 | } 107 | 108 | /*************************************************************************/ 109 | /* Keyboard Shortcuts */ 110 | /*************************************************************************/ 111 | 112 | protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 113 | { 114 | if (keyData != Keys.Escape) return base.ProcessCmdKey(ref msg, keyData); 115 | Close(); 116 | return true; 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /FileMasta/MainForm.cs: -------------------------------------------------------------------------------- 1 | using FileMasta.Controls; 2 | using FileMasta.Core; 3 | using FileMasta.Core.Extensions; 4 | using FileMasta.Core.Models; 5 | using FileMasta.Extensions; 6 | using FileMasta.Forms; 7 | using FileMasta.Utilities; 8 | using System; 9 | using System.Diagnostics; 10 | using System.Drawing; 11 | using System.IO; 12 | using System.Linq; 13 | using System.Threading.Tasks; 14 | using System.Windows.Forms; 15 | 16 | namespace FileMasta 17 | { 18 | public partial class MainForm : Form 19 | { 20 | /// 21 | /// Application splash screen instance 22 | /// 23 | private static SplashScreen FormSplashScreen { get; set; } = new SplashScreen(); 24 | 25 | /// 26 | /// Application instance 27 | /// 28 | public static MainForm Form { get; set; } 29 | 30 | /// 31 | /// Applcation database instance 32 | /// 33 | public OdDatabase DataCache { get; set; } 34 | 35 | public MainForm() 36 | { 37 | Program.Log.Info("Initializing"); 38 | InitializeComponent(); 39 | Form = this; 40 | 41 | Controls.Add(FormSplashScreen); 42 | FormSplashScreen.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom; 43 | FormSplashScreen.Location = new Point(0, 0); 44 | FormSplashScreen.Size = Form.ClientSize; 45 | FormSplashScreen.BringToFront(); 46 | FormSplashScreen.Show(); 47 | 48 | ListboxSearchType.SelectedIndex = 0; 49 | DropdownSearchSort.SelectedIndex = 0; 50 | DropdownSearchSizePrefix.SelectedIndex = 0; 51 | DateTimeMaxMTime.Value = DateTime.Now; 52 | } 53 | 54 | /*************************************************************************/ 55 | /* Form / Startup Events */ 56 | /*************************************************************************/ 57 | 58 | private void MainForm_Load(object sender, EventArgs e) 59 | { 60 | Program.Log.Info("Load events started"); 61 | Utilities.Update.CheckVersion(); 62 | Initialize(); 63 | } 64 | 65 | public async void Initialize() 66 | { 67 | await Task.Run(() => DataCache = new OdDatabase(Configuration.DatabaseUrl, Configuration.DatabaseLocation, Configuration.BookmarkedLocation)); 68 | 69 | Initialized(); 70 | } 71 | 72 | public void Initialized() 73 | { 74 | foreach (string keyword in DataCache.SearchKeywords) 75 | FlowpanelKeywords.Controls.Add(ControlExtensions.KeywordLabel(keyword, LabelKeyword_Click)); 76 | 77 | StatusStripDatabaseInfo.Text = string.Format(StatusStripDatabaseInfo.Text, 78 | StringExtensions.FormatNumber(DataCache.TotalFileCount)); 79 | // StringExtensions.BytesToPrefix(DataCache.SizeTotal)); 80 | 81 | Controls.Remove(FormSplashScreen); 82 | 83 | Program.Log.Info("Initialized"); 84 | } 85 | 86 | private void MainForm_FormClosing(object sender, FormClosingEventArgs e) 87 | { 88 | DataCache?.UpdateBookmarks(); 89 | Program.Log.Info("Updated saved file"); 90 | } 91 | 92 | private void MainForm_FormClosed(object sender, FormClosedEventArgs e) 93 | { 94 | Program.Log.Info("Closed"); 95 | } 96 | 97 | private void MainForm_SizeChanged(object sender, EventArgs e) 98 | { 99 | Refresh(); 100 | } 101 | 102 | protected override void OnPaint(PaintEventArgs e) { } 103 | 104 | /*************************************************************************/ 105 | /* Menu Strip */ 106 | /*************************************************************************/ 107 | 108 | // File 109 | private void MenuFileMinimizeToTray_Click(object sender, EventArgs e) 110 | { 111 | Hide(); 112 | NotifyTrayIcon.Visible = true; 113 | NotifyTrayIcon.ShowBalloonTip(1000); 114 | } 115 | 116 | private void MenuFileExit_Click(object sender, EventArgs e) 117 | { 118 | Application.Exit(); 119 | } 120 | 121 | private void NotifyTrayIcon_MouseDoubleClick(object sender, MouseEventArgs e) 122 | { 123 | Show(); 124 | WindowState = FormWindowState.Normal; 125 | NotifyTrayIcon.Visible = false; 126 | } 127 | 128 | // Bookmarks 129 | private void MenuStripBookmarks_Click(object sender, EventArgs e) 130 | { 131 | using (BookmarksWindow bookmarksWindow = new BookmarksWindow { DataCache = DataCache }) 132 | { 133 | _ = bookmarksWindow.ShowDialog(this); 134 | } 135 | } 136 | 137 | // Tools 138 | private void MenuToolsOptions_Click(object sender, EventArgs e) 139 | { 140 | using (OptionsWindow optionsWindow = new OptionsWindow()) 141 | { 142 | _ = optionsWindow.ShowDialog(this); 143 | } 144 | } 145 | 146 | // Help 147 | private void MenuHelpChangelog_Click(object sender, EventArgs e) 148 | { 149 | ControlExtensions.ShowDataWindow(this, "Change Log", Configuration.ChangelogUrl); 150 | } 151 | 152 | private void MenuHelpReportIssue_Click(object sender, EventArgs e) 153 | { 154 | Process.Start($"{Configuration.ProjectUrl}issues/new"); 155 | } 156 | 157 | private void MenuHelpAbout_Click(object sender, EventArgs e) 158 | { 159 | using (AboutWindow aboutWindow = new AboutWindow()) 160 | { 161 | _ = aboutWindow.ShowDialog(this); 162 | } 163 | } 164 | 165 | private void MenuHelpCheckForUpdate_Click(object sender, EventArgs e) 166 | { 167 | Utilities.Update.CheckVersion(); 168 | } 169 | 170 | /*************************************************************************/ 171 | /* Searching Files */ 172 | /*************************************************************************/ 173 | 174 | /// 175 | /// Search preference: Type 176 | /// 177 | private string[] SearchFileType { get; set; } = FileType.All.ToArray(); 178 | 179 | /// 180 | /// Search preference: Type 181 | /// 182 | private string SearchSizePrefix { get; set; } = "Bytes"; 183 | 184 | /// 185 | /// Search preference: Sort 186 | /// 187 | private Sort SearchSortBy { get; set; } = Sort.Name; 188 | 189 | private void TextBoxSearchQuery_KeyDown(object sender, KeyEventArgs e) 190 | { 191 | if (e.KeyCode != Keys.Enter) return; 192 | if (TextboxSearchName.Text.Length > 2) 193 | { 194 | PerformSearch(); 195 | } 196 | else 197 | SetStatus("Minimum 3 characters"); 198 | } 199 | 200 | private void ButtonSearchFiles_Click(object sender, EventArgs e) 201 | { 202 | if (TextboxSearchName.Text.Length > 2) 203 | { 204 | PerformSearch(); 205 | } 206 | else 207 | SetStatus("Minimum 3 characters"); 208 | } 209 | 210 | private void ButtonSearchEngine_Click(object sender, EventArgs e) 211 | { 212 | ContextMenuSearchExternal.Show(ButtonSearchExternal, ButtonSearchExternal.PointToClient(Cursor.Position)); 213 | } 214 | 215 | // External Searches 216 | private void MenuSearchGoogle_Click(object sender, EventArgs e) 217 | { 218 | Process.Start(ExternalEngine.CreateUrl(ExternalEngine.Engine.Google, TextboxSearchName.Text, SearchFileType).ToLower()); 219 | } 220 | 221 | private void MenuSearchGoogol_Click(object sender, EventArgs e) 222 | { 223 | Process.Start(ExternalEngine.CreateUrl(ExternalEngine.Engine.Googol, TextboxSearchName.Text, SearchFileType).ToLower()); 224 | } 225 | 226 | private void MenuSearchStartPage_Click(object sender, EventArgs e) 227 | { 228 | Process.Start(ExternalEngine.CreateUrl(ExternalEngine.Engine.StartPage, TextboxSearchName.Text, SearchFileType).ToLower()); 229 | } 230 | 231 | private void MenuSearchSearx_Click(object sender, EventArgs e) 232 | { 233 | Process.Start(ExternalEngine.CreateUrl(ExternalEngine.Engine.Searx, TextboxSearchName.Text, SearchFileType).ToLower()); 234 | } 235 | 236 | private void ListboxType_SelectedIndexChanged(object sender, EventArgs e) 237 | { 238 | switch (ListboxSearchType.SelectedIndex) 239 | { 240 | case 0: 241 | SearchFileType = FileType.All; 242 | break; 243 | case 1: 244 | SearchFileType = FileType.Audio; 245 | break; 246 | case 2: 247 | SearchFileType = FileType.Compressed; 248 | break; 249 | case 3: 250 | SearchFileType = FileType.Document; 251 | break; 252 | case 4: 253 | SearchFileType = FileType.Executable; 254 | break; 255 | case 5: 256 | SearchFileType = FileType.Picture; 257 | break; 258 | case 6: 259 | SearchFileType = FileType.Video; 260 | break; 261 | } 262 | } 263 | 264 | private void DropdownSearchSizePrefix_SelectedIndexChanged(object sender, EventArgs e) 265 | { 266 | SearchSizePrefix = DropdownSearchSizePrefix.GetItemText(DropdownSearchSizePrefix.SelectedItem); 267 | } 268 | 269 | private void ComboBoxSort_SelectedIndexChanged(object sender, EventArgs e) 270 | { 271 | switch (DropdownSearchSort.SelectedIndex) 272 | { 273 | case 0: 274 | SearchSortBy = Sort.Name; 275 | break; 276 | case 1: 277 | SearchSortBy = Sort.Size; 278 | break; 279 | case 2: 280 | SearchSortBy = Sort.Date; 281 | break; 282 | } 283 | } 284 | 285 | private void LabelKeyword_Click(object sender, EventArgs e) 286 | { 287 | TextboxSearchName.Text = ((Label)sender).Text; 288 | PerformSearch(); 289 | } 290 | 291 | private async void PerformSearch() 292 | { 293 | SetStatus("Searching..."); 294 | 295 | Program.Log.InfoFormat( 296 | "Searching with the following filters: Name: {0}, Sort: {1}, Type: {2}, Size : {3}, Last Modified : {4} to {5}", 297 | TextboxSearchName.Text, 298 | SearchSortBy.ToString(), 299 | SearchFileType.ToArray(), 300 | NumericSearchGreaterThan.Value, 301 | DateTimeMinMTime.Value, 302 | DateTimeMaxMTime.Value); 303 | 304 | EnableSearchControls(false); 305 | DataGridFiles.Rows.Clear(); 306 | var timer = new Stopwatch(); 307 | timer.Start(); 308 | 309 | foreach (FileItem file in 310 | from DataItem bookmark in 311 | await DataCache.SearchRecords( 312 | TextboxSearchName.Text, 313 | SearchFileType, 314 | StringExtensions.ParseFileSize($"{NumericSearchGreaterThan.Value} {SearchSizePrefix}"), 315 | DateTimeMinMTime.Value, 316 | DateTimeMaxMTime.Value) 317 | let file = FileExtensions.DataItemToFile(bookmark) 318 | select file) 319 | { 320 | _ = DataGridFiles.Rows.Add(file.Name, 321 | StringExtensions.BytesToPrefix(file.Size), 322 | file.Mtime.ToLocalTime(), 323 | file.Url); 324 | } 325 | 326 | timer.Stop(); 327 | SetStatus(message: $"{StringExtensions.FormatNumber(DataGridFiles.Rows.Count)} Results ({timer.Elapsed.TotalSeconds:0.000} seconds)"); 328 | timer.Reset(); 329 | EnableSearchControls(true); 330 | } 331 | 332 | private void DataGridFileItems_CellDoubleClick(object sender, DataGridViewCellEventArgs e) 333 | { 334 | if (e.RowIndex != -1) 335 | DisplayFileDetails(SelectedFile); 336 | } 337 | 338 | private void DataGridFileItems_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) 339 | { 340 | e.Paint(e.CellBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.Focus); 341 | e.Handled = true; 342 | } 343 | 344 | private void DataGridFileItems_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e) 345 | { 346 | e.PaintParts &= DataGridViewPaintParts.All & ~DataGridViewPaintParts.Focus; 347 | } 348 | 349 | private void DataGridFileItems_SelectionChanged(object sender, EventArgs e) 350 | { 351 | PanelFileDetails.Enabled = DataGridFiles.SelectedRows.Count != 0; 352 | 353 | if (DataGridFiles.CurrentRow != null) 354 | { 355 | SelectedFile = FileExtensions.CreateFile(DateTime.Parse(DataGridFiles.CurrentRow.Cells[2].Value.ToString()), StringExtensions.ParseFileSize(DataGridFiles.CurrentRow.Cells[1].Value.ToString()), DataGridFiles.CurrentRow.Cells[3].Value.ToString()); 356 | DisplayFileDetails(SelectedFile); 357 | } 358 | } 359 | 360 | private void MenuFileBookmark_Click(object sender, EventArgs e) 361 | { 362 | if (DataCache.IsBookmarked(SelectedFile)) 363 | { 364 | DataCache.RemoveBookmark(SelectedFile); 365 | ControlExtensions.SetControlTextWidth(ButtonBookmark, "Bookmark"); 366 | } 367 | else 368 | { 369 | DataCache.AddBookmark(SelectedFile); 370 | ControlExtensions.SetControlTextWidth(ButtonBookmark, "Unbookmark"); 371 | } 372 | } 373 | 374 | private void MenuFileOpen_Click(object sender, EventArgs e) 375 | { 376 | if (DataGridFiles.SelectedRows.Count > 0) 377 | Process.Start(SelectedFile.Url); 378 | } 379 | 380 | private void MenuFileViewDetails_Click(object sender, EventArgs e) 381 | { 382 | if (DataGridFiles.SelectedRows.Count > 0) 383 | DisplayFileDetails(SelectedFile); 384 | } 385 | 386 | private void MenuFileCopyURL_Click(object sender, EventArgs e) 387 | { 388 | if (DataGridFiles.SelectedRows.Count <= 0) return; 389 | Clipboard.SetText(SelectedFile.Url); 390 | SetStatus("Copied File URL to Clipboard"); 391 | } 392 | 393 | private void MenuFileEmail_Click(object sender, EventArgs e) 394 | { 395 | Process.Start("mailto:" + 396 | $"?body=File Report ({ListboxSearchType.SelectedItem})" + 397 | $"&subject=" + 398 | $"Name: {StringExtensions.GetFileName(SelectedFile.Url)} ({ListboxSearchType.SelectedItem})\n\n" + 399 | $"Direct URL: {SelectedFile}\n\n\n\n" + 400 | "Auto-generated by FileMasta: " + Configuration.ProjectUrl); 401 | } 402 | 403 | private FileItem SelectedFile { get; set; } 404 | 405 | /// 406 | /// Display selected file information in the details pane 407 | /// 408 | /// WebFile object 409 | private void DisplayFileDetails(FileItem file) 410 | { 411 | Program.Log.Info("Selected file " + file.Url); 412 | 413 | SelectedFile = file; 414 | LabelFileValueName.Text = Path.GetFileNameWithoutExtension(file.Name); 415 | LabelFileValueSize.Text = StringExtensions.BytesToPrefix(file.Size); 416 | LabelFileValueDomain.Text = new Uri(file.Url).Host; 417 | LabelFileValueModified.Text = file.Mtime.ToShortTimeString(); 418 | LabelFileValueAge.Text = DateTimeExtensions.TimeSpanAge(file.Mtime); 419 | LabelFileValueExtension.Text = file.GetExtension().ToUpper(); 420 | LabelFileValueURL.Text = Uri.UnescapeDataString(file.Url); 421 | LabelFileUrlBG.Height = LabelFileValueURL.Height + 17; 422 | 423 | foreach (ToolStripMenuItem item in ContextFileOpenWith.Items) 424 | item.Visible = false; 425 | 426 | if (FileType.Document.Contains(StringExtensions.GetFileExtension(file.Url))) 427 | { 428 | NitroReaderToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathNitroReader); 429 | } 430 | 431 | if (FileType.Video.Contains(StringExtensions.GetFileExtension(file.Url)) || FileType.Audio.Contains(file.GetExtension())) 432 | { 433 | WMPToolStripMenuItem.Visible = true; 434 | VLCToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathVlc); 435 | MPCToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathMpcCodec64) || File.Exists(LocalExtensions.PathMpc64) || File.Exists(LocalExtensions.PathMpc86); 436 | KMPlayerToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathKmPlayer); 437 | PotPlayerToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathPotPlayer); 438 | } 439 | 440 | IDMToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathIdm64) || File.Exists(LocalExtensions.PathIdm86); 441 | IDAToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathIda); 442 | FDMToolStripMenuItem.Visible = File.Exists(LocalExtensions.PathFdm); 443 | 444 | ControlExtensions.SetControlTextWidth(ButtonBookmark, DataCache.IsBookmarked(file) ? "Unbookmark" : "Bookmark"); 445 | 446 | ButtonRequestFileSize.Visible = file.Size.ToString() == "0"; 447 | ButtonOpenWith.Visible = ContextFileOpenWith.Items.Count > 0; 448 | } 449 | 450 | private void ButtonFileRequestSize_Click(object sender, EventArgs e) 451 | { 452 | ButtonRequestFileSize.Visible = false; 453 | LabelFileValueSize.Text = StringExtensions.BytesToPrefix(SelectedFile.Size); 454 | } 455 | 456 | 457 | private void ButtonFileDownload_Click(object sender, EventArgs e) 458 | { 459 | try 460 | { 461 | Process.Start(SelectedFile.Url); 462 | } 463 | catch (Exception ex) 464 | { 465 | SetStatus("There was an issue downloading the file. " + ex.Message); 466 | } 467 | } 468 | 469 | private void ButtonFileOpenWith_Click(object sender, EventArgs e) 470 | { 471 | ContextFileOpenWith.Show(ButtonOpenWith, ButtonOpenWith.PointToClient(Cursor.Position)); 472 | } 473 | 474 | private void ButtonFileSave_Click(object sender, EventArgs e) 475 | { 476 | if (DataCache.IsBookmarked(SelectedFile)) 477 | { 478 | DataCache.RemoveBookmark(SelectedFile); 479 | ControlExtensions.SetControlTextWidth(ButtonBookmark, "Bookmark"); 480 | } 481 | else 482 | { 483 | DataCache.AddBookmark(SelectedFile); 484 | ControlExtensions.SetControlTextWidth(ButtonBookmark, "Unbookmark"); 485 | } 486 | } 487 | 488 | private void NitroReaderToolStripMenuItem_Click(object sender, EventArgs e) 489 | { 490 | // Open file in Nitro Reader 491 | Process NitroReader = new Process(); 492 | NitroReader.StartInfo.FileName = LocalExtensions.PathNitroReader; 493 | NitroReader.StartInfo.Arguments = (SelectedFile.Url); 494 | NitroReader.Start(); 495 | } 496 | 497 | private void VLCToolStripMenuItem_Click(object sender, EventArgs e) 498 | { 499 | // Open file in VLC player, with subtitles (if found) 500 | using (Process VLC = new Process()) 501 | { 502 | VLC.StartInfo.FileName = LocalExtensions.PathVlc; 503 | VLC.StartInfo.Arguments = ("-vvv " + SelectedFile.Url); 504 | VLC.Start(); 505 | } 506 | } 507 | 508 | private void WMPToolStripMenuItem_Click(object sender, EventArgs e) 509 | { 510 | // Open file in Windows Media Player 511 | Process.Start("wmplayer.exe", SelectedFile.Url); 512 | } 513 | 514 | private void MPCToolStripMenuItem_Click(object sender, EventArgs e) 515 | { 516 | // Open file in Media Player Classic 517 | using (Process MPC = new Process()) 518 | { 519 | if (File.Exists(LocalExtensions.PathMpcCodec64)) 520 | MPC.StartInfo.FileName = LocalExtensions.PathMpcCodec64; 521 | else if (File.Exists(LocalExtensions.PathMpc64)) 522 | MPC.StartInfo.FileName = LocalExtensions.PathMpc64; 523 | else 524 | MPC.StartInfo.FileName = LocalExtensions.PathMpc86; 525 | MPC.StartInfo.Arguments = (SelectedFile.Url); 526 | MPC.Start(); 527 | } 528 | } 529 | 530 | private void KMPlayerToolStripMenuItem_Click(object sender, EventArgs e) 531 | { 532 | // Open file in KM Player 533 | using (Process KMP = new Process()) 534 | { 535 | KMP.StartInfo.FileName = LocalExtensions.PathKmPlayer; 536 | KMP.StartInfo.Arguments = (SelectedFile.Url); 537 | KMP.Start(); 538 | } 539 | } 540 | 541 | private void PotPlayerToolStripMenuItem_Click(object sender, EventArgs e) 542 | { 543 | // Open file in Pot Player 544 | using (Process PP = new Process()) 545 | { 546 | PP.StartInfo.FileName = LocalExtensions.PathPotPlayer; 547 | PP.StartInfo.Arguments = (SelectedFile.Url); 548 | PP.Start(); 549 | } 550 | } 551 | 552 | private void IDMToolStripMenuItem_Click(object sender, EventArgs e) 553 | { 554 | // Open file in Internet Download Manager 555 | using (Process IDM = new Process()) 556 | { 557 | if (File.Exists(LocalExtensions.PathIdm64)) 558 | IDM.StartInfo.FileName = LocalExtensions.PathIdm64; 559 | else 560 | IDM.StartInfo.FileName = LocalExtensions.PathIdm86; 561 | IDM.StartInfo.Arguments = ("-d " + SelectedFile.Url); 562 | IDM.Start(); 563 | } 564 | } 565 | 566 | private void IDAToolStripMenuItem_Click(object sender, EventArgs e) 567 | { 568 | // Open file in Internet Download Accelerator 569 | using (Process FDM = new Process()) 570 | { 571 | FDM.StartInfo.FileName = LocalExtensions.PathIda; 572 | FDM.StartInfo.Arguments = (SelectedFile.Url); 573 | FDM.Start(); 574 | } 575 | } 576 | 577 | private void FDMToolStripMenuItem_Click(object sender, EventArgs e) 578 | { 579 | // Open file in Free Download Manger 580 | using (Process FDM = new Process()) 581 | { 582 | FDM.StartInfo.FileName = LocalExtensions.PathFdm; 583 | FDM.StartInfo.Arguments = (SelectedFile.Url); 584 | FDM.Start(); 585 | } 586 | } 587 | 588 | /// 589 | /// Enable/Disable search controls, to prevent another search process which causes a crash 590 | /// 591 | /// Enable/Disable Controls 592 | private void EnableSearchControls(bool isEnabled) 593 | { 594 | TextboxSearchName.Enabled = isEnabled; 595 | ListboxSearchType.Enabled = isEnabled; 596 | ButtonSearch.Enabled = isEnabled; 597 | ButtonSearchExternal.Enabled = isEnabled; 598 | NumericSearchGreaterThan.Enabled = isEnabled; 599 | DropdownSearchSizePrefix.Enabled = isEnabled; 600 | DateTimeMinMTime.Enabled = isEnabled; 601 | DateTimeMaxMTime.Enabled = isEnabled; 602 | DropdownSearchSort.Enabled = isEnabled; 603 | foreach (object searchItem in FlowpanelKeywords.Controls) 604 | if (searchItem is Label label) 605 | label.Enabled = isEnabled; 606 | } 607 | 608 | /// 609 | /// Set the current status of the application 610 | /// 611 | /// Message/status to be displayed 612 | private void SetStatus(string message) 613 | { 614 | StatusStripStatus.Text = message; 615 | } 616 | 617 | /*************************************************************************/ 618 | /* Keyboard Shortcuts */ 619 | /*************************************************************************/ 620 | 621 | protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 622 | { 623 | switch (keyData) 624 | { 625 | // Focus on Search Box 626 | case Keys.Control | Keys.F: 627 | TextboxSearchName.Focus(); 628 | return true; 629 | // Close application 630 | case Keys.Control | Keys.W: 631 | Application.Exit(); 632 | return true; 633 | } 634 | 635 | return base.ProcessCmdKey(ref msg, keyData); 636 | } 637 | 638 | private void LabelSearchLastModified_Click(object sender, EventArgs e) 639 | { 640 | 641 | } 642 | 643 | private void DateTimeMaxMTime_ValueChanged(object sender, EventArgs e) 644 | { 645 | 646 | } 647 | 648 | private void DateTimeMinMTime_ValueChanged(object sender, EventArgs e) 649 | { 650 | 651 | } 652 | 653 | private void LabelSearchModifiedTo_Click(object sender, EventArgs e) 654 | { 655 | 656 | } 657 | 658 | private void LabelSort_Click(object sender, EventArgs e) 659 | { 660 | 661 | } 662 | } 663 | } -------------------------------------------------------------------------------- /FileMasta/Models/Metadata.cs: -------------------------------------------------------------------------------- 1 | namespace FileMasta.Models 2 | { 3 | /// 4 | /// Represents the database information 5 | /// 6 | public class Metadata 7 | { 8 | public readonly long TotalNoFiles; 9 | public readonly long TotalFilesSize; 10 | 11 | public Metadata(long totalNoFiles, long totalFilesSize) 12 | { 13 | TotalNoFiles = totalNoFiles; 14 | TotalFilesSize = totalFilesSize; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /FileMasta/Models/WebFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using FileMasta.Data; 5 | 6 | namespace FileMasta.Models 7 | { 8 | /// 9 | /// Represents a web file object 10 | /// 11 | public class WebFile 12 | { 13 | public readonly string Name; 14 | public readonly long Size; 15 | public readonly DateTime LastModified; 16 | public readonly string Url; 17 | 18 | public WebFile(string name, long size, DateTime lastModified, string url) 19 | { 20 | Name = name; 21 | Size = size; 22 | LastModified = lastModified; 23 | Url = url; 24 | } 25 | 26 | public string GetExtension() 27 | { 28 | return Path.GetExtension(Url)?.Replace(".", "").ToUpper(); 29 | } 30 | 31 | public bool IsType(string[] type) 32 | { 33 | return type == Types.All || type.Any(x => GetExtension().Contains(x.ToUpper())); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /FileMasta/Program.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Threading; 3 | using System.Windows.Forms; 4 | using System; 5 | using System.Net; 6 | using FileMasta.Extensions; 7 | 8 | namespace FileMasta 9 | { 10 | internal static class Program 11 | { 12 | public static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 13 | public static readonly WebClient WebClient = new WebClient(); 14 | private static Mutex _mutexInstance; 15 | 16 | /// 17 | /// The main entry point for the application. 18 | /// 19 | [STAThread] 20 | private static void Main() 21 | { 22 | _mutexInstance = new Mutex(true, "FileMasta", createdNew: out bool createdNew); 23 | 24 | if (!createdNew) 25 | { 26 | Log.Warn("There is already an instance of FileMasta running"); 27 | return; 28 | } 29 | 30 | if (Debugger.IsAttached) 31 | { 32 | Properties.Settings.Default.Reset(); 33 | Run(); 34 | return; 35 | } 36 | 37 | Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); 38 | Application.ThreadException += ExceptionExtensions.ApplicationThreadException; 39 | AppDomain.CurrentDomain.UnhandledException += ExceptionExtensions.CurrentDomainUnhandledException; 40 | 41 | Run(); 42 | } 43 | 44 | private static void Run() 45 | { 46 | Application.EnableVisualStyles(); 47 | Application.SetCompatibleTextRenderingDefault(false); 48 | Application.Run(new MainForm()); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /FileMasta/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("FileMasta")] 8 | [assembly: AssemblyDescription("A search application to explore, discover and share online files")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("mostlyash")] 11 | [assembly: AssemblyProduct("FileMasta")] 12 | [assembly: AssemblyCopyright("Copyright © 2018")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("75a2cfc6-b0b1-42a6-b1f7-66b3c68a06ca")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("0.4.6.0")] 35 | [assembly: AssemblyFileVersion("0.4.6.0")] 36 | [assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")] -------------------------------------------------------------------------------- /FileMasta/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace FileMasta.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FileMasta.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Bitmap. 65 | /// 66 | internal static System.Drawing.Bitmap app_logo { 67 | get { 68 | object obj = ResourceManager.GetObject("app_logo", resourceCulture); 69 | return ((System.Drawing.Bitmap)(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Bitmap. 75 | /// 76 | internal static System.Drawing.Bitmap book { 77 | get { 78 | object obj = ResourceManager.GetObject("book", resourceCulture); 79 | return ((System.Drawing.Bitmap)(obj)); 80 | } 81 | } 82 | 83 | /// 84 | /// Looks up a localized resource of type System.Drawing.Bitmap. 85 | /// 86 | internal static System.Drawing.Bitmap dots_horizontal { 87 | get { 88 | object obj = ResourceManager.GetObject("dots_horizontal", resourceCulture); 89 | return ((System.Drawing.Bitmap)(obj)); 90 | } 91 | } 92 | 93 | /// 94 | /// Looks up a localized resource of type System.Drawing.Bitmap. 95 | /// 96 | internal static System.Drawing.Bitmap download { 97 | get { 98 | object obj = ResourceManager.GetObject("download", resourceCulture); 99 | return ((System.Drawing.Bitmap)(obj)); 100 | } 101 | } 102 | 103 | /// 104 | /// Looks up a localized resource of type System.Drawing.Bitmap. 105 | /// 106 | internal static System.Drawing.Bitmap play_circle { 107 | get { 108 | object obj = ResourceManager.GetObject("play_circle", resourceCulture); 109 | return ((System.Drawing.Bitmap)(obj)); 110 | } 111 | } 112 | 113 | /// 114 | /// Looks up a localized resource of type System.Drawing.Bitmap. 115 | /// 116 | internal static System.Drawing.Bitmap vlc { 117 | get { 118 | object obj = ResourceManager.GetObject("vlc", resourceCulture); 119 | return ((System.Drawing.Bitmap)(obj)); 120 | } 121 | } 122 | 123 | /// 124 | /// Looks up a localized resource of type System.Drawing.Bitmap. 125 | /// 126 | internal static System.Drawing.Bitmap windows { 127 | get { 128 | object obj = ResourceManager.GetObject("windows", resourceCulture); 129 | return ((System.Drawing.Bitmap)(obj)); 130 | } 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /FileMasta/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\vlc.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | 125 | ..\Resources\play-circle-outline.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | 128 | ..\Resources\windows.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 129 | 130 | 131 | ..\Resources\download.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 132 | 133 | 134 | ..\Resources\dots-horizontal.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 135 | 136 | 137 | ..\Resources\filemasta-logo-v4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 138 | 139 | 140 | ..\Resources\book.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 141 | 142 | -------------------------------------------------------------------------------- /FileMasta/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace FileMasta.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 29 | public bool clearDataOnClose { 30 | get { 31 | return ((bool)(this["clearDataOnClose"])); 32 | } 33 | set { 34 | this["clearDataOnClose"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | [global::System.Configuration.DefaultSettingValueAttribute("")] 41 | public string proxyAddress { 42 | get { 43 | return ((string)(this["proxyAddress"])); 44 | } 45 | set { 46 | this["proxyAddress"] = value; 47 | } 48 | } 49 | 50 | [global::System.Configuration.UserScopedSettingAttribute()] 51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 52 | [global::System.Configuration.DefaultSettingValueAttribute("0")] 53 | public int proxyPort { 54 | get { 55 | return ((int)(this["proxyPort"])); 56 | } 57 | set { 58 | this["proxyPort"] = value; 59 | } 60 | } 61 | 62 | [global::System.Configuration.UserScopedSettingAttribute()] 63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 64 | [global::System.Configuration.DefaultSettingValueAttribute("")] 65 | public string proxyUsername { 66 | get { 67 | return ((string)(this["proxyUsername"])); 68 | } 69 | set { 70 | this["proxyUsername"] = value; 71 | } 72 | } 73 | 74 | [global::System.Configuration.UserScopedSettingAttribute()] 75 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 76 | [global::System.Configuration.DefaultSettingValueAttribute("")] 77 | public string proxyPassword { 78 | get { 79 | return ((string)(this["proxyPassword"])); 80 | } 81 | set { 82 | this["proxyPassword"] = value; 83 | } 84 | } 85 | 86 | [global::System.Configuration.UserScopedSettingAttribute()] 87 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 88 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 89 | public bool proxyUseCustom { 90 | get { 91 | return ((bool)(this["proxyUseCustom"])); 92 | } 93 | set { 94 | this["proxyUseCustom"] = value; 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /FileMasta/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | False 7 | 8 | 9 | 10 | 11 | 12 | 0 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | False 22 | 23 | 24 | -------------------------------------------------------------------------------- /FileMasta/Resources/book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohhsodead/FileMasta/990beecfb21de7b03572b3566a34669ff246d4a0/FileMasta/Resources/book.png -------------------------------------------------------------------------------- /FileMasta/Resources/dots-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohhsodead/FileMasta/990beecfb21de7b03572b3566a34669ff246d4a0/FileMasta/Resources/dots-horizontal.png -------------------------------------------------------------------------------- /FileMasta/Resources/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohhsodead/FileMasta/990beecfb21de7b03572b3566a34669ff246d4a0/FileMasta/Resources/download.png -------------------------------------------------------------------------------- /FileMasta/Resources/filemasta-logo-v4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohhsodead/FileMasta/990beecfb21de7b03572b3566a34669ff246d4a0/FileMasta/Resources/filemasta-logo-v4.png -------------------------------------------------------------------------------- /FileMasta/Resources/play-circle-outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohhsodead/FileMasta/990beecfb21de7b03572b3566a34669ff246d4a0/FileMasta/Resources/play-circle-outline.png -------------------------------------------------------------------------------- /FileMasta/Resources/vlc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohhsodead/FileMasta/990beecfb21de7b03572b3566a34669ff246d4a0/FileMasta/Resources/vlc.png -------------------------------------------------------------------------------- /FileMasta/Resources/windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohhsodead/FileMasta/990beecfb21de7b03572b3566a34669ff246d4a0/FileMasta/Resources/windows.png -------------------------------------------------------------------------------- /FileMasta/Utilities/ExternalEngine.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace FileMasta.Utilities 4 | { 5 | internal abstract class ExternalEngine 6 | { 7 | public enum Engine 8 | { 9 | Google, 10 | Googol, 11 | StartPage, 12 | Searx 13 | } 14 | 15 | public static string Google { get; set; } = "https://google.com/search?q="; 16 | public static string Googol { get; set; } = "https://googol.warriordudimanche.net/?q="; 17 | public static string StartPage { get; set; } = "https://startpage.com/do/dsearch?query="; 18 | public static string Searx { get; set; } = "https://searx.me/?q="; 19 | 20 | public static string CreateUrl(Engine engine, string name, string[] types) 21 | { 22 | string rootUrl = Google; 23 | 24 | if (engine == Engine.Google) 25 | { 26 | rootUrl = Google; 27 | } 28 | else if (engine == Engine.Googol) 29 | { 30 | rootUrl = Googol; 31 | } 32 | else if (engine == Engine.StartPage) 33 | { 34 | rootUrl = StartPage; 35 | } 36 | else if (engine == Engine.Searx) 37 | { 38 | rootUrl = Searx; 39 | } 40 | 41 | return $"{rootUrl}{name} %2B({string.Join("|", types.ToArray()).ToLower()}) %2Dinurl:(jsp|pl|php|html|aspx|htm|cf|shtml) intitle:index.of %2Dinurl:(listen77|mp3raid|mp3toss|mp3drug|index_of|index-of|wallywashis|downloadmana)"; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /FileMasta/Utilities/Update.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Reflection; 5 | using System.Windows.Forms; 6 | using FileMasta.Core.Extensions; 7 | using FileMasta.Extensions; 8 | 9 | namespace FileMasta.Utilities 10 | { 11 | internal abstract class Update 12 | { 13 | /// 14 | /// Check application for update. Installs the latest installer and runs the file before closing this instance 15 | /// 16 | public static void CheckVersion() 17 | { 18 | try 19 | { 20 | Program.Log.Info("Checking for update"); 21 | using (StreamReader sr = new StreamReader(HttpExtensions.GetStream(Configuration.VersionUrl))) 22 | { 23 | Version newVersion = new Version(sr.ReadToEnd()); 24 | Version curVersion = Assembly.GetExecutingAssembly().GetName().Version; 25 | if (curVersion.CompareTo(newVersion) < 0) 26 | RunInstaller(newVersion); 27 | else 28 | Program.Log.InfoFormat("Up to date. Version: {0}", newVersion); 29 | } 30 | } 31 | catch (Exception ex) 32 | { 33 | Program.Log.Error("Failed: ", ex); 34 | Application.Exit(); 35 | } 36 | } 37 | 38 | /// 39 | /// Downloads the newest update installer from GitHub and runs it for the user 40 | /// 41 | /// Newest version installer to run 42 | private static void RunInstaller(Version newVersion) 43 | { 44 | try 45 | { 46 | Program.Log.Info(@"New update available - Beginning to download the installer"); 47 | MessageBox.Show($@"FileMasta v{newVersion} is now available. Click OK to run the installer.", @"FileMasta - Update Available"); 48 | Program.WebClient.DownloadFile($"{Configuration.ProjectUrl}releases/download/{newVersion}/FileMasta.Installer.Windows.exe", $@"{KnownFolders.GetPath(KnownFolder.Downloads)}\FileMasta.Installer.Windows.exe.exe"); 49 | Process.Start($@"{KnownFolders.GetPath(KnownFolder.Downloads)}\FileMasta.Installer.Windows.exe.exe"); 50 | Application.Exit(); 51 | } 52 | catch (Exception ex) 53 | { 54 | Program.Log.Error("Update failed: ", ex); 55 | MessageBox.Show(@"There was an issue. You will need to manually install the latest available update from GitHub."); 56 | Process.Start($"{Configuration.ProjectUrl}releases/latest"); 57 | Application.Exit(); 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /FileMasta/app-logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohhsodead/FileMasta/990beecfb21de7b03572b3566a34669ff246d4a0/FileMasta/app-logo.ico -------------------------------------------------------------------------------- /FileMasta/log4net.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /FileMasta/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FileMasta [ABANDONED] 2 | 3 | [![GitHub Latest Release](https://img.shields.io/github/release/ohhsodead/FileMasta.svg)](https://github.com/ohhsodead/FileMasta/releases/) [![GitHub Downloads](https://img.shields.io/github/downloads/ohhsodead/FileMasta/total.svg)](https://github.com/ohhsodead/FileMasta/releases/) [![GitHub Open Issues](https://img.shields.io/github/issues/ohhsodead/FileMasta.svg)](https://gitHub.com/ohhsodead/FileMasta/issues/) [![GitHub Closed Issues](https://img.shields.io/github/issues-closed/ohhsodead/FileMasta.svg)](https://github.com/ohhsodead/FileMasta/issues?q=is%3Aissue+is%3Aclosed) [![GitHub Stargazers](https://img.shields.io/github/stars/ohhsodead/FileMasta.svg?style=social&label=Star&maxAge=2592000)](https://github.com/ohhsodead/FileMasta/stargazers/) 4 | 5 | A federated search application for discovering interesting files that are being shared online, such as video, music, books, software, games, subtitles and much more. All data is crawled by [od-database](https://github.com/simon987/od-database) which collects information about the contents of servers worldwide. We don't search file contents. 6 | 7 | ![FileMasta](https://github.com/HerbL27/FileMasta/blob/master/screenshot1.png?raw=true) 8 | 9 | >We host no content, we provide only access to already available files in the same way Google and other search engines do. 10 | 11 | >I'm currently looking for someone to help this project, like speeding up the loading and getting faster search results. Please email [me](emailto:bettercodes1@gmail.com) if you think you'd like to work on this with me. 12 | 13 | ## Installation 14 | Download and run the latest version of the installer from the [releases](https://github.com/mostlyash/FileMasta/releases/latest) page. 15 | 16 | ## Issues & Contributions 17 | If you find a bug or have a feature request, please [create an issue](https://github.com/mostlyash/FileMasta/issues/new). 18 | 19 | Contributions are highly welcome, however, except for very small changes, kindly file an issue and let's have a discussion before you open a pull request. 20 | 21 | ## Frequently Asked Questions 22 | ### I have found the files I need, but I cannot download them, the link does not work. Why? 23 | There could be several reasons for that: 24 | * These files were recently removed from the server they were located, by the owner of the files or by the owner of the server. 25 | * The server that contains the files has a limit of maximum number of concurrent users, and the limit has been reached. You can try to download the files later when some users are disconnected. 26 | * The server where the files are is turned off or is not connected to the Internet at the moment. 27 | * The owner of the server has put a restriction on downloading these files. 28 | 29 | ### How can I download files from FileMasta? Do I need any special program? 30 | You don't need a special program but it is very recommended. For example, if you just open the link in your web browser you can't see what is happening exactly between you and the web server (see previous question). So I would recommend to use a good web client that supports queuing or your favorite download manager, when you located the file you want to download just copy the link and paste it in your web client or whatever, that's it. 31 | 32 | ## License 33 | This project is licensed under the General Public License v3. 34 | -------------------------------------------------------------------------------- /References/CButtonLib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohhsodead/FileMasta/990beecfb21de7b03572b3566a34669ff246d4a0/References/CButtonLib.dll -------------------------------------------------------------------------------- /References/ChreneLib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohhsodead/FileMasta/990beecfb21de7b03572b3566a34669ff246d4a0/References/ChreneLib.dll -------------------------------------------------------------------------------- /TERMSOFUSE.md: -------------------------------------------------------------------------------- 1 | FileMasta software (collectively referred as "FM App") service is provided for your use subject to these terms and conditions ("Terms of Use") and which you agree to be bound by through your use of FM app. If you do not agree to these Terms of Use, please do not use any FM app service. 2 | 3 | All the search results produced by FM App contains links to files or archives located in web servers around the world, these files represent software, photos, video, text, graphics, music, sounds or any other material (collectively, referred as "content") that may be protected by copyrights, patents, trademarks, trade secrets or other proprietary rights, we assumes no responsibility for the content of any FTP server that is referenced by any search result page. 4 | 5 | FM App search results may contain links to web servers with offensive, adult oriented material or any other objectionable content or even dangerous computer viruses, it is exclusively the user responsibility the way he will use this information. FM App provide you a service that helps the user to find information located in web servers, but it is the user who must decide what to do with that information or those FTP apps. We will not be responsible for the use or misuse of any information derived from any of the search result pages. That responsibility rests solely in the hands of the user. 6 | 7 | YOU EXPRESSLY AGREE THAT USE OF FM APP IS AT YOUR OWN RISK. WE EXPRESSLY DISCLAIM ALL WARRANTIES OF ANY KIND, WHETHER IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. WE MAKE NO WARRANTY THAT OUR SERVICES WILL BE UNINTERRUPTED, TIMELY, SECURE OR ERROR FREE. YOU ACKNOWLEDGE AND AGREE THAT ANY MATERIAL, AND/OR DATA DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF FM APP SERVICE IS DONE AT YOUR OWN DISCRETION AND RISK, AND THAT YOU WILL BE SOLELY RESPONSIBLE FOR ANY DAMAGES TO YOUR COMPUTER SYSTEM OR LOSS OF DATA THAT RESULTS FROM THE DOWNLOAD OF SUCH MATERIAL AND/OR DATA. 8 | 9 | We are sometimes asked to remove links from our search results pages. We address these requests on a case-by-case basis and in general, follow the guidelines below: web servers are identified, indexed and catalogued automatically with software, which means there is no advance review by human beings. Given the enormous volume of information added to and changed on a daily basis, we cannot operate in any other way. This means that we do not screen information posted to FM App. If you want to restrict access to your web server, please let us know, send an e-mail to FM App owner and administrator using the following address: bettercodes1@gmail.com, you must include the offending URL to be removed from our index databases and a reason for the operation to be accomplished. -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohhsodead/FileMasta/990beecfb21de7b03572b3566a34669ff246d4a0/screenshot1.png --------------------------------------------------------------------------------