forked from lug/matterbridge
Add Mumble support (#1245)
This commit is contained in:
291
vendor/github.com/vincent-petithory/dataurl/dataurl.go
generated
vendored
Normal file
291
vendor/github.com/vincent-petithory/dataurl/dataurl.go
generated
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
package dataurl
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// EncodingBase64 is base64 encoding for the data url
|
||||
EncodingBase64 = "base64"
|
||||
// EncodingASCII is ascii encoding for the data url
|
||||
EncodingASCII = "ascii"
|
||||
)
|
||||
|
||||
func defaultMediaType() MediaType {
|
||||
return MediaType{
|
||||
"text",
|
||||
"plain",
|
||||
map[string]string{"charset": "US-ASCII"},
|
||||
}
|
||||
}
|
||||
|
||||
// MediaType is the combination of a media type, a media subtype
|
||||
// and optional parameters.
|
||||
type MediaType struct {
|
||||
Type string
|
||||
Subtype string
|
||||
Params map[string]string
|
||||
}
|
||||
|
||||
// ContentType returns the content type of the dataurl's data, in the form type/subtype.
|
||||
func (mt *MediaType) ContentType() string {
|
||||
return fmt.Sprintf("%s/%s", mt.Type, mt.Subtype)
|
||||
}
|
||||
|
||||
// String implements the Stringer interface.
|
||||
//
|
||||
// Params values are escaped with the Escape function, rather than in a quoted string.
|
||||
func (mt *MediaType) String() string {
|
||||
var (
|
||||
buf bytes.Buffer
|
||||
keys = make([]string, len(mt.Params))
|
||||
i int
|
||||
)
|
||||
for k := range mt.Params {
|
||||
keys[i] = k
|
||||
i++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
v := mt.Params[k]
|
||||
fmt.Fprintf(&buf, ";%s=%s", k, EscapeString(v))
|
||||
}
|
||||
return mt.ContentType() + (&buf).String()
|
||||
}
|
||||
|
||||
// DataURL is the combination of a MediaType describing the type of its Data.
|
||||
type DataURL struct {
|
||||
MediaType
|
||||
Encoding string
|
||||
Data []byte
|
||||
}
|
||||
|
||||
// New returns a new DataURL initialized with data and
|
||||
// a MediaType parsed from mediatype and paramPairs.
|
||||
// mediatype must be of the form "type/subtype" or it will panic.
|
||||
// paramPairs must have an even number of elements or it will panic.
|
||||
// For more complex DataURL, initialize a DataURL struct.
|
||||
// The DataURL is initialized with base64 encoding.
|
||||
func New(data []byte, mediatype string, paramPairs ...string) *DataURL {
|
||||
parts := strings.Split(mediatype, "/")
|
||||
if len(parts) != 2 {
|
||||
panic("dataurl: invalid mediatype")
|
||||
}
|
||||
|
||||
nParams := len(paramPairs)
|
||||
if nParams%2 != 0 {
|
||||
panic("dataurl: requires an even number of param pairs")
|
||||
}
|
||||
params := make(map[string]string)
|
||||
for i := 0; i < nParams; i += 2 {
|
||||
params[paramPairs[i]] = paramPairs[i+1]
|
||||
}
|
||||
|
||||
mt := MediaType{
|
||||
parts[0],
|
||||
parts[1],
|
||||
params,
|
||||
}
|
||||
return &DataURL{
|
||||
MediaType: mt,
|
||||
Encoding: EncodingBase64,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
// String implements the Stringer interface.
|
||||
//
|
||||
// Note: it doesn't guarantee the returned string is equal to
|
||||
// the initial source string that was used to create this DataURL.
|
||||
// The reasons for that are:
|
||||
// * Insertion of default values for MediaType that were maybe not in the initial string,
|
||||
// * Various ways to encode the MediaType parameters (quoted string or url encoded string, the latter is used),
|
||||
func (du *DataURL) String() string {
|
||||
var buf bytes.Buffer
|
||||
du.WriteTo(&buf)
|
||||
return (&buf).String()
|
||||
}
|
||||
|
||||
// WriteTo implements the WriterTo interface.
|
||||
// See the note about String().
|
||||
func (du *DataURL) WriteTo(w io.Writer) (n int64, err error) {
|
||||
var ni int
|
||||
ni, _ = fmt.Fprint(w, "data:")
|
||||
n += int64(ni)
|
||||
|
||||
ni, _ = fmt.Fprint(w, du.MediaType.String())
|
||||
n += int64(ni)
|
||||
|
||||
if du.Encoding == EncodingBase64 {
|
||||
ni, _ = fmt.Fprint(w, ";base64")
|
||||
n += int64(ni)
|
||||
}
|
||||
|
||||
ni, _ = fmt.Fprint(w, ",")
|
||||
n += int64(ni)
|
||||
|
||||
if du.Encoding == EncodingBase64 {
|
||||
encoder := base64.NewEncoder(base64.StdEncoding, w)
|
||||
ni, err = encoder.Write(du.Data)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
encoder.Close()
|
||||
} else if du.Encoding == EncodingASCII {
|
||||
ni, _ = fmt.Fprint(w, Escape(du.Data))
|
||||
n += int64(ni)
|
||||
} else {
|
||||
err = fmt.Errorf("dataurl: invalid encoding %s", du.Encoding)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalText decodes a Data URL string and sets it to *du
|
||||
func (du *DataURL) UnmarshalText(text []byte) error {
|
||||
decoded, err := DecodeString(string(text))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*du = *decoded
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalText writes du as a Data URL
|
||||
func (du *DataURL) MarshalText() ([]byte, error) {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if _, err := du.WriteTo(buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
type encodedDataReader func(string) ([]byte, error)
|
||||
|
||||
var asciiDataReader encodedDataReader = func(s string) ([]byte, error) {
|
||||
us, err := Unescape(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(us), nil
|
||||
}
|
||||
|
||||
var base64DataReader encodedDataReader = func(s string) ([]byte, error) {
|
||||
data, err := base64.StdEncoding.DecodeString(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(data), nil
|
||||
}
|
||||
|
||||
type parser struct {
|
||||
du *DataURL
|
||||
l *lexer
|
||||
currentAttr string
|
||||
unquoteParamVal bool
|
||||
encodedDataReaderFn encodedDataReader
|
||||
}
|
||||
|
||||
func (p *parser) parse() error {
|
||||
for item := range p.l.items {
|
||||
switch item.t {
|
||||
case itemError:
|
||||
return errors.New(item.String())
|
||||
case itemMediaType:
|
||||
p.du.MediaType.Type = item.val
|
||||
// Should we clear the default
|
||||
// "charset" parameter at this point?
|
||||
delete(p.du.MediaType.Params, "charset")
|
||||
case itemMediaSubType:
|
||||
p.du.MediaType.Subtype = item.val
|
||||
case itemParamAttr:
|
||||
p.currentAttr = item.val
|
||||
case itemLeftStringQuote:
|
||||
p.unquoteParamVal = true
|
||||
case itemParamVal:
|
||||
val := item.val
|
||||
if p.unquoteParamVal {
|
||||
p.unquoteParamVal = false
|
||||
us, err := strconv.Unquote("\"" + val + "\"")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
val = us
|
||||
} else {
|
||||
us, err := UnescapeToString(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
val = us
|
||||
}
|
||||
p.du.MediaType.Params[p.currentAttr] = val
|
||||
case itemBase64Enc:
|
||||
p.du.Encoding = EncodingBase64
|
||||
p.encodedDataReaderFn = base64DataReader
|
||||
case itemDataComma:
|
||||
if p.encodedDataReaderFn == nil {
|
||||
p.encodedDataReaderFn = asciiDataReader
|
||||
}
|
||||
case itemData:
|
||||
reader, err := p.encodedDataReaderFn(item.val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.du.Data = reader
|
||||
case itemEOF:
|
||||
if p.du.Data == nil {
|
||||
p.du.Data = []byte("")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
panic("EOF not found")
|
||||
}
|
||||
|
||||
// DecodeString decodes a Data URL scheme string.
|
||||
func DecodeString(s string) (*DataURL, error) {
|
||||
du := &DataURL{
|
||||
MediaType: defaultMediaType(),
|
||||
Encoding: EncodingASCII,
|
||||
}
|
||||
|
||||
parser := &parser{
|
||||
du: du,
|
||||
l: lex(s),
|
||||
}
|
||||
if err := parser.parse(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return du, nil
|
||||
}
|
||||
|
||||
// Decode decodes a Data URL scheme from a io.Reader.
|
||||
func Decode(r io.Reader) (*DataURL, error) {
|
||||
data, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return DecodeString(string(data))
|
||||
}
|
||||
|
||||
// EncodeBytes encodes the data bytes into a Data URL string, using base 64 encoding.
|
||||
//
|
||||
// The media type of data is detected using http.DetectContentType.
|
||||
func EncodeBytes(data []byte) string {
|
||||
mt := http.DetectContentType(data)
|
||||
// http.DetectContentType may add spurious spaces between ; and a parameter.
|
||||
// The canonical way is to not have them.
|
||||
cleanedMt := strings.Replace(mt, "; ", ";", -1)
|
||||
|
||||
return New(data, cleanedMt).String()
|
||||
}
|
||||
Reference in New Issue
Block a user