pdfkit 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pdfkit might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d761c045627c5f9435b7ea06b44d5e23abbbcdd6
4
- data.tar.gz: 9f55905b443cfb6532696bf373173fd55435be56
3
+ metadata.gz: 104694d613ddecebcd67c5373e1309d9da1322d0
4
+ data.tar.gz: eed2d02a43b9fb425508a4b978a24ffc53191c99
5
5
  SHA512:
6
- metadata.gz: 19210027b8208466fd91c6c3604b205739973e95ffb876feaecc6f0e0df76d2a78103dd2747c6f00e0d0af171da4235f31518f03da495fe5c9c638a804e3883d
7
- data.tar.gz: 7a82596a5548c9ab3fb2557aef2aae5445f0dbae59196c436fd2c6846b2d6d9c1f51be0b6b85e4073c4da07bd160801d028601206ac04de2f81839c0b081dc5e
6
+ metadata.gz: 1463a8202d9b64d4d90a018b998015f1f6b70fa630994b27ba9cc7ad4f749b285a14fc455058a0b90f9626ecb648daccaa31fc547ca613d59d5efabde816e772
7
+ data.tar.gz: 9392e87f053d898c9e49cc96f8630e5056f9f58b2cddbc7db95cffd87424e8f1670a9fb0b572b38df81e6901140efb97f09d61564a975c79caf9cb8aa64948be
@@ -8,5 +8,5 @@ before_script:
8
8
  - "export DISPLAY=:99.0"
9
9
  - "sh -e /etc/init.d/xvfb start"
10
10
  - "sudo apt-get -qq -y install fontconfig libxrender1"
11
- - "wget http://downloads.sourceforge.net/project/wkhtmltopdf/archive/0.12.1/wkhtmltox-0.12.1_linux-precise-amd64.deb"
11
+ - "wget http://download.gna.org/wkhtmltopdf/0.12/0.12.1/wkhtmltox-0.12.1_linux-precise-amd64.deb"
12
12
  - "sudo dpkg -i wkhtmltox-0.12.1_linux-precise-amd64.deb"
@@ -1,6 +1,12 @@
1
+ 2015-08-20
2
+ =================
3
+ * Bump to 0.8.1
4
+ * Fix shell escaping issues for Windows (thanks muness)
5
+ * Fix shell escaping issues for URLs, introduced in 0.5.3 release
6
+
1
7
  2015-07-08
2
8
  =================
3
- * Bump to 0.7.1
9
+ * Bump to 0.8.0
4
10
  * Support Cover and Table Of Contents options (thanks @nicpillinger)
5
11
  * Fix repeatings keys with string values
6
12
  * Fix caching bug (thanks @jocranford)
@@ -1,4 +1,5 @@
1
1
  require 'shellwords'
2
+ require 'rbconfig'
2
3
 
3
4
  class PDFKit
4
5
  class NoExecutableError < StandardError
@@ -33,16 +34,15 @@ class PDFKit
33
34
 
34
35
  def command(path = nil)
35
36
  args = @options.to_a.flatten.compact
37
+ shell_escaped_command = [executable, shell_escape_for_os(args)].join ' '
36
38
 
37
- if @source.html?
38
- args << '-' # Get HTML from stdin
39
- else
40
- args << @source.to_s
41
- end
42
-
43
- args << (path || '-') # Write to file or stdout
39
+ # In order to allow for URL parameters (e.g. https://www.google.com/search?q=pdfkit) we do
40
+ # not escape the source. The user is responsible for ensuring that no vulnerabilities exist
41
+ # in the source. Please see https://github.com/pdfkit/pdfkit/issues/164.
42
+ input_for_command = @source.to_input_for_command
43
+ output_for_command = path ? Shellwords.shellescape(path) : '-'
44
44
 
45
- [executable, args.shelljoin].join ' '
45
+ "#{shell_escaped_command} #{input_for_command} #{output_for_command}"
46
46
  end
47
47
 
48
48
  def executable
@@ -161,7 +161,7 @@ class PDFKit
161
161
  when Array
162
162
  value.flatten.collect{|x| x.to_s}
163
163
  else
164
- value.to_s
164
+ (host_is_windows? && value.to_s.index(' ')) ? "'#{ value.to_s }'" : value.to_s
165
165
  end
166
166
  end
167
167
 
@@ -196,4 +196,18 @@ class PDFKit
196
196
  # https://code.google.com/p/wkhtmltopdf/issues/detail?id=55
197
197
  %w(skip ignore).include?(@options['--load-error-handling'])
