middleman-core 3.3.12 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/cucumber.yml +2 -0
  4. data/features/asset_hash.feature +9 -0
  5. data/features/chained_templates.feature +4 -1
  6. data/features/cli/preview_server.feature +532 -0
  7. data/features/i18n_link_to.feature +209 -0
  8. data/features/javascript-testing.feature +18 -0
  9. data/features/redirects.feature +1 -0
  10. data/features/relative_assets.feature +11 -0
  11. data/features/support/env.rb +3 -0
  12. data/fixtures/asset-hash-app/source/fonts/fontawesome-webfont.woff +0 -0
  13. data/fixtures/asset-hash-app/source/fonts/fontawesome-webfont.woff2 +0 -0
  14. data/fixtures/asset-hash-app/source/stylesheets/uses_fonts.css +4 -0
  15. data/fixtures/chained-app/source/test.erb.combobreaker.str.erb +8 -0
  16. data/fixtures/javascript-app/config.rb +0 -0
  17. data/fixtures/javascript-app/source/index.html +17 -0
  18. data/fixtures/preview-server-app/bin/dns_server.rb +33 -0
  19. data/fixtures/preview-server-app/config-complications.rb +11 -0
  20. data/fixtures/preview-server-app/config-empty.rb +0 -0
  21. data/fixtures/preview-server-app/config.rb +11 -0
  22. data/fixtures/preview-server-app/source/index.html.erb +1 -0
  23. data/fixtures/preview-server-app/source/layout.erb +9 -0
  24. data/fixtures/preview-server-app/source/layouts/custom.erb +8 -0
  25. data/fixtures/preview-server-app/source/real.html +1 -0
  26. data/fixtures/preview-server-app/source/real/index.html.erb +5 -0
  27. data/fixtures/preview-server-app/source/should_be_ignored.html +1 -0
  28. data/fixtures/preview-server-app/source/should_be_ignored2.html +1 -0
  29. data/fixtures/preview-server-app/source/should_be_ignored3.html +1 -0
  30. data/fixtures/preview-server-app/source/static.html +1 -0
  31. data/fixtures/relative-assets-app/source/absolute_image_relative_css.html.erb +9 -0
  32. data/fixtures/relative-assets-app/source/javascripts/app.js +3 -0
  33. data/fixtures/relative-assets-app/source/relative_image.html.erb +1 -0
  34. data/fixtures/relative-assets-app/source/relative_image_absolute_css.html.erb +9 -0
  35. data/lib/middleman-core/application.rb +11 -5
  36. data/lib/middleman-core/cli/build.rb +3 -1
  37. data/lib/middleman-core/cli/bundler.rb +1 -1
  38. data/lib/middleman-core/cli/extension.rb +2 -2
  39. data/lib/middleman-core/cli/init.rb +3 -3
  40. data/lib/middleman-core/cli/server.rb +9 -1
  41. data/lib/middleman-core/configuration.rb +0 -2
  42. data/lib/middleman-core/core_extensions/data.rb +2 -2
  43. data/lib/middleman-core/core_extensions/external_helpers.rb +2 -1
  44. data/lib/middleman-core/core_extensions/file_watcher.rb +7 -0
  45. data/lib/middleman-core/core_extensions/front_matter.rb +13 -4
  46. data/lib/middleman-core/core_extensions/rendering.rb +20 -6
  47. data/lib/middleman-core/core_extensions/request.rb +2 -2
  48. data/lib/middleman-core/dns_resolver.rb +73 -0
  49. data/lib/middleman-core/dns_resolver/basic_network_resolver.rb +52 -0
  50. data/lib/middleman-core/dns_resolver/hosts_resolver.rb +63 -0
  51. data/lib/middleman-core/dns_resolver/local_link_resolver.rb +44 -0
  52. data/lib/middleman-core/dns_resolver/network_resolver.rb +42 -0
  53. data/lib/middleman-core/extension.rb +0 -1
  54. data/lib/middleman-core/meta_pages.rb +1 -1
  55. data/lib/middleman-core/preview_server.rb +94 -37
  56. data/lib/middleman-core/preview_server/checks.rb +81 -0
  57. data/lib/middleman-core/preview_server/information.rb +273 -0
  58. data/lib/middleman-core/preview_server/network_interface_inventory.rb +65 -0
  59. data/lib/middleman-core/preview_server/server_hostname.rb +39 -0
  60. data/lib/middleman-core/preview_server/server_information.rb +144 -0
  61. data/lib/middleman-core/preview_server/server_information_validator.rb +18 -0
  62. data/lib/middleman-core/preview_server/server_ip_address.rb +55 -0
  63. data/lib/middleman-core/preview_server/server_url.rb +50 -0
  64. data/lib/middleman-core/preview_server/tcp_port_prober.rb +29 -0
  65. data/lib/middleman-core/sitemap.rb +4 -4
  66. data/lib/middleman-core/sitemap/extensions/ignores.rb +5 -1
  67. data/lib/middleman-core/sitemap/extensions/proxies.rb +0 -1
  68. data/lib/middleman-core/sitemap/extensions/redirects.rb +2 -1
  69. data/lib/middleman-core/sitemap/queryable.rb +2 -1
  70. data/lib/middleman-core/sitemap/store.rb +3 -3
  71. data/lib/middleman-core/step_definitions.rb +1 -0
  72. data/lib/middleman-core/step_definitions/builder_steps.rb +7 -7
  73. data/lib/middleman-core/step_definitions/commandline_steps.rb +88 -0
  74. data/lib/middleman-core/step_definitions/server_steps.rb +25 -28
  75. data/lib/middleman-core/templates/extension/Gemfile +0 -1
  76. data/lib/middleman-core/templates/extension/Rakefile +1 -1
  77. data/lib/middleman-core/util.rb +24 -0
  78. data/lib/middleman-core/version.rb +1 -1
  79. data/lib/middleman-more/core_extensions/default_helpers.rb +49 -8
  80. data/lib/middleman-more/core_extensions/i18n.rb +101 -27
  81. data/lib/middleman-more/extensions/asset_hash.rb +1 -1
  82. data/lib/middleman-more/extensions/asset_host.rb +1 -1
  83. data/lib/middleman-more/extensions/automatic_image_sizes.rb +7 -0
  84. data/lib/middleman-more/extensions/cache_buster.rb +1 -1
  85. data/lib/middleman-more/extensions/lorem.rb +2 -2
  86. data/lib/middleman-more/extensions/minify_javascript.rb +6 -4
  87. data/lib/middleman-more/extensions/relative_assets.rb +4 -8
  88. data/middleman-core.gemspec +3 -3
  89. data/spec/middleman-core/dns_resolver_spec.rb +118 -0
  90. data/spec/middleman-core/preview_server/server_hostname_spec.rb +39 -0
  91. data/spec/middleman-core/preview_server/server_ip_address_spec.rb +43 -0
  92. data/spec/spec_helper.rb +26 -0
  93. metadata +81 -17
@@ -0,0 +1,63 @@
1
+ module Middleman
2
+ class DnsResolver
3
+ # Use network name server to resolve ips and names
4
+ class HostsResolver
5
+ private
6
+
7
+ attr_reader :resolver
8
+
9
+ public
10
+
11
+ def initialize(opts={})
12
+ # using the splat operator works around a non-existing HOSTSRC variable
13
+ # using nil as input does not work, but `*[]` does and then Resolv::Hosts
14
+ # uses its defaults
15
+ @resolver = opts.fetch(:resolver, Resolv::Hosts.new(*hosts_file))
16
+ end
17
+
18
+ # Get names for ip
19
+ #
20
+ # @param [#to_s] ip
21
+ # The ip to resolve into names
22
+ #
23
+ # @return [Array]
24
+ # Array of Names
25
+ def getnames(ip)
26
+ resolver.getnames(ip.to_s).map(&:to_s)
27
+ rescue Resolv::ResolvError
28
+ []
29
+ end
30
+
31
+ # Get ips for name
32
+ #
33
+ # @param [#to_s] name
34
+ # The name to resolve into ips
35
+ #
36
+ # @return [Array]
37
+ # Array of ipaddresses
38
+ def getaddresses(name)
39
+ resolver.getaddresses(name.to_s).map(&:to_s)
40
+ rescue Resolv::ResolvError
41
+ []
42
+ end
43
+
44
+ private
45
+
46
+ # Path to hosts file
47
+ #
48
+ # This looks for MM_HOSTSRC in your environment
49
+ #
50
+ # @return [Array]
51
+ # This needs to be an array, to make the splat operator work
52
+ #
53
+ # @example
54
+ # # <ip> <hostname>
55
+ # 127.0.0.1 localhost.localhost localhost
56
+ def hosts_file
57
+ return [ENV['MM_HOSTSRC']] if ENV.key?('MM_HOSTSRC') && File.file?(ENV['MM_HOSTSRC'])
58
+
59
+ []
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,44 @@
1
+ require 'middleman-core/dns_resolver/basic_network_resolver'
2
+
3
+ module Middleman
4
+ class DnsResolver
5
+ # Use network name server to resolve ips and names
6
+ class LocalLinkResolver < BasicNetworkResolver
7
+ def initialize(opts={})
8
+ super
9
+
10
+ @timeouts = opts.fetch(:timeouts, 1)
11
+ @resolver = opts.fetch(:resolver, Resolv::MDNS.new(nameserver_config))
12
+
13
+ self.timeouts = timeouts
14
+ end
15
+
16
+ private
17
+
18
+ # Hosts + Ports for MDNS resolver
19
+ #
20
+ # This looks for MM_MDNSRC in your environment. If you are going to use
21
+ # IPv6-addresses: Make sure you do not forget to add the port at the end.
22
+ #
23
+ # MM_MDNSRC=ip:port ip:port
24
+ #
25
+ # @return [Hash]
26
+ # Returns the configuration for the nameserver
27
+ #
28
+ # @example
29
+ # export MM_MDNSRC="224.0.0.251:5353 ff02::fb:5353"
30
+ #
31
+ def nameserver_config
32
+ return unless ENV.key?('MM_MDNSRC') && ENV['MM_MDNSRC']
33
+
34
+ address, port = ENV['MM_MDNSRC'].split(/:/)
35
+
36
+ {
37
+ nameserver_port: [[address, port.to_i]]
38
+ }
39
+ rescue StandardError
40
+ {}
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,42 @@
1
+ require 'middleman-core/dns_resolver/basic_network_resolver'
2
+
3
+ module Middleman
4
+ class DnsResolver
5
+ # Use network name server to resolve ips and names
6
+ class NetworkResolver < BasicNetworkResolver
7
+ def initialize(opts={})
8
+ super
9
+
10
+ @resolver = opts.fetch(:resolver, Resolv::DNS.new(nameserver_config))
11
+ self.timeouts = timeouts
12
+ end
13
+
14
+ private
15
+
16
+ # Hosts + Ports for MDNS resolver
17
+ #
18
+ # This looks for MM_MDNSRC in your environment. If you are going to use
19
+ # IPv6-addresses: Make sure you do not forget to add the port at the end.
20
+ #
21
+ # MM_MDNSRC=ip:port ip:port
22
+ #
23
+ # @return [Hash]
24
+ # Returns the configuration for the nameserver
25
+ #
26
+ # @example
27
+ # export MM_MDNSRC="224.0.0.251:5353 ff02::fb:5353"
28
+ #
29
+ def nameserver_config
30
+ return unless ENV.key?('MM_DNSRC') && ENV['MM_DNSRC']
31
+
32
+ address, port = ENV['MM_DNSRC'].split(/:/)
33
+
34
+ {
35
+ nameserver_port: [[address, port.to_i]]
36
+ }
37
+ rescue StandardError
38
+ {}
39
+ end
40
+ end
41
+ end
42
+ end
@@ -130,7 +130,6 @@ module Middleman
130
130
  @klass.after_configuration do
