Clean Filenames for Windows

Fixes #391
This commit is contained in:
2025-09-18 00:51:34 +02:00
parent 5af1605c5b
commit 55d6b46507
12 changed files with 53 additions and 43 deletions

View File

@@ -1,6 +1,7 @@
using API.Controllers.DTOs;
using API.Schema.MangaContext;
using API.Workers;
using API.Workers.MangaDownloadWorkers;
using Asp.Versioning;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;

View File

@@ -86,6 +86,6 @@ public abstract class MangaConnector(string name, string[] supportedLanguages, s
}
return filename;
return filename.CleanNameForWindows();
}
}

View File

@@ -36,7 +36,7 @@ public class Chapter : Identifiable, IComparable<Chapter>
this.VolumeNumber = volumeNumber;
this.ChapterNumber = chapterNumber;
this.Title = title;
this.FileName = GetArchiveFilePath();
this.FileName = GetArchiveFilePath().CleanNameForWindows();
this.Downloaded = false;
this.MangaConnectorIds = [];
}

View File

@@ -56,7 +56,7 @@ public class Manga : Identifiable
this.Links = links;
this.AltTitles = altTitles;
this.IgnoreChaptersBefore = ignoreChaptersBefore;
this.DirectoryName = CleanDirectoryName(name);
this.DirectoryName = name.CleanNameForWindows();
this.Year = year;
this.OriginalLanguage = originalLanguage;
this.Chapters = [];
@@ -95,42 +95,6 @@ public class Manga : Identifiable
return publicationFolder;
}
//https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
//less than 32 is control *forbidden*
//34 is " *forbidden*
//42 is * *forbidden*
//47 is / *forbidden*
//58 is : *forbidden*
//60 is < *forbidden*
//62 is > *forbidden*
//63 is ? *forbidden*
//92 is \ *forbidden*
//124 is | *forbidden*
//127 is delete *forbidden*
//Below 127 all except *******
private static readonly int[] ForbiddenCharsBelow127 = [34, 42, 47, 58, 60, 62, 63, 92, 124, 127];
//Above 127 none except *******
private static readonly int[] IncludeCharsAbove127 = [128, 138, 142];
//128 is € include
//138 is Š include
//142 is Ž include
//152 through 255 looks fine except 157, 172, 173, 175 *******
private static readonly int[] ForbiddenCharsAbove152 = [157, 172, 173, 175];
private static string CleanDirectoryName(string name)
{
StringBuilder sb = new ();
foreach (char c in name)
{
if (c >= 32 && c < 127 && ForbiddenCharsBelow127.Contains(c) == false)
sb.Append(c);
else if (c > 127 && c < 152 && IncludeCharsAbove127.Contains(c))
sb.Append(c);
else if(c >= 152 && c <= 255 && ForbiddenCharsAbove152.Contains(c) == false)
sb.Append(c);
}
return sb.ToString();
}
/// <summary>
/// Merges another Manga (MangaConnectorIds and Chapters)
/// </summary>

View File

@@ -6,11 +6,11 @@ using API.Schema.MangaContext;
using API.Schema.MangaContext.MetadataFetchers;
using API.Schema.NotificationsContext;
using API.Workers;
using API.Workers.MangaDownloadWorkers;
using API.Workers.PeriodicWorkers;
using API.Workers.PeriodicWorkers.MaintenanceWorkers;
using log4net;
using log4net.Config;
using Microsoft.EntityFrameworkCore;
namespace API;

42
API/Utils.cs Normal file
View File

@@ -0,0 +1,42 @@
using System.Text;
namespace API;
public static class Utils
{
//https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
//less than 32 is control *forbidden*
//34 is " *forbidden*
//42 is * *forbidden*
//47 is / *forbidden*
//58 is : *forbidden*
//60 is < *forbidden*
//62 is > *forbidden*
//63 is ? *forbidden*
//92 is \ *forbidden*
//124 is | *forbidden*
//127 is delete *forbidden*
//Below 127 all except *******
private static readonly int[] ForbiddenCharsBelow127 = [34, 42, 47, 58, 60, 62, 63, 92, 124, 127];
//Above 127 none except *******
private static readonly int[] IncludeCharsAbove127 = [128, 138, 142];
//128 is € include
//138 is Š include
//142 is Ž include
//152 through 255 looks fine except 157, 172, 173, 175 *******
private static readonly int[] ForbiddenCharsAbove152 = [157, 172, 173, 175];
public static string CleanNameForWindows(this string name)
{
StringBuilder sb = new ();
foreach (char c in name)
{
if (c >= 32 && c < 127 && ForbiddenCharsBelow127.Contains(c) == false)
sb.Append(c);
else if (c > 127 && c < 152 && IncludeCharsAbove127.Contains(c))
sb.Append(c);
else if(c >= 152 && c <= 255 && ForbiddenCharsAbove152.Contains(c) == false)
sb.Append(c);
}
return sb.ToString();
}
}

View File

@@ -11,7 +11,7 @@ using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Processors.Binarization;
using static System.IO.UnixFileMode;
namespace API.Workers;
namespace API.Workers.MangaDownloadWorkers;
/// <summary>
/// Downloads single chapter for Manga from Mangaconnector

View File

@@ -2,7 +2,7 @@ using API.MangaConnectors;
using API.Schema.MangaContext;
using Microsoft.EntityFrameworkCore;
namespace API.Workers;
namespace API.Workers.MangaDownloadWorkers;
/// <summary>
/// Downloads the cover for Manga from Mangaconnector

View File

@@ -2,7 +2,7 @@ using API.MangaConnectors;
using API.Schema.MangaContext;
using Microsoft.EntityFrameworkCore;
namespace API.Workers;
namespace API.Workers.MangaDownloadWorkers;
/// <summary>
/// Retrieves the metadata of available chapters on the Mangaconnector

View File

@@ -1,4 +1,5 @@
using API.Schema.MangaContext;
using API.Workers.MangaDownloadWorkers;
using Microsoft.EntityFrameworkCore;
namespace API.Workers.PeriodicWorkers;

View File

@@ -1,4 +1,5 @@
using API.Schema.MangaContext;
using API.Workers.MangaDownloadWorkers;
using Microsoft.EntityFrameworkCore;
namespace API.Workers.PeriodicWorkers;

View File

@@ -1,4 +1,5 @@
using API.Schema.MangaContext;
using API.Workers.MangaDownloadWorkers;
using Microsoft.EntityFrameworkCore;
namespace API.Workers.PeriodicWorkers;