aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller/Entities')
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicGenre.cs5
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs41
-rw-r--r--MediaBrowser.Controller/Entities/Genre.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Person.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Studio.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Year.cs5
7 files changed, 47 insertions, 24 deletions
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index c25694aba5..1e2d94d2a4 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -173,10 +173,7 @@ namespace MediaBrowser.Controller.Entities.Audio
public static string GetPath(string name, bool normalizeName)
{
- // Trim the period at the end because windows will have a hard time with that
- var validName = normalizeName ?
- FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
- name;
+ var validName = normalizeName ? GetItemByNameFolderName(name) : name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.ArtistsPath, validName);
}
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
index 65669e6804..23b3341dbc 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
@@ -80,10 +80,7 @@ namespace MediaBrowser.Controller.Entities.Audio
public static string GetPath(string name, bool normalizeName)
{
- // Trim the period at the end because windows will have a hard time with that
- var validName = normalizeName ?
- FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
- name;
+ var validName = normalizeName ? GetItemByNameFolderName(name) : name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.MusicGenrePath, validName);
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 28f40cb7fa..d030c8f420 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -48,6 +48,10 @@ namespace MediaBrowser.Controller.Entities
public const string ThemeSongFileName = "theme";
+ // Well below the 255 byte limit of the common Linux filesystems and the 255 character limit
+ // of Windows, so the files inside the folder still fit within MAX_PATH.
+ private const int MaxItemByNameFolderNameBytes = 128;
+
/// <summary>
/// The supported image extensions.
/// </summary>
@@ -942,6 +946,43 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
+ /// Turns an item-by-name entity's name into a folder name every supported filesystem accepts.
+ /// </summary>
+ /// <param name="name">The entity's name.</param>
+ /// <returns>The folder name.</returns>
+ public static string GetItemByNameFolderName(string name)
+ {
+ // Trim the period at the end because windows will have a hard time with that
+ var validName = FileSystem.GetValidFilename(name).Trim().TrimEnd('.');
+
+ // Most Linux filesystems cap a path component at 255 bytes, so a name past that cannot be
+ // turned into a folder at all - and an entity with no folder can never be created, which
+ // leaves the credit behind it stuck: not refreshable, not deletable, retried on every scan.
+ // Only broken provider data gets this long, but it still has to resolve to something, so
+ // keep a readable prefix and let a hash of the whole name tell two of them apart.
+ if (Encoding.UTF8.GetByteCount(validName) <= MaxItemByNameFolderNameBytes)
+ {
+ return validName;
+ }
+
+ var suffix = "-" + validName.GetMD5().ToString("N", CultureInfo.InvariantCulture);
+ var budget = MaxItemByNameFolderNameBytes - suffix.Length;
+ var length = Math.Min(validName.Length, budget);
+ while (length > 0 && Encoding.UTF8.GetByteCount(validName.AsSpan(0, length)) > budget)
+ {
+ length--;
+ }
+
+ // Never cut a surrogate pair in half, the lone half is not a valid file name character.
+ if (length > 0 && char.IsHighSurrogate(validName[length - 1]))
+ {
+ length--;
+ }
+
+ return string.Concat(validName.AsSpan(0, length).TrimEnd().TrimEnd('.'), suffix);
+ }
+
+ /// <summary>
/// Cleans a raw name into its sortable form by applying the configured sort rules.
/// </summary>
/// <param name="name">The raw name to clean.</param>
diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs
index 6ec78a270e..ef8acaef92 100644
--- a/MediaBrowser.Controller/Entities/Genre.cs
+++ b/MediaBrowser.Controller/Entities/Genre.cs
@@ -83,10 +83,7 @@ namespace MediaBrowser.Controller.Entities
public static string GetPath(string name, bool normalizeName)
{
- // Trim the period at the end because windows will have a hard time with that
- var validName = normalizeName ?
- FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
- name;
+ var validName = normalizeName ? GetItemByNameFolderName(name) : name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.GenrePath, validName);
}
diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs
index 14325d971a..bba5005eed 100644
--- a/MediaBrowser.Controller/Entities/Person.cs
+++ b/MediaBrowser.Controller/Entities/Person.cs
@@ -98,10 +98,7 @@ namespace MediaBrowser.Controller.Entities
public static string GetPath(string name, bool normalizeName)
{
- // Trim the period at the end because windows will have a hard time with that
- var validFilename = normalizeName ?
- FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
- name;
+ var validFilename = normalizeName ? GetItemByNameFolderName(name) : name;
string subFolderPrefix = null;
diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs
index 9103b09a95..a944b356c8 100644
--- a/MediaBrowser.Controller/Entities/Studio.cs
+++ b/MediaBrowser.Controller/Entities/Studio.cs
@@ -78,10 +78,7 @@ namespace MediaBrowser.Controller.Entities
public static string GetPath(string name, bool normalizeName)
{
- // Trim the period at the end because windows will have a hard time with that
- var validName = normalizeName ?
- FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
- name;
+ var validName = normalizeName ? GetItemByNameFolderName(name) : name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.StudioPath, validName);
}
diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs
index 37820296cc..03fb2156d3 100644
--- a/MediaBrowser.Controller/Entities/Year.cs
+++ b/MediaBrowser.Controller/Entities/Year.cs
@@ -85,10 +85,7 @@ namespace MediaBrowser.Controller.Entities
public static string GetPath(string name, bool normalizeName)
{
- // Trim the period at the end because windows will have a hard time with that
- var validName = normalizeName ?
- FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
- name;
+ var validName = normalizeName ? GetItemByNameFolderName(name) : name;
return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.YearPath, validName);
}