package site import "strings" // splitTilde splits a site URL path into its project and the rest. // // "/~proj" -> ("proj", "", true) // "/~proj/" -> ("proj", "/", true) // "/~proj/a/b" -> ("proj", "/a/b", true) // "/", "/x", "/~" -> ("", "", false) // // The remainder keeps its leading slash, because its absence is what // distinguishes "/~proj" — which has to be redirected before relative links // inside the page can resolve — from "/~proj/". // // This is hand-parsed rather than expressed as a ServeMux pattern because // net/http rejects "/~{project}/{path...}": its wildcards must start a path // segment. Registering "/" instead also keeps the mux's built-in ".." and "//" // redirects, though those are a convenience and not a defence — a // percent-encoded traversal arrives here already decoded and unredirected, so // Resolve does its own normalisation. func splitTilde(urlPath string) (project, rest string, ok bool) { if !strings.HasPrefix(urlPath, "/~") { return "", "", false } rest = urlPath[len("/~"):] if i := strings.IndexByte(rest, '/'); i >= 0 { project, rest = rest[:i], rest[i:] } else { project, rest = rest, "" } if project == "" { return "", "", false } return project, rest, true }