...
Code Block | ||
---|---|---|
| ||
private func parsePublication(at url: URL) -> PubBox? { do { guard let (pubBox, parsingCallback) = try Publication.parse(at: url) else { return nil } let (publication, container) = pubBox // TODO: SIMPLY-2840 // Parse .ncx document to update TOC and page list if publication doesn't contain TOC // -- the code below should be removed as described in SIMPLY-2840 -- if publication.tableOfContents.isEmpty { publication.otherCollections.append(contentsOf: parseNCXDocument(in: container, links: publication.links)) } // -- end of cleanup -- items[url.lastPathComponent] = (container, parsingCallback) return (publication, container) } catch { log(.error, "Error parsing publication at '\(url.absoluteString)': \(error.localizedDescription)") return nil } } } |
private func parsePublication(at url: URL) -> PubBox? {
do {
guard let (pubBox, parsingCallback) = try Publication.parse(at: url) else {
return nil
}
let (publication, container) = pubBox
// TODO: SIMPLY-2840
// Parse .ncx document to update TOC and page list if publication doesn't contain TOC
// -- the code below should be removed as described in SIMPLY-2840 --
if publication.tableOfContents.isEmpty {
publication.otherCollections.append(contentsOf: parseNCXDocument(in: container, links: publication.links))
}
// -- end of cleanup --
items[url.lastPathComponent] = (container, parsingCallback)
return (publication, container)
} catch {
log(.error, "Error parsing publication at '\(url.absoluteString)': \(error.localizedDescription)")
return nil
}
}
}
And parseNCXDocument(from container: Container, to publication: inout Publication) function was added in an extension to LibraryService.
The way Readium 2 creates Publication and Container objects may change in the future, the idea is to decrypt ncxDocumentData as shown below:
Original code: private func
Code Block | ||
---|---|---|
| ||
private func parseNCXDocument(in container: Container, links: [Link]) -> [PublicationCollection] |
...
{ // Get the link in the readingOrder pointing to the NCX document. |
...
guard let ncxLink = links.first(withType: .ncx), |
...
let ncxDocumentData = try? container.data(relativePath: ncxLink.href) |
...
{
return []
}
...
else { return [] } let ncx = NCXParser(data: ncxDocumentData, at: ncxLink.href) |
...
func makeCollection(_ type: NCXParser.NavType, role: String) |
...
-> PublicationCollection? { let links = ncx.links(for: type) |
...
guard !links.isEmpty else |
...
return nil
}
...
{ return nil } return PublicationCollection(role: role, links: links) |
...
}
return [
...
} return [ makeCollection(.tableOfContents, role: "toc"), |
...
makeCollection(.pageList, role: "pageList") |
...
].compactMap { $0 } } |
}Modified code decrypts ncx data (in bold): private func
Code Block | ||
---|---|---|
| ||
private func parseNCXDocument(in container: Container, links: [Link]) -> [PublicationCollection |
...
] { // Get the link in the readingOrder pointing to the NCX document. |
...
guard let ncxLink = links.first(withType: .ncx), |
...
let ncxDocumentData = try? container.data(relativePath: ncxLink.href) |
...
{
return []
}
// this part is added to decrypt ncx data
var data = ncxDocumentData
let license = AdobeDRMLicense(for: container)
...
else { return [] } // this part is added to decrypt ncx data var data = ncxDocumentData let license = AdobeDRMLicense(for: container) if let optionalDecipheredData = try? license.decipher(ncxDocumentData), |
...
let decipheredData = optionalDecipheredData {
data = decipheredData
}
// NCXParser here parses data instead of ncxDocumentData
let ncx = NCXParser(data: data, at: ncxLink.href)
func makeCollection(_ type: NCXParser.NavType, role: String) -> PublicationCollection? {
...
let decipheredData = optionalDecipheredData { data = decipheredData } // NCXParser here parses data instead of ncxDocumentData let ncx = NCXParser(data: data, at: ncxLink.href) func makeCollection(_ type: NCXParser.NavType, role: String) -> PublicationCollection? { let links = ncx.links(for: type) |
...
guard !links.isEmpty else {
return nil
}
...
guard !links.isEmpty else { return nil } return PublicationCollection(role: role, links: |
...
}
return [
...
links) } return [ makeCollection(.tableOfContents, role: "toc"), |
...
makeCollection(.pageList, role: "pageList") |
...
].compactMap { $0 } |
...
}
|
}
This workaround is temporary, the version of Readium 2 that supports multiple DRM services won’t need additional parsing of the navigation document, and this workaround should be removed.
...