198
198
  end
199
+
200
+ def host_is_windows?
201
+ @host_is_windows ||= !(RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince/).nil?
202
+ end
203
+
204
+ def shell_escape_for_os(args)
205
+ if (host_is_windows?)
206
+ # Windows reserved shell characters are: & | ( ) < > ^
207
+ # See http://technet.microsoft.com/en-us/library/cc723564.aspx#XSLTsection123121120120
208
+ args.map { |arg| arg.gsub(/([&|()<>^])/,'^\1') }.join(" ")
209
+ else
210
+ args.shelljoin
211
+ end
212
+ end
199
213
  end
@@ -1,23 +1,45 @@
1
1
  class PDFKit
2
2
  class Source
3
+ SOURCE_FROM_STDIN = '-'
4
+
3
5
  def initialize(url_file_or_html)
4
6
  @source = url_file_or_html
5
7
  end
6
-
8
+
7
9
  def url?
8
- @source.is_a?(String) && @source.match(/\Ahttp/)
10
+ @is_url ||= @source.is_a?(String) && @source.match(/\Ahttp/)
9
11
  end
10
-
12
+
11
13
  def file?
12
- @source.kind_of?(File)
14
+ @is_file ||= @source.kind_of?(File)
13
15
  end
14
-
16
+
15
17
  def html?
16
- !(url? || file?)
18
+ @is_html ||= !(url? || file?)
17
19
  end
18
-
20
+
21
+ def to_input_for_command
22
+ if file?
23
+ @source.path
24
+ elsif url?
25
+ %{"#{shell_safe_url}"}
26
+ else
27
+ SOURCE_FROM_STDIN
28
+ end
29
+ end
30
+
19
31
  def to_s
20
32
  file? ? @source.path : @source
21
33
  end
34
+
35
+ private
36
+
37
+ def shell_safe_url
38
+ url_needs_escaping? ? URI::escape(@source) : @source
39
+ end
40
+
41
+ def url_needs_escaping?
42
+ URI::decode(@source) == @source
43
+ end
22
44
  end
23
45
  end
@@ -1,3 +1,3 @@
1
1
  class PDFKit
2
- VERSION = "0.8.0"
2
+ VERSION = "0.8.1"
3
3
  end
@@ -243,14 +243,14 @@ describe PDFKit::Middleware do
243
243
  end
244
244
 
245
245
  context "when header PDFKit-save-pdf is present" do
246
- it "should saved the .pdf to disk" do
246
+ it "saves the .pdf to disk" do
247
247
  headers = { 'PDFKit-save-pdf' => 'spec/test_save.pdf' }
248
248
  mock_app({}, {only: '/public'}, headers)
249
249
  get 'http://www.example.org/public/test_save.pdf'
250
250
  expect(File.exists?('spec/test_save.pdf')).to eq(true)
251
251
  end
252
252
 
253
- it "should not raise when target directory does not exist" do
253
+ it "does not raise when target directory does not exist" do
254
254
  headers = { 'PDFKit-save-pdf' => '/this/dir/does/not/exist/spec/test_save.pdf' }
255
255
  mock_app({}, {only: '/public'}, headers)
