diff options
| author | Thomas Bellman <bellman@nsc.liu.se> | 2009-08-04 14:47:12 +0200 |
|---|---|---|
| committer | James Turnbull <james@lovedthanlost.net> | 2009-08-08 09:42:39 +1000 |
| commit | 79a4339e1f614647d8b3e074752d8bf0e583aef2 (patch) | |
| tree | 7c3e8687e13392f2cfdcf8a33cd5f8d86c8fc5ce | |
| parent | 79d705faec6b7de2bd644e77e5e4c88e8974f207 (diff) | |
| download | puppet-79a4339e1f614647d8b3e074752d8bf0e583aef2.tar.gz puppet-79a4339e1f614647d8b3e074752d8bf0e583aef2.tar.xz puppet-79a4339e1f614647d8b3e074752d8bf0e583aef2.zip | |
Add shellquote() function.
This adds a new function shellquote() which can be used for quoting
arguments in shell commands used in the exec type.
This only supports Unixoid operating systems. Other systems would
likely require some other quoting.
Signed-off-by: Thomas Bellman <bellman@nsc.liu.se>
| -rw-r--r-- | lib/puppet/parser/functions/shellquote.rb | 41 | ||||
| -rwxr-xr-x | spec/unit/parser/functions/shellquote.rb | 92 |
2 files changed, 133 insertions, 0 deletions
diff --git a/lib/puppet/parser/functions/shellquote.rb b/lib/puppet/parser/functions/shellquote.rb new file mode 100644 index 000000000..6c994520c --- /dev/null +++ b/lib/puppet/parser/functions/shellquote.rb @@ -0,0 +1,41 @@ +module Puppet::Parser::Functions + + Safe = 'a-zA-Z0-9@%_+=:,./-' # Safe unquoted + Dangerous = '!"`$\\' # Unsafe inside double quotes + + newfunction(:shellquote, :type => :rvalue, :doc => "\ + Quote and concatenate arguments for use in Bourne shell. + + Each argument is quoted separately, and then all are concatenated + with spaces. If an argument is an array, the elements of that + array is interpolated within the rest of the arguments; this makes + it possible to have an array of arguments and pass that array to + shellquote() instead of having to specify specify each argument + individually in the call. + ") \ + do |args| + + result = [] + args.flatten.each do |word| + if word.length != 0 and word.count(Safe) == word.length + result << word + elsif word.count(Dangerous) == 0 + result << ('"' + word + '"') + elsif word.count("'") == 0 + result << ("'" + word + "'") + else + r = '"' + word.each_byte() do |c| + if Dangerous.include?(c) + r += "\\" + end + r += c.chr() + end + r += '"' + result << r + end + end + + return result.join(" ") + end +end diff --git a/spec/unit/parser/functions/shellquote.rb b/spec/unit/parser/functions/shellquote.rb new file mode 100755 index 000000000..283a4de1e --- /dev/null +++ b/spec/unit/parser/functions/shellquote.rb @@ -0,0 +1,92 @@ +#! /usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +describe "the shellquote function" do + + before :each do + @scope = Puppet::Parser::Scope.new() + end + + it "should exist" do + Puppet::Parser::Functions.function("shellquote").should == "function_shellquote" + end + + + it "should handle no arguments" do + result = @scope.function_shellquote([]) + result.should(eql("")) + end + + it "should handle several simple arguments" do + result = @scope.function_shellquote( + ['foo', 'bar@example.com', 'localhost:/dev/null', 'xyzzy+-4711,23']) + result.should(eql( + 'foo bar@example.com localhost:/dev/null xyzzy+-4711,23')) + end + + it "should handle array arguments" do + result = @scope.function_shellquote( + ['foo', ['bar@example.com', 'localhost:/dev/null'], + 'xyzzy+-4711,23']) + result.should(eql( + 'foo bar@example.com localhost:/dev/null xyzzy+-4711,23')) + end + + it "should quote unsafe characters" do + result = @scope.function_shellquote( + ['/etc/passwd ', '(ls)', '*', '[?]', "'&'"]) + result.should(eql( + '"/etc/passwd " "(ls)" "*" "[?]" "\'&\'"')) + end + + it "should deal with double quotes" do + result = @scope.function_shellquote( + ['"foo"bar"']) + result.should(eql( + '\'"foo"bar"\'')) + end + + it "should cope with dollar signs" do + result = @scope.function_shellquote( + ['$PATH', 'foo$bar', '"x$"']) + result.should(eql( + "'$PATH' 'foo$bar' '\"x$\"'")) + end + + it "should deal with apostrophes (single quotes)" do + result = @scope.function_shellquote( + ["'foo'bar'", "`$'EDITOR'`"]) + result.should(eql( + '"\'foo\'bar\'" "\\`\\$\'EDITOR\'\\`"')) + end + + it "should cope with grave accents (backquotes)" do + result = @scope.function_shellquote( + ['`echo *`', '`ls "$MAILPATH"`']) + result.should(eql( + "'`echo *`' '`ls \"$MAILPATH\"`'")) + end + + it "should deal with both single and double quotes" do + result = @scope.function_shellquote( + ['\'foo"bar"xyzzy\'', '"foo\'bar\'xyzzy"']) + result.should(eql( + '"\'foo\\"bar\\"xyzzy\'" "\\"foo\'bar\'xyzzy\\""')) + end + + it "should handle multiple quotes *and* dollars and backquotes" do + result = @scope.function_shellquote( + ['\'foo"$x`bar`"xyzzy\'']) + result.should(eql( + '"\'foo\\"\\$x\\`bar\\`\\"xyzzy\'"')) + end + + it "should handle linefeeds" do + result = @scope.function_shellquote( + ["foo \n bar"]) + result.should(eql( + "\"foo \n bar\"")) + end + +end |
