|
|
@ -94,37 +94,51 @@ func isLocalReference(source string) bool {
|
|
|
|
// It works by checking whether the source looks like a URL and, if it does, running a
|
|
|
|
// It works by checking whether the source looks like a URL and, if it does, running a
|
|
|
|
// HEAD operation to see if the remote resource is a file that we understand.
|
|
|
|
// HEAD operation to see if the remote resource is a file that we understand.
|
|
|
|
func isRemoteHTTPArchive(source string) bool {
|
|
|
|
func isRemoteHTTPArchive(source string) bool {
|
|
|
|
if strings.HasPrefix(source, "http://") || strings.HasPrefix(source, "https://") {
|
|
|
|
if !isHTTPURL(source) {
|
|
|
|
res, err := http.Head(source)
|
|
|
|
return false
|
|
|
|
if err != nil {
|
|
|
|
}
|
|
|
|
// If we get an error at the network layer, we can't install it. So
|
|
|
|
|
|
|
|
// we return false.
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Next, we look for the content type or content disposition headers to see
|
|
|
|
|
|
|
|
// if they have matching extractors.
|
|
|
|
|
|
|
|
contentType := res.Header.Get("content-type")
|
|
|
|
|
|
|
|
var foundSuffix string
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if contentType == "application/octet-stream" {
|
|
|
|
contentType, err := getRemoteContentType(source)
|
|
|
|
foundSuffix = filepath.Ext(source)
|
|
|
|
if err != nil {
|
|
|
|
} else {
|
|
|
|
return false
|
|
|
|
foundSuffix, _ = mediaTypeToExtension(contentType)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if foundSuffix == "" {
|
|
|
|
// Handle octet-stream specially by checking file extension
|
|
|
|
// Media type not recognized
|
|
|
|
if contentType == "application/octet-stream" {
|
|
|
|
return false
|
|
|
|
for suffix := range Extractors {
|
|
|
|
|
|
|
|
if strings.HasSuffix(source, suffix) {
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_, ok := Extractors[foundSuffix]
|
|
|
|
return false
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return ok
|
|
|
|
// Check if we have an extractor for this media type
|
|
|
|
|
|
|
|
if suffix, ok := mediaTypeToExtension(contentType); ok {
|
|
|
|
|
|
|
|
_, hasExtractor := Extractors[suffix]
|
|
|
|
|
|
|
|
return hasExtractor
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return false
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// isHTTPURL checks if the source is an HTTP or HTTPS URL
|
|
|
|
|
|
|
|
func isHTTPURL(source string) bool {
|
|
|
|
|
|
|
|
return strings.HasPrefix(source, "http://") || strings.HasPrefix(source, "https://")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// getRemoteContentType performs a HEAD request and returns the content-type
|
|
|
|
|
|
|
|
func getRemoteContentType(url string) (string, error) {
|
|
|
|
|
|
|
|
res, err := http.Head(url)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return "", err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
defer res.Body.Close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return res.Header.Get("content-type"), nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// isPlugin checks if the directory contains a plugin.yaml file.
|
|
|
|
// isPlugin checks if the directory contains a plugin.yaml file.
|
|
|
|
func isPlugin(dirname string) bool {
|
|
|
|
func isPlugin(dirname string) bool {
|
|
|
|
_, err := os.Stat(filepath.Join(dirname, plugin.PluginFileName))
|
|
|
|
_, err := os.Stat(filepath.Join(dirname, plugin.PluginFileName))
|
|
|
|