256
256
  expect {
@@ -260,7 +260,7 @@ describe PDFKit::Middleware do
260
260
  end
261
261
 
262
262
  context "when header PDFKit-save-pdf is not present" do
263
- it "should not saved the .pdf to disk" do
263
+ it "does not saved the .pdf to disk" do
264
264
  mock_app({}, {only: '/public'}, {} )
265
265
  get 'http://www.example.org/public/test_save.pdf'
266
266
  expect(File.exists?('spec/test_save.pdf')).to eq(false)
@@ -325,31 +325,31 @@ describe PDFKit::Middleware do
325
325
  @env = { 'REQUEST_URI' => 'http://example.com/document.pdf', 'rack.url_scheme' => 'http', 'HTTP_HOST' => 'example.com' }
326
326
  end
327
327
 
328
- it "should correctly parse relative url with single quotes" do
328
+ it "correctly parses relative url with single quotes" do
329
329
  @body = %{<html><head><link href='/stylesheets/application.css' media='screen' rel='stylesheet' type='text/css' /></head><body><img alt='test' src="/test.png" /></body></html>}
330
330
  body = @pdf.send :translate_paths, @body, @env
331
331
  expect(body).to eq("<html><head><link href='http://example.com/stylesheets/application.css' media='screen' rel='stylesheet' type='text/css' /></head><body><img alt='test' src=\"http://example.com/test.png\" /></body></html>")
332
332
  end
333
333
 
334
- it "should correctly parse relative url with double quotes" do
334
+ it "correctly parses relative url with double quotes" do
335
335
  @body = %{<link href="/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />}
336
336
  body = @pdf.send :translate_paths, @body, @env
337
337
  expect(body).to eq("<link href=\"http://example.com/stylesheets/application.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />")
338
338
  end
339
339
 
340
- it "should correctly parse relative url with double quotes" do
340
+ it "correctly parses relative url with double quotes" do
341
341
  @body = %{<link href='//fonts.googleapis.com/css?family=Open+Sans:400,600' rel='stylesheet' type='text/css'>}
342
342
  body = @pdf.send :translate_paths, @body, @env
343
343
  expect(body).to eq("<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,600' rel='stylesheet' type='text/css'>")
344
344
  end
345
345
 
346
- it "should correctly parse multiple tags where first one is root url" do
346
+ it "correctly parses multiple tags where first one is root url" do
347
347
  @body = %{<a href='/'><img src='/logo.jpg' ></a>}
348
348
  body = @pdf.send :translate_paths, @body, @env
349
- body.should == "<a href='http://example.com/'><img src='http://example.com/logo.jpg' ></a>"
349
+ expect(body).to eq "<a href='http://example.com/'><img src='http://example.com/logo.jpg' ></a>"
350
350
  end
351
351
 
352
- it "should return the body even if there are no valid substitutions found" do
352
+ it "returns the body even if there are no valid substitutions found" do
353
353
  @body = "NO MATCH"
354
354
  body = @pdf.send :translate_paths, @body, @env
355
355
  expect(body).to eq("NO MATCH")
@@ -365,7 +365,7 @@ describe PDFKit::Middleware do
365
365
  end
366
366
  end
367
367
 
368
- it "should add the root_url" do
368
+ it "adds the root_url" do
369
369
  @body = %{<html><head><link href='/stylesheets/application.css' media='screen' rel='stylesheet' type='text/css' /></head><body><img alt='test' src="/test.png" /></body></html>}
370
370
  body = @pdf.send :translate_paths, @body, @env
371
371
  expect(body).to eq("<html><head><link href='http://example.net/stylesheets/application.css' media='screen' rel='stylesheet' type='text/css' /></head><body><img alt='test' src=\"http://example.net/test.png\" /></body></html>")
@@ -378,7 +378,7 @@ describe PDFKit::Middleware do
378
378
  end
379
379
  end
380
380
 
381
- it "should not get stuck rendering each request as pdf" do
381
+ it "does not get stuck rendering each request as pdf" do
382
382
  mock_app
383
383
  # false by default. No requests.
384
384
  expect(@app.send(:rendering_pdf?)).to eq(false)
@@ -4,19 +4,19 @@ require 'spec_helper'
4
4
  describe PDFKit do
5
5
  describe "initialization" do
6
6
  # Source
7
- it "should accept HTML as the source" do
7
+ it "accepts HTML as the source" do
8
8
  pdfkit = PDFKit.new('<h1>Oh Hai</h1>')
9
9
  expect(pdfkit.source).to be_html
10
10
  expect(pdfkit.source.to_s).to eq('<h1>Oh Hai</h1>')
11
11
  end
12
12
 
13
- it "should accept a URL as the source" do
13
+ it "accepts a URL as the source" do
14
14
  pdfkit = PDFKit.new('http://google.com')
15
15
  expect(pdfkit.source).to be_url
16
16
  expect(pdfkit.source.to_s).to eq('http://google.com')
17
17
  end
18
18
 
19
- it "should accept a File as the source" do
19
+ it "accepts a File as the source" do
20
20
  file_path = File.join(SPEC_ROOT,'fixtures','example.html')
21
21
  pdfkit = PDFKit.new(File.new(file_path))
22
22
  expect(pdfkit.source).to be_file
@@ -126,26 +126,26 @@ describe PDFKit do
126
126
  expect(pdfkit.options[['--allow', 'http://google.com']]).to eql nil
127
127
  end
128
128
 
129
- # Stylesheets
130
- it "has no stylesheet by default" do
131
- pdfkit = PDFKit.new('<h1>Oh Hai</h1>')
132
- expect(pdfkit.stylesheets).to be_empty
133
- end
134
-
135
- it "should not prepend cover with --" do
129
+ it "does not prepend cover option with --" do
136
130
  pdfkit = PDFKit.new('html', "cover" => 'http://google.com')
137
131
  expect(pdfkit.options).to have_key('cover')
138
132
  end
139
133
 
140
- it "should not prepend toc with --" do
134
+ it "does not prepend the toc option with --" do
141
135
  pdfkit = PDFKit.new('html', 'toc' => '')
142
136
  expect(pdfkit.options).to have_key('toc')
143
137
  end
144
138
 
145
- it "should handle special params passed as symbols" do
139
+ it "handles cover and toc params passed as symbols" do
146
140
  pdfkit = PDFKit.new('html', {toc: true})
147
141
  expect(pdfkit.options).to have_key('toc')
148
142
  end
143
+
144
+ # Stylesheets
145
+ it "has no stylesheet by default" do
146
+ pdfkit = PDFKit.new('<h1>Oh Hai</h1>')
147
+ expect(pdfkit.stylesheets).to be_empty
148
+ end
149
149
  end
150
150
 
151
151
  describe "#options" do
@@ -163,7 +163,7 @@ describe PDFKit do
163
163
  end
164
164
 
165
165
  describe "#command" do
166
- it "should construct the correct command" do
166
+ it "constructs the correct command" do
167
167
  pdfkit = PDFKit.new('html', :page_size => 'Letter', :toc_l1_font_size => 12, :replace => {'foo' => 'bar'})
168
168
  command = pdfkit.command
169
169
  expect(command).to include "wkhtmltopdf"
@@ -172,26 +172,37 @@ describe PDFKit do
172
172
  expect(command).to include "--replace foo bar"
173
173
  end
174
174
 
175
- it "should setup one cookie only" do
175
+ it "sets up one cookie when hash has only one cookie" do
176
176
  pdfkit = PDFKit.new('html', cookie: {cookie_name: :cookie_value})
177
177
  command = pdfkit.command
178
178
  expect(command).to include "--cookie cookie_name cookie_value"
179
179
  end
180
180
 
181
- it "should not break Windows paths" do
181
+ it "does not break Windows paths" do
182
182
  pdfkit = PDFKit.new('html')
183
183
  allow(PDFKit.configuration).to receive(:wkhtmltopdf).and_return 'c:/Program Files/wkhtmltopdf/wkhtmltopdf.exe'
184
184
  expect(pdfkit.command).not_to include('Program\ Files')
185
185
  end
186
186
 
187
- it "should setup multiple cookies when passed a hash" do
187
+ it "does not shell escape source URLs" do
188
+ pdfkit = PDFKit.new('https://www.google.com/search?q=pdfkit')
189
+ expect(pdfkit.command).to include "https://www.google.com/search?q=pdfkit"
190
+ end
191
+
192
+ it "formats source for the command" do
193
+ pdfkit = PDFKit.new('https://www.google.com/search?q=pdfkit')
194
+ expect(pdfkit.source).to receive(:to_input_for_command)
195
+ pdfkit.command
196
+ end
197
+
198
+ it "sets up multiple cookies when passed multiple cookies" do
188
199
  pdfkit = PDFKit.new('html', :cookie => {:cookie_name1 => :cookie_val1, :cookie_name2 => :cookie_val2})
189
200
  command = pdfkit.command
190
201
  expect(command).to include "--cookie cookie_name1 cookie_val1"
191
202
  expect(command).to include "--cookie cookie_name2 cookie_val2"
192
203
  end
193
204
 
194
- it "should setup multiple cookies when passed an array of tuples" do
205
+ it "sets up multiple cookies when passed an array of tuples" do
195
206
  pdfkit = PDFKit.new('html', :cookie => [[:cookie_name1, :cookie_val1], [:cookie_name2, :cookie_val2]])
196
207
  command = pdfkit.command
197
208
  expect(command).to include "--cookie cookie_name1 cookie_val1"
@@ -209,12 +220,12 @@ describe PDFKit do
209
220
  expect(pdfkit.command).not_to include('--disable-smart-shrinking')
210
221
  end
211
222
 
212
- it "should encapsulate string arguments in quotes" do
223
+ it "encapsulates string arguments in quotes" do
213
224
  pdfkit = PDFKit.new('html', :header_center => "foo [page]")
214
225
  expect(pdfkit.command).to include "--header-center foo\\ \\[page\\]"
215
226
  end
216
227
 
217
- it "should sanitize string arguments" do
228
+ it "sanitizes string arguments" do
218
229
  pdfkit = PDFKit.new('html', :header_center => "$(ls)")
219
230
  expect(pdfkit.command).to include "--header-center \\$\\(ls\\)"
220
231
  end
@@ -224,24 +235,30 @@ describe PDFKit do
224
235
  expect(pdfkit.command).to match /- -$/
225
236
  end
226
237
 
227
- it "specify the URL to the source if it is a url" do
238
+ it "specifies the URL to the source if it is a url" do
228
239
  pdfkit = PDFKit.new('http://google.com')
229
- expect(pdfkit.command).to match /http:\/\/google.com -$/
240
+ expect(pdfkit.command).to match /"http:\/\/google.com" -$/
230
241
  end
231
242
 
232
- it "should specify the path to the source if it is a file" do
243
+ it "does not break Windows paths" do
244
+ pdfkit = PDFKit.new('html')
245
+ allow(PDFKit.configuration).to receive(:wkhtmltopdf).and_return 'c:/Program Files/wkhtmltopdf/wkhtmltopdf.exe'
246
+ expect(pdfkit.command).not_to include('Program\ Files')
247
+ end
248
+
249
+ it "specifies the path to the source if it is a file" do
233
250
  file_path = File.join(SPEC_ROOT,'fixtures','example.html')
234
251
  pdfkit = PDFKit.new(File.new(file_path))
235
252
  expect(pdfkit.command).to match /#{file_path} -$/
236
253
  end
237
254
 
238
- it "should specify the path for the ouput if a path is given" do
255
+ it "specifies the path for the ouput if a path is given" do
239
256
  file_path = "/path/to/output.pdf"
240
257
  pdfkit = PDFKit.new("html")
241
258
  expect(pdfkit.command(file_path)).to match /#{file_path}$/
242
259
  end
243
260
 
244
- it "should detect special pdfkit meta tags" do
261
+ it "detects special pdfkit meta tags" do
245
262
  body = %{
246
263
  <html>
247
264
  <head>
@@ -256,7 +273,7 @@ describe PDFKit do
256
273
  expect(command).to include "--orientation Landscape"
257
274
  end
258
275
 
259
- it "should detect cookies meta tag" do
276
+ it "detects cookies meta tag" do
260
277
  body = %{
261
278
  <html>
262
279
  <head>
@@ -270,7 +287,7 @@ describe PDFKit do
270
287
  expect(command).to include "--cookie rails_session rails_session_value --cookie cookie_variable cookie_variable_value"
271
288
  end
272
289
 
273
- it "should detect disable_smart_shrinking meta tag" do
290
+ it "detects disable_smart_shrinking meta tag" do
274
291
  body = %{
275
292
  <html>
276
293
  <head>
@@ -284,7 +301,7 @@ describe PDFKit do
284
301
  expect(command).not_to include "--disable-smart-shrinking true"
285
302
  end
286
303
 
287
- it "should detect names with hyphens instead of underscores" do
304
+ it "detects names with hyphens instead of underscores" do
288
305
  body = %{
289
306
  <html>
290
307
  <head>
@@ -298,7 +315,7 @@ describe PDFKit do
298
315
  expect(pdfkit.command).not_to include 'name\='
299
316
  end
300
317
 
301
- it "should detect special pdfkit meta tags despite bad markup" do
318
+ it "detects special pdfkit meta tags despite bad markup" do
302
319
  body = %{
303
320
  <html>
304
321
  <head>
@@ -314,7 +331,7 @@ describe PDFKit do
314
331
  expect(command).to include "--orientation Landscape"
315
332
  end
316
333
 
317
- it "should skip non-pdfkit meta tags" do
334
+ it "skips non-pdfkit meta tags" do
318
335
  body = %{
319
336
  <html>
320
337
  <head>
@@ -330,17 +347,17 @@ describe PDFKit do
330
347
  expect(command).to include "--orientation Landscape"
331
348
  end
332
349
 
333
- it "should not use quiet" do
350
+ it "does not use quiet when told to" do
334
351
  pdfkit = PDFKit.new('html', quiet: false)
335
352
  expect(pdfkit.command).not_to include '--quiet'
336
353
  end
337
354
 
338
- it "should use quiet option by default" do
355
+ it "uses quiet option by default" do
339
356
  pdfkit = PDFKit.new('html')
340
357
  expect(pdfkit.command).to include '--quiet'
341
358
  end
342
359
 
343
- it "should not use quiet option in verbose mode" do
360
+ it "does not use quiet option in verbose mode" do
344
361
  PDFKit.configure do |config|
345
362
  config.verbose = true
346
363
  end
@@ -353,7 +370,7 @@ describe PDFKit do
353
370
  end
354
371
  end
355
372
 
356
- it "should not use quiet option in verbose mode when option of quiet is configured" do
373
+ it "does not use quiet option in verbose mode when option of quiet is configured" do
357
374
  PDFKit.configure do |config|
358
375
  config.verbose = true
359
376
  config.default_options[:quiet] = true
@@ -366,10 +383,26 @@ describe PDFKit do
366
383
  config.verbose = false
367
384
  end
368
385
  end
386
+
387
+ context "on windows" do
388
+ before do
389
+ allow_any_instance_of(PDFKit).to receive(:host_is_windows?).and_return(true)
390
+ end
391
+
392
+ it "escapes special windows characters" do
393
+ pdf = PDFKit.new('html', :title => 'hello(world)')
394
+ expect(pdf.command).to include 'hello^(world^)'
395
+ end
396
+
397
+ it "quotes spaces in options" do
398
+ pdf = PDFKit.new('html', :title => 'hello world')
399
+ expect(pdf.command).to include "--title 'hello world'"
400
+ end
401
+ end
369
402
  end
370
403
 
371
404
  describe "#to_pdf" do
372
- it "should not read the contents of the pdf when saving it as a file" do
405
+ it "does not read the contents of the pdf when saving it as a file" do
373
406
  file_path = "/my/file/path.pdf"
374
407
  pdfkit = PDFKit.new('html', :page_size => 'Letter')
375
408
 
@@ -388,25 +421,25 @@ describe PDFKit do
388
421
  pdfkit.to_pdf(file_path)
389
422
  end
390
423
 
391
- it "should generate a PDF of the HTML" do
424
+ it "generates a PDF of the HTML" do
392
425
  pdfkit = PDFKit.new('html', :page_size => 'Letter')
393
426
  pdf = pdfkit.to_pdf
394
427
  expect(pdf[0...4]).to eq("%PDF") # PDF Signature at beginning of file
395
428
  end
396
429
 
397
- it "should generate a PDF with a numerical parameter" do
430
+ it "generates a PDF with a numerical parameter" do
398
431
  pdfkit = PDFKit.new('html', :header_spacing => 1)
399
432
  pdf = pdfkit.to_pdf
400
433
  expect(pdf[0...4]).to eq("%PDF") # PDF Signature at beginning of file
401
434
  end
402
435
 
403
- it "should generate a PDF with a symbol parameter" do
436
+ it "generates a PDF with a symbol parameter" do
404
437
  pdfkit = PDFKit.new('html', :page_size => :Letter)
405
438
  pdf = pdfkit.to_pdf
406
439
  expect(pdf[0...4]).to eq("%PDF") # PDF Signature at beginning of file
407
440
  end
408
441
 
409
- it "should have the stylesheet added to the head if it has one" do
442
+ it "adds the stylesheet to the head tag if it has a head tag" do
410
443
  pdfkit = PDFKit.new("<html><head></head><body>Hai!</body></html>")
411
444
  css = File.join(SPEC_ROOT,'fixtures','example.css')
412
445
  pdfkit.stylesheets << css
@@ -414,7 +447,7 @@ describe PDFKit do
414
447
  expect(pdfkit.source.to_s).to include("<style>#{File.read(css)}</style>")
415
448
  end
416
449
 
417
- it "should prepend style tags if the HTML doesn't have a head tag" do
450
+ it "prepends style tags if the HTML doesn't have a head tag" do
418
451
  pdfkit = PDFKit.new("<html><body>Hai!</body></html>")
419
452
  css = File.join(SPEC_ROOT,'fixtures','example.css')
420
453
  pdfkit.stylesheets << css
@@ -422,14 +455,14 @@ describe PDFKit do
422
455
  expect(pdfkit.source.to_s).to include("<style>#{File.read(css)}</style><html>")
423
456
  end
424
457
 
425
- it "should throw an error if the source is not html and stylesheets have been added" do
458
+ it "throws an error if the source is not html and stylesheets have been added" do
426
459
  pdfkit = PDFKit.new('http://google.com')
427
460
  css = File.join(SPEC_ROOT,'fixtures','example.css')
428
461
  pdfkit.stylesheets << css
429
462
  expect { pdfkit.to_pdf }.to raise_error(PDFKit::ImproperSourceError)
430
463
  end
431
464
 
432
- it "should be able to deal with ActiveSupport::SafeBuffer" do
465
+ it "can deal with ActiveSupport::SafeBuffer" do
433
466
  pdfkit = PDFKit.new(ActiveSupport::SafeBuffer.new "<html><head></head><body>Hai!</body></html>")
434
467
  css = File.join(SPEC_ROOT,'fixtures','example.css')
435
468
  pdfkit.stylesheets << css
@@ -437,7 +470,7 @@ describe PDFKit do
437
470
  expect(pdfkit.source.to_s).to include("<style>#{File.read(css)}</style></head>")
438
471
  end
439
472
 
440
- it "should escape \\X in stylesheets" do
473
+ it "escapes \\X in stylesheets" do
441
474
  pdfkit = PDFKit.new("<html><head></head><body>Hai!</body></html>")
442
475
  css = File.join(SPEC_ROOT,'fixtures','example_with_hex_symbol.css')
443
476
  pdfkit.stylesheets << css
@@ -446,22 +479,28 @@ describe PDFKit do
446
479
  end
447
480
 
448
481
  #NOTICE: This test is failed if use wkhtmltopdf-binary (0.9.9.1)
449
- it "should throw an error if it is unable to connect" do
482
+ it "throws an error if it is unable to connect" do
450
483
  pdfkit = PDFKit.new("http://google.com/this-should-not-be-found/404.html")
451
484
  expect { pdfkit.to_pdf }.to raise_error /exitstatus=1/
452
485
  end
453
486
 
454
- it "should not throw an error if it is unable to connect", pending: 'this test works for wkhtmltopdf-binary (0.9.9.1)' do
487
+ it "does not throw an error if it is unable to connect", pending: 'this test works for wkhtmltopdf-binary (0.9.9.1)' do
455
488
  pdfkit = PDFKit.new("http://localhost/this-should-not-be-found/404.html")
456
489
  pdf = pdfkit.to_pdf
457
490
  expect(pdf[0...4]).to eq("%PDF") # PDF Signature at the beginning
458
491
  end
459
492
 
460
- it "should generate PDF if there are missing assets" do
493
+ it "generates a PDF if there are missing assets" do
461
494
  pdfkit = PDFKit.new("<html><body><img alt='' src='http://example.com/surely-it-doesnt-exist.gif' /></body></html>")
462
495
  pdf = pdfkit.to_pdf
463
496
  expect(pdf[0...4]).to eq("%PDF") # PDF Signature at the beginning
464
497
  end
498
+
499
+ it "can handle ampersands in URLs" do
500
+ pdfkit = PDFKit.new('https://www.google.com/search?q=pdfkit&sort=ASC')
501
+ pdf = pdfkit.to_pdf
502
+ expect(pdf[0...4]).to eq("%PDF") # PDF Signature at the beginning
503
+ end
465
504
  end
466
505
 
467
506
  describe "#to_file" do
@@ -474,14 +513,14 @@ describe PDFKit do
474
513
  File.delete(@file_path)
475
514
  end
476
515
 
477
- it "should create a file with the PDF as content" do
516
+ it "creates a file with the PDF as content" do
478
517
  pdfkit = PDFKit.new('html', :page_size => 'Letter')
479
518
  file = pdfkit.to_file(@file_path)
480
519
  expect(file).to be_instance_of(File)
481
520
  expect(File.read(file.path)[0...4]).to eq("%PDF") # PDF Signature at beginning of file
482
521
  end
483
522
 
484
- it "should not truncate data (in Ruby 1.8.6)" do
523
+ it "does not truncate data (in Ruby 1.8.6)" do
485
524
  file_path = File.join(SPEC_ROOT,'fixtures','example.html')
486
525
  pdfkit = PDFKit.new(File.new(file_path))
487
526
  pdf_data = pdfkit.to_pdf
@@ -501,7 +540,7 @@ describe PDFKit do
501
540
  File.delete(@test_path) if File.exist?(@test_path)
502
541
  end
503
542
 
504
- it "should not allow shell injection in options" do
543
+ it "does not allow shell injection in options" do
505
544
  pdfkit = PDFKit.new('html', :header_center => "a title\"; touch #{@test_path} #")
506
545
  pdfkit.to_pdf
507
546
  expect(File.exist?(@test_path)).to eq(false)
@@ -2,73 +2,95 @@ require 'spec_helper'
2
2
 
3
3
  describe PDFKit::Source do
4
4
  describe "#url?" do
5
- it "should return true if passed a url like string" do
5
+ it "returns true if passed a url like string" do
6
6
  source = PDFKit::Source.new('http://google.com')
7
7
  expect(source).to be_url
8
8
  end
9
9
 
10
- it "should return false if passed a file" do
10
+ it "returns false if passed a file" do
11
11
  source = PDFKit::Source.new(File.new(__FILE__))
12
12
  expect(source).not_to be_url
13
13
  end
14
14
 
15
- it "should return false if passed HTML" do
15
+ it "returns false if passed HTML" do
16
16
  source = PDFKit::Source.new('<blink>Oh Hai!</blink>')
17
17
  expect(source).not_to be_url
18
18
  end
19
19
 
20
- it "should return false if passed HTML with embedded urls at the beginning of a line" do
20
+ it "returns false if passed HTML with embedded urls at the beginning of a line" do
21
21
  source = PDFKit::Source.new("<blink>Oh Hai!</blink>\nhttp://www.google.com")
22
22
  expect(source).not_to be_url
23
23
  end
24
24
  end
25
25
 
26
26
  describe "#file?" do
27
- it "should return true if passed a file" do
27
+ it "returns true if passed a file" do
28
28
  source = PDFKit::Source.new(::File.new(__FILE__))
29
29
  expect(source).to be_file
30
30
  end
31
31
 
32
- it "should return false if passed a url like string" do
32
+ it "returns false if passed a url like string" do
33
33
  source = PDFKit::Source.new('http://google.com')
34
34
  expect(source).not_to be_file
35
35
  end
36
36
 
37
- it "should return false if passed HTML" do
37
+ it "returns false if passed HTML" do
38
38
  source = PDFKit::Source.new('<blink>Oh Hai!</blink>')
39
39
  expect(source).not_to be_file
40
40
  end
41
41
  end
42
42
 
43
43
  describe "#html?" do
44
- it "should return true if passed HTML" do
44
+ it "returns true if passed HTML" do
45
45
  source = PDFKit::Source.new('<blink>Oh Hai!</blink>')
46
46
  expect(source).to be_html
47
47
  end
48
48
 
49
- it "should return false if passed a file" do
49
+ it "returns false if passed a file" do
50
50
  source = PDFKit::Source.new(::File.new(__FILE__))
51
51
  expect(source).not_to be_html
52
52
  end
53
53
 
54
- it "should return false if passed a url like string" do
54
+ it "returns false if passed a url like string" do
55
55
  source = PDFKit::Source.new('http://google.com')
56
56
  expect(source).not_to be_html
57
57
  end
58
58
  end
59
59
 
60
+ describe "#to_input_for_command" do
61
+ it "URI escapes source URLs and encloses them in quotes to accomodate ampersands" do
62
+ source = PDFKit::Source.new("https://www.google.com/search?q='cat<dev/zero>/dev/null'")
63
+ expect(source.to_input_for_command).to eq "\"https://www.google.com/search?q='cat%3Cdev/zero%3E/dev/null'\""
64
+ end
65
+
66
+ it "does not URI escape previously escaped source URLs" do
67
+ source = PDFKit::Source.new("https://www.google.com/search?q='cat%3Cdev/zero%3E/dev/null'")
68
+ expect(source.to_input_for_command).to eq "\"https://www.google.com/search?q='cat%3Cdev/zero%3E/dev/null'\""
69
+ end
70
+
71
+ it "returns a '-' for HTML strings to indicate that we send that content through STDIN" do
72
+ source = PDFKit::Source.new('<blink>Oh Hai!</blink>')
73
+ expect(source.to_input_for_command).to eq '-'
74
+ end
75
+
76
+ it "returns the file path for file sources" do
77
+ source = PDFKit::Source.new(::File.new(__FILE__))
78
+ expect(source.to_input_for_command).to match 'spec/source_spec.rb'
79
+ end
80
+ end
81
+
60
82
  describe "#to_s" do
61
- it "should return the HTML if passed HTML" do
83
+ it "returns the HTML if passed HTML" do
62
84
  source = PDFKit::Source.new('<blink>Oh Hai!</blink>')
63
85
  expect(source.to_s).to eq('<blink>Oh Hai!</blink>')
64
86
  end
65
87
 
66
- it "should return a path if passed a file" do
88
+ it "returns a path if passed a file" do
67
89
  source = PDFKit::Source.new(::File.new(__FILE__))
68
90
  expect(source.to_s).to eq(__FILE__)
69
91
  end
70
92
 
71
- it "should return the url if passed a url like string" do
93
+ it "returns the url if passed a url like string" do
72
94
  source = PDFKit::Source.new('http://google.com')
73
95
  expect(source.to_s).to eq('http://google.com')
74
96
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdfkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jared Pace
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-07-08 00:00:00.000000000 Z
12
+ date: 2015-08-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport