Skip to content

Commit

Permalink
Stop escaping some characters on json serialization of a license
Browse files Browse the repository at this point in the history
Fixes readium#162, issue with character '&' (and '<', '>') in hints.
  • Loading branch information
llemeurfr committed Dec 22, 2017
1 parent e11e27e commit d5f89b6
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 36 deletions.
2 changes: 2 additions & 0 deletions frontend/api/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ func GetLicense(w http.ResponseWriter, r *http.Request, s IServer) {

// returns the full license to the caller
enc := json.NewEncoder(w)
// do not escape characters
enc.SetEscapeHTML(false)
err = enc.Encode(fullLicense)
if err != nil {
problem.Error(w, r, problem.Problem{Detail: err.Error()}, http.StatusInternalServerError)
Expand Down
2 changes: 2 additions & 0 deletions frontend/api/purchase.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ func GetPurchasedLicense(w http.ResponseWriter, r *http.Request, s IServer) {
w.Header().Set("Content-Disposition", "attachment; filename=\""+attachmentName+".lcpl\"")

enc := json.NewEncoder(w)
// does not escape characters
enc.SetEscapeHTML(false)
err = enc.Encode(fullLicense)

if err != nil {
Expand Down
19 changes: 17 additions & 2 deletions lcpserver/api/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ func GetLicense(w http.ResponseWriter, r *http.Request, s Server) {
aLicense.Encryption.Profile = ""
// return the partial license
enc := json.NewEncoder(w)
// does not escape characters
enc.SetEscapeHTML(false)
enc.Encode(aLicense)
return
}
Expand All @@ -92,6 +94,7 @@ func GetLicense(w http.ResponseWriter, r *http.Request, s Server) {

// debug message, in case the input license causes problems
/*
log.Print("Partial license:")
jsonBody, err := json.Marshal(lic)
if err != nil {
return
Expand Down Expand Up @@ -126,6 +129,8 @@ func GetLicense(w http.ResponseWriter, r *http.Request, s Server) {
w.WriteHeader(http.StatusOK)
// return the license
enc := json.NewEncoder(w)
// does not escape characters
enc.SetEscapeHTML(false)
enc.Encode(aLicense)
}

Expand Down Expand Up @@ -274,6 +279,8 @@ func GenerateLicense(w http.ResponseWriter, r *http.Request, s Server) {
w.WriteHeader(http.StatusCreated)

enc := json.NewEncoder(w)
// does not escape characters
enc.SetEscapeHTML(false)
enc.Encode(lic)
}

Expand Down Expand Up @@ -381,15 +388,19 @@ func GenerateProtectedPublication(w http.ResponseWriter, r *http.Request, s Serv
problem.Error(w, r, problem.Problem{Detail: err.Error(), Instance: contentID}, http.StatusInternalServerError)
return
}
//add license to publication
// add the license to publication
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
// do not escape characters
enc.SetEscapeHTML(false)
enc.Encode(newLicense)
// Suppress the trailing newline
// FIXME/ try to optimize with buf.ReadBytes(byte('\n')) instead of creating a new buffer.
var buf2 bytes.Buffer
buf2.Write(bytes.TrimRight(buf.Bytes(), "\n"))
ep.Add(epub.LicenseFile, &buf2, uint64(buf2.Len()))

//set HTTP headers
// set HTTP headers
w.Header().Add("Content-Type", epub.ContentType_EPUB)
w.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, content.Location))
// FIXME: check the use of X-Lcp-License by the caller (frontend?)
Expand Down Expand Up @@ -621,6 +632,8 @@ func ListLicenses(w http.ResponseWriter, r *http.Request, s Server) {
w.Header().Set("Content-Type", api.ContentType_JSON)

enc := json.NewEncoder(w)
// do not escape characters
enc.SetEscapeHTML(false)
err = enc.Encode(licenses)
if err != nil {
problem.Error(w, r, problem.Problem{Detail: err.Error()}, http.StatusBadRequest)
Expand Down Expand Up @@ -688,6 +701,8 @@ func ListLicensesForContent(w http.ResponseWriter, r *http.Request, s Server) {
}
w.Header().Set("Content-Type", api.ContentType_JSON)
enc := json.NewEncoder(w)
// do not escape characters
enc.SetEscapeHTML(false)
err = enc.Encode(licenses)
if err != nil {
problem.Error(w, r, problem.Problem{Detail: err.Error()}, http.StatusBadRequest)
Expand Down
60 changes: 26 additions & 34 deletions sign/canon.go
Original file line number Diff line number Diff line change
@@ -1,53 +1,45 @@
// Copyright (c) 2016 Readium Foundation
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
// 3. Neither the name of the organization nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Copyright 2017 European Digital Reading Lab. All rights reserved.
// Licensed to the Readium Foundation under one or more contributor license agreements.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file exposed on Github (readium) in the project repository.

package sign

import "encoding/json"
import "strings"
import "io"
import (
"bytes"
"encoding/json"
"io"
"strings"
)

func Canon(in interface{}) ([]byte, error) {
// the easiest way to canonicalize is to marshal it and reify it as a map
// which will sort stuff correctly
b, err := json.Marshal(in)
if err != nil {
return b, err
b, err1 := json.Marshal(in)
if err1 != nil {
return b, err1
}

var jsonObj interface{} // map[string]interface{} ==> auto sorting

dec := json.NewDecoder(strings.NewReader(string(b)))
dec.UseNumber()
for {
if er := dec.Decode(&jsonObj); er == io.EOF {
if err2 := dec.Decode(&jsonObj); err2 == io.EOF {
break
} else if er != nil {
return nil, er
} else if err2 != nil {
return nil, err2
}
}
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
// do not escape characters
enc.SetEscapeHTML(false)
err := enc.Encode(jsonObj)
if err != nil {
return nil, err
}
// remove the trailing newline, added by encode
return bytes.TrimRight(buf.Bytes(), "\n"), nil

return json.Marshal(jsonObj)
}

0 comments on commit d5f89b6

Please sign in to comment.