Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect normalization to UNC paths causes failed library scan #2913

Open
DL444 opened this issue Apr 24, 2024 · 0 comments
Open

Incorrect normalization to UNC paths causes failed library scan #2913

DL444 opened this issue Apr 24, 2024 · 0 comments
Labels
enhancement New feature or request needs-triage Needs to be triaged by a developer and assigned a release

Comments

@DL444
Copy link

DL444 commented Apr 24, 2024

What happened?

Kavita fails to access files in folders added to libraries by UNC paths (e.g. \\Server\Share\Directory\File), so series in those folders cannot be discovered during library scans.

The problem is two-fold:

A. Web UI applies incorrect path normalization before sending API request

At library-settings-modal.components.ts:286 and :297:

model.folders = model.folders.map((item: string) => item.startsWith('\\') ? item.substr(1, item.length) : item);

This truncates leading \\ into \, so UNC path \\Server\Share\Directory\File becomes \Server\Share\Directory\File, which is then sent to the backend. The latter is no longer a UNC path and will be interpreted as a relative path instead.

Entering the UNC path with forward slashes (//Server/Share/Directory/File, uncanonical) avoids the truncation and works around this problem, which brings us to:

B. Backend applies incorrect path normalization during library scan

At Parser.cs:1190:

/// <summary>
/// Normalizes the slashes in a path to be <see cref="Path.AltDirectorySeparatorChar"/>
/// </summary>
/// <example>/manga/1\1 -> /manga/1/1</example>
/// <param name="path"></param>
/// <returns></returns>
public static string NormalizePath(string? path)
{
    return string.IsNullOrEmpty(path) ? string.Empty : path.Replace('\\', Path.AltDirectorySeparatorChar)
        .Replace(@"//", Path.AltDirectorySeparatorChar + string.Empty);
}

Any double forward slashes will be combines into one. So //Server/Share/Directory/File would be normalized into /Server/Share/Directory/File. This is again interpreted as a relative path, and upon file access the .NET BCL will expand it into an absolute path based on the application's current drive, which by default is the drive where the application's executable file is located. For example, if kavita.exe is located at C:\Kavita\kavita.exe, the actual file Kavita tries to access will be C:/Server/Share/Directory/File. Such files most probably do not exist, so access will fail.

Removing the second Replace() call solves the problem for me, so I believe the changes required to address those problems should be trivial, and I'm glad to make such contributions. However, seeing it as a potentially breaking change, and that there are tests for this specific behavior, I would really like to have a discussion first in order to know more background for those decisions.

What did you expect?

There should be end-to-end support for UNC paths, so users can add folders hosted on remote file shares to their libraries.

Kavita Version Number - If you don not see your version number listed, please update Kavita and see if your issue still persists.

0.8.1 - Stable

What operating system is Kavita being hosted from?

Windows

If the issue is being seen on Desktop, what OS are you running where you see the issue?

None

If the issue is being seen in the UI, what browsers are you seeing the problem on?

No response

If the issue is being seen on Mobile, what OS are you running where you see the issue?

None

If the issue is being seen on the Mobile UI, what browsers are you seeing the problem on?

No response

Relevant log output

[Kavita] [2024-04-24 12:15:32.657 -07:00  91] [Information] API.Services.TaskScheduler Enqueuing library scan for: 5
[Kavita] [2024-04-24 12:15:32.660 -07:00  91] [Information] Serilog.AspNetCore.RequestLoggingMiddleware HTTP POST /api/library/scan?libraryId=5&force=true responded 200 in 5.5382 ms
[Kavita] [2024-04-24 12:15:32.661 -07:00  18] [Information] API.Services.Tasks.CleanupService Performing cleanup of Cache directories
[Kavita] [2024-04-24 12:15:32.662 -07:00  18] [Information] API.Services.Tasks.CleanupService Cache directory purged
[Kavita] [2024-04-24 12:15:32.665 -07:00  89] [Information] API.Services.Tasks.ScannerService [ScannerService] Beginning file scan on Manga
[Kavita] [2024-04-24 12:15:32.675 -07:00  89] [Debug] API.Services.Tasks.ScannerService [ScannerService] Found 11 files for //Media/Manga/Test\Nichijou
[Kavita] [2024-04-24 12:15:33.136 -07:00  89] [Information] API.Services.Tasks.Scanner.ProcessSeries [ScannerService] Beginning series update on Nichijou, Forced: true
[Kavita] [2024-04-24 12:15:33.140 -07:00  89] [Information] API.Services.Tasks.Scanner.ProcessSeries [ScannerService] Processing series Nichijou
[Kavita] [2024-04-24 12:15:33.140 -07:00  89] [Debug] API.Services.Tasks.Scanner.ProcessSeries [ScannerService] Updating 11 volumes on Nichijou
[Kavita] [2024-04-24 12:15:33.140 -07:00  89] [Debug] API.Services.Tasks.Scanner.ProcessSeries [ScannerService] Parsing Nichijou - Volume 1
[Kavita] [2024-04-24 12:15:33.141 -07:00  89] [Debug] API.Services.Tasks.Scanner.ProcessSeries [ScannerService] Adding new chapter, Nichijou - Vol 1 Ch -100000
[Kavita] [2024-04-24 12:15:33.141 -07:00  89] [Warning] API.Services.ArchiveService Archive /Media/Manga/Test/Nichijou/Nichijou v01 (2016) (Digital) (1r0n).cbz could not be found
[Kavita] [2024-04-24 12:15:33.141 -07:00  89] [Error] API.Services.ArchiveService Archive /Media/Manga/Test/Nichijou/Nichijou v01 (2016) (Digital) (1r0n).cbz could not be found
[Kavita] [2024-04-24 12:15:33.142 -07:00  89] [Error] API.Services.Tasks.Scanner.ProcessSeries [ScannerService] There was an exception updating series for Nichijou
System.IO.FileNotFoundException: Could not find file 'C:\Media\Manga\Test\Nichijou\Nichijou v01 (2016) (Digital) (1r0n).cbz'.
File name: 'C:\Media\Manga\Test\Nichijou\Nichijou v01 (2016) (Digital) (1r0n).cbz'
   at System.IO.FileInfo.get_Length()
   at System.IO.Abstractions.FileInfoWrapper.get_Length()
   at API.Services.Tasks.Scanner.ProcessSeries.AddOrUpdateFileForChapter(Chapter chapter, ParserInfo info, Boolean forceUpdate) in C:\Users\josep\Documents\Projects\KavitaOrg\Kavita\API\Services\Tasks\Scanner\ProcessSeries.cs:line 757
   at API.Services.Tasks.Scanner.ProcessSeries.UpdateChapters(Series series, Volume volume, IList`1 parsedInfos, Boolean forceUpdate) in C:\Users\josep\Documents\Projects\KavitaOrg\Kavita\API\Services\Tasks\Scanner\ProcessSeries.cs:line 702
   at API.Services.Tasks.Scanner.ProcessSeries.UpdateVolumes(Series series, IList`1 parsedInfos, Boolean forceUpdate) in C:\Users\josep\Documents\Projects\KavitaOrg\Kavita\API\Services\Tasks\Scanner\ProcessSeries.cs:line 619
   at API.Services.Tasks.Scanner.ProcessSeries.ProcessSeriesAsync(IList`1 parsedInfos, Library library, Boolean forceUpdate) in C:\Users\josep\Documents\Projects\KavitaOrg\Kavita\API\Services\Tasks\Scanner\ProcessSeries.cs:line 148
[Kavita] [2024-04-24 12:15:33.143 -07:00  89] [Information] API.Services.Tasks.ScannerService [ScannerService] Finished file scan in 465 milliseconds. Updating database
[Kavita] [2024-04-24 12:15:33.171 -07:00  89] [Information] API.Services.Tasks.ScannerService [ScannerService] Finished library scan of 11 files and 1 series in 510 milliseconds for Manga
[Kavita] [2024-04-24 12:15:33.171 -07:00  89] [Debug] API.Services.Tasks.ScannerService [ScannerService] Removing Series that were not found during the scan
[Kavita] [2024-04-24 12:15:33.172 -07:00  86] [Debug] API.Controllers.LibraryController Caching libraries for library_DL444
[Kavita] [2024-04-24 12:15:33.173 -07:00  89] [Debug] API.Services.Tasks.ScannerService [ScannerService] Found 1 series that needs to be removed: ["Nichijou"]
[Kavita] [2024-04-24 12:15:33.173 -07:00  89] [Debug] API.Services.Tasks.ScannerService [ScannerService] Removing Series that were not found during the scan - complete

Additional Notes

One workaround is to map the file shares to drive letters and access the files by them. This should be trivial for interactive workstation deployments but can be more involved for headless server deployments using Windows service wrappers.

Some service wrapper implementations provide features to facilitate this. For example, WinSW seems to support this scenario. However, I don't see any information on this for Shawl, so the workaround might not always be available.

@DL444 DL444 added the needs-triage Needs to be triaged by a developer and assigned a release label Apr 24, 2024
@majora2007 majora2007 added the enhancement New feature or request label Apr 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request needs-triage Needs to be triaged by a developer and assigned a release
Projects
None yet
Development

No branches or pull requests

2 participants