podman

Форк
0
/
normalizer_windows.go 
154 строки · 5.1 Кб
1
// -build windows
2

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

17
package spec
18

19
import (
20
	"net/url"
21
	"os"
22
	"path"
23
	"path/filepath"
24
	"strings"
25
)
26

27
// absPath makes a file path absolute and compatible with a URI path component
28
//
29
// The parameter must be a path, not an URI.
30
func absPath(in string) string {
31
	// NOTE(windows): filepath.Abs exhibits a special behavior on windows for empty paths.
32
	// See https://github.com/golang/go/issues/24441
33
	if in == "" {
34
		in = "."
35
	}
36

37
	anchored, err := filepath.Abs(in)
38
	if err != nil {
39
		specLogger.Printf("warning: could not resolve current working directory: %v", err)
40
		return in
41
	}
42

43
	pth := strings.ReplaceAll(strings.ToLower(anchored), `\`, `/`)
44
	if !strings.HasPrefix(pth, "/") {
45
		pth = "/" + pth
46
	}
47

48
	return path.Clean(pth)
49
}
50

51
// repairURI tolerates invalid file URIs with common typos
52
// such as 'file://E:\folder\file', that break the regular URL parser.
53
//
54
// Adopting the same defaults as for unixes (e.g. return an empty path) would
55
// result into a counter-intuitive result for that case (e.g. E:\folder\file is
56
// eventually resolved as the current directory). The repair will detect the missing "/".
57
//
58
// Note that this only works for the file scheme.
59
func repairURI(in string) (*url.URL, string) {
60
	const prefix = fileScheme + "://"
61
	if !strings.HasPrefix(in, prefix) {
62
		// giving up: resolve to empty path
63
		u, _ := parseURL("")
64

65
		return u, ""
66
	}
67

68
	// attempt the repair, stripping the scheme should be sufficient
69
	u, _ := parseURL(strings.TrimPrefix(in, prefix))
70
	debugLog("repaired URI: original: %q, repaired: %q", in, u.String())
71

72
	return u, u.String()
73
}
74

75
// fixWindowsURI tolerates an absolute file path on windows such as C:\Base\File.yaml or \\host\share\Base\File.yaml
76
// and makes it a canonical URI: file:///c:/base/file.yaml
77
//
78
// Catch 22 notes for Windows:
79
//
80
// * There may be a drive letter on windows (it is lower-cased)
81
// * There may be a share UNC, e.g. \\server\folder\data.xml
82
// * Paths are case insensitive
83
// * Paths may already contain slashes
84
// * Paths must be slashed
85
//
86
// NOTE: there is no escaping. "/" may be valid separators just like "\".
87
// We don't use ToSlash() (which escapes everything) because windows now also
88
// tolerates the use of "/". Hence, both C:\File.yaml and C:/File.yaml will work.
89
func fixWindowsURI(u *url.URL, in string) {
90
	drive := filepath.VolumeName(in)
91

92
	if len(drive) > 0 {
93
		if len(u.Scheme) == 1 && strings.EqualFold(u.Scheme, drive[:1]) { // a path with a drive letter
94
			u.Scheme = fileScheme
95
			u.Host = ""
96
			u.Path = strings.Join([]string{drive, u.Opaque, u.Path}, `/`) // reconstruct the full path component (no fragment, no query)
97
		} else if u.Host == "" && strings.HasPrefix(u.Path, drive) { // a path with a \\host volume
98
			// NOTE: the special host@port syntax for UNC is not supported (yet)
99
			u.Scheme = fileScheme
100

101
			// this is a modified version of filepath.Dir() to apply on the VolumeName itself
102
			i := len(drive) - 1
103
			for i >= 0 && !os.IsPathSeparator(drive[i]) {
104
				i--
105
			}
106
			host := drive[:i] // \\host\share => host
107

108
			u.Path = strings.TrimPrefix(u.Path, host)
109
			u.Host = strings.TrimPrefix(host, `\\`)
110
		}
111

112
		u.Opaque = ""
113
		u.Path = strings.ReplaceAll(strings.ToLower(u.Path), `\`, `/`)
114

115
		// ensure we form an absolute path
116
		if !strings.HasPrefix(u.Path, "/") {
117
			u.Path = "/" + u.Path
118
		}
119

120
		u.Path = path.Clean(u.Path)
121

122
		return
123
	}
124

125
	if u.Scheme == fileScheme {
126
		// Handle dodgy cases for file://{...} URIs on windows.
127
		// A canonical URI should always be followed by an absolute path.
128
		//
129
		// Examples:
130
		//   * file:///folder/file => valid, unchanged
131
		//   * file:///c:\folder\file => slashed
132
		//   * file:///./folder/file => valid, cleaned to remove the dot
133
		//   * file:///.\folder\file => remapped to cwd
134
		//   * file:///. => dodgy, remapped to / (consistent with the behavior on unix)
135
		//   * file:///.. => dodgy, remapped to / (consistent with the behavior on unix)
136
		if (!path.IsAbs(u.Path) && !filepath.IsAbs(u.Path)) || (strings.HasPrefix(u.Path, `/.`) && strings.Contains(u.Path, `\`)) {
137
			// ensure we form an absolute path
138
			u.Path, _ = filepath.Abs(strings.TrimLeft(u.Path, `/`))
139
			if !strings.HasPrefix(u.Path, "/") {
140
				u.Path = "/" + u.Path
141
			}
142
		}
143
		u.Path = strings.ToLower(u.Path)
144
	}
145

146
	// NOTE: lower case normalization does not propagate to inner resources,
147
	// generated when rebasing: when joining a relative URI with a file to an absolute base,
148
	// only the base is currently lower-cased.
149
	//
150
	// For now, we assume this is good enough for most use cases
151
	// and try not to generate too many differences
152
	// between the output produced on different platforms.
153
	u.Path = path.Clean(strings.ReplaceAll(u.Path, `\`, `/`))
154
}
155

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.