From 449b20d61587286a89a2d75c01e9e3e2a00301b6 Mon Sep 17 00:00:00 2001 From: qnga <32197639+qnga@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:38:54 +0100 Subject: [PATCH] Add `LcpService.injectLicenseDocument` (#473) --- CHANGELOG.md | 8 +++++- .../java/org/readium/r2/lcp/LcpService.kt | 16 +++++++++++ .../readium/r2/lcp/service/LicensesService.kt | 27 +++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e5fef0943..156124b6f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,15 @@ All notable changes to this project will be documented in this file. Take a look ### Added -* The new `HyperlinkNavigator.shouldFollowInternalLink(Link, LinkContext?)` allows you to handle footnotes according to your preference. +#### Navigator + +* The new `HyperlinkNavigator.shouldfollowinternallink(Link, LinkContext?)` allows you to handle footnotes according to your preference. * By default, the navigator now moves to the footnote content instead of displaying a pop-up as it did in version 2.x. +#### LCP + +* You can use `LcpService.injectLicenseDocument()` to insert an LCPL into a package, if you downloaded it manually instead of using `LcpService.acquirePublication()`. + ## [3.0.0-alpha.1] diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt index b56b12c0b3..fe37a7f9b8 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/LcpService.kt @@ -29,6 +29,7 @@ import org.readium.r2.shared.util.Try import org.readium.r2.shared.util.asset.Asset import org.readium.r2.shared.util.asset.AssetRetriever import org.readium.r2.shared.util.format.Format +import org.readium.r2.shared.util.mediatype.MediaType /** * Service used to acquire and open publications protected with LCP. @@ -49,6 +50,8 @@ public interface LcpService { /** * Acquires a protected publication from a standalone LCPL's bytes. * + * License will be injected into the publication archive without explicitly calling + * [injectLicenseDocument]. * You can cancel the on-going acquisition by cancelling its parent coroutine context. * * @param onProgress Callback to follow the acquisition progress from 0.0 to 1.0. @@ -61,6 +64,8 @@ public interface LcpService { /** * Acquires a protected publication from a standalone LCPL file. * + * License will be injected into the publication archive without explicitly calling + * [injectLicenseDocument]. * You can cancel the on-going acquisition by cancelling its parent coroutine context. * * @param onProgress Callback to follow the acquisition progress from 0.0 to 1.0. @@ -114,6 +119,17 @@ public interface LcpService { allowUserInteraction: Boolean ): Try + /** + * Injects a [licenseDocument] into the given [publicationFile] package. + * + * This is useful if you downloaded the publication yourself instead of using [acquirePublication]. + */ + public suspend fun injectLicenseDocument( + licenseDocument: LicenseDocument, + publicationFile: File, + mediaType: MediaType? = null + ): Try + /** * Creates a [ContentProtection] instance which can be used with a Streamer to unlock * LCP protected publications. diff --git a/readium/lcp/src/main/java/org/readium/r2/lcp/service/LicensesService.kt b/readium/lcp/src/main/java/org/readium/r2/lcp/service/LicensesService.kt index 70c4d4f1b1..94ab351041 100644 --- a/readium/lcp/src/main/java/org/readium/r2/lcp/service/LicensesService.kt +++ b/readium/lcp/src/main/java/org/readium/r2/lcp/service/LicensesService.kt @@ -66,6 +66,33 @@ internal class LicensesService( ): ContentProtection = LcpContentProtection(this, authentication, assetRetriever) + override suspend fun injectLicenseDocument( + licenseDocument: LicenseDocument, + publicationFile: File, + mediaType: MediaType? + ): Try { + val format = assetRetriever.sniffFormat(publicationFile, FormatHints(mediaType)) + .getOrElse { + Format( + specification = FormatSpecification( + ZipSpecification, + EpubSpecification, + LcpSpecification + ), + mediaType = MediaType.EPUB, + fileExtension = FileExtension("epub") + ) + } + + return try { + val container = createLicenseContainer(publicationFile, format.specification) + container.write(licenseDocument) + Try.success(Unit) + } catch (e: Exception) { + Try.failure(LcpError.wrap(e)) + } + } + override suspend fun acquirePublication( lcpl: File, onProgress: (Double) -> Unit