Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
################################################################################
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################

/.vs
/packages
/LibgenDesktop
/LibgenDesktop.Setup/obj/Debug x64
6 changes: 1 addition & 5 deletions LibgenDesktop/LibgenDesktop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,9 @@
<Reference Include="System.Security" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Transactions" />
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
Expand Down Expand Up @@ -252,6 +247,7 @@
<Compile Include="ViewModels\DetailsItems\FictionDetailsItemViewModel.cs" />
<Compile Include="ViewModels\DetailsItems\NonFictionDetailsItemViewModel.cs" />
<Compile Include="ViewModels\DetailsItems\SciMagDetailsItemViewModel.cs" />
<Compile Include="ViewModels\Library\ScanResultErrorItemViewModel.cs" />
<Compile Include="ViewModels\Library\SciMagScanResultItemViewModel.cs" />
<Compile Include="ViewModels\Library\FictionScanResultItemViewModel.cs" />
<Compile Include="ViewModels\Library\NonFictionScanResultItemViewModel.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using LibgenDesktop.Models.ProgressArgs;

namespace LibgenDesktop.Models.Localization.Localizators
{
Expand All @@ -22,6 +23,8 @@ public LibraryTabLocalizator(List<Translation> prioritizedTranslationList, Langu
ColumnsFile = Format(translation => translation?.File);
ColumnsAuthors = Format(translation => translation?.Authors);
ColumnsTitle = Format(translation => translation?.Title);
ColumnsErrorType = Format(translation => translation?.ErrorType);
ColumnsErrorDescription = Format(translation => translation?.ErrorDescription);
}

public string TabTitle { get; }
Expand All @@ -35,13 +38,46 @@ public LibraryTabLocalizator(List<Translation> prioritizedTranslationList, Langu
public string Added { get; }
public string ScanLog { get; }
public string Error { get; }
public string ColumnsErrorType { get; }
public string ColumnsErrorDescription { get; }
public string ColumnsFile { get; }
public string ColumnsAuthors { get; }
public string ColumnsTitle { get; }

public string GetScanStartedString(string directory) => Format(translation => translation?.ScanStarted, new { directory });
public string GetFoundString(int count) => Format(translation => translation?.Found, new { count });
public string GetNotFoundString(int count) => Format(translation => translation?.NotFound, new { count });
public string GetErrorsString(int count) => Format(translation => translation?.Errors, new { count });
public string GetErrorDescription(ErrorTypes errorType)
{
switch (errorType)
{
case ErrorTypes.ERROR_NONE:
return "";
case ErrorTypes.ERROR_DIRECTORY_ACCESS:
return Format(translation => translation?.Library.ErrorDescriptions.DirectoryAccess);
case ErrorTypes.ERROR_DIRECTORY_NOT_FOUND:
return Format(translation => translation?.Library.ErrorDescriptions.DirectoryNotFound);
case ErrorTypes.ERROR_FILE_SIZE_ZERO:
return Format(translation => translation?.Library.ErrorDescriptions.FileSize);
case ErrorTypes.ERROR_FILE_NOT_FOUND:
return Format(translation => translation?.Library.ErrorDescriptions.FileNotFound);
case ErrorTypes.ERROR_FILE_PATH_TOO_LONG:
return Format(translation => translation?.Library.ErrorDescriptions.FilePathTooLong);
case ErrorTypes.ERROR_FILE_ACCESS:
return Format(translation => translation?.Library.ErrorDescriptions.FileAccess);
case ErrorTypes.ERROR_FILE_IN_USE:
return Format(translation => translation?.Library.ErrorDescriptions.FileInUse);
case ErrorTypes.ERROR_IO_EXCEPTION:
return Format(translation => translation?.Library.ErrorDescriptions.IoException);
case ErrorTypes.ERROR_MD5_HASH_NOT_IN_DB:
return Format(translation => translation?.Library.ErrorDescriptions.MD5HashError);
case ErrorTypes.ERROR_OTHER:
return Format(translation => translation?.Library.ErrorDescriptions.OtherException);
default: throw new ArgumentOutOfRangeException();
}
}

public string GetScanCompleteString(int found, int notFound, int errors) => Format(translation => translation?.ScanComplete,
new { found = Formatter.ToFormattedString(found), notFound = Formatter.ToFormattedString(notFound),
errors = Formatter.ToFormattedString(errors) });
Expand Down
18 changes: 18 additions & 0 deletions LibgenDesktop/Models/Localization/Translation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,22 @@ internal class LibraryColumnsTranslation
public string File { get; set; }
public string Authors { get; set; }
public string Title { get; set; }
public string ErrorType { get; set; }
public string ErrorDescription { get; set; }
}

internal class LibraryErrorDescriptionsTranslation
{
public string DirectoryAccess { get; set; }
public string DirectoryNotFound { get; set; }
public string FileSize { get; set; }
public string FileNotFound { get; set; }
public string FilePathTooLong { get; set; }
public string FileAccess { get; set; }
public string FileInUse { get; set; }
public string IoException { get; set; }
public string MD5HashError { get; set; }
public string OtherException { get; set; }
}

internal class LibraryTranslation
Expand All @@ -588,8 +604,10 @@ internal class LibraryTranslation
public string NotFound { get; set; }
public string ScanLog { get; set; }
public string Error { get; set; }
public string Errors { get; set; }
public string ScanComplete { get; set; }
public LibraryColumnsTranslation Columns { get; set; }
public LibraryErrorDescriptionsTranslation ErrorDescriptions { get; set; }
}

internal class DatabaseTranslation
Expand Down
99 changes: 87 additions & 12 deletions LibgenDesktop/Models/MainModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ public Task<DatabaseStats> GetDatabaseStatsAsync()

public async Task<Updater.UpdateCheckResult> CheckForApplicationUpdateAsync()
{
Updater.UpdateCheckResult result = await updater.CheckForUpdateAsync(ignoreSpecifiedRelease: false);
Updater.UpdateCheckResult result = await updater.CheckForUpdateAsync(false);
if (result != null && result.NewReleaseName != AppSettings.LastUpdate.IgnoreReleaseName)
{
LastApplicationUpdateCheckResult = result;
Expand Down Expand Up @@ -1083,56 +1083,131 @@ private void ScanDirectory<T>(string rootScanDirectory, string scanDirectory, IP
{
relativeFilePath = relativeFilePath.Substring(rootScanDirectory.Length + 1);
}

if (!StringExtensions.HasEbookExtension(relativeFilePath))
{
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, false, ErrorTypes.ERROR_NONE));
notFound++;
continue;
}

string md5Hash;
try
{
using (MD5 md5 = MD5.Create())
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var md5 = MD5.Create())
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 8192, true))
{
if (fileStream.Length <= 0)
{
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, true, ErrorTypes.ERROR_FILE_SIZE_ZERO));
errors++;
continue;
}
var md5HashArray = md5.ComputeHash(fileStream);
md5Hash = BitConverter.ToString(md5HashArray).Replace("-", "").ToLowerInvariant();
}
}
catch (IOException ex)
{
int hresult = ExceptionUtils.GetHRForException(ex);
const int E_PATHTOOLONG = unchecked((int) 0x800700CE);
const int E_FILENOTFOUND = unchecked((int) 0x80070002);
const int E_ACCESSDENIED = unchecked((int) 0x80070005);
const int E_SHARING_VIOLATION = unchecked((int) 0x80070020);

switch (hresult)
{
byte[] md5HashArray = md5.ComputeHash(fileStream);
md5Hash = BitConverter.ToString(md5HashArray).Replace("-", String.Empty).ToLowerInvariant();
case E_PATHTOOLONG:
Logger.Debug($"Error: {nameof(ErrorTypes.ERROR_FILE_PATH_TOO_LONG).Replace("_", " ")}, length: {filePath.Length}");
Logger.Exception(ex);
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, true, ErrorTypes.ERROR_FILE_PATH_TOO_LONG));
errors++;
continue;
case E_FILENOTFOUND:
Logger.Debug($"Error: {nameof(ErrorTypes.ERROR_FILE_NOT_FOUND).Replace("_", " ")}, filePath: {filePath}");
Logger.Exception(ex);
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, true, ErrorTypes.ERROR_FILE_NOT_FOUND));
errors++;
continue;
case E_ACCESSDENIED:
Logger.Debug($"Error: {nameof(ErrorTypes.ERROR_FILE_ACCESS).Replace("_", " ")}, filePath: {filePath}");
Logger.Exception(ex);
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, true, ErrorTypes.ERROR_FILE_ACCESS));
errors++;
continue;
case E_SHARING_VIOLATION:
Logger.Debug($"Error: {nameof(ErrorTypes.ERROR_FILE_IN_USE).Replace("_", " ")}, filePath: {filePath}");
Logger.Exception(ex);
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, true, ErrorTypes.ERROR_FILE_IN_USE));
errors++;
continue;
}

