mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Cover Image Picking + Forwarding Headers with EPUBs (#700)
* Ensure Kavita knows about forwarding headers (fixes issue with epub urls not going through https with reverse proxy). Fixed a case where cover image selection preferred nested folders vs files in root directory. * Fixed broken unit test * Added bug that I fixed to the unit tests
This commit is contained in:
parent
a3caad3e8e
commit
49d1021049
@ -140,9 +140,10 @@ namespace API.Tests.Services
|
|||||||
[InlineData(new [] {"page 2.jpg", "page 10.jpg"}, "page 2.jpg")]
|
[InlineData(new [] {"page 2.jpg", "page 10.jpg"}, "page 2.jpg")]
|
||||||
[InlineData(new [] {"__MACOSX/cover.jpg", "vol1/page 01.jpg"}, "vol1/page 01.jpg")]
|
[InlineData(new [] {"__MACOSX/cover.jpg", "vol1/page 01.jpg"}, "vol1/page 01.jpg")]
|
||||||
[InlineData(new [] {"Akame ga KILL! ZERO - c055 (v10) - p000 [Digital] [LuCaZ].jpg", "Akame ga KILL! ZERO - c055 (v10) - p000 [Digital] [LuCaZ].jpg", "Akame ga KILL! ZERO - c060 (v10) - p200 [Digital] [LuCaZ].jpg", "folder.jpg"}, "Akame ga KILL! ZERO - c055 (v10) - p000 [Digital] [LuCaZ].jpg")]
|
[InlineData(new [] {"Akame ga KILL! ZERO - c055 (v10) - p000 [Digital] [LuCaZ].jpg", "Akame ga KILL! ZERO - c055 (v10) - p000 [Digital] [LuCaZ].jpg", "Akame ga KILL! ZERO - c060 (v10) - p200 [Digital] [LuCaZ].jpg", "folder.jpg"}, "Akame ga KILL! ZERO - c055 (v10) - p000 [Digital] [LuCaZ].jpg")]
|
||||||
|
[InlineData(new [] {"001.jpg", "001 - chapter 1/001.jpg"}, "001.jpg")]
|
||||||
public void FindFirstEntry(string[] files, string expected)
|
public void FindFirstEntry(string[] files, string expected)
|
||||||
{
|
{
|
||||||
var foundFile = _archiveService.FirstFileEntry(files);
|
var foundFile = ArchiveService.FirstFileEntry(files, string.Empty);
|
||||||
Assert.Equal(expected, string.IsNullOrEmpty(foundFile) ? "" : foundFile);
|
Assert.Equal(expected, string.IsNullOrEmpty(foundFile) ? "" : foundFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,10 @@ using static System.String;
|
|||||||
|
|
||||||
namespace API.Comparators
|
namespace API.Comparators
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to emulate Windows explorer sorting
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This is not thread-safe</remarks>
|
||||||
public sealed class NaturalSortComparer : IComparer<string>, IDisposable
|
public sealed class NaturalSortComparer : IComparer<string>, IDisposable
|
||||||
{
|
{
|
||||||
private readonly bool _isAscending;
|
private readonly bool _isAscending;
|
||||||
@ -23,7 +27,6 @@ namespace API.Comparators
|
|||||||
{
|
{
|
||||||
if (x == y) return 0;
|
if (x == y) return 0;
|
||||||
|
|
||||||
// Should be fixed: Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct.
|
|
||||||
if (!_table.TryGetValue(x ?? Empty, out var x1))
|
if (!_table.TryGetValue(x ?? Empty, out var x1))
|
||||||
{
|
{
|
||||||
x1 = Regex.Split(x ?? Empty, "([0-9]+)");
|
x1 = Regex.Split(x ?? Empty, "([0-9]+)");
|
||||||
@ -33,7 +36,6 @@ namespace API.Comparators
|
|||||||
if (!_table.TryGetValue(y ?? Empty, out var y1))
|
if (!_table.TryGetValue(y ?? Empty, out var y1))
|
||||||
{
|
{
|
||||||
y1 = Regex.Split(y ?? Empty, "([0-9]+)");
|
y1 = Regex.Split(y ?? Empty, "([0-9]+)");
|
||||||
// Should be fixed: EXCEPTION: An item with the same key has already been added. Key: M:\Girls of the Wild's\Girls of the Wild's - Ep. 083 (Season 1) [LINE Webtoon].cbz
|
|
||||||
_table.Add(y ?? Empty, y1);
|
_table.Add(y ?? Empty, y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +61,7 @@ namespace API.Comparators
|
|||||||
returnVal = 0;
|
returnVal = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return _isAscending ? returnVal : -returnVal;
|
return _isAscending ? returnVal : -returnVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +123,24 @@ namespace API.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="entryFullNames"></param>
|
/// <param name="entryFullNames"></param>
|
||||||
/// <returns>Entry name of match, null if no match</returns>
|
/// <returns>Entry name of match, null if no match</returns>
|
||||||
public string FirstFileEntry(IEnumerable<string> entryFullNames)
|
public static string FirstFileEntry(IEnumerable<string> entryFullNames, string archiveName)
|
||||||
{
|
{
|
||||||
var result = entryFullNames.OrderBy(Path.GetFileName, new NaturalSortComparer())
|
// First check if there are any files that are not in a nested folder before just comparing by filename. This is needed
|
||||||
.FirstOrDefault(x => !Parser.Parser.HasBlacklistedFolderInPath(x)
|
// because NaturalSortComparer does not work with paths and doesn't seem 001.jpg as before chapter 1/001.jpg.
|
||||||
&& Parser.Parser.IsImage(x)
|
var fullNames = entryFullNames.Where(x =>!Parser.Parser.HasBlacklistedFolderInPath(x)
|
||||||
&& !x.StartsWith(Parser.Parser.MacOsMetadataFileStartsWith));
|
&& Parser.Parser.IsImage(x)
|
||||||
|
&& !x.StartsWith(Parser.Parser.MacOsMetadataFileStartsWith)).ToList();
|
||||||
|
if (fullNames.Count == 0) return null;
|
||||||
|
|
||||||
|
var nonNestedFile = fullNames.Where(entry => (Path.GetDirectoryName(entry) ?? string.Empty).Equals(archiveName))
|
||||||
|
.OrderBy(Path.GetFullPath, new NaturalSortComparer())
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(nonNestedFile)) return nonNestedFile;
|
||||||
|
|
||||||
|
var result = fullNames
|
||||||
|
.OrderBy(Path.GetFileName, new NaturalSortComparer())
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
return string.IsNullOrEmpty(result) ? null : result;
|
return string.IsNullOrEmpty(result) ? null : result;
|
||||||
}
|
}
|
||||||
@ -158,7 +170,7 @@ namespace API.Services
|
|||||||
using var archive = ZipFile.OpenRead(archivePath);
|
using var archive = ZipFile.OpenRead(archivePath);
|
||||||
var entryNames = archive.Entries.Select(e => e.FullName).ToArray();
|
var entryNames = archive.Entries.Select(e => e.FullName).ToArray();
|
||||||
|
|
||||||
var entryName = FindFolderEntry(entryNames) ?? FirstFileEntry(entryNames);
|
var entryName = FindFolderEntry(entryNames) ?? FirstFileEntry(entryNames, Path.GetFileName(archivePath));
|
||||||
var entry = archive.Entries.Single(e => e.FullName == entryName);
|
var entry = archive.Entries.Single(e => e.FullName == entryName);
|
||||||
using var stream = entry.Open();
|
using var stream = entry.Open();
|
||||||
|
|
||||||
@ -169,7 +181,7 @@ namespace API.Services
|
|||||||
using var archive = ArchiveFactory.Open(archivePath);
|
using var archive = ArchiveFactory.Open(archivePath);
|
||||||
var entryNames = archive.Entries.Where(archiveEntry => !archiveEntry.IsDirectory).Select(e => e.Key).ToList();
|
var entryNames = archive.Entries.Where(archiveEntry => !archiveEntry.IsDirectory).Select(e => e.Key).ToList();
|
||||||
|
|
||||||
var entryName = FindFolderEntry(entryNames) ?? FirstFileEntry(entryNames);
|
var entryName = FindFolderEntry(entryNames) ?? FirstFileEntry(entryNames, Path.GetFileName(archivePath));
|
||||||
var entry = archive.Entries.Single(e => e.Key == entryName);
|
var entry = archive.Entries.Single(e => e.Key == entryName);
|
||||||
|
|
||||||
using var stream = entry.OpenEntryStream();
|
using var stream = entry.OpenEntryStream();
|
||||||
|
@ -138,7 +138,10 @@ namespace API
|
|||||||
|
|
||||||
app.UseResponseCompression();
|
app.UseResponseCompression();
|
||||||
|
|
||||||
app.UseForwardedHeaders();
|
app.UseForwardedHeaders(new ForwardedHeadersOptions
|
||||||
|
{
|
||||||
|
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
|
||||||
|
});
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user