matterbridge/vendor/go.mau.fi/whatsmeow/binary/xml.go

109 lines
2.6 KiB
Go

// Copyright (c) 2021 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package binary
import (
"encoding/hex"
"fmt"
"sort"
"strings"
"unicode"
"unicode/utf8"
)
// Options to control how Node.XMLString behaves.
var (
IndentXML = false
MaxBytesToPrintAsHex = 128
)
// XMLString converts the Node to its XML representation
func (n *Node) XMLString() string {
content := n.contentString()
if len(content) == 0 {
return fmt.Sprintf("<%[1]s%[2]s/>", n.Tag, n.attributeString())
}
newline := "\n"
if len(content) == 1 || !IndentXML {
newline = ""
}
return fmt.Sprintf("<%[1]s%[2]s>%[4]s%[3]s%[4]s</%[1]s>", n.Tag, n.attributeString(), strings.Join(content, newline), newline)
}
func (n *Node) attributeString() string {
if len(n.Attrs) == 0 {
return ""
}
stringAttrs := make([]string, len(n.Attrs)+1)
i := 1
for key, value := range n.Attrs {
stringAttrs[i] = fmt.Sprintf(`%s="%v"`, key, value)
i++
}
sort.Strings(stringAttrs)
return strings.Join(stringAttrs, " ")
}
func printable(data []byte) string {
if !utf8.Valid(data) {
return ""
}
str := string(data)
for _, c := range str {
if !unicode.IsPrint(c) {
return ""
}
}
return str
}
func (n *Node) contentString() []string {
split := make([]string, 0)
switch content := n.Content.(type) {
case []Node:
for _, item := range content {
split = append(split, strings.Split(item.XMLString(), "\n")...)
}
case []byte:
if strContent := printable(content); len(strContent) > 0 {
if IndentXML {
split = append(split, strings.Split(string(content), "\n")...)
} else {
split = append(split, strings.ReplaceAll(string(content), "\n", "\\n"))
}
} else if len(content) > MaxBytesToPrintAsHex {
split = append(split, fmt.Sprintf("<!-- %d bytes -->", len(content)))
} else if !IndentXML {
split = append(split, hex.EncodeToString(content))
} else {
hexData := hex.EncodeToString(content)
for i := 0; i < len(hexData); i += 80 {
if len(hexData) < i+80 {
split = append(split, hexData[i:])
} else {
split = append(split, hexData[i:i+80])
}
}
}
case nil:
// don't append anything
default:
strContent := fmt.Sprintf("%s", content)
if IndentXML {
split = append(split, strings.Split(strContent, "\n")...)
} else {
split = append(split, strings.ReplaceAll(strContent, "\n", "\\n"))
}
}
if len(split) > 1 && IndentXML {
for i, line := range split {
split[i] = " " + line
}
}
return split
}