using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Threading; using System.Threading.Tasks; using System.Xml; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.Books.OpenPackagingFormat { /// /// Provides the primary image for EPUB items that have embedded covers. /// public class EpubImageProvider : IDynamicImageProvider { private readonly ILogger _logger; /// /// Initializes a new instance of the class. /// /// Instance of the interface. public EpubImageProvider(ILogger logger) { _logger = logger; } /// public string Name => "EPUB Metadata"; /// public bool Supports(BaseItem item) { return item is Book; } /// public IEnumerable GetSupportedImages(BaseItem item) { yield return ImageType.Primary; } /// public Task GetImage(BaseItem item, ImageType type, CancellationToken cancellationToken) { if (string.Equals(Path.GetExtension(item.Path), ".epub", StringComparison.OrdinalIgnoreCase)) { return GetFromZip(item, cancellationToken); } return Task.FromResult(new DynamicImageResponse { HasImage = false }); } private async Task LoadCover(ZipArchive epub, XmlDocument opf, string opfRootDirectory, CancellationToken cancellationToken) { var utilities = new OpfReader(opf, _logger); var coverReference = utilities.ReadCoverPath(opfRootDirectory); if (coverReference == null) { return new DynamicImageResponse { HasImage = false }; } var cover = coverReference.Value; var coverFile = epub.GetEntry(cover.Path); if (coverFile == null) { return new DynamicImageResponse { HasImage = false }; } var memoryStream = new MemoryStream(); var coverStream = await coverFile.OpenAsync(cancellationToken).ConfigureAwait(false); await using (coverStream.ConfigureAwait(false)) { await coverStream.CopyToAsync(memoryStream, cancellationToken).ConfigureAwait(false); } memoryStream.Position = 0; var response = new DynamicImageResponse { HasImage = true, Stream = memoryStream }; response.SetFormatFromMimeType(cover.MimeType); return response; } private async Task GetFromZip(BaseItem item, CancellationToken cancellationToken) { using var epub = await ZipFile.OpenReadAsync(item.Path, cancellationToken).ConfigureAwait(false); var opfFilePath = EpubUtils.ReadContentFilePath(epub); if (opfFilePath == null) { return new DynamicImageResponse { HasImage = false }; } var opfRootDirectory = Path.GetDirectoryName(opfFilePath); if (opfRootDirectory == null) { return new DynamicImageResponse { HasImage = false }; } var opfFile = epub.GetEntry(opfFilePath); if (opfFile == null) { return new DynamicImageResponse { HasImage = false }; } using var opfStream = await opfFile.OpenAsync(cancellationToken).ConfigureAwait(false); var opfDocument = new XmlDocument(); opfDocument.Load(opfStream); return await LoadCover(epub, opfDocument, opfRootDirectory, cancellationToken).ConfigureAwait(false); } } }