blob: e7f0456cacbf2a5bdaa49e6d87af885791257e83 [file] [log] [blame]
Colin Cross41ca49f2016-09-29 13:19:34 -07001// Copyright 2016 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package proptools
16
17import "strings"
18
Colin Crosscc1ec0f2018-09-19 16:05:43 -070019// NinjaEscapeList takes a slice of strings that may contain characters that are meaningful to ninja
Colin Cross41ca49f2016-09-29 13:19:34 -070020// ($), and escapes each string so they will be passed to bash. It is not necessary on input,
21// output, or dependency names, those are handled by ModuleContext.Build. It is generally required
22// on strings from properties in Blueprint files that are used as Args to ModuleContext.Build. A
23// new slice containing the escaped strings is returned.
Colin Crosscc1ec0f2018-09-19 16:05:43 -070024func NinjaEscapeList(slice []string) []string {
Colin Cross41ca49f2016-09-29 13:19:34 -070025 slice = append([]string(nil), slice...)
26 for i, s := range slice {
Colin Crosscc1ec0f2018-09-19 16:05:43 -070027 slice[i] = NinjaEscape(s)
Colin Cross41ca49f2016-09-29 13:19:34 -070028 }
29 return slice
30}
31
Colin Crosscc1ec0f2018-09-19 16:05:43 -070032// NinjaEscapeList takes a string that may contain characters that are meaningful to ninja
33// ($), and escapes it so it will be passed to bash. It is not necessary on input,
34// output, or dependency names, those are handled by ModuleContext.Build. It is generally required
35// on strings from properties in Blueprint files that are used as Args to ModuleContext.Build. A
36// new slice containing the escaped strings is returned.
37func NinjaEscape(s string) string {
38 return ninjaEscaper.Replace(s)
39}
40
Colin Cross41ca49f2016-09-29 13:19:34 -070041var ninjaEscaper = strings.NewReplacer(
42 "$", "$$")
43
Colin Crosscc1ec0f2018-09-19 16:05:43 -070044// ShellEscapeList takes a slice of strings that may contain characters that are meaningful to bash and
45// escapes them if necessary by wrapping them in single quotes, and replacing internal single quotes with
Colin Cross41ca49f2016-09-29 13:19:34 -070046// '\'' (one single quote to end the quoting, a shell-escaped single quote to insert a real single
47// quote, and then a single quote to restarting quoting. A new slice containing the escaped strings
48// is returned.
Colin Crosscc1ec0f2018-09-19 16:05:43 -070049func ShellEscapeList(slice []string) []string {
50 slice = append([]string(nil), slice...)
51
52 for i, s := range slice {
53 slice[i] = ShellEscape(s)
54 }
55 return slice
56
57}
58
59// ShellEscapeList takes string that may contain characters that are meaningful to bash and
60// escapes it if necessary by wrapping it in single quotes, and replacing internal single quotes with
61// '\'' (one single quote to end the quoting, a shell-escaped single quote to insert a real single
62// quote, and then a single quote to restarting quoting.
63func ShellEscape(s string) string {
Colin Cross41ca49f2016-09-29 13:19:34 -070064 shellUnsafeChar := func(r rune) bool {
65 switch {
66 case 'A' <= r && r <= 'Z',
67 'a' <= r && r <= 'z',
68 '0' <= r && r <= '9',
69 r == '_',
70 r == '+',
71 r == '-',
72 r == '=',
73 r == '.',
74 r == ',',
75 r == '/',
76 r == ' ':
77 return false
78 default:
79 return true
80 }
81 }
82
Colin Crosscc1ec0f2018-09-19 16:05:43 -070083 if strings.IndexFunc(s, shellUnsafeChar) == -1 {
84 // No escaping necessary
85 return s
Colin Cross41ca49f2016-09-29 13:19:34 -070086 }
Colin Cross41ca49f2016-09-29 13:19:34 -070087
Colin Crosscc1ec0f2018-09-19 16:05:43 -070088 return `'` + singleQuoteReplacer.Replace(s) + `'`
Colin Cross41ca49f2016-09-29 13:19:34 -070089}
90
Colin Crosscc1ec0f2018-09-19 16:05:43 -070091func NinjaAndShellEscapeList(slice []string) []string {
92 return ShellEscapeList(NinjaEscapeList(slice))
93}
94
95func NinjaAndShellEscape(s string) string {
96 return ShellEscape(NinjaEscape(s))
Colin Cross41ca49f2016-09-29 13:19:34 -070097}
98
99var singleQuoteReplacer = strings.NewReplacer(`'`, `'\''`)