helpers/shell_escape.go (113 lines of code) (raw):

package helpers // https://github.com/zimbatm/direnv/blob/master/shell.go import ( "bytes" "encoding/hex" "strings" ) /* * Escaping */ const ( ACK = 6 TAB = 9 LF = 10 CR = 13 US = 31 SPACE = 32 AMPERSTAND = 38 SINGLE_QUOTE = 39 PLUS = 43 NINE = 57 QUESTION = 63 LOWERCASE_Z = 90 OPEN_BRACKET = 91 BACKSLASH = 92 UNDERSCORE = 95 CLOSE_BRACKET = 93 BACKTICK = 96 TILDA = 126 DEL = 127 ) // ShellEscape is taken from https://github.com/solidsnack/shell-escape/blob/master/Text/ShellEscape/Bash.hs /* A Bash escaped string. The strings are wrapped in @$\'...\'@ if any bytes within them must be escaped; otherwise, they are left as is. Newlines and other control characters are represented as ANSI escape sequences. High bytes are represented as hex codes. Thus Bash escaped strings will always fit on one line and never contain non-ASCII bytes. */ func ShellEscape(str string) string { if str == "" { return "''" } in := []byte(str) out := bytes.NewBuffer(make([]byte, 0, len(str)*2)) i := 0 l := len(in) escape := false hex := func(char byte) { escape = true data := []byte{BACKSLASH, 'x', 0, 0} hex.Encode(data[2:], []byte{char}) out.Write(data) } backslash := func(char byte) { escape = true out.Write([]byte{BACKSLASH, char}) } escaped := func(str string) { escape = true out.WriteString(str) } quoted := func(char byte) { escape = true out.WriteByte(char) } literal := func(char byte) { out.WriteByte(char) } for i < l { char := in[i] switch { case char == TAB: escaped(`\t`) case char == LF: escaped(`\n`) case char == CR: escaped(`\r`) case char <= US: hex(char) case char <= AMPERSTAND: quoted(char) case char == SINGLE_QUOTE: backslash(char) case char <= PLUS: quoted(char) case char <= NINE: literal(char) case char <= QUESTION: quoted(char) case char <= LOWERCASE_Z: literal(char) case char == OPEN_BRACKET: quoted(char) case char == BACKSLASH: backslash(char) case char <= CLOSE_BRACKET: quoted(char) case char == UNDERSCORE: literal(char) case char <= BACKTICK: quoted(char) case char <= LOWERCASE_Z: literal(char) case char <= TILDA: quoted(char) case char == DEL: hex(char) default: hex(char) } i++ } outStr := out.String() if escape { outStr = "$'" + outStr + "'" } return outStr } func ToBackslash(path string) string { return strings.Replace(path, "/", "\\", -1) } func ToSlash(path string) string { return strings.Replace(path, "\\", "/", -1) }