Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ require (
cloud.google.com/go/storage v1.59.2
github.com/agext/regexp v1.3.0
github.com/andybalholm/cascadia v1.3.3
github.com/antchfx/xmlquery v1.5.1
github.com/antchfx/xpath v1.3.6
github.com/aws/aws-sdk-go-v2 v1.41.1
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.0
github.com/aws/smithy-go v1.24.0
Expand All @@ -18,7 +20,6 @@ require (
github.com/kettek/apng v0.0.0-20220823221153-ff692776a607
github.com/pdfcpu/pdfcpu v0.11.1
github.com/pkg/errors v0.9.1
github.com/readium/xmlquery v0.0.0-20230106230237-8f493145aef4
github.com/relvacode/iso8601 v1.7.0
github.com/stretchr/testify v1.11.1
github.com/trimmer-io/go-xmp v1.0.0
Expand All @@ -41,7 +42,6 @@ require (
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0 // indirect
github.com/antchfx/xpath v1.3.6 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 // indirect
Expand Down
8 changes: 3 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ github.com/agext/regexp v1.3.0 h1:6+9tp+S41TU48gFNV47bX+pp1q7WahGofw6JccmsCDs=
github.com/agext/regexp v1.3.0/go.mod h1:6phv1gViOJXWcTfpxOi9VMS+MaSAo+SUDf7do3ur1HA=
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
github.com/antchfx/xpath v1.2.1/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/antchfx/xmlquery v1.5.1 h1:T9I4Ns1EXiWHy0IqKupGhnfTQtJwlGrpXtauYOoNv78=
github.com/antchfx/xmlquery v1.5.1/go.mod h1:bVqnl7TaDXSReKINrhZz+2E/PbCu2tUahb+wZ7WZNT8=
github.com/antchfx/xpath v1.3.6 h1:s0y+ElRRtTQdfHP609qFu0+c6bglDv20pqOViQjjdPI=
github.com/antchfx/xpath v1.3.6/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
github.com/aws/aws-sdk-go-v2 v1.41.1 h1:ABlyEARCDLN034NhxlRUSZr4l71mh+T5KAeGh6cerhU=
Expand Down Expand Up @@ -127,6 +128,7 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
Expand Down Expand Up @@ -197,8 +199,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/readium/xmlquery v0.0.0-20230106230237-8f493145aef4 h1:iEQhT4jOppg7EK/r4/1e4ULIeCsugv35O+sDlvce5Bo=
github.com/readium/xmlquery v0.0.0-20230106230237-8f493145aef4/go.mod h1:S7gZ8KUgPbsdlF9/iomcwnU31iHMyFEO66+JFJE8uz8=
github.com/relvacode/iso8601 v1.7.0 h1:BXy+V60stMP6cpswc+a93Mq3e65PfXCgDFfhvNNGrdo=
github.com/relvacode/iso8601 v1.7.0/go.mod h1:FlNp+jz+TXpyRqgmM7tnzHHzBnz776kmAH2h3sZCn0I=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
Expand Down Expand Up @@ -301,7 +301,6 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
Expand Down Expand Up @@ -347,7 +346,6 @@ golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
11 changes: 5 additions & 6 deletions pkg/fetcher/resource.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fetcher

import (
"bytes"
"context"
"encoding/json"
"encoding/xml"
Expand All @@ -9,11 +10,10 @@ import (
"io"
"net/http"
"os"
"strings"

"github.com/antchfx/xmlquery"
"github.com/readium/go-toolkit/pkg/archive"
"github.com/readium/go-toolkit/pkg/manifest"
"github.com/readium/xmlquery"
"golang.org/x/text/encoding"
"golang.org/x/text/encoding/unicode"
)
Expand Down Expand Up @@ -92,13 +92,12 @@ func ReadResourceAsJSON(ctx context.Context, r Resource) (map[string]interface{}
return object, nil
}

func ReadResourceAsXML(ctx context.Context, r Resource, prefixes map[string]string) (*xmlquery.Node, *ResourceError) {
bytes, ex := r.Read(ctx, 0, 0)
func ReadResourceAsXML(ctx context.Context, r Resource) (*xmlquery.Node, *ResourceError) {
bin, ex := r.Read(ctx, 0, 0)
if ex != nil {
return nil, ex
}
node, err := xmlquery.ParseWithOptions(strings.NewReader(string(bytes)), xmlquery.ParserOptions{
Prefixes: prefixes,
node, err := xmlquery.ParseWithOptions(bytes.NewReader(bin), xmlquery.ParserOptions{
Decoder: &xmlquery.DecoderOptions{
Strict: true,
Entity: xml.HTMLEntity,
Expand Down
6 changes: 1 addition & 5 deletions pkg/parser/epub/media_overlay_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,7 @@ func (s *MediaOverlayService) GuideForResource(ctx context.Context, href string)
res := s.fetcher.Get(ctx, link)
defer res.Close()

n, rerr := fetcher.ReadResourceAsXML(ctx, res, map[string]string{
NamespaceOPS: "epub",
NamespaceSMIL: "smil",
NamespaceSMIL2: "smil2",
})
n, rerr := fetcher.ReadResourceAsXML(ctx, res)
if rerr != nil {
return nil, rerr.Cause
}
Expand Down
19 changes: 10 additions & 9 deletions pkg/parser/epub/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ import (
"strings"
"time"

"github.com/antchfx/xmlquery"
"github.com/readium/go-toolkit/pkg/internal/extensions"
"github.com/readium/go-toolkit/pkg/manifest"
"github.com/readium/go-toolkit/pkg/mediatype"
"github.com/readium/go-toolkit/pkg/util/url"
"github.com/readium/xmlquery"
)

var (
xpMetaLanguage = mustCompileNS("//opf:metadata/dc:language")
xpMetadata = mustCompileNS("//opf:metadata")
)

type Title struct {
Expand Down Expand Up @@ -52,22 +57,18 @@ func NewMetadataParser(epubVersion float64, prefixMap map[string]string) Metadat

func (m MetadataParser) Parse(document *xmlquery.Node, filePath url.URL) *EPUBMetadata {
// Init lang
if l := document.SelectElement("/" + NSSelect(NamespaceOPF, "package")); l != nil {
if l := xmlquery.QuerySelector(document, xpPackage); l != nil {
for _, attr := range l.Attr {
if attr.Name.Local == "lang" {
m.packageLanguage = attr.Value
}
}
}
if l := document.SelectElement(
"//" + NSSelect(NamespaceOPF, "metadata") + "/" + NSSelect(NamespaceDC, "language"),
); l != nil {
if l := xmlquery.QuerySelector(document, xpMetaLanguage); l != nil {
m.metaLanguage = strings.TrimSpace(l.InnerText())
}

metadata := document.SelectElement(
"//" + NSSelect(NamespaceOPF, "metadata"),
)
metadata := xmlquery.QuerySelector(document, xpMetadata)
if metadata == nil {
return nil
}
Expand Down Expand Up @@ -1091,7 +1092,7 @@ func (m *PubMetadataAdapter) OtherMetadata() map[string]interface{} {
if _, ok := usedProperties[k]; ok {
continue
}
values := make([]interface{}, len(v))
values := make([]any, len(v))
for i, val := range v {
values[i] = val.ToMap()
}
Expand Down
7 changes: 1 addition & 6 deletions pkg/parser/epub/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@ import (
)

func loadMetadata(ctx context.Context, name string) (*manifest.Metadata, error) {
n, rerr := fetcher.ReadResourceAsXML(ctx, fetcher.NewFileResource(manifest.Link{}, "./testdata/package/"+name+".opf"), map[string]string{
NamespaceOPF: "opf",
NamespaceDC: "dc",
VocabularyDCTerms: "dcterms",
"http://www.idpf.org/2013/rendition": "rendition",
})
n, rerr := fetcher.ReadResourceAsXML(ctx, fetcher.NewFileResource(manifest.Link{}, "./testdata/package/"+name+".opf"))
if rerr != nil {
return nil, rerr.Cause
}
Expand Down
26 changes: 6 additions & 20 deletions pkg/parser/epub/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,7 @@ func (p Parser) Parse(ctx context.Context, asset asset.PublicationAsset, f fetch

// Detect DRM

opfXmlDocument, errx := fetcher.ReadResourceAsXML(ctx, f.Get(ctx, manifest.Link{Href: manifest.NewHREF(opfPath)}), map[string]string{
NamespaceOPF: "opf",
NamespaceDC: "dc",
VocabularyDCTerms: "dcterms",
"http://www.idpf.org/2013/rendition": "rendition",
})
opfXmlDocument, errx := fetcher.ReadResourceAsXML(ctx, f.Get(ctx, manifest.Link{Href: manifest.NewHREF(opfPath)}))
if errx != nil {
return nil, errx
}
Expand Down Expand Up @@ -80,11 +75,7 @@ func (p Parser) Parse(ctx context.Context, asset asset.PublicationAsset, f fetch
}

func parseEncryptionData(ctx context.Context, f fetcher.Fetcher) (ret map[url.URL]manifest.Encryption) {
n, err := fetcher.ReadResourceAsXML(ctx, f.Get(ctx, manifest.Link{Href: manifest.MustNewHREFFromString("META-INF/encryption.xml", false)}), map[string]string{
NamespaceENC: "enc",
NamespaceSIG: "ds",
NamespaceCOMP: "comp",
})
n, err := fetcher.ReadResourceAsXML(ctx, f.Get(ctx, manifest.Link{Href: manifest.MustNewHREFFromString("META-INF/encryption.xml", false)}))
if err != nil {
return
}
Expand Down Expand Up @@ -113,9 +104,7 @@ func parseNavigationData(ctx context.Context, packageDocument PackageDocument, f
if ncxItem == nil {
return
}
n, nerr := fetcher.ReadResourceAsXML(ctx, f.Get(ctx, manifest.Link{Href: manifest.NewHREF(ncxItem.Href)}), map[string]string{
NamespaceNCX: "ncx",
})
n, nerr := fetcher.ReadResourceAsXML(ctx, f.Get(ctx, manifest.Link{Href: manifest.NewHREF(ncxItem.Href)}))
if nerr != nil {
return
}
Expand All @@ -136,10 +125,7 @@ func parseNavigationData(ctx context.Context, packageDocument PackageDocument, f
if navItem == nil {
return
}
n, errx := fetcher.ReadResourceAsXML(ctx, f.Get(ctx, manifest.Link{Href: manifest.NewHREF(navItem.Href)}), map[string]string{
NamespaceXHTML: "html",
NamespaceOPS: "epub",
})
n, errx := fetcher.ReadResourceAsXML(ctx, f.Get(ctx, manifest.Link{Href: manifest.NewHREF(navItem.Href)}))
if errx != nil {
return
}
Expand All @@ -150,9 +136,9 @@ func parseNavigationData(ctx context.Context, packageDocument PackageDocument, f

func parseDisplayOptions(ctx context.Context, f fetcher.Fetcher) (ret map[string]string) {
ret = make(map[string]string)
displayOptionsXml, err := fetcher.ReadResourceAsXML(ctx, f.Get(ctx, manifest.Link{Href: manifest.MustNewHREFFromString("META-INF/com.apple.ibooks.display-options.xml", false)}), nil)
displayOptionsXml, err := fetcher.ReadResourceAsXML(ctx, f.Get(ctx, manifest.Link{Href: manifest.MustNewHREFFromString("META-INF/com.apple.ibooks.display-options.xml", false)}))
if err != nil {
displayOptionsXml, err = fetcher.ReadResourceAsXML(ctx, f.Get(ctx, manifest.Link{Href: manifest.MustNewHREFFromString("META-INF/com.kobobooks.display-options.xml", false)}), nil)
displayOptionsXml, err = fetcher.ReadResourceAsXML(ctx, f.Get(ctx, manifest.Link{Href: manifest.MustNewHREFFromString("META-INF/com.kobobooks.display-options.xml", false)}))
if err != nil {
return
}
Expand Down
32 changes: 22 additions & 10 deletions pkg/parser/epub/parser_encryption.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,26 @@ package epub
import (
"strconv"

"github.com/antchfx/xmlquery"
"github.com/readium/go-toolkit/pkg/manifest"
"github.com/readium/go-toolkit/pkg/protection"
"github.com/readium/go-toolkit/pkg/util/url"
"github.com/readium/xmlquery"
)

var (
xpEncEncData = mustCompileNS("//enc:EncryptedData")
xpEncCipherData = mustCompileNS("enc:CipherData")
xpEncCipherRef = mustCompileNS("enc:CipherReference")
xpEncKeyInfo = mustCompileNS("ds:KeyInfo")
xpEncRetrieval = mustCompileNS("ds:RetrievalMethod")
xpEncMethod = mustCompileNS("enc:EncryptionMethod")
xpEncProps = mustCompileNS("enc:EncryptionProperties")
xpEncProp = mustCompileNS("enc:EncryptionProperty")
xpEncCompress = mustCompileNS("comp:Compression")
)

func ParseEncryption(document *xmlquery.Node) (ret map[url.URL]manifest.Encryption) {
for _, node := range document.SelectElements("//" + NSSelect(NamespaceENC, "EncryptedData")) {
for _, node := range xmlquery.QuerySelectorAll(document, xpEncEncData) {
u, e := parseEncryptedData(node)
if e != nil {
if ret == nil {
Expand All @@ -23,19 +35,19 @@ func ParseEncryption(document *xmlquery.Node) (ret map[url.URL]manifest.Encrypti
}

func parseEncryptedData(node *xmlquery.Node) (url.URL, *manifest.Encryption) {
cdat := node.SelectElement(NSSelect(NamespaceENC, "CipherData"))
cdat := xmlquery.QuerySelector(node, xpEncCipherData)
if cdat == nil {
return nil, nil
}
cipherref := cdat.SelectElement(NSSelect(NamespaceENC, "CipherReference"))
cipherref := xmlquery.QuerySelector(cdat, xpEncCipherRef)
if cipherref == nil {
return nil, nil
}
resourceURI := cipherref.SelectAttr("URI")

retrievalMethod := ""
if keyinfo := node.SelectElement(NSSelect(NamespaceSIG, "KeyInfo")); keyinfo != nil {
if r := keyinfo.SelectElement(NSSelect(NamespaceSIG, "RetrievalMethod")); r != nil {
if keyinfo := xmlquery.QuerySelector(node, xpEncKeyInfo); keyinfo != nil {
if r := xmlquery.QuerySelector(keyinfo, xpEncRetrieval); r != nil {
retrievalMethod = r.SelectAttr("URI")
}
}
Expand All @@ -48,11 +60,11 @@ func parseEncryptedData(node *xmlquery.Node) (url.URL, *manifest.Encryption) {
ret.Scheme = protection.SchemeLCP
}

if encryptionmethod := node.SelectElement(NSSelect(NamespaceENC, "EncryptionMethod")); encryptionmethod != nil {
if encryptionmethod := xmlquery.QuerySelector(node, xpEncMethod); encryptionmethod != nil {
ret.Algorithm = encryptionmethod.SelectAttr("Algorithm")
}

if encryptionproperties := node.SelectElement(NSSelect(NamespaceENC, "EncryptionProperties")); encryptionproperties != nil {
if encryptionproperties := xmlquery.QuerySelector(node, xpEncProps); encryptionproperties != nil {
originalLength, method := parseEncryptionProperties(encryptionproperties)
if method != "" {
ret.Compression = method
Expand All @@ -69,8 +81,8 @@ func parseEncryptedData(node *xmlquery.Node) (url.URL, *manifest.Encryption) {
}

func parseEncryptionProperties(encryptionProperties *xmlquery.Node) (int64, string) {
for _, encryptionProperty := range encryptionProperties.SelectElements(NSSelect(NamespaceENC, "EncryptionProperty")) {
if compressionElement := encryptionProperty.SelectElement(NSSelect(NamespaceCOMP, "Compression")); compressionElement != nil {
for _, encryptionProperty := range xmlquery.QuerySelectorAll(encryptionProperties, xpEncProp) {
if compressionElement := xmlquery.QuerySelector(encryptionProperty, xpEncCompress); compressionElement != nil {
if originalLength, method := parseCompressionElement(compressionElement); method != "" {
return originalLength, method
}
Expand Down
6 changes: 1 addition & 5 deletions pkg/parser/epub/parser_encryption_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@ import (
)

func loadEncryption(ctx context.Context, name string) (map[string]manifest.Encryption, error) {
n, rerr := fetcher.ReadResourceAsXML(ctx, fetcher.NewFileResource(manifest.Link{}, "./testdata/encryption/encryption-"+name+".xml"), map[string]string{
NamespaceENC: "enc",
NamespaceSIG: "ds",
NamespaceCOMP: "comp",
})
n, rerr := fetcher.ReadResourceAsXML(ctx, fetcher.NewFileResource(manifest.Link{}, "./testdata/encryption/encryption-"+name+".xml"))
if rerr != nil {
return nil, rerr.Cause
}
Expand Down
Loading
Loading