grover 1.1.8 → 1.1.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bfcdc3d84dade94866bbb29eca6c1e91b9459a5f020ebd175341f740dfdd585
4
- data.tar.gz: 539a10195c08de66249983fccdf3f5314f1adec83b400d6058f87d127e731f86
3
+ metadata.gz: 82b9a3edaa4f0d20c326f3e79d61b1d2a0190454ac9ffb6867191a9607ec1ea0
4
+ data.tar.gz: 4e71234c41bf19c88a5b44c0a043a1c2ae5a74f94d0606fb0cd627c02e8511a2
5
5
  SHA512:
6
- metadata.gz: 6322c7cd633f776d58bb2fcad105d067a3df4782dcbc2fb15aff4fe60dcc2e8e1a58075e4972bb9f65362075eebe973e51f8aa385bd651d89ad41078e00fd4ca
7
- data.tar.gz: e9431f9a613f4b40f5d836616ad2e8afd6470a606a8daf80ad5553e248a461035228c62e290f0778e742aa2f2a9b663fe23f0590600cdda592cd8a26339ba391
6
+ metadata.gz: 737079399ecd8ef4c6a88c535495a2aa52fcb9e2e8fa0ca171d3453b58134d795237e606487a9f3dd06afad73baac8fac834a76a33445a1099e168f929f13835
7
+ data.tar.gz: 767e6ebf33ce60336d9afd71859e004b54765910136387ed81b44a12489de7728ff88d0b5f33890dea45314a58476972d31a1f3e9e5e7834f6d68979acf0eb19
@@ -7,7 +7,7 @@ class Grover
7
7
  class Configuration
8
8
  attr_accessor :options, :meta_tag_prefix, :ignore_path, :ignore_request,
9
9
  :root_url, :use_pdf_middleware, :use_png_middleware,
10
- :use_jpeg_middleware, :node_env_vars
10
+ :use_jpeg_middleware, :node_env_vars, :allow_file_uris
11
11
 
12
12
  def initialize
13
13
  @options = {}
@@ -19,6 +19,7 @@ class Grover
19
19
  @use_png_middleware = false
20
20
  @use_jpeg_middleware = false
21
21
  @node_env_vars = {}
22
+ @allow_file_uris = false
22
23
  end
23
24
  end
24
25
  end
data/lib/grover/errors.rb CHANGED
@@ -15,4 +15,5 @@ class Grover
15
15
  const_set name, Class.new(Error)
16
16
  end
17
17
  end
18
+ UnsafeConfigurationError = Class.new(Error)
18
19
  end
@@ -26,7 +26,7 @@ const fs = require('fs');
26
26
  const os = require('os');
27
27
  const path = require('path');
28
28
 
