Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop escaping HTML #224

Merged
merged 1 commit into from Oct 16, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions Makefile
@@ -1,6 +1,11 @@
.PHONY: test
test: unit fuzz

.PHONY: format
format:
gofmt -w .
gosimports -w -local github.com/spdx .

.PHONY: unit
unit:
go test -v -covermode=count -coverprofile=profile.cov ./...
Expand Down
4 changes: 2 additions & 2 deletions convert/spdx_document_conversion_test.go
Expand Up @@ -3,12 +3,12 @@
package convert

import (
"encoding/json"
"reflect"
"testing"

"github.com/stretchr/testify/require"

"github.com/spdx/tools-golang/json/marshal"
"github.com/spdx/tools-golang/spdx"
"github.com/spdx/tools-golang/spdx/v2/common"
"github.com/spdx/tools-golang/spdx/v2/v2_1"
Expand Down Expand Up @@ -2128,7 +2128,7 @@ func Test_ConvertSPDXDocuments(t *testing.T) {
}

func toJSON(data interface{}) string {
bytes, err := json.Marshal(data)
bytes, err := marshal.JSON(data)
if err != nil {
panic(err)
}
Expand Down
15 changes: 15 additions & 0 deletions json/marshal/json.go
@@ -0,0 +1,15 @@
package marshal

import (
"bytes"
"encoding/json"
)

// JSON marshals the object _without_ escaping HTML
func JSON(obj interface{}) ([]byte, error) {
buf := &bytes.Buffer{}
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
err := enc.Encode(obj)
return bytes.TrimSpace(buf.Bytes()), err
}
60 changes: 60 additions & 0 deletions json/marshal/json_test.go
@@ -0,0 +1,60 @@
package marshal

import (
"testing"

"github.com/stretchr/testify/require"
)

func Test_MarshalJSON(t *testing.T) {
tests := []struct {
name string
in interface{}
expected string
}{
{
name: "basic usage",
in: "<html>",
expected: `"<html>"`,
},
{
name: "within MarshalJSON callbacks",
in: s1{
s2{
s3{
Value: "<html>",
},
},
},
expected: `{"S2":{"S3":{"Value":"<html>"}}}`,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
got, err := JSON(test.in)
require.NoError(t, err)
require.Equal(t, test.expected, string(got))
})
}
}

type s1 struct {
S2 s2
}

type s2 struct {
S3 s3
}

func (s *s2) MarshalJSON() ([]byte, error) {
return JSON(s.S3)
}

type s3 struct {
Value string
}

func (s *s3) MarshalJSON() ([]byte, error) {
return JSON(s.Value)
}
6 changes: 4 additions & 2 deletions json/writer_test.go
Expand Up @@ -2,11 +2,13 @@ package json_test

import (
"bytes"
"testing"

"github.com/stretchr/testify/assert"

"github.com/spdx/tools-golang/json"
"github.com/spdx/tools-golang/spdx/common"
spdx "github.com/spdx/tools-golang/spdx/v2/v2_3"
"github.com/stretchr/testify/assert"
"testing"
)

func Test_Write(t *testing.T) {
Expand Down
5 changes: 3 additions & 2 deletions spdx/v2/common/annotation.go
Expand Up @@ -3,9 +3,10 @@
package common

import (
"encoding/json"
"fmt"
"strings"

"github.com/spdx/tools-golang/json/marshal"
)

type Annotator struct {
Expand Down Expand Up @@ -37,7 +38,7 @@ func (a *Annotator) UnmarshalJSON(data []byte) error {
// This function is also used when marshalling to YAML
func (a Annotator) MarshalJSON() ([]byte, error) {
if a.Annotator != "" {
return json.Marshal(fmt.Sprintf("%s: %s", a.AnnotatorType, a.Annotator))
return marshal.JSON(fmt.Sprintf("%s: %s", a.AnnotatorType, a.Annotator))
}

return []byte{}, nil
Expand Down
5 changes: 3 additions & 2 deletions spdx/v2/common/creation_info.go
Expand Up @@ -3,9 +3,10 @@
package common

import (
"encoding/json"
"fmt"
"strings"

"github.com/spdx/tools-golang/json/marshal"
)

// Creator is a wrapper around the Creator SPDX field. The SPDX field contains two values, which requires special
Expand Down Expand Up @@ -37,7 +38,7 @@ func (c *Creator) UnmarshalJSON(data []byte) error {
// This function is also used with marshalling to YAML
func (c Creator) MarshalJSON() ([]byte, error) {
if c.Creator != "" {
return json.Marshal(fmt.Sprintf("%s: %s", c.CreatorType, c.Creator))
return marshal.JSON(fmt.Sprintf("%s: %s", c.CreatorType, c.Creator))
}

return []byte{}, nil
Expand Down
11 changes: 6 additions & 5 deletions spdx/v2/common/identifier.go
Expand Up @@ -3,9 +3,10 @@
package common

import (
"encoding/json"
"fmt"
"strings"

"github.com/spdx/tools-golang/json/marshal"
)

const (
Expand All @@ -21,7 +22,7 @@ type ElementID string

// MarshalJSON returns an SPDXRef- prefixed JSON string
func (d ElementID) MarshalJSON() ([]byte, error) {
return json.Marshal(prefixElementId(d))
return marshal.JSON(prefixElementId(d))
}

// UnmarshalJSON validates SPDXRef- prefixes and removes them when processing ElementIDs
Expand Down Expand Up @@ -85,11 +86,11 @@ type DocElementID struct {
func (d DocElementID) MarshalJSON() ([]byte, error) {
if d.DocumentRefID != "" && d.ElementRefID != "" {
idStr := prefixElementId(d.ElementRefID)
return json.Marshal(fmt.Sprintf("%s%s:%s", documentRefPrefix, d.DocumentRefID, idStr))
return marshal.JSON(fmt.Sprintf("%s%s:%s", documentRefPrefix, d.DocumentRefID, idStr))
} else if d.ElementRefID != "" {
return json.Marshal(prefixElementId(d.ElementRefID))
return marshal.JSON(prefixElementId(d.ElementRefID))
} else if d.SpecialID != "" {
return json.Marshal(d.SpecialID)
return marshal.JSON(d.SpecialID)
}

return []byte{}, fmt.Errorf("failed to marshal empty DocElementID")
Expand Down
8 changes: 5 additions & 3 deletions spdx/v2/common/identifier_test.go
Expand Up @@ -8,6 +8,8 @@ import (
"reflect"
"strings"
"testing"

"github.com/spdx/tools-golang/json/marshal"
)

func Test_DocElementIDEncoding(t *testing.T) {
Expand Down Expand Up @@ -50,7 +52,7 @@ func Test_DocElementIDEncoding(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result, err := json.Marshal(test.value)
result, err := marshal.JSON(test.value)
switch {
case !test.err && err != nil:
t.Fatalf("unexpected error: %v", err)
Expand Down Expand Up @@ -167,7 +169,7 @@ func Test_ElementIDEncoding(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result, err := json.Marshal(test.value)
result, err := marshal.JSON(test.value)
switch {
case !test.err && err != nil:
t.Fatalf("unexpected error: %v", err)
Expand Down Expand Up @@ -255,7 +257,7 @@ func Test_ElementIDStructEncoding(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result, err := json.Marshal(test.value)
result, err := marshal.JSON(test.value)
switch {
case !test.err && err != nil:
t.Fatalf("unexpected error: %v", err)
Expand Down
11 changes: 6 additions & 5 deletions spdx/v2/common/package.go
Expand Up @@ -3,9 +3,10 @@
package common

import (
"encoding/json"
"fmt"
"strings"

"github.com/spdx/tools-golang/json/marshal"
)

type Supplier struct {
Expand Down Expand Up @@ -43,9 +44,9 @@ func (s *Supplier) UnmarshalJSON(data []byte) error {
// This function is also used when marshalling to YAML
func (s Supplier) MarshalJSON() ([]byte, error) {
if s.Supplier == "NOASSERTION" {
return json.Marshal(s.Supplier)
return marshal.JSON(s.Supplier)
} else if s.SupplierType != "" && s.Supplier != "" {
return json.Marshal(fmt.Sprintf("%s: %s", s.SupplierType, s.Supplier))
return marshal.JSON(fmt.Sprintf("%s: %s", s.SupplierType, s.Supplier))
}

return []byte{}, fmt.Errorf("failed to marshal invalid Supplier: %+v", s)
Expand Down Expand Up @@ -84,9 +85,9 @@ func (o *Originator) UnmarshalJSON(data []byte) error {
// This function is also used when marshalling to YAML
func (o Originator) MarshalJSON() ([]byte, error) {
if o.Originator == "NOASSERTION" {
return json.Marshal(o.Originator)
return marshal.JSON(o.Originator)
} else if o.Originator != "" {
return json.Marshal(fmt.Sprintf("%s: %s", o.OriginatorType, o.Originator))
return marshal.JSON(fmt.Sprintf("%s: %s", o.OriginatorType, o.Originator))
}

return []byte{}, nil
Expand Down
3 changes: 2 additions & 1 deletion spdx/v2/v2_2/package.go
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"strings"

"github.com/spdx/tools-golang/json/marshal"
"github.com/spdx/tools-golang/spdx/v2/common"
)

Expand Down Expand Up @@ -199,5 +200,5 @@ func (r *PackageExternalReference) MarshalJSON() ([]byte, error) {
rr = ref(*r)
rr.Category = strings.ReplaceAll(rr.Category, "-", "_")

return json.Marshal(&rr)
return marshal.JSON(&rr)
}
3 changes: 2 additions & 1 deletion spdx/v2/v2_3/package.go
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/json"
"strings"

"github.com/spdx/tools-golang/json/marshal"
"github.com/spdx/tools-golang/spdx/v2/common"
)

Expand Down Expand Up @@ -217,5 +218,5 @@ func (r *PackageExternalReference) MarshalJSON() ([]byte, error) {

rr.Category = strings.ReplaceAll(rr.Category, "_", "-")

return json.Marshal(&rr)
return marshal.JSON(&rr)
}
6 changes: 3 additions & 3 deletions spdxlib/described_elements.go
Expand Up @@ -12,9 +12,9 @@ import (

// GetDescribedPackageIDs returns a slice of ElementIDs for all Packages
// in this Document that it "describes," according to SPDX rules:
// - If the document has only one Package, its ID is returned.
// - If the document has 2+ Packages, it returns the IDs of those that have
// a DESCRIBES (or DESCRIBED_BY) relationship to this DOCUMENT.
// - If the document has only one Package, its ID is returned.
// - If the document has 2+ Packages, it returns the IDs of those that have
// a DESCRIBES (or DESCRIBED_BY) relationship to this DOCUMENT.
func GetDescribedPackageIDs(doc *spdx.Document) ([]common.ElementID, error) {
// if nil Packages map or zero packages in it, return empty slice
if doc.Packages == nil {
Expand Down