passenger 4.0.33 → 4.0.34

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

Potentially problematic release.


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

Files changed (112) hide show
  1. checksums.yaml +15 -0
  2. checksums.yaml.gz.asc +12 -0
  3. data.tar.gz.asc +7 -7
  4. data/NEWS +60 -0
  5. data/bin/passenger-config +1 -1
  6. data/bin/passenger-install-apache2-module +510 -40
  7. data/bin/passenger-install-nginx-module +26 -2
  8. data/build/cxx_tests.rb +1 -1
  9. data/build/documentation.rb +19 -21
  10. data/build/integration_tests.rb +39 -12
  11. data/build/misc.rb +18 -0
  12. data/build/packaging.rb +116 -56
  13. data/build/rpm.rb +20 -11
  14. data/build/ruby_tests.rb +2 -3
  15. data/build/test_basics.rb +9 -0
  16. data/debian.template/passenger.conf +2 -0
  17. data/debian.template/passenger.load +2 -0
  18. data/dev/run_travis.sh +3 -5
  19. data/dev/test_rpm_packaging.sh +28 -0
  20. data/doc/Users guide Apache.idmap.txt +6 -4
  21. data/doc/users_guide_snippets/installation.txt +20 -2
  22. data/doc/users_guide_snippets/tips.txt +1 -1
  23. data/ext/common/ApplicationPool2/Pool.h +1 -1
  24. data/ext/common/Constants.h +5 -1
  25. data/ext/common/agents/HelperAgent/RequestHandler.h +1 -1
  26. data/ext/common/agents/Watchdog/AgentWatcher.cpp +20 -0
  27. data/ext/common/agents/Watchdog/Main.cpp +10 -0
  28. data/ext/ruby/passenger_native_support.c +23 -11
  29. data/helper-scripts/classic-rails-loader.rb +9 -3
  30. data/helper-scripts/classic-rails-preloader.rb +10 -4
  31. data/helper-scripts/download_binaries/extconf.rb +46 -22
  32. data/helper-scripts/meteor-loader.rb +0 -1
  33. data/helper-scripts/node-loader.js +2 -1
  34. data/helper-scripts/prespawn +7 -1
  35. data/helper-scripts/rack-loader.rb +32 -3
  36. data/helper-scripts/rack-preloader.rb +10 -4
  37. data/lib/phusion_passenger.rb +40 -21
  38. data/lib/phusion_passenger/abstract_installer.rb +7 -4
  39. data/lib/phusion_passenger/analytics_logger.rb +4 -3
  40. data/lib/phusion_passenger/config/about_command.rb +27 -6
  41. data/lib/phusion_passenger/{config.rb → config/main.rb} +3 -2
  42. data/lib/phusion_passenger/config/restart_app_command.rb +1 -1
  43. data/lib/phusion_passenger/config/validate_install_command.rb +231 -0
  44. data/lib/phusion_passenger/constants.rb +2 -0
  45. data/lib/phusion_passenger/loader_shared_helpers.rb +92 -19
  46. data/lib/phusion_passenger/native_support.rb +33 -11
  47. data/lib/phusion_passenger/packaging.rb +1 -0
  48. data/lib/phusion_passenger/platform_info.rb +5 -2
  49. data/lib/phusion_passenger/platform_info/apache.rb +229 -60
  50. data/lib/phusion_passenger/platform_info/apache_detector.rb +26 -31
  51. data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +4 -4
  52. data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +4 -4
  53. data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +1 -1
  54. data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +1 -1
  55. data/lib/phusion_passenger/platform_info/linux.rb +2 -1
  56. data/lib/phusion_passenger/platform_info/ruby.rb +7 -0
  57. data/lib/phusion_passenger/preloader_shared_helpers.rb +2 -1
  58. data/lib/phusion_passenger/request_handler.rb +2 -1
  59. data/lib/phusion_passenger/request_handler/thread_handler.rb +2 -1
  60. data/lib/phusion_passenger/standalone/runtime_installer.rb +35 -13
  61. data/lib/phusion_passenger/standalone/start_command.rb +2 -2
  62. data/lib/phusion_passenger/utils.rb +1 -23
  63. data/lib/phusion_passenger/utils/ansi_colors.rb +7 -1
  64. data/lib/phusion_passenger/utils/download.rb +36 -2
  65. data/lib/phusion_passenger/utils/native_support_utils.rb +65 -0
  66. data/resources/templates/apache2/apache_install_broken.txt.erb +20 -0
  67. data/resources/templates/apache2/config_snippets.txt.erb +2 -4
  68. data/resources/templates/apache2/present_choice_for_no_update_config.txt.erb +5 -0
  69. data/resources/templates/installer_common/cannot_access_files_as_root.txt.erb +15 -0
  70. data/resources/templates/installer_common/run_installer_as_root.txt.erb +6 -3
  71. data/resources/templates/nginx/nginx_module_sources_not_available.txt.erb +1 -1
  72. data/resources/templates/nginx/other_nginx_installations_exist.txt.erb +17 -0
  73. data/rpm/apache-passenger.conf.in +26 -0
  74. data/rpm/config.json +30 -0
  75. data/rpm/passenger.logrotate +7 -0
  76. data/rpm/passenger.spec.template +456 -0
  77. data/rpm/passenger_dynamic_thread_group.patch +16 -0
  78. data/rpm/passenger_tests_default_config_example.patch +44 -0
  79. data/rpm/rubygem-passenger-4.0.18-GLIBC_HAVE_LONG_LONG.patch +21 -0
  80. data/rpm/rubygem-passenger-4.0.18-gcc47-include-sys_types.patch +45 -0
  81. data/test/config.json.rpm-automation +15 -0
  82. data/test/integration_tests/downloaded_binaries_tests.rb +80 -2
  83. data/test/integration_tests/native_packaging_spec.rb +136 -44
  84. data/test/integration_tests/standalone_tests.rb +2 -11
  85. data/test/ruby/analytics_logger_spec.rb +65 -19
  86. data/test/ruby/utils_spec.rb +2 -0
  87. metadata +532 -548
  88. metadata.gz.asc +7 -7
  89. data/resources/templates/apache2/no_write_permission_to_passenger_root.txt.erb +0 -9
  90. data/rpm/README.rdoc +0 -117
  91. data/rpm/config/apache-passenger.conf.in +0 -19
  92. data/rpm/config/nginx-passenger.conf.in +0 -10
  93. data/rpm/config/rubygem-passenger.te +0 -10
  94. data/rpm/doc/README.nginx-alternatives +0 -5
  95. data/rpm/doc/example_yum_repository_htaccess +0 -5
  96. data/rpm/doc/footer.shtml +0 -12
  97. data/rpm/doc/header.shtml +0 -156
  98. data/rpm/nginx-alternatives.spec +0 -97
  99. data/rpm/passenger-release.spec +0 -91
  100. data/rpm/passenger.spec +0 -667
  101. data/rpm/patches/passenger-force-native.patch +0 -63
  102. data/rpm/release/RPM-GPG-KEY-stealthymonkeys +0 -33
  103. data/rpm/release/build-release.sh +0 -35
  104. data/rpm/release/build.rb +0 -301
  105. data/rpm/release/create-mirrors.sh +0 -16
  106. data/rpm/release/mirrors +0 -1
  107. data/rpm/release/mock-repo/comps.xml +0 -21
  108. data/rpm/release/mock-repo/rubygem-daemon_controller-0.2.5-1.noarch.rpm +0 -0
  109. data/rpm/release/mock-repo/rubygem-file-tail-1.0.5-1.noarch.rpm +0 -0
  110. data/rpm/release/mock-repo/rubygem-spruz-0.2.2-1.noarch.rpm +0 -0
  111. data/rpm/release/mocksetup-first.sh +0 -102
  112. data/rpm/release/mocksetup.sh +0 -67
