using System; using System.IO; using MediaBrowser.Common.Configuration; using Microsoft.Extensions.Logging; namespace Jellyfin.Plugin.JRay.Services; /// /// Removes the pause-overlay script tag that an earlier version of JRay /// injected into the web client's index.html on disk. /// /// /// This class cannot inject. JRay reaches the web client only through /// , which rewrites /// index.html as it is served. Patching the file on disk was removed /// rather than left switched off: the patch outlives an uninstall, a web-client /// upgrade discards it silently, and it races any other plugin patching the same /// file. An unreachable write path is also the one nobody runs, which is the one /// a later refactor re-enables by accident. /// /// Removal remains because users upgrading from a version that did patch the /// file must not be left with a stale injection pointing at endpoints that have /// since changed. It keys on JRay's own <!-- jray-overlay --> /// marker, so it is unambiguous and touches nothing another plugin added. /// // TRACES: JR-021, JR-022 | PR-004 public static class WebClientPatchService { private const string Marker = ""; private const string ScriptTag = ""; /// /// Removes a legacy on-disk overlay injection, if one is present. Safe to /// call on every startup: it is a no-op once the marker is gone. /// /// The Jellyfin application paths. /// The logger. public static void RemoveLegacyPatch(IApplicationPaths applicationPaths, ILogger logger) { ArgumentNullException.ThrowIfNull(applicationPaths); ArgumentNullException.ThrowIfNull(logger); var indexPath = Path.Combine(applicationPaths.WebPath, "index.html"); try { if (!File.Exists(indexPath)) { logger.LogDebug("JRay: web client index.html not found at {Path}", indexPath); return; } var html = File.ReadAllText(indexPath); if (!html.Contains(Marker, StringComparison.Ordinal)) { return; } var cleaned = RemoveInjection(html); File.WriteAllText(indexPath, cleaned); logger.LogInformation( "JRay: removed a pause-overlay script left in {Path} by an earlier version. " + "JRay no longer modifies this file; the overlay is served through File Transformation.", indexPath); } catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) { logger.LogWarning(ex, "JRay: failed to remove the legacy overlay patch from {Path}", indexPath); } } /// /// Strips the marked script tag from the document. /// /// The document contents. /// The contents with JRay's injection removed. internal static string RemoveInjection(string html) { ArgumentNullException.ThrowIfNull(html); // The trailing newline is stripped with the tag when present, so removing // a patch restores the document byte-for-byte rather than leaving a blank // line that accumulates across upgrades. return html .Replace(ScriptTag + Marker + "\n", string.Empty, StringComparison.Ordinal) .Replace(ScriptTag + Marker, string.Empty, StringComparison.Ordinal); } }