lib/pdfkit/pdfkit.rb in pdfkit-0.8.0 vs lib/pdfkit/pdfkit.rb in pdfkit-0.8.1
- old
+ new
@@ -1,6 +1,7 @@
require 'shellwords'
+require 'rbconfig'
class PDFKit
class NoExecutableError < StandardError
def initialize
msg = "No wkhtmltopdf executable found at #{PDFKit.configuration.wkhtmltopdf}\n"
@@ -31,20 +32,19 @@
raise NoExecutableError.new unless File.exists?(PDFKit.configuration.wkhtmltopdf)
end
def command(path = nil)
args = @options.to_a.flatten.compact
+ shell_escaped_command = [executable, shell_escape_for_os(args)].join ' '
- if @source.html?
- args << '-' # Get HTML from stdin
- else
- args << @source.to_s
- end
+ # In order to allow for URL parameters (e.g. https://www.google.com/search?q=pdfkit) we do
+ # not escape the source. The user is responsible for ensuring that no vulnerabilities exist
+ # in the source. Please see https://github.com/pdfkit/pdfkit/issues/164.
+ input_for_command = @source.to_input_for_command
+ output_for_command = path ? Shellwords.shellescape(path) : '-'
- args << (path || '-') # Write to file or stdout
-
- [executable, args.shelljoin].join ' '
+ "#{shell_escaped_command} #{input_for_command} #{output_for_command}"
end
def executable
default = PDFKit.configuration.wkhtmltopdf
return default if default !~ /^\// # its not a path, so nothing we can do
@@ -159,11 +159,11 @@
when Hash
value.to_a.flatten.collect{|x| normalize_value(x)}.compact
when Array
value.flatten.collect{|x| x.to_s}
else
- value.to_s
+ (host_is_windows? && value.to_s.index(' ')) ? "'#{ value.to_s }'" : value.to_s
end
end
def normalize_repeatable_value(option_name, value)
case value
@@ -193,7 +193,21 @@
def error_handling?
@options.key?('--ignore-load-errors') ||
# wkhtmltopdf v0.10.0 beta4 replaces ignore-load-errors with load-error-handling
# https://code.google.com/p/wkhtmltopdf/issues/detail?id=55
%w(skip ignore).include?(@options['--load-error-handling'])
+ end
+
+ def host_is_windows?
+ @host_is_windows ||= !(RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince/).nil?
+ end
+
+ def shell_escape_for_os(args)
+ if (host_is_windows?)
+ # Windows reserved shell characters are: & | ( ) < > ^
+ # See http://technet.microsoft.com/en-us/library/cc723564.aspx#XSLTsection123121120120
+ args.map { |arg| arg.gsub(/([&|()<>^])/,'^\1') }.join(" ")
+ else
+ args.shelljoin
+ end
end
end