Logger.Debug($"Error: {nameof(ErrorTypes.ERROR_IO_EXCEPTION).Replace("_", " ")}, IOException: {ex}");
Logger.Exception(ex);
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, true, ErrorTypes.ERROR_IO_EXCEPTION));
errors++;
continue;
}
catch (Exception exception)
{
Logger.Debug($"Couldn't calculate MD5 hash for the file: {filePath}");
Logger.Exception(exception);
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, error: true));
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, true, ErrorTypes.ERROR_OTHER));
errors++;
continue;
}
try
{
T libgenObject = getObjectByMd5HashFunction(md5Hash);
var libgenObject = getObjectByMd5HashFunction(md5Hash);
if (libgenObject != null)
{
progressHandler.Report(new ScanProgress<T>(relativeFilePath, libgenObject));
found++;
}
else
{
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, error: false));
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, false, ErrorTypes.ERROR_NONE));
notFound++;
}
}
catch (Exception exception)
{
Logger.Debug($"Couldn't lookup the MD5 hash: {md5Hash} in the database for the file: {filePath}");
Logger.Debug($"Error: {nameof(ErrorTypes.ERROR_MD5_HASH_NOT_IN_DB).Replace("_", " ")}, MD5 hash: {md5Hash} in the database for the file: {filePath}");
Logger.Exception(exception);
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, error: true));
progressHandler.Report(new ScanUnknownProgress(relativeFilePath, true, ErrorTypes.ERROR_MD5_HASH_NOT_IN_DB));
errors++;
continue;
}
}
foreach (string directoryPath in Directory.EnumerateDirectories(scanDirectory))
{
ScanDirectory(rootScanDirectory, directoryPath, progressHandler, getObjectByMd5HashFunction, ref found, ref notFound, ref errors);
}
}
catch (UnauthorizedAccessException ex)
{
Logger.Debug($"Error: {nameof(ErrorTypes.ERROR_DIRECTORY_ACCESS).Replace("_", " ")}, filePath: {scanDirectory}");
Logger.Exception(ex);
progressHandler.Report(new ScanUnknownProgress(scanDirectory, true, ErrorTypes.ERROR_DIRECTORY_ACCESS));
errors++;
}
catch (IOException ex)
{
int hresult = ExceptionUtils.GetHRForException(ex);
const int E_DIRECTORYNOTFOUND = unchecked((int)0x80070003);

if (hresult == E_DIRECTORYNOTFOUND)
{
Logger.Debug($"Error: {nameof(ErrorTypes.ERROR_DIRECTORY_NOT_FOUND).Replace("_", " ")}, filePath: {scanDirectory}");
Logger.Exception(ex);
progressHandler.Report(new ScanUnknownProgress(scanDirectory, true, ErrorTypes.ERROR_DIRECTORY_NOT_FOUND));
errors++;
}
}
catch (Exception exception)
{
Logger.Exception(exception);
progressHandler.Report(new ScanUnknownProgress(scanDirectory, error: true));
progressHandler.Report(new ScanUnknownProgress(scanDirectory, true, ErrorTypes.ERROR_OTHER));
errors++;
}
}
Expand Down
21 changes: 19 additions & 2 deletions LibgenDesktop/Models/ProgressArgs/ScanUnknownProgress.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
namespace LibgenDesktop.Models.ProgressArgs
{
internal enum ErrorTypes
{
ERROR_NONE,
ERROR_DIRECTORY_ACCESS,
ERROR_DIRECTORY_NOT_FOUND,
ERROR_FILE_NOT_FOUND,
ERROR_FILE_PATH_TOO_LONG,
ERROR_FILE_ACCESS,
ERROR_FILE_IN_USE,
ERROR_FILE_SIZE_ZERO,
ERROR_IO_EXCEPTION,
ERROR_MD5_HASH_NOT_IN_DB,
ERROR_OTHER
}

internal class ScanUnknownProgress
{
public ScanUnknownProgress(string relativeFilePath, bool error)
public ScanUnknownProgress(string relativeFilePath, bool error, ErrorTypes errorType)
{
RelativeFilePath = relativeFilePath;
Error = error;
ErrorType = errorType;
}

public string RelativeFilePath { get; }
public bool Error { get; }
public ErrorTypes ErrorType {get;}
}
}
}
12 changes: 12 additions & 0 deletions LibgenDesktop/Models/Utils/ExceptionUtils.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
using System;
using System.Runtime.InteropServices;

namespace LibgenDesktop.Models.Utils
{
internal static class ExceptionUtils
{
public static int GetHRForException(Exception exception)
{
if (exception == null) throw new ArgumentNullException();

//on first call there is possible pollution of thread IErrorInfo with sensitive data
int hr = Marshal.GetHRForException(exception);
//therefore call with empty ex. obj. to cleanup IErrorInfo
Marshal.GetHRForException(new Exception());
return hr;
}

public static Exception GetInnermostException(this Exception exception)
{
while (exception.InnerException != null)
Expand Down
5 changes: 5 additions & 0 deletions LibgenDesktop/Models/Utils/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ namespace LibgenDesktop.Models.Utils
{
internal static class StringExtensions
{
public static bool HasEbookExtension(string source)
{
return (source.EndsWith(".djvu") || source.EndsWith(".mobi") || source.EndsWith(".pdf") || source.EndsWith(".epub")|| source.EndsWith(".doc") || source.EndsWith(".docx") );
}

public static bool CompareOrdinalIgnoreCase(this string currentString, string otherString)
{
return String.Compare(currentString, otherString, StringComparison.OrdinalIgnoreCase) == 0;
Expand Down
Loading