Add unicode replacements for illegal characters
This commit is contained in:
parent
45c5efffbd
commit
490d121db3
@ -5,7 +5,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AAXClean.Codecs" Version="0.2.8" />
|
||||
<PackageReference Include="AAXClean.Codecs" Version="0.2.9" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@ -42,10 +42,10 @@ namespace AaxDecrypter
|
||||
|
||||
var outDir = Path.GetDirectoryName(OutputFileName);
|
||||
if (!Directory.Exists(outDir))
|
||||
throw new DirectoryNotFoundException($"Directory does not exist: {nameof(outDir)}");
|
||||
Directory.CreateDirectory(outDir);
|
||||
|
||||
if (!Directory.Exists(cacheDirectory))
|
||||
throw new DirectoryNotFoundException($"Directory does not exist: {nameof(cacheDirectory)}");
|
||||
Directory.CreateDirectory(cacheDirectory);
|
||||
|
||||
jsonDownloadState = Path.Combine(cacheDirectory, Path.GetFileName(Path.ChangeExtension(OutputFileName, ".json")));
|
||||
TempFilePath = Path.ChangeExtension(jsonDownloadState, ".aaxc");
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using AAXClean;
|
||||
using AAXClean.Codecs;
|
||||
@ -19,12 +20,12 @@ namespace FileLiberator
|
||||
private long fileSize;
|
||||
private static string Mp3FileName(string m4bPath) => Path.ChangeExtension(m4bPath ?? "", ".mp3");
|
||||
|
||||
public override Task CancelAsync() => m4bBook?.CancelAsync();
|
||||
public override Task CancelAsync() => m4bBook?.CancelAsync() ?? Task.CompletedTask;
|
||||
|
||||
public static bool ValidateMp3(LibraryBook libraryBook)
|
||||
{
|
||||
var path = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId);
|
||||
return path?.ToString()?.ToLower()?.EndsWith(".m4b") == true && !File.Exists(Mp3FileName(path));
|
||||
var paths = AudibleFileStorage.Audio.GetPaths(libraryBook.Book.AudibleProductId);
|
||||
return paths.Any(path => path?.ToString()?.ToLower()?.EndsWith(".m4b") == true && !File.Exists(Mp3FileName(path)));
|
||||
}
|
||||
|
||||
public override bool Validate(LibraryBook libraryBook) => ValidateMp3(libraryBook);
|
||||
@ -35,7 +36,13 @@ namespace FileLiberator
|
||||
|
||||
try
|
||||
{
|
||||
var m4bPath = AudibleFileStorage.Audio.GetPath(libraryBook.Book.AudibleProductId);
|
||||
var m4bPaths = AudibleFileStorage.Audio.GetPaths(libraryBook.Book.AudibleProductId);
|
||||
|
||||
foreach (var m4bPath in m4bPaths)
|
||||
{
|
||||
var proposedMp3Path = Mp3FileName(m4bPath);
|
||||
if (File.Exists(proposedMp3Path) || !File.Exists(m4bPath)) continue;
|
||||
|
||||
m4bBook = new Mp4File(m4bPath, FileAccess.Read);
|
||||
m4bBook.ConversionProgressUpdate += M4bBook_ConversionProgressUpdate;
|
||||
|
||||
@ -52,7 +59,6 @@ namespace FileLiberator
|
||||
m4bBook.InputStream.Close();
|
||||
mp3File.Close();
|
||||
|
||||
var proposedMp3Path = Mp3FileName(m4bPath);
|
||||
var realMp3Path = FileUtility.SaferMoveToValidPath(mp3File.Name, proposedMp3Path);
|
||||
OnFileCreated(libraryBook, realMp3Path);
|
||||
|
||||
@ -60,7 +66,7 @@ namespace FileLiberator
|
||||
return new StatusHandler { "Conversion failed" };
|
||||
else if (result == ConversionResult.Cancelled)
|
||||
return new StatusHandler { "Cancelled" };
|
||||
else
|
||||
}
|
||||
return new StatusHandler();
|
||||
}
|
||||
finally
|
||||
|
||||
@ -21,7 +21,7 @@ namespace FileLiberator
|
||||
|
||||
public override bool Validate(LibraryBook libraryBook) => !libraryBook.Book.Audio_Exists();
|
||||
|
||||
public override Task CancelAsync() => abDownloader?.CancelAsync();
|
||||
public override Task CancelAsync() => abDownloader?.CancelAsync() ?? Task.CompletedTask;
|
||||
|
||||
public override async Task<StatusHandler> ProcessAsync(LibraryBook libraryBook)
|
||||
{
|
||||
|
||||
@ -32,12 +32,18 @@ namespace FileManager
|
||||
Init();
|
||||
}
|
||||
|
||||
public string FindFile(System.Text.RegularExpressions.Regex regex)
|
||||
public LongPath FindFile(System.Text.RegularExpressions.Regex regex)
|
||||
{
|
||||
lock (fsCacheLocker)
|
||||
return fsCache.FirstOrDefault(s => regex.IsMatch(s));
|
||||
}
|
||||
|
||||
public List<LongPath> FindFiles(System.Text.RegularExpressions.Regex regex)
|
||||
{
|
||||
lock (fsCacheLocker)
|
||||
return fsCache.Where(s => regex.IsMatch(s)).ToList();
|
||||
}
|
||||
|
||||
public void RefreshFiles()
|
||||
{
|
||||
lock (fsCacheLocker)
|
||||
|
||||
@ -90,9 +90,9 @@ namespace FileManager
|
||||
|
||||
var pathNoPrefix = path.PathWithoutPrefix;
|
||||
|
||||
pathNoPrefix = pathNoPrefix?.Replace(':', '꞉')?.Replace('?', '︖')?.Replace('*', '⁎');
|
||||
|
||||
pathNoPrefix = replaceInvalidChars(pathNoPrefix, illegalCharacterReplacements);
|
||||
pathNoPrefix = standardizeSlashes(pathNoPrefix);
|
||||
pathNoPrefix = replaceColons(pathNoPrefix, illegalCharacterReplacements);
|
||||
pathNoPrefix = removeDoubleSlashes(pathNoPrefix);
|
||||
|
||||
return pathNoPrefix;
|
||||
@ -107,24 +107,6 @@ namespace FileManager
|
||||
private static string replaceInvalidChars(string path, string illegalCharacterReplacements)
|
||||
=> string.Join(illegalCharacterReplacements ?? "", path.Split(invalidChars));
|
||||
|
||||
private static string standardizeSlashes(string path)
|
||||
=> path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
|
||||
|
||||
private static string replaceColons(string path, string illegalCharacterReplacements)
|
||||
{
|
||||
// replace all colons except within the first 2 chars
|
||||
var builder = new System.Text.StringBuilder();
|
||||
for (var i = 0; i < path.Length; i++)
|
||||
{
|
||||
var c = path[i];
|
||||
if (i >= 2 && c == ':')
|
||||
builder.Append(illegalCharacterReplacements);
|
||||
else
|
||||
builder.Append(c);
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private static string removeDoubleSlashes(string path)
|
||||
{
|
||||
if (path.Length < 2)
|
||||
|
||||
@ -27,7 +27,7 @@ namespace FileManager
|
||||
|
||||
//File I/O functions in the Windows API convert "/" to "\" as part of converting
|
||||
//the name to an NT-style name, except when using the "\\?\" prefix
|
||||
path = path.Replace('/', '\\');
|
||||
path = path.Replace(System.IO.Path.AltDirectorySeparatorChar, System.IO.Path.DirectorySeparatorChar);
|
||||
|
||||
if (path.StartsWith(LONG_PATH_PREFIX))
|
||||
return new LongPath { Path = path };
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
@ -9,6 +10,7 @@ namespace LibationFileManager
|
||||
public abstract class AudibleFileStorage
|
||||
{
|
||||
protected abstract LongPath GetFilePathCustom(string productId);
|
||||
protected abstract List<LongPath> GetFilePathsCustom(string productId);
|
||||
|
||||
#region static
|
||||
public static LongPath DownloadsInProgressDirectory => Directory.CreateDirectory(Path.Combine(Configuration.Instance.InProgress, "DownloadsInProgress")).FullName;
|
||||
@ -57,6 +59,9 @@ namespace LibationFileManager
|
||||
return firstOrNull;
|
||||
}
|
||||
|
||||
public List<LongPath> GetPaths(string productId)
|
||||
=> GetFilePathsCustom(productId);
|
||||
|
||||
protected Regex GetBookSearchRegex(string productId)
|
||||
{
|
||||
var pattern = string.Format(regexTemplate, productId);
|
||||
@ -70,11 +75,14 @@ namespace LibationFileManager
|
||||
internal AaxcFileStorage() : base(FileType.AAXC) { }
|
||||
|
||||
protected override LongPath GetFilePathCustom(string productId)
|
||||
=> GetFilePathsCustom(productId).FirstOrDefault();
|
||||
|
||||
protected override List<LongPath> GetFilePathsCustom(string productId)
|
||||
{
|
||||
var regex = GetBookSearchRegex(productId);
|
||||
return FileUtility
|
||||
.SaferEnumerateFiles(DownloadsInProgressDirectory, "*.*", SearchOption.AllDirectories)
|
||||
.FirstOrDefault(s => regex.IsMatch(s));
|
||||
.Where(s => regex.IsMatch(s)).ToList();
|
||||
}
|
||||
|
||||
public bool Exists(string productId) => GetFilePath(productId) is not null;
|
||||
@ -87,7 +95,11 @@ namespace LibationFileManager
|
||||
|
||||
private static BackgroundFileSystem BookDirectoryFiles { get; set; }
|
||||
private static object bookDirectoryFilesLocker { get; } = new();
|
||||
|
||||
protected override LongPath GetFilePathCustom(string productId)
|
||||
=> GetFilePathsCustom(productId).FirstOrDefault();
|
||||
|
||||
protected override List<LongPath> GetFilePathsCustom(string productId)
|
||||
{
|
||||
// If user changed the BooksDirectory: reinitialize
|
||||
lock (bookDirectoryFilesLocker)
|
||||
@ -95,11 +107,12 @@ namespace LibationFileManager
|
||||
BookDirectoryFiles = new BackgroundFileSystem(BooksDirectory, "*.*", SearchOption.AllDirectories);
|
||||
|
||||
var regex = GetBookSearchRegex(productId);
|
||||
return BookDirectoryFiles.FindFile(regex);
|
||||
return BookDirectoryFiles.FindFiles(regex);
|
||||
}
|
||||
|
||||
public void Refresh() => BookDirectoryFiles.RefreshFiles();
|
||||
|
||||
public LongPath GetPath(string productId) => GetFilePath(productId);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ namespace LibationWinForms
|
||||
{
|
||||
SetQueueCollapseState(false);
|
||||
await Task.Run(() => processBookQueue1.AddConvertMp3(ApplicationServices.DbContexts.GetLibrary_Flat_NoTracking()
|
||||
.Where(lb => lb.Book.UserDefinedItem.BookStatus is DataLayer.LiberatedStatus.Liberated)));
|
||||
.Where(lb => lb.Book.UserDefinedItem.BookStatus is DataLayer.LiberatedStatus.Liberated && lb.Book.ContentType is DataLayer.ContentType.Product)));
|
||||
}
|
||||
//Only Queue Liberated books for conversion. This isn't a perfect filter, but it's better than nothing.
|
||||
}
|
||||
|
||||
@ -44,6 +44,12 @@
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Dialogs\SettingsDialog.*.cs">
|
||||
<DependentUpon>Dialogs\SettingsDialog.cs</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
|
||||
@ -138,7 +138,7 @@ namespace LibationWinForms.ProcessQueue
|
||||
return Result;
|
||||
}
|
||||
|
||||
public async Task Cancel()
|
||||
public async Task CancelAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@ -212,7 +212,7 @@ namespace LibationWinForms.ProcessQueue
|
||||
private void cancelAllBtn_Click(object sender, EventArgs e)
|
||||
{
|
||||
Queue.ClearQueue();
|
||||
Queue.Current?.Cancel();
|
||||
Queue.Current?.CancelAsync();
|
||||
virtualFlowControl2.VirtualControlCount = Queue.Count;
|
||||
UpdateAllControls();
|
||||
}
|
||||
@ -331,7 +331,7 @@ namespace LibationWinForms.ProcessQueue
|
||||
ProcessBook item = Queue[queueIndex];
|
||||
if (buttonName == nameof(panelClicked.cancelBtn))
|
||||
{
|
||||
await item.Cancel();
|
||||
await item.CancelAsync();
|
||||
Queue.RemoveQueued(item);
|
||||
virtualFlowControl2.VirtualControlCount = Queue.Count;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user