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.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/cucumber.yml +2 -0
- data/features/asset_hash.feature +9 -0
- data/features/chained_templates.feature +4 -1
- data/features/cli/preview_server.feature +532 -0
- data/features/i18n_link_to.feature +209 -0
- data/features/javascript-testing.feature +18 -0
- data/features/redirects.feature +1 -0
- data/features/relative_assets.feature +11 -0
- data/features/support/env.rb +3 -0
- data/fixtures/asset-hash-app/source/fonts/fontawesome-webfont.woff +0 -0
- data/fixtures/asset-hash-app/source/fonts/fontawesome-webfont.woff2 +0 -0
- data/fixtures/asset-hash-app/source/stylesheets/uses_fonts.css +4 -0
- data/fixtures/chained-app/source/test.erb.combobreaker.str.erb +8 -0
- data/fixtures/javascript-app/config.rb +0 -0
- data/fixtures/javascript-app/source/index.html +17 -0
- data/fixtures/preview-server-app/bin/dns_server.rb +33 -0
- data/fixtures/preview-server-app/config-complications.rb +11 -0
- data/fixtures/preview-server-app/config-empty.rb +0 -0
- data/fixtures/preview-server-app/config.rb +11 -0
- data/fixtures/preview-server-app/source/index.html.erb +1 -0
- data/fixtures/preview-server-app/source/layout.erb +9 -0
- data/fixtures/preview-server-app/source/layouts/custom.erb +8 -0
- data/fixtures/preview-server-app/source/real.html +1 -0
- data/fixtures/preview-server-app/source/real/index.html.erb +5 -0
- data/fixtures/preview-server-app/source/should_be_ignored.html +1 -0
- data/fixtures/preview-server-app/source/should_be_ignored2.html +1 -0
- data/fixtures/preview-server-app/source/should_be_ignored3.html +1 -0
- data/fixtures/preview-server-app/source/static.html +1 -0
- data/fixtures/relative-assets-app/source/absolute_image_relative_css.html.erb +9 -0
- data/fixtures/relative-assets-app/source/javascripts/app.js +3 -0
- data/fixtures/relative-assets-app/source/relative_image.html.erb +1 -0
- data/fixtures/relative-assets-app/source/relative_image_absolute_css.html.erb +9 -0
- data/lib/middleman-core/application.rb +11 -5
- data/lib/middleman-core/cli/build.rb +3 -1
- data/lib/middleman-core/cli/bundler.rb +1 -1
- data/lib/middleman-core/cli/extension.rb +2 -2
- data/lib/middleman-core/cli/init.rb +3 -3
- data/lib/middleman-core/cli/server.rb +9 -1
- data/lib/middleman-core/configuration.rb +0 -2
- data/lib/middleman-core/core_extensions/data.rb +2 -2
- data/lib/middleman-core/core_extensions/external_helpers.rb +2 -1
- data/lib/middleman-core/core_extensions/file_watcher.rb +7 -0
- data/lib/middleman-core/core_extensions/front_matter.rb +13 -4
- data/lib/middleman-core/core_extensions/rendering.rb +20 -6
- data/lib/middleman-core/core_extensions/request.rb +2 -2
- data/lib/middleman-core/dns_resolver.rb +73 -0
- data/lib/middleman-core/dns_resolver/basic_network_resolver.rb +52 -0
- data/lib/middleman-core/dns_resolver/hosts_resolver.rb +63 -0
- data/lib/middleman-core/dns_resolver/local_link_resolver.rb +44 -0
- data/lib/middleman-core/dns_resolver/network_resolver.rb +42 -0
- data/lib/middleman-core/extension.rb +0 -1
- data/lib/middleman-core/meta_pages.rb +1 -1
- data/lib/middleman-core/preview_server.rb +94 -37
- data/lib/middleman-core/preview_server/checks.rb +81 -0
- data/lib/middleman-core/preview_server/information.rb +273 -0
- data/lib/middleman-core/preview_server/network_interface_inventory.rb +65 -0
- data/lib/middleman-core/preview_server/server_hostname.rb +39 -0
- data/lib/middleman-core/preview_server/server_information.rb +144 -0
- data/lib/middleman-core/preview_server/server_information_validator.rb +18 -0
- data/lib/middleman-core/preview_server/server_ip_address.rb +55 -0
- data/lib/middleman-core/preview_server/server_url.rb +50 -0
- data/lib/middleman-core/preview_server/tcp_port_prober.rb +29 -0
- data/lib/middleman-core/sitemap.rb +4 -4
- data/lib/middleman-core/sitemap/extensions/ignores.rb +5 -1
- data/lib/middleman-core/sitemap/extensions/proxies.rb +0 -1
- data/lib/middleman-core/sitemap/extensions/redirects.rb +2 -1
- data/lib/middleman-core/sitemap/queryable.rb +2 -1
- data/lib/middleman-core/sitemap/store.rb +3 -3
- data/lib/middleman-core/step_definitions.rb +1 -0
- data/lib/middleman-core/step_definitions/builder_steps.rb +7 -7
- data/lib/middleman-core/step_definitions/commandline_steps.rb +88 -0
- data/lib/middleman-core/step_definitions/server_steps.rb +25 -28
- data/lib/middleman-core/templates/extension/Gemfile +0 -1
- data/lib/middleman-core/templates/extension/Rakefile +1 -1
- data/lib/middleman-core/util.rb +24 -0
- data/lib/middleman-core/version.rb +1 -1
- data/lib/middleman-more/core_extensions/default_helpers.rb +49 -8
- data/lib/middleman-more/core_extensions/i18n.rb +101 -27
- data/lib/middleman-more/extensions/asset_hash.rb +1 -1
- data/lib/middleman-more/extensions/asset_host.rb +1 -1
- data/lib/middleman-more/extensions/automatic_image_sizes.rb +7 -0
- data/lib/middleman-more/extensions/cache_buster.rb +1 -1
- data/lib/middleman-more/extensions/lorem.rb +2 -2
- data/lib/middleman-more/extensions/minify_javascript.rb +6 -4
- data/lib/middleman-more/extensions/relative_assets.rb +4 -8
- data/middleman-core.gemspec +3 -3
- data/spec/middleman-core/dns_resolver_spec.rb +118 -0
- data/spec/middleman-core/preview_server/server_hostname_spec.rb +39 -0
- data/spec/middleman-core/preview_server/server_ip_address_spec.rb +43 -0
- data/spec/spec_helper.rb +26 -0
- 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(
|
|
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
|
-
|
|
11
|
+
class PreviewServer
|
|
11
12
|
class << self
|
|
12
|
-
attr_reader :app, :
|
|
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
|
-
|
|
25
|
-
logger.
|
|
26
|
-
logger.
|
|
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]
|
|
114
|
-
config[:port]
|
|
115
|
-
config[:
|
|
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
|
-
|
|
121
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
|
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
|