2018-10-13 14:04:17 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"archive/zip"
|
|
|
|
"encoding/xml"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"regexp"
|
2022-03-21 13:46:32 +00:00
|
|
|
"strings"
|
2018-10-13 14:04:17 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func acquireFile(specFilename string, xmlSpecURL string) error {
|
2022-03-21 13:46:32 +00:00
|
|
|
tmpFilename := specFilename + ".download"
|
|
|
|
defer os.Remove(tmpFilename)
|
|
|
|
|
|
|
|
if fileExists(specFilename) {
|
2018-10-13 14:04:17 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-07-11 13:44:55 +00:00
|
|
|
if err := downloadFile(tmpFilename, xmlSpecURL); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-03-21 13:46:32 +00:00
|
|
|
return copyFile(specFilename, tmpFilename)
|
2021-07-11 13:44:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func downloadFile(filename, url string) error {
|
|
|
|
resp, err := http.Get(url)
|
2018-10-13 14:04:17 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
2021-07-11 13:44:55 +00:00
|
|
|
return fmt.Errorf("could not download %q from %q: %s",
|
|
|
|
filename, url, resp.Status)
|
2018-10-13 14:04:17 +00:00
|
|
|
}
|
|
|
|
|
2021-07-11 13:44:55 +00:00
|
|
|
w, err := os.Create(filename)
|
2018-10-13 14:04:17 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-07-11 13:44:55 +00:00
|
|
|
if _, err := io.Copy(w, resp.Body); err != nil {
|
|
|
|
w.Close()
|
2018-10-13 14:04:17 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-07-11 13:44:55 +00:00
|
|
|
return w.Close()
|
2018-10-13 14:04:17 +00:00
|
|
|
}
|
|
|
|
|
2022-03-21 13:46:32 +00:00
|
|
|
func globFiles(pattern string, archive []*zip.File) []*zip.File {
|
2018-10-13 14:04:17 +00:00
|
|
|
var files []*zip.File
|
2022-03-21 13:46:32 +00:00
|
|
|
pattern = strings.ToLower(pattern)
|
|
|
|
for _, f := range archive {
|
|
|
|
if matched, err := path.Match(pattern, strings.ToLower(f.Name)); err != nil {
|
2018-10-13 14:04:17 +00:00
|
|
|
// This shouldn't happen - all patterns are hard-coded, errors in them
|
|
|
|
// are a programming error.
|
|
|
|
panic(err)
|
|
|
|
} else if matched {
|
|
|
|
files = append(files, f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return files
|
|
|
|
}
|
|
|
|
|
|
|
|
func unmarshalXmlFile(file *zip.File, data interface{}) error {
|
|
|
|
r, err := file.Open()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
decoder := xml.NewDecoder(r)
|
|
|
|
defer r.Close()
|
|
|
|
return decoder.Decode(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
var scpdFilenameRe = regexp.MustCompile(
|
|
|
|
`.*/([a-zA-Z0-9]+)([0-9]+)\.xml`)
|
|
|
|
|
2022-11-01 19:03:30 +00:00
|
|
|
func urnPartsFromSCPDFilename(filename string, svcURNPrefix string) (*URNParts, error) {
|
2018-10-13 14:04:17 +00:00
|
|
|
parts := scpdFilenameRe.FindStringSubmatch(filename)
|
|
|
|
if len(parts) != 3 {
|
|
|
|
return nil, fmt.Errorf("SCPD filename %q does not have expected number of parts", filename)
|
|
|
|
}
|
|
|
|
name, version := parts[1], parts[2]
|
|
|
|
return &URNParts{
|
2022-11-01 19:03:30 +00:00
|
|
|
URN: svcURNPrefix + name + ":" + version,
|
2018-10-13 14:04:17 +00:00
|
|
|
Name: name,
|
|
|
|
Version: version,
|
|
|
|
}, nil
|
|
|
|
}
|
2022-03-21 13:46:32 +00:00
|
|
|
|
|
|
|
func copyFile(dst string, src string) error {
|
|
|
|
f, err := os.Open(src)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return writeFile(dst, f)
|
|
|
|
}
|
|
|
|
|
|
|
|
func writeFile(dst string, r io.ReadCloser) error {
|
|
|
|
defer r.Close()
|
|
|
|
f, err := os.Create(dst)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
_, err = io.Copy(f, r)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func fileExists(p string) bool {
|
|
|
|
f, err := os.Open(p)
|
|
|
|
if err != nil {
|
|
|
|
return !os.IsNotExist(err)
|
|
|
|
}
|
|
|
|
f.Close()
|
|
|
|
return true
|
|
|
|
}
|