...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package signappx
18
19 import (
20 "encoding/xml"
21 "path"
22 "sort"
23 )
24
25 var defaultExtensions = map[string]string{
26 "dll": "application/x-msdownload",
27 "exe": "application/x-msdownload",
28 "png": "image/png",
29 "xml": "application/vnd.ms-appx.manifest+xml",
30 "appx": "application/vnd.ms-appx",
31 }
32
33 var defaultOverrides = map[string]string{
34 "/AppxBlockMap.xml": "application/vnd.ms-appx.blockmap+xml",
35 "/AppxSignature.p7x": "application/vnd.ms-appx.signature",
36 "/AppxMetadata/CodeIntegrity.cat": "application/vnd.ms-pkiseccat",
37 }
38
39 const (
40 octetStreamType = "application/octet-stream"
41 bundleManifestType = "application/vnd.ms-appx.bundlemanifest+xml"
42 )
43
44 type ContentTypes struct {
45 ByExt map[string]string
46 ByOverride map[string]string
47 }
48
49 type xmlContentTypes struct {
50 XMLName xml.Name `xml:"http://schemas.openxmlformats.org/package/2006/content-types Types"`
51 Default []contentTypeDefault
52 Override []contentTypeOverride
53 }
54
55 type contentTypeDefault struct {
56 Extension string `xml:",attr"`
57 ContentType string `xml:",attr"`
58 }
59
60 type contentTypeOverride struct {
61 PartName string `xml:",attr"`
62 ContentType string `xml:",attr"`
63 }
64
65 func NewContentTypes() *ContentTypes {
66 return &ContentTypes{
67 ByExt: make(map[string]string),
68 ByOverride: make(map[string]string),
69 }
70 }
71
72 func (c *ContentTypes) Parse(blob []byte) error {
73 var xct xmlContentTypes
74 if err := xml.Unmarshal(blob, &xct); err != nil {
75 return err
76 }
77 for _, def := range xct.Default {
78 c.ByExt[def.Extension] = def.ContentType
79 }
80 for _, ovr := range xct.Override {
81 c.ByOverride[ovr.PartName] = ovr.ContentType
82 }
83 return nil
84 }
85
86 func (c *ContentTypes) Add(name string) {
87 if name == bundleManifestFile {
88 c.ByExt["xml"] = bundleManifestType
89 return
90 }
91 oname := "/" + name
92 if ctype := defaultOverrides[oname]; ctype != "" {
93 c.ByOverride[oname] = ctype
94 return
95 } else if ctype := c.ByOverride[oname]; ctype != "" {
96 return
97 }
98 ext := path.Ext(path.Base(name))
99 if ext[0] == '.' {
100 ext = ext[1:]
101 if ctype := defaultExtensions[ext]; ctype != "" {
102 c.ByExt[ext] = ctype
103 } else if ctype := c.ByExt[ext]; ctype != "" {
104 return
105 } else {
106 c.ByExt[ext] = octetStreamType
107 }
108 } else {
109 c.ByOverride[oname] = octetStreamType
110 }
111 }
112
113 func (c *ContentTypes) Find(name string) string {
114 oname := "/" + name
115 if ctype := c.ByOverride[oname]; ctype != "" {
116 return ctype
117 }
118 ext := path.Ext(path.Base(name))
119 if ext[0] == '.' {
120 if ctype := c.ByExt[ext[1:]]; ctype != "" {
121 return ctype
122 }
123 }
124 return ""
125 }
126
127 func (c *ContentTypes) Marshal() ([]byte, error) {
128 var xct xmlContentTypes
129 extnames := make([]string, 0, len(c.ByExt))
130 for name := range c.ByExt {
131 extnames = append(extnames, name)
132 }
133 sort.Strings(extnames)
134 for _, name := range extnames {
135 xct.Default = append(xct.Default, contentTypeDefault{
136 Extension: name,
137 ContentType: c.ByExt[name],
138 })
139 }
140 ovrnames := make([]string, 0, len(c.ByOverride))
141 for name := range c.ByOverride {
142 ovrnames = append(ovrnames, name)
143 }
144 sort.Strings(ovrnames)
145 for _, name := range ovrnames {
146 xct.Override = append(xct.Override, contentTypeOverride{
147 PartName: name,
148 ContentType: c.ByOverride[name],
149 })
150 }
151 return marshalXML(xct, true)
152 }
153
View as plain text