From c48208e818fa0d6003669dbe83b9925ea07697a2 Mon Sep 17 00:00:00 2001 From: Giovanni Orciuolo Date: Thu, 2 Dec 2021 10:46:51 +0100 Subject: [PATCH 1/4] Less restrictive checks in MTOMDecoder, makes more MTOM-based services work correctly --- soap/MTOMEncoder.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/soap/MTOMEncoder.go b/soap/MTOMEncoder.go index 6f214ecd..3a7181ac 100644 --- a/soap/MTOMEncoder.go +++ b/soap/MTOMEncoder.go @@ -202,8 +202,8 @@ func getMtomHeader(contentType string) (string, error) { } startInfo, ok := params["start-info"] - if !ok || startInfo != "application/soap+xml" { - return "", fmt.Errorf(`Expected param start-info="application/soap+xml", got %s`, startInfo) + if !ok || !strings.Contains(startInfo, "application/soap+xml") { + return "", fmt.Errorf(`Expected param start-info to contain "application/soap+xml", got %s`, startInfo) } return boundary, nil } @@ -231,7 +231,7 @@ func (d *mtomDecoder) Decode(v interface{}) error { return err } contentType := p.Header.Get("Content-Type") - if contentType == "application/xop+xml" { + if strings.Contains(contentType, "application/xop+xml") { err := xml.NewDecoder(p).Decode(v) if err != nil { return err From 2748e5e9b8f76415a433ff1391ccaa1c3a1607b5 Mon Sep 17 00:00:00 2001 From: Giovanni Orciuolo Date: Thu, 2 Dec 2021 12:56:32 +0100 Subject: [PATCH 2/4] Use HasPrefix in MTOMEncoder mime check and text/xml as valid start-info param --- soap/MTOMEncoder.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soap/MTOMEncoder.go b/soap/MTOMEncoder.go index 3a7181ac..ca91c4d4 100644 --- a/soap/MTOMEncoder.go +++ b/soap/MTOMEncoder.go @@ -202,7 +202,7 @@ func getMtomHeader(contentType string) (string, error) { } startInfo, ok := params["start-info"] - if !ok || !strings.Contains(startInfo, "application/soap+xml") { + if !ok || (!strings.Contains(startInfo, "application/soap+xml") && !strings.Contains(startInfo, "text/xml")) { return "", fmt.Errorf(`Expected param start-info to contain "application/soap+xml", got %s`, startInfo) } return boundary, nil @@ -231,7 +231,7 @@ func (d *mtomDecoder) Decode(v interface{}) error { return err } contentType := p.Header.Get("Content-Type") - if strings.Contains(contentType, "application/xop+xml") { + if strings.HasPrefix(contentType, "application/xop+xml") { err := xml.NewDecoder(p).Decode(v) if err != nil { return err From b0ed54f18db1f7a757bf7eca9a3185ce1bacd613 Mon Sep 17 00:00:00 2001 From: Giovanni Orciuolo Date: Thu, 2 Dec 2021 12:58:37 +0100 Subject: [PATCH 3/4] Fix error message in MTOMEncoder --- soap/MTOMEncoder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soap/MTOMEncoder.go b/soap/MTOMEncoder.go index ca91c4d4..cd92873d 100644 --- a/soap/MTOMEncoder.go +++ b/soap/MTOMEncoder.go @@ -203,7 +203,7 @@ func getMtomHeader(contentType string) (string, error) { startInfo, ok := params["start-info"] if !ok || (!strings.Contains(startInfo, "application/soap+xml") && !strings.Contains(startInfo, "text/xml")) { - return "", fmt.Errorf(`Expected param start-info to contain "application/soap+xml", got %s`, startInfo) + return "", fmt.Errorf(`Expected param start-info to contain "application/soap+xml" or "text/xml", got %s`, startInfo) } return boundary, nil } From ef55c308c64d25a2eb8a44dddf00302dbee41bfa Mon Sep 17 00:00:00 2001 From: Giovanni Orciuolo Date: Thu, 9 Dec 2021 11:55:40 +0100 Subject: [PATCH 4/4] More comprehensive reflect parser logic in MTOMEncoder getBinaryFields function --- soap/MTOMEncoder.go | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/soap/MTOMEncoder.go b/soap/MTOMEncoder.go index cd92873d..640073e3 100644 --- a/soap/MTOMEncoder.go +++ b/soap/MTOMEncoder.go @@ -152,18 +152,33 @@ func (e *mtomEncoder) Flush() error { func getBinaryFields(data interface{}, fields *[]reflect.Value) { v := reflect.Indirect(reflect.ValueOf(data)) - if v.Kind() != reflect.Struct { - return - } - for i := 0; i < v.NumField(); i++ { - if !v.Field(i).CanInterface() { - continue + switch v.Kind() { + case reflect.Ptr: + getBinaryFields(v.Elem(), fields) + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + if !v.Field(i).CanInterface() { + continue + } + f := v.Field(i) + if _, ok := f.Interface().(*Binary); ok { + *fields = append(*fields, f) + } else { + getBinaryFields(f.Interface(), fields) + } } - f := v.Field(i) - if _, ok := f.Interface().(*Binary); ok { - *fields = append(*fields, f) - } else { - getBinaryFields(f.Interface(), fields) + break + case reflect.Slice: + for i := 0; i < v.Len(); i++ { + e := v.Index(i) + if !e.CanInterface() { + continue + } + if _, ok := e.Interface().(*Binary); ok { + *fields = append(*fields, v) + } else { + getBinaryFields(e.Interface(), fields) + } } } } @@ -218,9 +233,6 @@ func newMtomDecoder(r io.Reader, boundary string) *mtomDecoder { } func (d *mtomDecoder) Decode(v interface{}) error { - fields := make([]reflect.Value, 0) - getBinaryFields(v, &fields) - packages := make(map[string]*Binary, 0) for { p, err := d.reader.NextPart() @@ -254,6 +266,10 @@ func (d *mtomDecoder) Decode(v interface{}) error { } } + // Get binary fields after reading the structure, so I have all fields mapped + fields := make([]reflect.Value, 0) + getBinaryFields(v, &fields) + // Set binary fields with correct content for _, f := range fields { b := f.Interface().(*Binary)