Skip to content

Instantly share code, notes, and snippets.

@Mazwak
Created May 28, 2015 15:37
Show Gist options
  • Save Mazwak/19f1176a95c0b10f9a89 to your computer and use it in GitHub Desktop.
Save Mazwak/19f1176a95c0b10f9a89 to your computer and use it in GitHub Desktop.
diff --git a/lib/winrm/winrm_service.rb b/lib/winrm/winrm_service.rb
index 0882832..d2978e2 100644
--- a/lib/winrm/winrm_service.rb
+++ b/lib/winrm/winrm_service.rb
@@ -55,7 +55,7 @@ module WinRM
end
# Operation timeout.
- #
+ #
# Unless specified the client receive timeout will be 10s + the operation
# timeout.
#
@@ -150,22 +150,22 @@ module WinRM
"#{NS_WSMAN_DMTF}:Option" => [consolemode, skipcmd],
:attributes! => {"#{NS_WSMAN_DMTF}:Option" => {'Name' => ['WINRS_CONSOLEMODE_STDIN','WINRS_SKIP_CMD_SHELL']}}}
}
- body = { "#{NS_WIN_SHELL}:Command" => "\"#{command}\"", "#{NS_WIN_SHELL}:Arguments" => arguments}
+
+ if command.index(" ") then
+ raise "Command should not contain spaces"
+ end
+ body = { "#{NS_WIN_SHELL}:Command" => "#{command}", "#{NS_WIN_SHELL}:Arguments" => arguments}
builder = Builder::XmlMarkup.new
builder.instruct!(:xml, :encoding => 'UTF-8')
builder.tag! :env, :Envelope, namespaces do |env|
env.tag!(:env, :Header) { |h| h << Gyoku.xml(merge_headers(header,resource_uri_cmd,action_command,h_opts,selector_shell_id(shell_id))) }
env.tag!(:env, :Body) do |env_body|
- env_body.tag!("#{NS_WIN_SHELL}:CommandLine") { |cl| cl << Gyoku.xml(body) }
+ env_body.tag!("#{NS_WIN_SHELL}:CommandLine") { |cl| cl << Gyoku.xml(body).gsub('&#39;', "'") }
end
end
- # Grab the command element and unescape any single quotes - issue 69
xml = builder.target!
- escaped_cmd = /<#{NS_WIN_SHELL}:Command>(.+)<\/#{NS_WIN_SHELL}:Command>/m.match(xml)[1]
- xml[escaped_cmd] = escaped_cmd.gsub(/&#39;/, "'")
-
resp_doc = send_message(xml)
command_id = REXML::XPath.first(resp_doc, "//#{NS_WIN_SHELL}:CommandId").text
@@ -289,6 +289,25 @@ module WinRM
true
end
+ # Splits a command string into an array
+ # @param [String] command with arguments
+ # @return [Array <String>] [command, arg1, arg2, …]
+ def shell_split(line)
+ words = []
+ field = ''
+ line.gsub!(/\^(['"])/, '\\\\\1')
+ line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/m) do
+ |word, sq, dq, esc, garbage, sep|
+ raise ArgumentError, "Unmatched double quote: #{line.inspect}" if garbage
+ field << (word || sq || (dq || esc).gsub(/\\(.)/, '\\1'))
+ if sep
+ words << field.gsub(/(['"])/, '^\1')
+ field = ''
+ end
+ end
+ words
+ end
+
# Run a CMD command
# @param [String] command The command to run on the remote system
# @param [Array <String>] arguments arguments to the command
@@ -297,6 +316,10 @@ module WinRM
def run_cmd(command, arguments = [], &block)
command_output = nil
open_shell do |shell_id|
+ if command.index(" ") then
+ warn "WinRS::run_cmd: Passing the command as one big string is discouraged"
+ command, *arguments = shell_split(command).concat(arguments)
+ end
run_command(shell_id, command, arguments) do |command_id|
command_output = get_command_output(shell_id, command_id, &block)
end
@@ -336,14 +359,14 @@ module WinRM
builder.tag! :env, :Envelope, namespaces do |env|
env.tag!(:env, :Header) { |h| h << Gyoku.xml(merge_headers(header,resource_uri_wmi,action_enumerate)) }
env.tag!(:env, :Body) do |env_body|
- env_body.tag!("#{NS_ENUM}:Enumerate") { |en| en << Gyoku.xml(body) }
+ env_body.tag!("#{NS_ENUM}:Enumerate") { |en| en << Gyoku.xml(body).gsub('&#39;', "'") }
end
end
resp = send_message(builder.target!)
parser = Nori.new(:parser => :rexml, :advanced_typecasting => false, :convert_tags_to => lambda { |tag| tag.snakecase.to_sym }, :strip_namespaces => true)
hresp = parser.parse(resp.to_s)[:envelope][:body]
-
+
# Normalize items so the type always has an array even if it's just a single item.
items = {}
if hresp[:enumerate_response][:items]
@@ -416,7 +439,7 @@ module WinRM
rescue WinRMWSManFault => e
# If no output is available before the wsman:OperationTimeout expires,
# the server MUST return a WSManFault with the Code attribute equal to
- # 2150858793. When the client receives this fault, it SHOULD issue
+ # 2150858793. When the client receives this fault, it SHOULD issue
# another Receive request.
# http://msdn.microsoft.com/en-us/library/cc251676.aspx
if e.fault_code == '2150858793'
@@ -429,7 +452,7 @@ module WinRM
def send_message(message)
@xfer.send_request(message)
end
-
+
# Helper methods for SOAP Headers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment