| // 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(`'`, `'\''`) |