Repository: zyedidia/micro
File: internal/util/util.go (Go)

Code before:

// DetermineEscapePath escapes a path, determining whether it should be escaped
// using URL encoding (preferred, since it encodes unambiguously) or
// legacy encoding with '%' (for backward compatibility, if the legacy-escaped
// path exists in the given directory).
// In case the escaped path, including the backup extension, exceeds the
// filename length limit it is hashed and the hash is used as final filename.
// A second filename is provided to optionally fill this file with the original
// path to resolve the hashed filename.
func DetermineEscapePath(dir string, path string) (string, string) {
	fresolve := ""
	fname := EscapePathUrl(path)
	length := len(fname)
	if length+len(".micro-backup") > 255 {
		fname = HashStringMd5(path)
		fresolve = filepath.Join(dir, fname+".path")
	}

	fpath := filepath.Join(dir, fname)
	if _, err := os.Stat(fpath); err == nil {
		return fpath, fresolve
	}

	legacy := filepath.Join(dir, EscapePathLegacy(path))
	if _, err := os.Stat(legacy); err == nil {
		return legacy, fresolve
	}

	return fpath, fresolve
}

// GetLeadingWhitespace returns the leading whitespace of the given byte array
func GetLeadingWhitespace(b []byte) []byte {
	ws := []byte{}
	for len(b) > 0 {
		r, _, size := DecodeCharacter(b)
		if r == ' ' || r == '\t' {
			ws = append(ws, byte(r))
		} else {
			break
		}

		b = b[size:]
	}
	return ws
}

// GetTrailingWhitespace returns the trailing whitespace of the given byte array
func GetTrailingWhitespace(b []byte) []byte {
	ws := []byte{}
	for len(b) > 0 {

Review comment (security):
We shouldn't return a resolve path if we return a legacy escaped path, right?

Well, in such case `fresolve` is gonna be `""` anyway, but it's cleaner to explicitly return `""`.

...Actually the code looks a bit messy overall. Why not keep it readable:

```go
	url := filepath.Join(dir, EscapePathUrl(path))
	if _, err := os.Stat(url); err == nil {
		return url, ""
	}

	legacy := filepath.Join(dir, EscapePathLegacy(path))
	if _, err := os.Stat(legacy); err == nil {
		return legacy, ""
	}

	if len(url)+len(".micro-backup") > 255 {
		hash := HashStringMd5(path)
		return hash, filepath.Join(dir, hash+".path")
	}

	return url, ""
```

Code after:
// using URL encoding (preferred, since it encodes unambiguously) or
// legacy encoding with '%' (for backward compatibility, if the legacy-escaped
// path exists in the given directory).
// In case the length of the escaped path (plus the backup extension) exceeds
// the filename length limit, a hash of the path is returned instead. In such
// case the second return value is the name of a file the original path should
// be saved to (since the original path cannot be derived from its hash).
// Otherwise the second return value is an empty string.
func DetermineEscapePath(dir string, path string) (string, string) {
	url := filepath.Join(dir, EscapePathUrl(path))
	if _, err := os.Stat(url); err == nil {
		return url, ""
	}

	legacy := filepath.Join(dir, EscapePathLegacy(path))
	if _, err := os.Stat(legacy); err == nil {
		return legacy, ""
	}

	if len(url)+len(BackupSuffix) > 255 {
		hash := HashStringMd5(path)
		return filepath.Join(dir, hash), filepath.Join(dir, hash+".path")
	}

	return url, ""
}

// GetLeadingWhitespace returns the leading whitespace of the given byte array
func GetLeadingWhitespace(b []byte) []byte {
	ws := []byte{}
	for len(b) > 0 {
		r, _, size := DecodeCharacter(b)
		if r == ' ' || r == '\t' {
			ws = append(ws, byte(r))
		} else {
			break
		}

		b = b[size:]
	}
	return ws
}

// GetTrailingWhitespace returns the trailing whitespace of the given byte array
func GetTrailingWhitespace(b []byte) []byte {
	ws := []byte{}
	for len(b) > 0 {
		r, size := utf8.DecodeLastRune(b)
		if IsWhitespace(r) {
			ws = append([]byte(string(r)), ws...)
		} else {