github.com/alloyci/alloy-runner@v1.0.1-0.20180222164613-925503ccafd6/helpers/shell_escape.go (about)

     1  package helpers
     2  
     3  // https://github.com/zimbatm/direnv/blob/master/shell.go
     4  
     5  import (
     6  	"bytes"
     7  	"encoding/hex"
     8  	"strings"
     9  )
    10  
    11  /*
    12   * Escaping
    13   */
    14  
    15  const (
    16  	ACK           = 6
    17  	TAB           = 9
    18  	LF            = 10
    19  	CR            = 13
    20  	US            = 31
    21  	SPACE         = 32
    22  	AMPERSTAND    = 38
    23  	SINGLE_QUOTE  = 39
    24  	PLUS          = 43
    25  	NINE          = 57
    26  	QUESTION      = 63
    27  	LOWERCASE_Z   = 90
    28  	OPEN_BRACKET  = 91
    29  	BACKSLASH     = 92
    30  	UNDERSCORE    = 95
    31  	CLOSE_BRACKET = 93
    32  	BACKTICK      = 96
    33  	TILDA         = 126
    34  	DEL           = 127
    35  )
    36  
    37  // ShellEscape is taken from https://github.com/solidsnack/shell-escape/blob/master/Text/ShellEscape/Bash.hs
    38  /*
    39  A Bash escaped string. The strings are wrapped in @$\'...\'@ if any
    40  bytes within them must be escaped; otherwise, they are left as is.
    41  Newlines and other control characters are represented as ANSI escape
    42  sequences. High bytes are represented as hex codes. Thus Bash escaped
    43  strings will always fit on one line and never contain non-ASCII bytes.
    44  */
    45  func ShellEscape(str string) string {
    46  	if str == "" {
    47  		return "''"
    48  	}
    49  	in := []byte(str)
    50  	out := bytes.NewBuffer(make([]byte, 0, len(str)*2))
    51  	i := 0
    52  	l := len(in)
    53  	escape := false
    54  
    55  	hex := func(char byte) {
    56  		escape = true
    57  
    58  		data := []byte{BACKSLASH, 'x', 0, 0}
    59  		hex.Encode(data[2:], []byte{char})
    60  		out.Write(data)
    61  	}
    62  
    63  	backslash := func(char byte) {
    64  		escape = true
    65  		out.Write([]byte{BACKSLASH, char})
    66  	}
    67  
    68  	escaped := func(str string) {
    69  		escape = true
    70  		out.WriteString(str)
    71  	}
    72  
    73  	quoted := func(char byte) {
    74  		escape = true
    75  		out.WriteByte(char)
    76  	}
    77  
    78  	literal := func(char byte) {
    79  		out.WriteByte(char)
    80  	}
    81  
    82  	for i < l {
    83  		char := in[i]
    84  		switch {
    85  		case char == TAB:
    86  			escaped(`\t`)
    87  		case char == LF:
    88  			escaped(`\n`)
    89  		case char == CR:
    90  			escaped(`\r`)
    91  		case char <= US:
    92  			hex(char)
    93  		case char <= AMPERSTAND:
    94  			quoted(char)
    95  		case char == SINGLE_QUOTE:
    96  			backslash(char)
    97  		case char <= PLUS:
    98  			quoted(char)
    99  		case char <= NINE:
   100  			literal(char)
   101  		case char <= QUESTION:
   102  			quoted(char)
   103  		case char <= LOWERCASE_Z:
   104  			literal(char)
   105  		case char == OPEN_BRACKET:
   106  			quoted(char)
   107  		case char == BACKSLASH:
   108  			backslash(char)
   109  		case char <= CLOSE_BRACKET:
   110  			quoted(char)
   111  		case char == UNDERSCORE:
   112  			literal(char)
   113  		case char <= BACKTICK:
   114  			quoted(char)
   115  		case char <= LOWERCASE_Z:
   116  			literal(char)
   117  		case char <= TILDA:
   118  			quoted(char)
   119  		case char == DEL:
   120  			hex(char)
   121  		default:
   122  			hex(char)
   123  		}
   124  		i++
   125  	}
   126  
   127  	outStr := out.String()
   128  
   129  	if escape {
   130  		outStr = "$'" + outStr + "'"
   131  	}
   132  
   133  	return outStr
   134  }
   135  
   136  func ToBackslash(path string) string {
   137  	return strings.Replace(path, "/", "\\", -1)
   138  }
   139  
   140  func ToSlash(path string) string {
   141  	return strings.Replace(path, "\\", "/", -1)
   142  }