// cleanPath removes leading and trailing forward slashes
// and makes sure that the path does not only contain a tag.
18118
func cleanPath(s string) (string, error) {
	s = strings.Trim(s, "/")
	if strings.HasPrefix(s, ":") {
		return "", fmt.Errorf("Path cannot be made up of just a tag: %q", s)
	}
	return s, nil
}
564142
func cleanGlobPath(path string) string {
	switch path {
	case "":
		return "."
	case string(separator):
		// do nothing to the path
		return path
	default:
		return path[0 : len(path)-1] // chop off trailing separator
	}
}
48193
func trimPath(filename string) string {
	for _, prefix := range trimPaths {
		if trimmed := strings.TrimPrefix(filename, prefix); len(trimmed) < len(filename) {
			return trimmed
		}
	}
	return filename
}
351774
func cleanAndExpandPath(path string) string {
	// NOTE: The os.ExpandEnv doesn't work with Windows cmd.exe-style
	// %VARIABLE%, but they variables can still be expanded via POSIX-style
	// $VARIABLE.
	path = os.ExpandEnv(path)

	if !strings.HasPrefix(path, "~") {
		return filepath.Clean(path)
	}

	// Expand initial ~ to the current user's home directory, or ~otheruser
	// to otheruser's home directory.  On Windows, both forward and backward
	// slashes can be used.
	path = path[1:]

	var pathSeparators string
	if runtime.GOOS == "windows" {
		pathSeparators = string(os.PathSeparator) + "/"
	} else {
		pathSeparators = string(os.PathSeparator)
	}

	userName := ""
	if i := strings.IndexAny(path, pathSeparators); i != -1 {
		userName = path[:i]
		path = path[i:]
	}

	homeDir := ""
	var u *user.User
	var err error
	if userName == "" {
		u, err = user.Current()
	} else {
		u, err = user.Lookup(userName)
	}
	if err == nil {
		homeDir = u.HomeDir
	}
	// Fallback to CWD if user lookup fails or user has no home directory.
	if homeDir == "" {
		homeDir = "."
	}

	return filepath.Join(homeDir, path)
}
1113381
func Path(s string) string {
	// Start with lowercase string
	filePath := strings.ToLower(s)
	filePath = strings.Replace(filePath, "..", "", -1)
	filePath = path.Clean(filePath)

	// Remove illegal characters for paths, flattening accents
	// and replacing some common separators with -
	filePath = cleanString(filePath, illegalPath)

	// NB this may be of length 0, caller must check
	return filePath
}
1029216
func SanitizeFileName(fileName string) string {
	ext := filepath.Ext(fileName)
	cleanExt := sanitize.BaseName(ext)
	if cleanExt == "" {
		cleanExt = ".unknown"
	}
	return strings.Replace(fmt.Sprintf(
		"%s.%s",
		sanitize.BaseName(fileName[:len(fileName)-len(ext)]),
		cleanExt[1:],
	), "-", "_", -1)
}
927062
func (r *Router) FilterPath(path string, filter http.HandlerFunc) {
	pattern := path
	pattern = strings.Replace(pattern, "*", "(.+)", -1)
	pattern = strings.Replace(pattern, "**", "([^/]+)", -1)
	regex := regexp.MustCompile(pattern)
	r.Filter(func(w http.ResponseWriter, req *http.Request) {
		if regex.MatchString(req.URL.Path) { filter(w, req) }
	})
}
1180714
func Clean(os, path string) string {
	abs := IsAbs(os, path)
	sep := Separator(os)
	elements := strings.Split(path, string(sep))

	// Replace multiple Separator elements with a single one.
	for i := 0; i < len(elements); i++ {
		if len(elements[i]) == 0 {
			elements = append(elements[:i], elements[i+1:]...)
			i--
		}
	}

	// Eliminate each . path name element (the current directory).
	for i := 0; i < len(elements); i++ {
		if elements[i] == "." && len(elements) > 1 {
			elements = append(elements[:i], elements[i+1:]...)
			i--
		}
	}

	// Eliminate each inner .. path name element (the parent directory)
	// along with the non-.. element that precedes it.
	for i := 1; i < len(elements); i++ {
		if i == 1 && abs && sep == '\\' {
			continue
		}
		if i > 0 && elements[i] == ".." {
			elements = append(elements[:i-1], elements[i+1:]...)
			i -= 2
		}
	}

	// Eliminate .. elements that begin a rooted path:
	// that is, replace "/.." by "/" at the beginning of a path,
	// assuming Separator is '/'.
	offset := 0
	if sep == '\\' {
		offset = 1
	}
	if abs {
		for len(elements) > offset && elements[offset] == ".." {
			elements = append(elements[:offset], elements[offset+1:]...)
		}
	}

	cleaned := strings.Join(elements, string(sep))
	if abs {
		if sep == '/' {
			cleaned = fmt.Sprintf("%c%s", sep, cleaned)
		} else if len(elements) == 1 {
			cleaned = fmt.Sprintf("%s%c", cleaned, sep)
		}
	}

	// If the result of this process is an empty string, Clean returns
	// the string ".".
	if len(cleaned) == 0 {
		cleaned = "."
	}

	if cleaned == path {
		return path
	}
	return Clean(os, cleaned)
}
213127
func (p *PathManager) RemovePathPrefix(prefix string) {
	p.l.Lock()
	defer p.l.Unlock()

	// We trim any trailing *, but we don't touch whether it is a trailing
	// slash or not since we want to be able to ignore prefixes that fully
	// specify a file
	p.paths, _ = p.paths.DeletePrefix([]byte(strings.TrimSuffix(prefix, "*")))
}
795255
func Clean(output string, err error) (string, error) {
	output = strings.Replace(strings.Split(output, "\n")[0], "'", "", -1)
	if err != nil {
		err = errors.New(strings.TrimSuffix(err.Error(), "\n"))
	}
	return output, err
}
31749
func HashSequencer(path, hash string) string {
	cleanHash := strings.Replace(hash, "#", ".", -1)
	return strings.Replace(cleanHash, "/", ".", -1)
}
1283745
func cleanHTML(r io.Reader, all bool) string {
	output := ""
	if !all {
		output = "<html><head></head>"
	}
	mainSection := false
	junkSection := false

	d := html.NewTokenizer(r)
	for {
		// token type
		tokenType := d.Next()
		if tokenType == html.ErrorToken {
			return output
		}
		token := d.Token()

		switch tokenType {
		case html.StartTagToken: // <tag>
			if token.Data == "body" || (token.Data == "html" && all) {
				mainSection = true
			}
			if !acceptedHTMLTag(token.Data) {
				junkSection = true
			}

			if !junkSection && mainSection {
				output += "<" + token.Data + ">"
			}

		case html.TextToken: // text between start and end tag
			if !junkSection && mainSection {
				output += token.Data
			}

		case html.EndTagToken: // </tag>
			if !junkSection && mainSection {
				output += "</" + token.Data + ">"
			}
			if !acceptedHTMLTag(token.Data) {
				junkSection = false
			}

		case html.SelfClosingTagToken: // <tag/>
			if !junkSection && mainSection {
				output += "<" + token.Data + " />" // TODO: Can probably keep attributes from the meta tags
			}
		}
	}
}
274994
func resolvePath(base, ref string) string {
	var full string
	if ref == "" {
		full = base
	} else if ref[0] != '/' {
		i := strings.LastIndex(base, "/")
		full = base[:i+1] + ref
	} else {
		full = ref
	}
	if full == "" {
		return ""
	}
	var dst []string
	src := strings.Split(full, "/")
	for _, elem := range src {
		switch elem {
		case ".":
			// drop
		case "..":
			if len(dst) > 0 {
				dst = dst[:len(dst)-1]
			}
		default:
			dst = append(dst, elem)
		}
	}
	if last := src[len(src)-1]; last == "." || last == ".." {
		// Add final slash to the joined path.
		dst = append(dst, "")
	}
	return "/" + strings.TrimLeft(strings.Join(dst, "/"), "/")
}
542287
func prettyPaths(paths []string) []string {
	// sort paths first
	sort.Strings(paths)
	pp := make([]string, 0, len(paths))
	for _, path := range paths {
		// manually escape "" and designate that it is all paths with an extra print <all paths>
		if path == "" {
			path = "\"\" <all paths>"
		}
		pp = append(pp, path)
	}
	return pp
}
1286431
func trimCallerPath(path string) string {
	// lovely borrowed from zap
	// nb. To make sure we trim the path correctly on Windows too, we
	// counter-intuitively need to use '/' and *not* os.PathSeparator here,
	// because the path given originates from Go stdlib, specifically
	// runtime.Caller() which (as of Mar/17) returns forward slashes even on
	// Windows.
	//
	// See https://github.com/golang/go/issues/3335
	// and https://github.com/golang/go/issues/18151
	//
	// for discussion on the issue on Go side.

	// Find the last separator.
	idx := strings.LastIndexByte(path, '/')
	if idx == -1 {
		return path
	}

	// Find the penultimate separator.
	idx = strings.LastIndexByte(path[:idx], '/')
	if idx == -1 {
		return path
	}

	return path[idx+1:]
}
86553
func normalizePaths(paths []string) ([]string, string, error) {
	namenode := ""
	cleanPaths := make([]string, 0, len(paths))

	for _, rawurl := range paths {
		url, err := url.Parse(rawurl)
		if err != nil {
			return nil, "", err
		}

		if url.Host != "" {
			if namenode != "" && namenode != url.Host {
				return nil, "", errMultipleNamenodeUrls
			}

			namenode = url.Host
		}

		cleanPaths = append(cleanPaths, path.Clean(url.Path))
	}

	return cleanPaths, namenode, nil
}
86876
func CleanURLPath(p string) string {
	if p == "" {
		return "/"
	}
	if p[0] != '/' {
		p = "/" + p
	}
	cp := path.Clean(p)
	// Add the trailing slash back, as it's relevant to a URL.
	if p[len(p)-1] == '/' && cp != "/" {
		cp += "/"
	}
	return cp
}