vendor: revendor
This commit is contained in:
110
vendor/github.com/russellhaering/goxmldsig/canonicalize.go
generated
vendored
110
vendor/github.com/russellhaering/goxmldsig/canonicalize.go
generated
vendored
@@ -2,7 +2,6 @@ package dsig
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/beevik/etree"
|
||||
"github.com/russellhaering/goxmldsig/etreeutils"
|
||||
@@ -15,28 +14,25 @@ type Canonicalizer interface {
|
||||
}
|
||||
|
||||
type c14N10ExclusiveCanonicalizer struct {
|
||||
InclusiveNamespaces map[string]struct{}
|
||||
prefixList string
|
||||
}
|
||||
|
||||
// MakeC14N10ExclusiveCanonicalizerWithPrefixList constructs an exclusive Canonicalizer
|
||||
// from a PrefixList in NMTOKENS format (a white space separated list).
|
||||
func MakeC14N10ExclusiveCanonicalizerWithPrefixList(prefixList string) Canonicalizer {
|
||||
prefixes := strings.Fields(prefixList)
|
||||
prefixSet := make(map[string]struct{}, len(prefixes))
|
||||
|
||||
for _, prefix := range prefixes {
|
||||
prefixSet[prefix] = struct{}{}
|
||||
}
|
||||
|
||||
return &c14N10ExclusiveCanonicalizer{
|
||||
InclusiveNamespaces: prefixSet,
|
||||
prefixList: prefixList,
|
||||
}
|
||||
}
|
||||
|
||||
// Canonicalize transforms the input Element into a serialized XML document in canonical form.
|
||||
func (c *c14N10ExclusiveCanonicalizer) Canonicalize(el *etree.Element) ([]byte, error) {
|
||||
scope := make(map[string]c14nSpace)
|
||||
return canonicalSerialize(excCanonicalPrep(el, scope, c.InclusiveNamespaces))
|
||||
err := etreeutils.TransformExcC14n(el, c.prefixList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return canonicalSerialize(el)
|
||||
}
|
||||
|
||||
func (c *c14N10ExclusiveCanonicalizer) Algorithm() AlgorithmID {
|
||||
@@ -75,94 +71,6 @@ type c14nSpace struct {
|
||||
|
||||
const nsSpace = "xmlns"
|
||||
|
||||
// excCanonicalPrep accepts an *etree.Element and recursively transforms it into one
|
||||
// which is ready for serialization to exclusive canonical form. Specifically this
|
||||
// entails:
|
||||
//
|
||||
// 1. Stripping re-declarations of namespaces
|
||||
// 2. Stripping unused namespaces
|
||||
// 3. Sorting attributes into canonical order.
|
||||
//
|
||||
// NOTE(russell_h): Currently this function modifies the passed element.
|
||||
func excCanonicalPrep(el *etree.Element, _nsAlreadyDeclared map[string]c14nSpace, inclusiveNamespaces map[string]struct{}) *etree.Element {
|
||||
//Copy alreadyDeclared map (only contains namespaces)
|
||||
nsAlreadyDeclared := make(map[string]c14nSpace, len(_nsAlreadyDeclared))
|
||||
for k := range _nsAlreadyDeclared {
|
||||
nsAlreadyDeclared[k] = _nsAlreadyDeclared[k]
|
||||
}
|
||||
|
||||
//Track the namespaces used on the current element
|
||||
nsUsedHere := make(map[string]struct{})
|
||||
|
||||
//Make sure to track the element namespace for the case:
|
||||
//<foo:bar xmlns:foo="..."/>
|
||||
if el.Space != "" {
|
||||
nsUsedHere[el.Space] = struct{}{}
|
||||
}
|
||||
|
||||
toRemove := make([]string, 0, 0)
|
||||
|
||||
for _, a := range el.Attr {
|
||||
switch a.Space {
|
||||
case nsSpace:
|
||||
|
||||
//For simplicity, remove all xmlns attribues; to be added in one pass
|
||||
//later. Otherwise, we need another map/set to track xmlns attributes
|
||||
//that we left alone.
|
||||
toRemove = append(toRemove, a.Space+":"+a.Key)
|
||||
if _, ok := nsAlreadyDeclared[a.Key]; !ok {
|
||||
//If we're not tracking ancestor state already for this namespace, add
|
||||
//it to the map
|
||||
nsAlreadyDeclared[a.Key] = c14nSpace{a: a, used: false}
|
||||
}
|
||||
|
||||
// This algorithm accepts a set of namespaces which should be treated
|
||||
// in an inclusive fashion. Specifically that means we should keep the
|
||||
// declaration of that namespace closest to the root of the tree. We can
|
||||
// accomplish that be pretending it was used by this element.
|
||||
_, inclusive := inclusiveNamespaces[a.Key]
|
||||
if inclusive {
|
||||
nsUsedHere[a.Key] = struct{}{}
|
||||
}
|
||||
|
||||
default:
|
||||
//We only track namespaces, so ignore attributes without one.
|
||||
if a.Space != "" {
|
||||
nsUsedHere[a.Space] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Remove all attributes so that we can add them with much-simpler logic
|
||||
for _, attrK := range toRemove {
|
||||
el.RemoveAttr(attrK)
|
||||
}
|
||||
|
||||
//For all namespaces used on the current element, declare them if they were
|
||||
//not declared (and used) in an ancestor.
|
||||
for k := range nsUsedHere {
|
||||
spc := nsAlreadyDeclared[k]
|
||||
//If previously unused, mark as used
|
||||
if !spc.used {
|
||||
el.Attr = append(el.Attr, spc.a)
|
||||
spc.used = true
|
||||
|
||||
//Assignment here is only to update the pre-existing `used` tracking value
|
||||
nsAlreadyDeclared[k] = spc
|
||||
}
|
||||
}
|
||||
|
||||
//Canonicalize all children, passing down the ancestor tracking map
|
||||
for _, child := range el.ChildElements() {
|
||||
excCanonicalPrep(child, nsAlreadyDeclared, inclusiveNamespaces)
|
||||
}
|
||||
|
||||
//Sort attributes lexicographically
|
||||
sort.Sort(etreeutils.SortedAttrs(el.Attr))
|
||||
|
||||
return el.Copy()
|
||||
}
|
||||
|
||||
// canonicalPrep accepts an *etree.Element and transforms it into one which is ready
|
||||
// for serialization into inclusive canonical form. Specifically this
|
||||
// entails:
|
||||
@@ -208,7 +116,7 @@ func canonicalPrep(el *etree.Element, seenSoFar map[string]struct{}) *etree.Elem
|
||||
|
||||
func canonicalSerialize(el *etree.Element) ([]byte, error) {
|
||||
doc := etree.NewDocument()
|
||||
doc.SetRoot(el)
|
||||
doc.SetRoot(el.Copy())
|
||||
|
||||
doc.WriteSettings = etree.WriteSettings{
|
||||
CanonicalAttrVal: true,
|
||||
|
Reference in New Issue
Block a user