@@ -40,9 +40,13 @@ class NativeSupportLoader
40
40
  end
41
41
 
42
42
  def start
43
- if try_load
43
+ if ENV['PASSENGER_USE_RUBY_NATIVE_SUPPORT'] == '0'
44
+ STDERR.puts " --> Continuing without #{library_name}."
45
+ STDERR.puts " Because PASSENGER_USE_RUBY_NATIVE_SUPPORT is set to 0."
46
+ return false
47
+ elsif try_load
44
48
  return true
45
- elsif download_binary_and_load || compile_and_load
49
+ elsif compile_and_load || download_binary_and_load
46
50
  STDERR.puts " --> #{library_name} successfully loaded."
47
51
  return true
48
52
  else
@@ -139,10 +143,11 @@ private
139
143
  PhusionPassenger.require_passenger_lib 'platform_info/ruby'
140
144
  PhusionPassenger.require_passenger_lib 'utils/tmpio'
141
145
  PhusionPassenger.require_passenger_lib 'utils/download'
146
+
142
147
  PhusionPassenger::Utils.mktmpdir("passenger-native-support-") do |dir|
143
148
  Dir.chdir(dir) do
144
149
  basename = "rubyext-#{archdir}.tar.gz"
145
- if !download(basename, dir)
150
+ if !download(basename, dir, :total_timeout => 30)
146
151
  return false
147
152
  end
148
153
 
@@ -234,16 +239,33 @@ private
234
239
  return target_dirs
235
240
  end
236
241
 
237
- def download(name, output_dir)
238
- url = "#{PhusionPassenger::BINARIES_URL_ROOT}/#{PhusionPassenger::VERSION_STRING}/#{name}"
239
- filename = "#{output_dir}/#{name}"
242
+ def download(name, output_dir, options = {})
240
243
  logger = Logger.new(STDERR)
241
244
  logger.level = Logger::WARN
242
- logger.formatter = proc { |severity, datetime, progname, msg| " #{msg}\n" }
243
- return PhusionPassenger::Utils::Download.download(url, filename,
244
- :cacert => PhusionPassenger.binaries_ca_cert_path,
245
+ logger.formatter = proc do |severity, datetime, progname, msg|
246
+ msg.gsub(/^/, " ") + "\n"
247
+ end
248
+ sites = PhusionPassenger.binaries_sites
249
+ sites.each_with_index do |site, i|
250
+ if real_download(site, name, output_dir, logger, options)
251
+ logger.warn "Download OK!" if i > 0
252
+ return true
253
+ elsif i != sites.size - 1
254
+ logger.warn "Trying next mirror..."
255
+ end
256
+ end
257
+ return false
258
+ end
259
+
260
+ def real_download(site, name, output_dir, logger, options)
261
+ url = "#{site[:url]}/#{VERSION_STRING}/#{name}"
262
+ filename = "#{output_dir}/#{name}"
263
+ real_options = options.merge(
264
+ :cacert => site[:cacert],
245
265
  :use_cache => true,
246
- :logger => logger)
266
+ :logger => logger
267
+ )
268
+ return PhusionPassenger::Utils::Download.download(url, filename, real_options)
247
269
  end
248
270
 
249
271
  def mkdir(dir)
@@ -265,7 +287,7 @@ private
265
287
  PhusionPassenger::Utils.mktmpdir("passenger-native-support-") do |tmpdir|
266
288
  s_tmpdir = Shellwords.escape(tmpdir)
267
289
  result = system("#{command_string} >#{s_tmpdir}/log 2>&1")
268
- system("cat #{s_tmpdir}/log | sed 's/^/ /'")
290
+ system("cat #{s_tmpdir}/log | sed 's/^/ /' >&2")
269
291
  return result
270
292
  end
271
293
  end
@@ -111,6 +111,7 @@ module Packaging
111
111
  'test/.rspec',
112
112
  'test/*.example',
113
113
  'test/*.travis',
114
+ 'test/*.rpm-automation',
114
115
  'test/*.supp',
115
116
  'test/support/*.{c,cpp,h,rb}',
116
117
  'test/tut/*',