131
131
  ext.after_configuration if ext.respond_to?(:after_configuration)
132
132
 
133
- # rubocop:disable IfUnlessModifier
134
133
  if ext.respond_to?(:manipulate_resource_list)
135
134
  ext.app.sitemap.register_resource_list_manipulator(ext.class.extension_name, ext)
136
135
  end
@@ -90,7 +90,7 @@ module Middleman
90
90
  # Render a template with the given name and locals
91
91
  def template(template_name, locals={})
92
92
  template_path = File.join(File.dirname(__FILE__), 'meta_pages', 'templates', template_name)
93
- content = Tilt.new(template_path).render(nil, locals)
93
+ content = Tilt.new(template_path).render(::Object.new, locals)
94
94
  response(content)
95
95
  end
96
96
 
@@ -1,15 +1,16 @@
1
1
  require 'webrick'
2
2
  require 'webrick/https'
3
3
  require 'openssl'
4
- require 'socket'
5
4
  require 'middleman-core/meta_pages'
6
5
  require 'middleman-core/logger'
6
+ require 'middleman-core/preview_server/server_information'
7
+ require 'middleman-core/preview_server/server_url'
7
8
 
8
9
  # rubocop:disable GlobalVars
9
10
  module Middleman
10
- module PreviewServer
11
+ class PreviewServer
11
12
  class << self
