github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/internal/osutils/shellescape.go (about)

     1  package osutils
     2  
     3  import (
     4  	"regexp"
     5  	"strings"
     6  )
     7  
     8  // ShellEscape serve to escape arguments passed to shell commands
     9  type ShellEscape struct {
    10  	wordPattern   *regexp.Regexp
    11  	escapePattern *regexp.Regexp
    12  	escapeWith    string
    13  }
    14  
    15  //NewBashEscaper creates a new instance of ShellEscape that's configured for escaping bash style arguments
    16  func NewBashEscaper() *ShellEscape {
    17  	return &ShellEscape{
    18  		regexp.MustCompile(`^[\w]+$`),
    19  		regexp.MustCompile(`(\\|"|\$)`),
    20  		`\$1`,
    21  	}
    22  }
    23  
    24  // NewBatchEscaper creates a new instance of ShellEscape that's configured for escaping batch style arguments
    25  func NewBatchEscaper() *ShellEscape {
    26  	return &ShellEscape{
    27  		regexp.MustCompile(`^[\w]+$`),
    28  		regexp.MustCompile(`"`),
    29  		`""`,
    30  	}
    31  }
    32  
    33  // NewCmdEscaper creates a new instance of ShellEscape that's configured for escaping cmd arguments
    34  func NewCmdEscaper() *ShellEscape {
    35  	return &ShellEscape{
    36  		regexp.MustCompile(`^[^ &()\[\]{}^=;!'+,~]+$`), // cmd.exe /? lists these characters as requiring quotes
    37  		regexp.MustCompile(`"`),
    38  		`""`,
    39  	}
    40  }
    41  
    42  // EscapeLineEnd will escape any line end characters that require escaping for the purpose of quoting
    43  func (s *ShellEscape) EscapeLineEnd(value string) string {
    44  	value = strings.Replace(value, "\n", `\n`, -1)
    45  	value = strings.Replace(value, "\r", `\r`, -1)
    46  	return value
    47  }
    48  
    49  // Escape will escape any characters that require escaping for the purpose of quoting
    50  func (s *ShellEscape) Escape(value string) string {
    51  	return s.escapePattern.ReplaceAllString(value, s.escapeWith)
    52  }
    53  
    54  // Quote implements SubShell.Quote
    55  func (s *ShellEscape) Quote(value string) string {
    56  	if len(value) == 0 {
    57  		return `""`
    58  	}
    59  	if s.wordPattern.MatchString(value) {
    60  		return value
    61  	}
    62  	return `"` + s.EscapeLineEnd(s.Escape(value)) + `"`
    63  }