@@ -1,5 +1,6 @@
1
+ # encoding: binary
1
2
  # Phusion Passenger - https://www.phusionpassenger.com/
2
- # Copyright (c) 2010-2013 Phusion
3
+ # Copyright (c) 2010-2014 Phusion
3
4
  #
4
5
  # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
5
6
  #
@@ -218,7 +219,9 @@ public
218
219
  end
219
220
 
220
221
  def self.read_file(filename)
221
- return File.read(filename)
222
+ return File.open(filename, "rb") do |f|
223
+ f.read
224
+ end
222
225
  rescue
223
226
  return ""
224
227
  end
@@ -101,6 +101,27 @@ module PlatformInfo
101
101
  end
102
102
  memoize :httpd_version
103
103
 
104
+ # Run `httpd -V` and return its output. On some systems, such as Ubuntu 13.10,
105
+ # `httpd -V` fails without the environment variables defined in various scripts.
106
+ # Here we take care of evaluating those scripts before running `httpd -V`.
107
+ def self.httpd_V(options = nil)
108
+ if options
109
+ httpd = options[:httpd] || self.httpd(options)
110
+ else
111
+ httpd = self.httpd
112
+ end
113
+ if httpd
114
+ command = "#{httpd} -V"
115
+ if envvars_file = httpd_envvars_file(options)
116
+ command = ". '#{envvars_file}' && #{command}"
117
+ end
118
+ return `#{command}`
119
+ else
120
+ return nil
121
+ end
122
+ end
123
+ memoize :httpd_V
124
+
104
125
  # The Apache executable's architectural bits. Returns 32 or 64,
105
126
  # or nil if unable to detect.
106
127
  def self.httpd_architecture_bits(options = nil)
@@ -125,27 +146,38 @@ module PlatformInfo
125
146
  end
126
147
  memoize :httpd_architecture_bits
127
148
 
128
- # The Apache root directory.
129
- def self.httpd_root(options = nil)
130
- if info = httpd_V(options)
149
+ # The default Apache root directory, as specified by its compilation parameters.
150
+ # This may be different from the value of the ServerRoot directive.
151
+ def self.httpd_default_root(options = nil)
152
+ if options
153
+ info = httpd_V(options)
154
+ else
155
+ info = httpd_V
156
+ end
157
+ if info
131
158
  info =~ / -D HTTPD_ROOT="(.+)"$/
132
159
  return $1
133
160
  else
134
161
  return nil
135
162
  end
136
163
  end
137
- memoize :httpd_root
164
+ memoize :httpd_default_root
138
165
 
139
166
  # The default Apache configuration file, or nil if Apache is not found.
140
167
  def self.httpd_default_config_file(options = nil)
141
- if info = httpd_V(options)
168
+ if options
169
+ info = httpd_V(options)
170
+ else
171
+ info = httpd_V
172
+ end
173
+ if info
142
174
  info =~ /-D SERVER_CONFIG_FILE="(.+)"$/
143
175
  filename = $1
144
176
  if filename =~ /\A\//
145
177
  return filename
146
178
  else
147
- # Not an absolute path. Infer from root.
148
- if root = httpd_root(options)
179
+ # Not an absolute path. Infer from default root.
180
+ if root = httpd_default_root(options)
149
181
  return "#{root}/#{filename}"
150
182
  else
151
183
  return nil
@@ -157,6 +189,26 @@ module PlatformInfo
157
189
  end
158
190
  memoize :httpd_default_config_file
159
191
 
192
+ # Given an Apache config file, returns the a hash with the following elements:
193
+ #
194
+ # * `:files` - An array containing `config_file`, as well as all config files
195
+ # included from that config file, including recursively included
196
+ # ones. Only filenames that actually exist are put here.
197
+ # * `:unreadable_files` - All config files that this function was unable
198
+ # to read.
199
+ def self.httpd_included_config_files(config_file, options = nil)
200
+ state = {
201
+ :files => { config_file => true },
202
+ :unreadable_files => [],
203
+ :root => httpd_default_root(options)
204
+ }
205
+ scan_for_included_apache2_config_files(config_file, state, options)
206
+ return {
207
+ :files => state[:files].keys,
208
+ :unreadable_files => state[:unreadable_files]
209
+ }
210
+ end
211
+
160
212
  # The default Apache error log's filename, as it is compiled into the Apache