29
- const _processPage = (async (convertAction, urlOrHtml, options) => {
29
+ const _processPage = (async (convertAction, uriOrHtml, options) => {
30
30
  let browser, page, errors = [], tmpDir, wsConnection = false;
31
31
 
32
32
  try {
@@ -173,10 +173,12 @@ const _processPage = (async (convertAction, urlOrHtml, options) => {
173
173
  }
174
174
 
175
175
  const waitUntil = options.waitUntil; delete options.waitUntil;
176
- if (urlOrHtml.match(/^http/i)) {
176
+ const allowFileUri = options.allowFileUri; delete options.allowFileUri;
177
+ const uriRegex = allowFileUri ? /^(https?|file):\/\//i : /^https?:\/\//i;
178
+ if (uriOrHtml.match(uriRegex)) {
177
179
  // Request is for a URL, so request it
178
180
  requestOptions.waitUntil = waitUntil || 'networkidle2';
179
- await page.goto(urlOrHtml, requestOptions);
181
+ await page.goto(uriOrHtml, requestOptions);
180
182
  } else {
181
183
  // Request is some HTML content. Use request interception to assign the body
182
184
  requestOptions.waitUntil = waitUntil || 'networkidle0';
@@ -188,7 +190,7 @@ const _processPage = (async (convertAction, urlOrHtml, options) => {
188
190
  request.continue();
189
191
  else {
190
192
  htmlIntercepted = true
191
- request.respond({ body: urlOrHtml === '' ? ' ' : urlOrHtml });
193
+ request.respond({ body: uriOrHtml === '' ? ' ' : uriOrHtml });
192
194
  }
193
195
  });
194
196
  const displayUrl = options.displayUrl; delete options.displayUrl;
@@ -24,11 +24,14 @@ class Grover
24
24
  dup._call(env)
25
25
  end
26
26
 
27
- def _call(env)
27
+ def _call(env) # rubocop:disable Metrics/MethodLength
28
28
  @request = Rack::Request.new(env)
29
29
  identify_request_type
30
30
 
31
- configure_env_for_grover_request(env) if grover_request?
31
+ if grover_request?
32
+ check_file_uri_configuration
33
+ configure_env_for_grover_request(env)
34
+ end
32
35
  status, headers, response = @app.call(env)
33
36
  response = update_response response, headers if grover_request? && html_content?(headers)
34
37
 
@@ -45,6 +48,14 @@ class Grover
45
48
 
46
49
  attr_reader :pdf_request, :png_request, :jpeg_request
47
50
 
51
+ def check_file_uri_configuration
52
+ return unless Grover.configuration.allow_file_uris
53
+
54
+ # The combination of middleware and allowing file URLs is exceptionally
55
+ # unsafe as it can lead to data exfiltration from the host system.
56
+ raise UnsafeConfigurationError, 'using `allow_file_uris` configuration with middleware is exceptionally unsafe'
57
+ end
58
+
48
59
  def identify_request_type
49
60
  @pdf_request = Grover.configuration.use_pdf_middleware && path_matches?(PDF_REGEX)
50
61
  @png_request = Grover.configuration.use_png_middleware && path_matches?(PNG_REGEX)
@@ -8,12 +8,12 @@ class Grover
8
8
  # Build options from Grover.configuration, meta_options, and passed-in options
9
9
  #
10
10
  class OptionsBuilder < Hash
11
- def initialize(options, url)
11
+ def initialize(options, uri)
12
12
  super()
13
- @url = url
13
+ @uri = uri
14
14
  combined = grover_configuration
15
15
  Utils.deep_merge! combined, Utils.deep_stringify_keys(options)
16
- Utils.deep_merge! combined, meta_options unless url_source?
16
+ Utils.deep_merge! combined, meta_options unless uri_source?
17
17
 
18
18
  update OptionsFixer.new(combined).run
19
19
  end
@@ -41,11 +41,11 @@ class Grover
41
41
  end
42
42
 
43
43
  def meta_tags
44
- Nokogiri::HTML(@url).xpath('//meta')
44
+ Nokogiri::HTML(@uri).xpath('//meta')
45
45
  end
46
46
 
47
- def url_source?
48
- @url.match(/\Ahttp/i)
47
+ def uri_source?
48
+ @uri.match?(%r{\A(https?|file)://}i)
49
49
  end
50
50
  end
51
51
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Grover
4
- VERSION = '1.1.8'
4
+ VERSION = '1.1.9'
5
5
  end
data/lib/grover.rb CHANGED
@@ -28,40 +28,40 @@ class Grover
28
28
  attr_reader :front_cover_path, :back_cover_path
29
29
 
30
30
  #
31
- # @param [String] url URL of the page to convert
31
+ # @param [String] uri URI of the page to convert
32
32
  # @param [Hash] options Optional parameters to pass to PDF processor
33
33
  # see https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.pdfoptions.md
34
34
  # and https://github.com/puppeteer/puppeteer/blob/main/docs/api/puppeteer.screenshotoptions.md
35
35
  #
36
- def initialize(url, **options)
37
- @url = url.to_s
38
- @options = OptionsBuilder.new(options, @url)
36
+ def initialize(uri, **options)
37
+ @uri = uri.to_s
38
+ @options = OptionsBuilder.new(options, @uri)
39
39
  @root_path = @options.delete 'root_path'
40
40
  @front_cover_path = @options.delete 'front_cover_path'
41
41
  @back_cover_path = @options.delete 'back_cover_path'
42
42
  end
43
43
 
44
44
  #
45
- # Request URL with provided options and create PDF
45
+ # Request URI with provided options and create PDF
46
46
  #
47
47
  # @param [String] path Optional path to write the PDF to
48
48
  # @return [String] The resulting PDF data
49
49
  #
50
50
  def to_pdf(path = nil)
51
- processor.convert :pdf, @url, normalized_options(path: path)
51
+ processor.convert :pdf, @uri, normalized_options(path: path)
52
52
  end
53
53
 
54
54
  #
55
- # Request URL with provided options and render HTML
55
+ # Request URI with provided options and render HTML
56
56
  #
57
57
  # @return [String] The resulting HTML string
58
58
  #
59
59
  def to_html
60
- processor.convert :content, @url, normalized_options(path: nil)
60
+ processor.convert :content, @uri, normalized_options(path: nil)
61
61
  end
62
62
 
63
63
  #
64
- # Request URL with provided options and create screenshot
64
+ # Request URI with provided options and create screenshot
65
65
  #
66
66
  # @param [String] path Optional path to write the screenshot to
67
67
  # @param [String] format Optional format of the screenshot
@@ -70,11 +70,11 @@ class Grover
70
70
  def screenshot(path: nil, format: nil)
71
71
  options = normalized_options(path: path)
72
72
  options['type'] = format if %w[png jpeg].include? format
73
- processor.convert :screenshot, @url, options
73
+ processor.convert :screenshot, @uri, options
74
74
  end
75
75
 
76
76
  #
77
- # Request URL with provided options and create PNG
77
+ # Request URI with provided options and create PNG
78
78
  #
79
79
  # @param [String] path Optional path to write the screenshot to
80
80
  # @return [String] The resulting PNG data
@@ -84,7 +84,7 @@ class Grover
84
84
  end
85
85
 
86
86
  #
87
- # Request URL with provided options and create JPEG
87
+ # Request URI with provided options and create JPEG
88
88
  #
89
89
  # @param [String] path Optional path to write the screenshot to
90
90
  # @return [String] The resulting JPEG data
@@ -116,10 +116,10 @@ class Grover
116
116
  #
117
117
  def inspect
118
118
  format(
119
- '#<%<class_name>s:0x%<object_id>p @url="%<url>s">',
119
+ '#<%<class_name>s:0x%<object_id>p @uri="%<uri>s">',
120
120
  class_name: self.class.name,
121
121
  object_id: object_id,
122
- url: @url
122
+ uri: @uri
123
123
  )
124
124
  end
125
125
 
@@ -147,6 +147,7 @@ class Grover
147
147
  def normalized_options(path:)
148
148
  normalized_options = Utils.normalize_object @options, excluding: ['extraHTTPHeaders']
149
149
  normalized_options['path'] = path if path.is_a? ::String
150
+ normalized_options['allowFileUri'] = Grover.configuration.allow_file_uris == true
150
151
  normalized_options
151
152
  end
152
153
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grover
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.8
4
+ version: 1.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Bromwich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-23 00:00:00.000000000 Z
11
+ date: 2024-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: combine_pdf