// Copyright 2016 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package proptools import "strings" // NinjaEscape takes a slice of strings that may contain characters that are meaningful to ninja // ($), and escapes each string so they will be passed to bash. It is not necessary on input, // output, or dependency names, those are handled by ModuleContext.Build. It is generally required // on strings from properties in Blueprint files that are used as Args to ModuleContext.Build. A // new slice containing the escaped strings is returned. func NinjaEscape(slice []string) []string { slice = append([]string(nil), slice...) for i, s := range slice { slice[i] = ninjaEscaper.Replace(s) } return slice } var ninjaEscaper = strings.NewReplacer( "$", "$$") // ShellEscape takes a slice of strings that may contain characters that are meaningful to bash and // escapes if necessary by wrapping them in single quotes, and replacing internal single quotes with // '\'' (one single quote to end the quoting, a shell-escaped single quote to insert a real single // quote, and then a single quote to restarting quoting. A new slice containing the escaped strings // is returned. func ShellEscape(slice []string) []string { shellUnsafeChar := func(r rune) bool { switch { case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z', '0' <= r && r <= '9', r == '_', r == '+', r == '-', r == '=', r == '.', r == ',', r == '/', r == ' ': return false default: return true } } slice = append([]string(nil), slice...) for i, s := range slice { if strings.IndexFunc(s, shellUnsafeChar) == -1 { // No escaping necessary continue } slice[i] = `'` + singleQuoteReplacer.Replace(s) + `'` } return slice } func NinjaAndShellEscape(slice []string) []string { return ShellEscape(NinjaEscape(slice)) } var singleQuoteReplacer = strings.NewReplacer(`'`, `'\''`)