forked from ebhomengo/niki
1
0
Fork 0
niki/vendor/github.com/go-openapi/spec/normalizer_windows.go

260 lines
5.2 KiB
Go
Raw Normal View History

2024-05-14 13:07:09 +00:00
// -build windows
// Copyright 2015 go-swagger maintainers
2024-05-14 13:07:09 +00:00
//
2024-05-14 13:07:09 +00:00
// Licensed under the Apache License, Version 2.0 (the "License");
2024-05-14 13:07:09 +00:00
// you may not use this file except in compliance with the License.
2024-05-14 13:07:09 +00:00
// You may obtain a copy of the License at
2024-05-14 13:07:09 +00:00
//
2024-05-14 13:07:09 +00:00
// http://www.apache.org/licenses/LICENSE-2.0
2024-05-14 13:07:09 +00:00
//
2024-05-14 13:07:09 +00:00
// Unless required by applicable law or agreed to in writing, software
2024-05-14 13:07:09 +00:00
// distributed under the License is distributed on an "AS IS" BASIS,
2024-05-14 13:07:09 +00:00
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2024-05-14 13:07:09 +00:00
// See the License for the specific language governing permissions and
2024-05-14 13:07:09 +00:00
// limitations under the License.
package spec
import (
"net/url"
"os"
"path"
"path/filepath"
"strings"
)
// absPath makes a file path absolute and compatible with a URI path component
2024-05-14 13:07:09 +00:00
//
2024-05-14 13:07:09 +00:00
// The parameter must be a path, not an URI.
2024-05-14 13:07:09 +00:00
func absPath(in string) string {
2024-05-14 13:07:09 +00:00
// NOTE(windows): filepath.Abs exhibits a special behavior on windows for empty paths.
2024-05-14 13:07:09 +00:00
// See https://github.com/golang/go/issues/24441
2024-05-14 13:07:09 +00:00
if in == "" {
2024-05-14 13:07:09 +00:00
in = "."
2024-05-14 13:07:09 +00:00
}
anchored, err := filepath.Abs(in)
2024-05-14 13:07:09 +00:00
if err != nil {
2024-05-14 13:07:09 +00:00
specLogger.Printf("warning: could not resolve current working directory: %v", err)
2024-05-14 13:07:09 +00:00
return in
2024-05-14 13:07:09 +00:00
}
pth := strings.ReplaceAll(strings.ToLower(anchored), `\`, `/`)
2024-05-14 13:07:09 +00:00
if !strings.HasPrefix(pth, "/") {
2024-05-14 13:07:09 +00:00
pth = "/" + pth
2024-05-14 13:07:09 +00:00
}
return path.Clean(pth)
2024-05-14 13:07:09 +00:00
}
// repairURI tolerates invalid file URIs with common typos
2024-05-14 13:07:09 +00:00
// such as 'file://E:\folder\file', that break the regular URL parser.
2024-05-14 13:07:09 +00:00
//
2024-05-14 13:07:09 +00:00
// Adopting the same defaults as for unixes (e.g. return an empty path) would
2024-05-14 13:07:09 +00:00
// result into a counter-intuitive result for that case (e.g. E:\folder\file is
2024-05-14 13:07:09 +00:00
// eventually resolved as the current directory). The repair will detect the missing "/".
2024-05-14 13:07:09 +00:00
//
2024-05-14 13:07:09 +00:00
// Note that this only works for the file scheme.
2024-05-14 13:07:09 +00:00
func repairURI(in string) (*url.URL, string) {
2024-05-14 13:07:09 +00:00
const prefix = fileScheme + "://"
2024-05-14 13:07:09 +00:00
if !strings.HasPrefix(in, prefix) {
2024-05-14 13:07:09 +00:00
// giving up: resolve to empty path
2024-05-14 13:07:09 +00:00
u, _ := parseURL("")
return u, ""
2024-05-14 13:07:09 +00:00
}
// attempt the repair, stripping the scheme should be sufficient
2024-05-14 13:07:09 +00:00
u, _ := parseURL(strings.TrimPrefix(in, prefix))
2024-05-14 13:07:09 +00:00
debugLog("repaired URI: original: %q, repaired: %q", in, u.String())
return u, u.String()
2024-05-14 13:07:09 +00:00
}
// fixWindowsURI tolerates an absolute file path on windows such as C:\Base\File.yaml or \\host\share\Base\File.yaml
2024-05-14 13:07:09 +00:00
// and makes it a canonical URI: file:///c:/base/file.yaml
2024-05-14 13:07:09 +00:00
//
2024-05-14 13:07:09 +00:00
// Catch 22 notes for Windows:
2024-05-14 13:07:09 +00:00
//
2024-05-14 13:07:09 +00:00
// * There may be a drive letter on windows (it is lower-cased)
2024-05-14 13:07:09 +00:00
// * There may be a share UNC, e.g. \\server\folder\data.xml
2024-05-14 13:07:09 +00:00
// * Paths are case insensitive
2024-05-14 13:07:09 +00:00
// * Paths may already contain slashes
2024-05-14 13:07:09 +00:00
// * Paths must be slashed
2024-05-14 13:07:09 +00:00
//
2024-05-14 13:07:09 +00:00
// NOTE: there is no escaping. "/" may be valid separators just like "\".
2024-05-14 13:07:09 +00:00
// We don't use ToSlash() (which escapes everything) because windows now also
2024-05-14 13:07:09 +00:00
// tolerates the use of "/". Hence, both C:\File.yaml and C:/File.yaml will work.
2024-05-14 13:07:09 +00:00
func fixWindowsURI(u *url.URL, in string) {
2024-05-14 13:07:09 +00:00
drive := filepath.VolumeName(in)
if len(drive) > 0 {
2024-05-14 13:07:09 +00:00
if len(u.Scheme) == 1 && strings.EqualFold(u.Scheme, drive[:1]) { // a path with a drive letter
2024-05-14 13:07:09 +00:00
u.Scheme = fileScheme
2024-05-14 13:07:09 +00:00
u.Host = ""
2024-05-14 13:07:09 +00:00
u.Path = strings.Join([]string{drive, u.Opaque, u.Path}, `/`) // reconstruct the full path component (no fragment, no query)
2024-05-14 13:07:09 +00:00
} else if u.Host == "" && strings.HasPrefix(u.Path, drive) { // a path with a \\host volume
2024-05-14 13:07:09 +00:00
// NOTE: the special host@port syntax for UNC is not supported (yet)
2024-05-14 13:07:09 +00:00
u.Scheme = fileScheme
// this is a modified version of filepath.Dir() to apply on the VolumeName itself
2024-05-14 13:07:09 +00:00
i := len(drive) - 1
2024-05-14 13:07:09 +00:00
for i >= 0 && !os.IsPathSeparator(drive[i]) {
2024-05-14 13:07:09 +00:00
i--
2024-05-14 13:07:09 +00:00
}
2024-05-14 13:07:09 +00:00
host := drive[:i] // \\host\share => host
u.Path = strings.TrimPrefix(u.Path, host)
2024-05-14 13:07:09 +00:00
u.Host = strings.TrimPrefix(host, `\\`)
2024-05-14 13:07:09 +00:00
}
u.Opaque = ""
2024-05-14 13:07:09 +00:00
u.Path = strings.ReplaceAll(strings.ToLower(u.Path), `\`, `/`)
// ensure we form an absolute path
2024-05-14 13:07:09 +00:00
if !strings.HasPrefix(u.Path, "/") {
2024-05-14 13:07:09 +00:00
u.Path = "/" + u.Path
2024-05-14 13:07:09 +00:00
}
u.Path = path.Clean(u.Path)
return
2024-05-14 13:07:09 +00:00
}
if u.Scheme == fileScheme {
2024-05-14 13:07:09 +00:00
// Handle dodgy cases for file://{...} URIs on windows.
2024-05-14 13:07:09 +00:00
// A canonical URI should always be followed by an absolute path.
2024-05-14 13:07:09 +00:00
//
2024-05-14 13:07:09 +00:00
// Examples:
2024-05-14 13:07:09 +00:00
// * file:///folder/file => valid, unchanged
2024-05-14 13:07:09 +00:00
// * file:///c:\folder\file => slashed
2024-05-14 13:07:09 +00:00
// * file:///./folder/file => valid, cleaned to remove the dot
2024-05-14 13:07:09 +00:00
// * file:///.\folder\file => remapped to cwd
2024-05-14 13:07:09 +00:00
// * file:///. => dodgy, remapped to / (consistent with the behavior on unix)
2024-05-14 13:07:09 +00:00
// * file:///.. => dodgy, remapped to / (consistent with the behavior on unix)
2024-05-14 13:07:09 +00:00
if (!path.IsAbs(u.Path) && !filepath.IsAbs(u.Path)) || (strings.HasPrefix(u.Path, `/.`) && strings.Contains(u.Path, `\`)) {
2024-05-14 13:07:09 +00:00
// ensure we form an absolute path
2024-05-14 13:07:09 +00:00
u.Path, _ = filepath.Abs(strings.TrimLeft(u.Path, `/`))
2024-05-14 13:07:09 +00:00
if !strings.HasPrefix(u.Path, "/") {
2024-05-14 13:07:09 +00:00
u.Path = "/" + u.Path
2024-05-14 13:07:09 +00:00
}
2024-05-14 13:07:09 +00:00
}
2024-05-14 13:07:09 +00:00
u.Path = strings.ToLower(u.Path)
2024-05-14 13:07:09 +00:00
}
// NOTE: lower case normalization does not propagate to inner resources,
2024-05-14 13:07:09 +00:00
// generated when rebasing: when joining a relative URI with a file to an absolute base,
2024-05-14 13:07:09 +00:00
// only the base is currently lower-cased.
2024-05-14 13:07:09 +00:00
//
2024-05-14 13:07:09 +00:00
// For now, we assume this is good enough for most use cases
2024-05-14 13:07:09 +00:00
// and try not to generate too many differences
2024-05-14 13:07:09 +00:00
// between the output produced on different platforms.
2024-05-14 13:07:09 +00:00
u.Path = path.Clean(strings.ReplaceAll(u.Path, `\`, `/`))
2024-05-14 13:07:09 +00:00
}