12
- attr_reader :app, :host, :port, :ssl_certificate, :ssl_private_key
13
+ attr_reader :app, :ssl_certificate, :ssl_private_key, :environment, :server_information
13
14
  delegate :logger, to: :app
14
15
 
15
16
  def https?
@@ -19,11 +20,31 @@ module Middleman
19
20
  # Start an instance of Middleman::Application
20
21
  # @return [void]
21
22
  def start(opts={})
23
+ # Do not buffer output, otherwise testing of output does not work
24
+ $stdout.sync = true
25
+ $stderr.sync = true
26
+
22
27
  @options = opts
28
+ @server_information = ServerInformation.new
29
+
30
+ # New app evaluates the middleman configuration. Since this can be
31
+ # invalid as well, we need to evaluate the configuration BEFORE
32
+ # checking for validity
33
+ the_app = new_app
34
+
35
+ # And now comes the check
36
+ unless server_information.valid?
37
+ logger.fatal %(== Running Middleman failed: #{server_information.reason}. Please fix that and try again.)
38
+ exit 1
39
+ end
40
+
41
+ mount_instance(the_app)
23
42
 
24
- mount_instance(new_app)
25
- logger.info "== The Middleman is standing watch at #{uri} (#{uri(public_ip)})"
26
- logger.info "== Inspect your site configuration at #{uri + '__middleman'}"
43
+ logger.debug %(== Server information is provided by #{server_information.handler})
44
+ logger.debug %(== The Middleman is running in "#{environment}" environment)
45
+ logger.debug format('== The Middleman preview server is bind to %s', ServerUrl.new(hosts: server_information.listeners, port: server_information.port, https: https?).to_bind_addresses.join(', '))
46
+ logger.info format('== View your site at %s', ServerUrl.new(hosts: server_information.site_addresses, port: server_information.port, https: https?).to_urls.join(', '))
47
+ logger.info format('== Inspect your site configuration at %s', ServerUrl.new(hosts: server_information.site_addresses, port: server_information.port, https: https?).to_config_urls.join(', '))
27
48
 
28
49
  @initialized ||= false
29
50
  return if @initialized
@@ -79,6 +100,10 @@ module Middleman
79
100
  end
80
101
 
81
102
  unmount_instance
103
+
104
+ @webrick.shutdown
105
+ @webrick = nil
106
+
82
107
  mount_instance(app)
83
108
 
84
109
  logger.info '== The Middleman has reloaded'
@@ -110,15 +135,26 @@ module Middleman
110
135
  opts[:instrumenting] || false
111
136
  )
112
137
 
113
- config[:environment] = opts[:environment].to_sym if opts[:environment]
114
- config[:port] = opts[:port] if opts[:port]
115
- config[:https] = opts[:https] unless opts[:https].nil?
138
+ config[:environment] = opts[:environment].to_sym if opts[:environment]
139
+ config[:port] = opts[:port] if opts[:port]
140
+ config[:bind_address] = opts[:bind_address]
141
+ config[:server_name] = opts[:server_name]
142
+ config[:https] = opts[:https] unless opts[:https].nil?
116
143
  config[:ssl_certificate] = opts[:ssl_certificate] if opts[:ssl_certificate]
117
144
  config[:ssl_private_key] = opts[:ssl_private_key] if opts[:ssl_private_key]
118
145
  end
119
146
 
120
- @port = @app.config[:port]
121
- @https = @app.config[:https]
147
+ # store configured port to make a check later on possible
148
+ configured_port = @app.config[:port]
149
+
150
+ # Use configuration values to set `bind_address` etc. in
151
+ # `server_information`
152
+ server_information.use @app.config
153
+
154
+ logger.warn format('== The Middleman uses a different port "%s" then the configured one "%s" because some other server is listening on that port.', server_information.port, configured_port) unless @app.config[:port] == configured_port
155
+
156
+ @https = @app.config[:https]
157
+ @environment = @app.config[:environment]
122
158
 
123
159
  @ssl_certificate = @app.config[:ssl_certificate]
124
160
  @ssl_private_key = @app.config[:ssl_private_key]
@@ -135,7 +171,7 @@ module Middleman
135
171
  options = { force_polling: @options[:force_polling] }
136
172
  options[:latency] = @options[:latency] if @options[:latency]
137
173
 
138
- @listener = Listen.to(Dir.pwd, options) do |modified, added, removed|
174
+ @listener = Listen.to(::Middleman::Util.current_directory, options) do |modified, added, removed|
139
175
  added_and_modified = (modified + added)
140
176
 
141
177
  # See if the changed file is config.rb or lib/*.rb
@@ -143,14 +179,16 @@ module Middleman
143
179
  $mm_reload = true
144
180
  @webrick.stop
145
181
  else
182
+ wd = Pathname(::Middleman::Util.current_directory)
183
+
146
184
  added_and_modified.each do |path|
147
- relative_path = Pathname(path).relative_path_from(Pathname(Dir.pwd)).to_s
185
+ relative_path = Pathname(path).relative_path_from(wd).to_s
148
186
  next if app.files.ignored?(relative_path)
149
187
  app.files.did_change(relative_path)
150
188
  end
151
189
 
152
190
  removed.each do |path|
153
- relative_path = Pathname(path).relative_path_from(Pathname(Dir.pwd)).to_s
191
+ relative_path = Pathname(path).relative_path_from(wd).to_s
154
192
  next if app.files.ignored?(relative_path)
155
193
  app.files.did_delete(relative_path)
156
194
  end
@@ -179,8 +217,10 @@ module Middleman
179
217
  # @return [void]
180
218
  def setup_webrick(is_logging)
181
219
  http_opts = {
182
- Port: port,
220
+ Port: server_information.port,
183
221
  AccessLog: [],
222
+ ServerName: server_information.server_name,
223
+ BindAddress: server_information.bind_address.to_s,
184
224
  DoNotReverseLookup: true
185
225
  }
186
226
 
@@ -188,15 +228,14 @@ module Middleman
188
228
  http_opts[:SSLEnable] = true
189
229
 
190
230
  if ssl_certificate || ssl_private_key
191
- raise "You must provide both :ssl_certificate and :ssl_private_key" unless ssl_private_key && ssl_certificate
231
+ raise 'You must provide both :ssl_certificate and :ssl_private_key' unless ssl_private_key && ssl_certificate
192
232
  http_opts[:SSLCertificate] = OpenSSL::X509::Certificate.new File.read ssl_certificate
193
233
  http_opts[:SSLPrivateKey] = OpenSSL::PKey::RSA.new File.read ssl_private_key
194
234
  else
195
235
  # use a generated self-signed cert
196
- http_opts[:SSLCertName] = [
197
- %w(CN localhost),
198
- %w(CN #{Socket.gethostname})
199
- ].uniq
236
+ cert, key = create_self_signed_cert(1024, [['CN', server_information.server_name]], server_information.site_addresses, 'Middleman Preview Server')
237
+ http_opts[:SSLCertificate] = cert
238
+ http_opts[:SSLPrivateKey] = key
200
239
  end
201
240
  end
202
241
 
@@ -209,11 +248,44 @@ module Middleman
209
248
  begin
210
249
  ::WEBrick::HTTPServer.new(http_opts)
211
250
  rescue Errno::EADDRINUSE
212
- logger.error "== Port #{port} is unavailable. Either close the instance of Middleman already running on #{port} or start this Middleman on a new port with: --port=#{port.to_i + 1}"
213
- exit(1)
251
+ logger.error %(== Port "#{http_opts[:Port]}" is in use. This should not have happened. Please start "middleman server" again.)
214
252
  end
215
253
  end
216
254
 
255
+ # Copy of https://github.com/nahi/ruby/blob/webrick_trunk/lib/webrick/ssl.rb#L39
256
+ # that uses a different serial number each time the cert is generated in order to
257
+ # avoid errors in Firefox. Also doesn't print out stuff to $stderr unnecessarily.
258
+ def create_self_signed_cert(bits, cn, aliases, comment)
259
+ rsa = OpenSSL::PKey::RSA.new(bits)
260
+ cert = OpenSSL::X509::Certificate.new
261
+ cert.version = 2
262
+ cert.serial = Time.now.to_i % (1 << 20)
263
+ name = OpenSSL::X509::Name.new(cn)
264
+ cert.subject = name
265
+ cert.issuer = name
266
+ cert.not_before = Time.now
267
+ cert.not_after = Time.now + (365 * 24 * 60 * 60)
268
+ cert.public_key = rsa.public_key
269
+
270
+ ef = OpenSSL::X509::ExtensionFactory.new(nil, cert)
271
+ ef.issuer_certificate = cert
272
+ cert.extensions = [
273
+ ef.create_extension('basicConstraints', 'CA:FALSE'),
274
+ ef.create_extension('keyUsage', 'keyEncipherment'),
275
+ ef.create_extension('subjectKeyIdentifier', 'hash'),
276
+ ef.create_extension('extendedKeyUsage', 'serverAuth'),
277
+ ef.create_extension('nsComment', comment)
278
+ ]
279
+ aki = ef.create_extension('authorityKeyIdentifier',
280
+ 'keyid:always,issuer:always')
281
+ cert.add_extension(aki)
282
+ cert.add_extension ef.create_extension('subjectAltName', aliases.map { |d| "DNS: #{d}" }.join(','))
283
+
284
+ cert.sign(rsa, OpenSSL::Digest::SHA1.new)
285
+
286
+ [cert, rsa]
287
+ end
288
+
217
289
  # Attach a new Middleman::Application instance
218
290
  # @param [Middleman::Application] app
219
291
  # @return [void]
@@ -261,21 +333,6 @@ module Middleman
261
333
  end
262
334
  end
263
335
  end
264
-
265
- # Returns the URI the preview server will run on
266
- # @return [URI]
267
- def uri(host = Socket.gethostname)
268
- scheme = https? ? 'https' : 'http'
269
- URI("#{scheme}://#{host}:#{@port}/")
270
- end
271
-
272
- # An IPv4 address on this machine which should be externally addressable.
273
- # @return [String]
274
- def public_ip
275
- ip = Socket.ip_address_list.find { |ai| ai.ipv4? && !ai.ipv4_loopback? }
276
- ip ? ip.ip_address : '127.0.0.1'
277
- end
278
-
279
336
  end
280
337
 
281
338
  class FilteredWebrickLog < ::WEBrick::Log
@@ -0,0 +1,81 @@
1
+ require 'ipaddr'
2
+
3
+ module Middleman
4
+ class PreviewServer
5
+ # Checks for input of preview server
6
+ module Checks
7
+ # This one will get all default setup
8
+ class BasicCheck; end
9
+
10
+ # This checks if the server name resolves to the bind_address
11
+ #
12
+ # If the users enters:
13
+ #
14
+ # 1. server_name: www.example.com (10.0.0.1)
15
+ # 2. bind_address: 127.0.0.01
16
+ #
17
+ # This validation will fail
18
+ class ServerNameResolvesToBindAddress < BasicCheck
19
+ private
20
+
21
+ attr_reader :resolver
22
+
23
+ public
24
+
25
+ def initialize
26
+ @resolver = DnsResolver.new
27
+ end
28
+
29
+ # Validate
30
+ #
31
+ # @param [Information] information
32
+ # The information to be validated
33
+ def validate(information)
34
+ return if resolver.ips_for(information.server_name).include? information.bind_address
35
+
36
+ information.valid = false
37
+ information.reason = format('Server name "%s" does not resolve to bind address "%s"', information.server_name, information.bind_address)
38
+ end
39
+ end
40
+
41
+ # This validation fails if the user chooses to use an ip address which is
42
+ # not available on his/her system
43
+ class InterfaceIsAvailableOnSystem < BasicCheck
44
+ # Validate
45
+ #
46
+ # @param [Information] information
47
+ # The information to be validated
48
+ def validate(information)
49
+ return if information.bind_address.blank? || information.local_network_interfaces.include?(information.bind_address.to_s) || %w(0.0.0.0 ::).any? { |b| information.bind_address == b } || IPAddr.new('127.0.0.0/8').include?(information.bind_address.to_s)
50
+
51
+ information.valid = false
52
+ information.reason = format('Bind address "%s" is not available on your system. Please use one of %s', information.bind_address, information.local_network_interfaces.map { |i| %("#{i}") }.join(', '))
53
+ end
54
+ end
55
+
56
+ # This one requires a bind address if the user entered a server name
57
+ #
58
+ # If the `bind_address` is blank this check will fail
59
+ class RequiresBindAddressIfServerNameIsGiven < BasicCheck
60
+ def validate(information)
61
+ return unless information.bind_address.blank?
62
+
63
+ information.valid = false
64
+ information.reason = format('Server name "%s" does not resolve to an ip address', information.server_name)
65
+ end
66
+ end
67
+
68
+ # This validation always fails
69
+ class DenyAnyAny < BasicCheck
70
+ # Validate
71
+ #
72
+ # @param [Information] information
73
+ # The information to be validated
74
+ def validate(information)
75
+ information.valid = false
76
+ information.reason = 'Undefined combination of options "--server-name" and "--bind-address". If you think this is wrong, please file a bug at "https://github.com/middleman/middleman"'
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end