...

Source file src/github.com/sassoftware/relic/lib/signappx/contenttypes.go

Documentation: github.com/sassoftware/relic/lib/signappx

     1  //
     2  // Copyright (c) SAS Institute Inc.
     3  //
     4  // Licensed under the Apache License, Version 2.0 (the "License");
     5  // you may not use this file except in compliance with the License.
     6  // You may obtain a copy of the License at
     7  //
     8  //     http://www.apache.org/licenses/LICENSE-2.0
     9  //
    10  // Unless required by applicable law or agreed to in writing, software
    11  // distributed under the License is distributed on an "AS IS" BASIS,
    12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  // See the License for the specific language governing permissions and
    14  // limitations under the License.
    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