161
213
  # main executable. This may not be the actual error log that is used. The actual
162
214
  # error log depends on the configuration file.
@@ -170,8 +222,8 @@ module PlatformInfo
170
222
  if filename =~ /\A\//
171
223
  return filename
172
224
  else
173
- # Not an absolute path. Infer from root.
174
- if root = httpd_root(options)
225
+ # Not an absolute path. Infer from default root.
226
+ if root = httpd_default_root(options)
175
227
  return "#{root}/#{filename}"
176
228
  else
177
229
  return nil
@@ -188,35 +240,16 @@ module PlatformInfo
188
240
  begin
189
241
  contents = File.open(config_file, "rb") { |f| f.read }
190
242
  rescue Errno::EACCES
243
+ log "Unable to open #{config_file} for reading"
191
244
  return nil
192
245
  end
193
246
  # We don't want to match comments
194
247
  contents.gsub!(/^[ \t]*#.*/, '')
195
- if contents =~ /^ErrorLog (.+)$/
196
- filename = $1.strip.sub(/^"/, '').sub(/"$/, '')
197
- if filename.include?("${")
198
- log "Error log seems to be located in \"#{filename}\", " +
199
- "but value contains environment variables. " +
200
- "Attempting to substitute them..."
201
- end
202
- # The Apache config file supports environment variable
203
- # substitution. Ubuntu uses this extensively.
204
- filename.gsub!(/\$\{(.+?)\}/) do |varname|
205
- if value = httpd_infer_envvar($1, options)
206
- log "Substituted \"#{varname}\" -> \"#{value}\""
207
- value
208
- else
209
- log "Cannot substituted \"#{varname}\""
210
- varname
211
- end
212
- end
213
- if filename.include?("${")
214
- # We couldn't substitute everything.
215
- return nil
216
- end
217
- if filename !~ /\A\//
248
+ if contents =~ /^[ \t]*ErrorLog[ \t]+(.+)[ \t]*$/i
249
+ filename = unescape_apache_config_value($1, options)
250
+ if filename && filename !~ /\A\//
218
251
  # Not an absolute path. Infer from root.
219
- if root = httpd_root(options)
252
+ if root = httpd_default_root(options)
220
253
  return "#{root}/#{filename}"
221
254
  else
222
255
  return nil
@@ -224,13 +257,15 @@ module PlatformInfo
224
257
  else
225
258
  return filename
226
259
  end
227
- elsif contents =~ /ErrorLog/
260
+ elsif contents =~ /ErrorLog/i
228
261
  # The user apparently has ErrorLog set somewhere but
229
262
  # we can't parse it. The default error log location,
230
263
  # as reported by `httpd -V`, may be wrong (it is on OS X).
231
264
  # So to be safe, let's assume that we don't know.
265
+ log "Unable to parse ErrorLog directive in Apache configuration file"
232
266
  return nil
233
267
  else
268
+ log "No ErrorLog directive in Apache configuration file"
234
269
  return httpd_default_error_log(options)
235
270
  end
236
271
  else
@@ -278,25 +313,67 @@ module PlatformInfo
278
313
  end
279
314
  end
280
315
 
281
- # Whether Apache appears to support a2enmod and a2dismod.
282
- def self.httpd_supports_a2enmod?(options = nil)
316
+ # Returns the path to the Apache `mods-available` subdirectory,
317
+ # or nil if it's not supported by this Apache.
318
+ def self.httpd_mods_available_directory(options = nil)
283
319
  config_file = httpd_default_config_file(options)
284
- if config_file
285
- config_dir = File.dirname(config_file)
286
- return File.exist?("#{config_dir}/mods-available") &&
287
- File.exist?("#{config_dir}/mods-enabled")
320
+ return nil if !config_file
321
+
322
+ # mods-available is supposed to be a Debian extension that only works
323
+ # on the APT-installed Apache, so only return non-nil if we're
324
+ # working against the APT-installed Apache.
325
+ config_dir = File.dirname(config_file)
326
+ if config_dir == "/etc/httpd" || config_dir == "/etc/apache2"
327
+ if File.exist?("#{config_dir}/mods-available") &&
328
+ File.exist?("#{config_dir}/mods-enabled")
329
+ return "#{config_dir}/mods-available"
330
+ else
331
+ return nil
332
+ end
333
+ else
334
+ return nil
335
+ end
336
+ end
337
+ memoize :httpd_mods_available_directory
338
+
339
+ # Returns the path to the Apache `mods-enabled` subdirectory,
340
+ # or nil if it's not supported by this Apache.
341
+ def self.httpd_mods_enabled_directory(options = nil)
342
+ config_file = httpd_default_config_file(options)
343
+ return nil if !config_file
344
+
345
+ # mods-enabled is supposed to be a Debian extension that only works
346
+ # on the APT-installed Apache, so only return non-nil if we're
347
+ # working against the APT-installed Apache.
348
+ config_dir = File.dirname(config_file)
349
+ if config_dir == "/etc/httpd" || config_dir == "/etc/apache2"
350
+ if File.exist?("#{config_dir}/mods-available") &&
351
+ File.exist?("#{config_dir}/mods-enabled")
352
+ return "#{config_dir}/mods-enabled"
353
+ else
354
+ return nil
355
+ end
288
356
  else
289
357
  return nil
290
358
  end
291
359
  end
360
+ memoize :httpd_mods_enabled_directory
292
361
 
293
362
  # The absolute path to the 'a2enmod' executable.
294
363
  def self.a2enmod(options = {})
295
364
  apxs2 = options[:apxs2] || self.apxs2
296
- if env_defined?('A2ENMOD')
297
- return ENV['A2ENMOD']
365
+ dir = File.dirname(apxs2)
366
+ # a2enmod is supposed to be a Debian extension that only works
367
+ # on the APT-installed Apache, so only return non-nil if we're
368
+ # working against the APT-installed Apache.
369
+ if dir == "/usr/bin" || dir == "/usr/sbin"
370
+ if env_defined?('A2ENMOD')
371
+ return ENV['A2ENMOD']
372
+ else
373
+ return find_apache2_executable("a2enmod", options)
374
+ end
298
375
  else
299
- return find_apache2_executable("a2enmod", options)
376
+ return nil
300
377
  end
301
378
  end
302
379
  memoize :a2enmod
@@ -304,10 +381,16 @@ module PlatformInfo
304
381
  # The absolute path to the 'a2enmod' executable.
305
382
  def self.a2dismod(options = {})
306
383
  apxs2 = options[:apxs2] || self.apxs2
307
- if env_defined?('A2DISMOD')
308
- return ENV['A2DISMOD']
309
- else
310
- return find_apache2_executable("a2dismod", options)
384
+ dir = File.dirname(apxs2)
385
+ # a2dismod is supposed to be a Debian extension that only works
386
+ # on the APT-installed Apache, so only return non-nil if we're
387
+ # working against the APT-installed Apache.
388
+ if dir == "/usr/bin" || dir == "/usr/sbin"
389
+ if env_defined?('A2DISMOD')
390
+ return ENV['A2DISMOD']
391
+ else
392
+ return find_apache2_executable("a2dismod", options)
393
+ end
311
394
  end
312
395
  end
313
396
  memoize :a2dismod
@@ -590,25 +673,111 @@ private
590
673
  memoize :determine_apu_info, true
591
674
  private_class_method :determine_apu_info
592
675
 
593
- # Run `httpd -V` and return its output. On some systems, such as Ubuntu 13.10,
594
- # `httpd -V` fails without the environment variables defined in various scripts.
595
- # Here we take care of evaluating those scripts before running `httpd -V`.
596
- def self.httpd_V(options = nil)
597
- if options
598
- httpd = options[:httpd] || self.httpd(options)
599
- else
600
- httpd = self.httpd
676
+ def self.scan_for_included_apache2_config_files(config_file, state, options = nil)
677
+ begin
678
+ config = File.open(config_file, "rb") do |f|
679
+ f.read
680
+ end
681
+ rescue Errno::EACCES
682
+ state[:unreadable_files] << config_file
683
+ return
601
684
  end
602
- if httpd
603
- command = "#{httpd} -V"
604
- if envvars_file = httpd_envvars_file(options)
605
- command = ". '#{envvars_file}' && #{command}"
685
+
686
+ found_filenames = []
687
+
688
+ config.scan(/^[ \t]*(Include(Optional)?|ServerRoot)[ \t]+(.+?)[ \t]*$/i) do |match|
689
+ if match[0].downcase == "serverroot"
690
+ new_root = unescape_apache_config_value(match[2], options)
691
+ state[:root] = new_root if new_root
692
+ else
693
+ filename = unescape_apache_config_value(match[2], options)
694
+ next if filename.nil? || filename.empty?
695
+ if filename !~ /\A\//
696
+ # Not an absolute path. Infer from root.
697
+ filename = "#{state[:root]}/#{filename}"
698
+ end
699
+ expand_apache2_glob(filename).each do |filename2|
700
+ if !state[:files].has_key?(filename2)
701
+ state[:files][filename2] = true
702
+ scan_for_included_apache2_config_files(filename2, state, options)
703
+ end
704
+ end
606
705
  end
607
- return `#{command}`
706
+ end
707
+ end
708
+ private_class_method :scan_for_included_apache2_config_files
709
+
710
+ def self.expand_apache2_glob(glob)
711
+ if File.directory?(glob)
712
+ glob = glob.sub(/\/*$/, '')
713
+ result = Dir["#{glob}/**/*"]
608
714
  else
715
+ result = []
716
+ Dir[glob].each do |filename|
717
+ if File.directory?(filename)
718
+ result.concat(Dir["#{filename}/**/*"])
719
+ else
720
+ result << filename
721
+ end
722
+ end
723
+ end
724
+ result.reject! do |filename|
725
+ File.directory?(filename)
726
+ end
727
+ return result
728
+ end
729
+ private_class_method :expand_apache2_glob
730
+
731
+ def self.unescape_apache_config_value(value, options = nil)
732
+ if value =~ /^"(.*)"$/
733
+ value = unescape_c_string($1)
734
+ end
735
+ if value.include?("${")
736
+ log "Attempting to substitute environment variables in Apache config value #{value.inspect}..."
737
+ end
738
+ # The Apache config file supports environment variable
739
+ # substitution. Ubuntu uses this extensively.
740
+ value.gsub!(/\$\{(.+?)\}/) do |varname|
741
+ if substitution = httpd_infer_envvar($1, options)
742
+ log "Substituted \"#{varname}\" -> \"#{substitution}\""
743
+ substitution
744
+ else
745
+ log "Cannot substitute \"#{varname}\""
746
+ varname
747
+ end
748
+ end
749
+ if value.include?("${")
750
+ # We couldn't substitute everything.
609
751
  return nil
752
+ else
753
+ return value
754
+ end
755
+ end
756
+ private_class_method :unescape_apache_config_value
757
+
758
+ def self.unescape_c_string(s)
759
+ state = 0
760
+ res = ''
761
+ backslash = "\\"
762
+ s.each_char do |c|
763
+ case state
764
+ when 0
765
+ case c
766
+ when backslash then state = 1
767
+ else res << c
768
+ end
769
+ when 1
770
+ case c
771
+ when 'n' then res << "\n"; state = 0
772
+ when 't' then res << "\t"; state = 0
773
+ when backslash then res << backslash; state = 0
774
+ else res << backslash; res << c; state = 0
775
+ end
776
+ end
610
777
  end
778
+ return res
611
779
  end
780
+ private_class_method :unescape_c_string
612
781
  end
613
782
 
614
783
  end