Skip to content

Commit 2cc906c

Browse files
authored
Revamp format specifications and other changes (readium#500)
1 parent 5a6a239 commit 2cc906c

File tree

20 files changed

+343
-362
lines changed

20 files changed

+343
-362
lines changed

readium/lcp/src/main/java/org/readium/r2/lcp/LcpContentProtection.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,7 @@ import org.readium.r2.shared.util.data.decodeRwpm
2828
import org.readium.r2.shared.util.data.decodeXml
2929
import org.readium.r2.shared.util.data.readDecodeOrElse
3030
import org.readium.r2.shared.util.flatMap
31-
import org.readium.r2.shared.util.format.EpubSpecification
32-
import org.readium.r2.shared.util.format.LcpLicenseSpecification
33-
import org.readium.r2.shared.util.format.LcpSpecification
31+
import org.readium.r2.shared.util.format.Specification
3432
import org.readium.r2.shared.util.getOrElse
3533
import org.readium.r2.shared.util.resource.Resource
3634
import org.readium.r2.shared.util.resource.TransformingContainer
@@ -57,7 +55,7 @@ internal class LcpContentProtection(
5755
allowUserInteraction: Boolean
5856
): Try<ContentProtection.OpenResult, ContentProtection.OpenError> {
5957
if (
60-
!asset.format.conformsTo(LcpSpecification)
58+
!asset.format.conformsTo(Specification.Lcp)
6159
) {
6260
return Try.failure(ContentProtection.OpenError.AssetNotSupported())
6361
}
@@ -91,7 +89,7 @@ internal class LcpContentProtection(
9189

9290
val encryptionData =
9391
when {
94-
asset.format.conformsTo(EpubSpecification) -> parseEncryptionDataEpub(
92+
asset.format.conformsTo(Specification.Epub) -> parseEncryptionDataEpub(
9593
asset.container
9694
)
9795
else -> parseEncryptionDataRpf(asset.container)
@@ -151,7 +149,7 @@ internal class LcpContentProtection(
151149
credentials: String?,
152150
allowUserInteraction: Boolean
153151
): Try<ContentProtection.OpenResult, ContentProtection.OpenError> {
154-
if (!licenseAsset.format.conformsTo(LcpLicenseSpecification)) {
152+
if (!licenseAsset.format.conformsTo(Specification.LcpLicense)) {
155153
return Try.failure(ContentProtection.OpenError.AssetNotSupported())
156154
}
157155

readium/lcp/src/main/java/org/readium/r2/lcp/license/container/LicenseContainer.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ import org.readium.r2.shared.util.asset.Asset
1919
import org.readium.r2.shared.util.asset.ContainerAsset
2020
import org.readium.r2.shared.util.asset.ResourceAsset
2121
import org.readium.r2.shared.util.data.Container
22-
import org.readium.r2.shared.util.format.EpubSpecification
2322
import org.readium.r2.shared.util.format.FormatSpecification
24-
import org.readium.r2.shared.util.format.LcpLicenseSpecification
23+
import org.readium.r2.shared.util.format.Specification
2524
import org.readium.r2.shared.util.resource.Resource
2625

2726
private val LICENSE_IN_EPUB = Url("META-INF/license.lcpl")!!
@@ -44,11 +43,11 @@ internal fun createLicenseContainer(
4443
formatSpecification: FormatSpecification
4544
): WritableLicenseContainer =
4645
when {
47-
formatSpecification.conformsTo(EpubSpecification) -> FileZipLicenseContainer(
46+
formatSpecification.conformsTo(Specification.Epub) -> FileZipLicenseContainer(
4847
file.path,
4948
LICENSE_IN_EPUB
5049
)
51-
formatSpecification.conformsTo(LcpLicenseSpecification) -> LcplLicenseContainer(file)
50+
formatSpecification.conformsTo(Specification.LcpLicense) -> LcplLicenseContainer(file)
5251
// Assuming it's a Readium WebPub package (e.g. audiobook, LCPDF, etc.) as a fallback
5352
else -> FileZipLicenseContainer(file.path, LICENSE_IN_RPF)
5453
}
@@ -70,7 +69,7 @@ internal fun createLicenseContainer(
7069
resource: Resource,
7170
formatSpecification: FormatSpecification
7271
): LicenseContainer {
73-
if (!formatSpecification.conformsTo(LcpLicenseSpecification)) {
72+
if (!formatSpecification.conformsTo(Specification.LcpLicense)) {
7473
throw LcpException(LcpError.Container.OpenFailed)
7574
}
7675

@@ -88,7 +87,7 @@ internal fun createLicenseContainer(
8887
formatSpecification: FormatSpecification
8988
): LicenseContainer {
9089
val licensePath = when {
91-
formatSpecification.conformsTo(EpubSpecification) -> LICENSE_IN_EPUB
90+
formatSpecification.conformsTo(Specification.Epub) -> LICENSE_IN_EPUB
9291
// Assuming it's a Readium WebPub package (e.g. audiobook, LCPDF, etc.) as a fallback
9392
else -> LICENSE_IN_RPF
9493
}

readium/lcp/src/main/java/org/readium/r2/lcp/service/LicensesService.kt

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,10 @@ import org.readium.r2.shared.util.FileExtension
4242
import org.readium.r2.shared.util.Try
4343
import org.readium.r2.shared.util.asset.Asset
4444
import org.readium.r2.shared.util.asset.AssetRetriever
45-
import org.readium.r2.shared.util.format.EpubSpecification
4645
import org.readium.r2.shared.util.format.Format
4746
import org.readium.r2.shared.util.format.FormatHints
4847
import org.readium.r2.shared.util.format.FormatSpecification
49-
import org.readium.r2.shared.util.format.LcpSpecification
50-
import org.readium.r2.shared.util.format.ZipSpecification
48+
import org.readium.r2.shared.util.format.Specification
5149
import org.readium.r2.shared.util.getOrElse
5250
import org.readium.r2.shared.util.mediatype.MediaType
5351
import timber.log.Timber
@@ -71,14 +69,23 @@ internal class LicensesService(
7169
licenseDocument: LicenseDocument,
7270
publicationFile: File
7371
): Try<Unit, LcpError> {
72+
val hashIsCorrect = licenseDocument.publicationLink.hash
73+
?.let { publicationFile.checkSha256(it) }
74+
75+
if (hashIsCorrect == false) {
76+
return Try.failure(
77+
LcpError.Network(Exception("Digest mismatch: download looks corrupted."))
78+
)
79+
}
80+
7481
val mediaType = licenseDocument.publicationLink.mediaType
7582
val format = assetRetriever.sniffFormat(publicationFile, FormatHints(mediaType))
7683
.getOrElse {
7784
Format(
7885
specification = FormatSpecification(
79-
ZipSpecification,
80-
EpubSpecification,
81-
LcpSpecification
86+
Specification.Zip,
87+
Specification.Epub,
88+
Specification.Lcp
8289
),
8390
mediaType = MediaType.EPUB,
8491
fileExtension = FileExtension("epub")
@@ -152,13 +159,14 @@ internal class LicensesService(
152159
onProgress = onProgress
153160
)
154161

155-
license.publicationLink.hash
156-
?.takeIf { destination.checkSha256(it) == false }
157-
?.run {
158-
throw LcpException(
159-
LcpError.Network(Exception("Digest mismatch: download looks corrupted."))
160-
)
161-
}
162+
val hashIsCorrect = license.publicationLink.hash
163+
?.let { destination.checkSha256(it) }
164+
165+
if (hashIsCorrect == false) {
166+
throw LcpException(
167+
LcpError.Network(Exception("Digest mismatch: download looks corrupted."))
168+
)
169+
}
162170

163171
val format =
164172
assetRetriever.sniffFormat(
@@ -179,9 +187,9 @@ internal class LicensesService(
179187
is AssetRetriever.RetrieveError.FormatNotSupported -> {
180188
Format(
181189
specification = FormatSpecification(
182-
ZipSpecification,
183-
EpubSpecification,
184-
LcpSpecification
190+
Specification.Zip,
191+
Specification.Epub,
192+
Specification.Lcp
185193
),
186194
mediaType = MediaType.EPUB,
187195
fileExtension = FileExtension("epub")

readium/shared/src/main/java/org/readium/r2/shared/publication/protection/FallbackContentProtection.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ import org.readium.r2.shared.util.Error
1414
import org.readium.r2.shared.util.Try
1515
import org.readium.r2.shared.util.asset.Asset
1616
import org.readium.r2.shared.util.asset.ContainerAsset
17-
import org.readium.r2.shared.util.format.AdeptSpecification
18-
import org.readium.r2.shared.util.format.LcpSpecification
17+
import org.readium.r2.shared.util.format.Specification
1918

2019
/**
2120
* [ContentProtection] implementation used as a fallback when detecting known DRMs
@@ -35,9 +34,9 @@ public class FallbackContentProtection : ContentProtection {
3534
}
3635

3736
val protectionServiceFactory = when {
38-
asset.format.conformsTo(LcpSpecification) ->
37+
asset.format.conformsTo(Specification.Lcp) ->
3938
Service.createFactory(Scheme.Lcp, "Readium LCP")
40-
asset.format.conformsTo(AdeptSpecification) ->
39+
asset.format.conformsTo(Specification.Adept) ->
4140
Service.createFactory(Scheme.Adept, "Adobe ADEPT")
4241
else ->
4342
return Try.failure(ContentProtection.OpenError.AssetNotSupported())

readium/shared/src/main/java/org/readium/r2/shared/publication/services/CoverService.kt

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ package org.readium.r2.shared.publication.services
1111

1212
import android.graphics.Bitmap
1313
import android.util.Size
14+
import kotlinx.coroutines.Dispatchers
15+
import kotlinx.coroutines.withContext
1416
import org.readium.r2.shared.extensions.scaleToFit
1517
import org.readium.r2.shared.publication.Link
1618
import org.readium.r2.shared.publication.Publication
@@ -76,15 +78,16 @@ internal class ResourceCoverService(
7678
private val container: Container<Resource>
7779
) : CoverService {
7880

79-
override suspend fun cover(): Bitmap? {
80-
val resource = container[coverUrl]
81-
?: return null
81+
override suspend fun cover(): Bitmap? =
82+
withContext(Dispatchers.IO) {
83+
val resource = container[coverUrl]
84+
?: return@withContext null
8285

83-
return resource
84-
.read()
85-
.flatMap { it.decodeBitmap() }
86-
.getOrNull()
87-
}
86+
return@withContext resource
87+
.read()
88+
.flatMap { it.decodeBitmap() }
89+
.getOrNull()
90+
}
8891

8992
companion object {
9093

readium/shared/src/main/java/org/readium/r2/shared/util/format/Format.kt

Lines changed: 90 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -61,91 +61,93 @@ public value class FormatSpecification(public val specifications: Set<Specificat
6161
specifications.containsAll(other.specifications)
6262
}
6363

64-
public interface Specification
65-
66-
/*
67-
* Archive specifications
68-
*/
69-
public object ZipSpecification : Specification
70-
public object RarSpecification : Specification
71-
72-
/*
73-
* Syntax specifications
74-
*/
75-
public object JsonSpecification : Specification
76-
public object XmlSpecification : Specification
77-
78-
/*
79-
* Publication manifest specifications
80-
*/
81-
public object W3cPubManifestSpecification : Specification
82-
public object RwpmSpecification : Specification
83-
84-
/*
85-
* Technical document specifications
86-
*/
87-
public object ProblemDetailsSpecification : Specification
88-
public object LcpLicenseSpecification : Specification
89-
90-
/*
91-
* Media format specifications
92-
*/
93-
public object PdfSpecification : Specification
94-
public object HtmlSpecification : Specification
95-
96-
/*
97-
* Drm specifications
98-
*/
99-
public object LcpSpecification : Specification
100-
public object AdeptSpecification : Specification
101-
102-
/*
103-
* Bitmap specifications
104-
*/
105-
public object AvifSpecification : Specification
106-
public object BmpSpecification : Specification
107-
public object GifSpecification : Specification
108-
public object JpegSpecification : Specification
109-
public object JxlSpecification : Specification
110-
public object PngSpecification : Specification
111-
public object TiffSpecification : Specification
112-
public object WebpSpecification : Specification
113-
114-
/*
115-
* Audio specifications
116-
*/
117-
public object AacSpecification : Specification
118-
public object AiffSpecification : Specification
119-
public object FlacSpecification : Specification
120-
public object Mp4Specification : Specification
121-
public object Mp3Specification : Specification
122-
public object OggSpecification : Specification
123-
public object OpusSpecification : Specification
124-
public object WavSpecification : Specification
125-
public object WebmSpecification : Specification
126-
127-
/*
128-
* Publication package specifications
129-
*/
130-
public object EpubSpecification : Specification
131-
public object RpfSpecification : Specification
132-
public object LpfSpecification : Specification
133-
public object InformalAudiobookSpecification : Specification
134-
public object InformalComicSpecification : Specification
135-
136-
/*
137-
* Opds specifications
138-
*/
139-
public object Opds1CatalogSpecification : Specification
140-
public object Opds1EntrySpecification : Specification
141-
public object Opds2CatalogSpecification : Specification
142-
public object Opds2PublicationSpecification : Specification
143-
public object OpdsAuthenticationSpecification : Specification
144-
145-
/*
146-
* Language specifications
147-
*/
148-
149-
public object JavaScriptSpecification : Specification
150-
151-
public object CssSpecification : Specification
64+
public interface Specification {
65+
66+
public companion object {}
67+
68+
/*
69+
* Archive specifications
70+
*/
71+
public object Zip : Specification
72+
public object Rar : Specification
73+
74+
/*
75+
* Syntax specifications
76+
*/
77+
public object Json : Specification
78+
public object Xml : Specification
79+
80+
/*
81+
* Publication manifest specifications
82+
*/
83+
public object W3cPubManifest : Specification
84+
public object Rwpm : Specification
85+
86+
/*
87+
* Technical document specifications
88+
*/
89+
public object ProblemDetails : Specification
90+
public object LcpLicense : Specification
91+
92+
/*
93+
* Media format specifications
94+
*/
95+
public object Pdf : Specification
96+
public object Html : Specification
97+
98+
/*
99+
* Drm specifications
100+
*/
101+
public object Lcp : Specification
102+
public object Adept : Specification
103+
104+
/*
105+
* Bitmap specifications
106+
*/
107+
public object Avif : Specification
108+
public object Bmp : Specification
109+
public object Gif : Specification
110+
public object Jpeg : Specification
111+
public object Jxl : Specification
112+
public object Png : Specification
113+
public object Tiff : Specification
114+
public object Webp : Specification
115+
116+
/*
117+
* Audio specifications
118+
*/
119+
public object Aac : Specification
120+
public object Aiff : Specification
121+
public object Flac : Specification
122+
public object Mp4 : Specification
123+
public object Mp3 : Specification
124+
public object Ogg : Specification
125+
public object Opus : Specification
126+
public object Wav : Specification
127+
public object Webm : Specification
128+
129+
/*
130+
* Publication package specifications
131+
*/
132+
public object Epub : Specification
133+
public object Rpf : Specification
134+
public object Lpf : Specification
135+
public object InformalAudiobook : Specification
136+
public object InformalComic : Specification
137+
138+
/*
139+
* Opds specifications
140+
*/
141+
public object Opds1Catalog : Specification
142+
public object Opds1Entry : Specification
143+
public object Opds2Catalog : Specification
144+
public object Opds2Publication : Specification
145+
public object OpdsAuthentication : Specification
146+
147+
/*
148+
* Language specifications
149+
*/
150+
151+
public object JavaScript : Specification
152+
public object Css : Specification
153+
}

0 commit comments

Comments
 (0)