-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathnamespace.go
83 lines (76 loc) · 1.67 KB
/
namespace.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package mimemagic
import (
"bytes"
"encoding/xml"
"golang.org/x/net/html/charset"
"io"
)
type namespace struct {
namespaceURI, localName string
mediaType int
}
// MatchXMLReader is an io.Reader wrapper for MatchXML that
// can be supplied with a limit on the data to read.
func MatchXMLReader(r io.Reader, limit int) MediaType {
if limit < 0 || limit > 1024 {
limit = 1024
}
return mediaTypes[matchXML(io.LimitReader(r, int64(limit)))]
}
// MatchXML determines the MIME type of the xml file in a byte
// slice form. Returns application/octet-stream in case the
// file isn't a valid xml and application/xml if the
// identification comes back negative.
func MatchXML(data []byte) MediaType {
if len(data) > 1024 {
data = data[:1024]
}
return mediaTypes[matchXML(bytes.NewReader(data))]
}
func matchXML(r io.Reader) int {
uType := unknownType
dec := xml.NewDecoder(r)
dec.Strict = false
dec.CharsetReader = charset.NewReaderLabel
for {
t, err := dec.Token()
if err != nil {
break
}
switch t := t.(type) {
case xml.ProcInst, xml.Directive, xml.Comment:
uType = unknownXML
case xml.StartElement:
uType = unknownXML
var m int
if m = isLocalName(t.Name.Local); m < 0 {
continue
}
for _, attr := range t.Attr {
if attr.Name.Local == "xmlns" {
if m := isNameSpace(attr.Value); m > -1 {
return m
}
}
}
return m
}
}
return uType
}
func isLocalName(name string) int {
for _, n := range namespaces {
if n.localName == name {
return n.mediaType
}
}
return -1
}
func isNameSpace(name string) int {
for _, n := range namespaces {
if n.namespaceURI == name {
return n.mediaType
}
}
return -1
}