rubygems-update 2.7.10 → 3.0.0

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

Potentially problematic release.


This version of rubygems-update might be problematic. Click here for more details.

Files changed (345) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +66 -0
  3. data/.travis.yml +22 -18
  4. data/CONTRIBUTING.md +141 -0
  5. data/History.txt +291 -14
  6. data/MAINTAINERS.txt +1 -0
  7. data/Manifest.txt +13 -9
  8. data/POLICIES.md +92 -0
  9. data/README.md +47 -26
  10. data/Rakefile +47 -207
  11. data/{UPGRADING.rdoc → UPGRADING.md} +31 -32
  12. data/appveyor.yml +20 -45
  13. data/bin/gem +1 -2
  14. data/bin/update_rubygems +2 -3
  15. data/bundler/CHANGELOG.md +54 -0
  16. data/bundler/bundler.gemspec +7 -1
  17. data/bundler/lib/bundler.rb +26 -8
  18. data/bundler/lib/bundler/build_metadata.rb +2 -2
  19. data/bundler/lib/bundler/cli.rb +63 -21
  20. data/bundler/lib/bundler/cli/add.rb +15 -5
  21. data/bundler/lib/bundler/cli/binstubs.rb +8 -2
  22. data/bundler/lib/bundler/cli/doctor.rb +47 -1
  23. data/bundler/lib/bundler/cli/install.rb +8 -5
  24. data/bundler/lib/bundler/cli/list.rb +41 -5
  25. data/bundler/lib/bundler/cli/outdated.rb +7 -1
  26. data/bundler/lib/bundler/cli/pristine.rb +4 -0
  27. data/bundler/lib/bundler/cli/remove.rb +18 -0
  28. data/bundler/lib/bundler/definition.rb +15 -16
  29. data/bundler/lib/bundler/dependency.rb +2 -2
  30. data/bundler/lib/bundler/dsl.rb +19 -3
  31. data/bundler/lib/bundler/feature_flag.rb +7 -0
  32. data/bundler/lib/bundler/gem_version_promoter.rb +4 -2
  33. data/bundler/lib/bundler/injector.rb +168 -9
  34. data/bundler/lib/bundler/installer.rb +29 -6
  35. data/bundler/lib/bundler/installer/parallel_installer.rb +5 -0
  36. data/bundler/lib/bundler/plugin.rb +10 -3
  37. data/bundler/lib/bundler/plugin/events.rb +61 -0
  38. data/bundler/lib/bundler/resolver.rb +2 -2
  39. data/bundler/lib/bundler/runtime.rb +8 -2
  40. data/bundler/lib/bundler/settings.rb +24 -3
  41. data/bundler/lib/bundler/settings/validator.rb +23 -0
  42. data/bundler/lib/bundler/shared_helpers.rb +19 -3
  43. data/bundler/lib/bundler/source.rb +9 -9
  44. data/bundler/lib/bundler/templates/newgem/lib/newgem.rb.tt +1 -0
  45. data/bundler/lib/bundler/version.rb +1 -1
  46. data/bundler/man/bundle-add.ronn +13 -2
  47. data/bundler/man/bundle-config.ronn +21 -0
  48. data/bundler/man/bundle-install.ronn +1 -1
  49. data/bundler/man/bundle-list.ronn +19 -1
  50. data/bundler/man/bundle-outdated.ronn +4 -0
  51. data/bundler/man/bundle-remove.ronn +23 -0
  52. data/bundler/man/bundle-update.ronn +1 -1
  53. data/lib/rubygems.rb +70 -96
  54. data/lib/rubygems/available_set.rb +1 -1
  55. data/lib/rubygems/basic_specification.rb +12 -12
  56. data/lib/rubygems/bundler_version_finder.rb +3 -3
  57. data/lib/rubygems/command.rb +22 -15
  58. data/lib/rubygems/command_manager.rb +20 -11
  59. data/lib/rubygems/commands/build_command.rb +27 -8
  60. data/lib/rubygems/commands/cert_command.rb +45 -24
  61. data/lib/rubygems/commands/check_command.rb +1 -1
  62. data/lib/rubygems/commands/cleanup_command.rb +14 -7
  63. data/lib/rubygems/commands/contents_command.rb +14 -15
  64. data/lib/rubygems/commands/dependency_command.rb +17 -17
  65. data/lib/rubygems/commands/environment_command.rb +20 -1
  66. data/lib/rubygems/commands/fetch_command.rb +2 -3
  67. data/lib/rubygems/commands/generate_index_command.rb +2 -3
  68. data/lib/rubygems/commands/help_command.rb +12 -13
  69. data/lib/rubygems/commands/info_command.rb +33 -0
  70. data/lib/rubygems/commands/install_command.rb +21 -17
  71. data/lib/rubygems/commands/list_command.rb +0 -1
  72. data/lib/rubygems/commands/lock_command.rb +3 -4
  73. data/lib/rubygems/commands/open_command.rb +16 -10
  74. data/lib/rubygems/commands/owner_command.rb +20 -11
  75. data/lib/rubygems/commands/pristine_command.rb +23 -16
  76. data/lib/rubygems/commands/push_command.rb +17 -8
  77. data/lib/rubygems/commands/query_command.rb +24 -24
  78. data/lib/rubygems/commands/rdoc_command.rb +3 -4
  79. data/lib/rubygems/commands/search_command.rb +0 -1
  80. data/lib/rubygems/commands/server_command.rb +1 -2
  81. data/lib/rubygems/commands/setup_command.rb +78 -38
  82. data/lib/rubygems/commands/signin_command.rb +2 -1
  83. data/lib/rubygems/commands/signout_command.rb +2 -2
  84. data/lib/rubygems/commands/sources_command.rb +11 -12
  85. data/lib/rubygems/commands/specification_command.rb +7 -7
  86. data/lib/rubygems/commands/uninstall_command.rb +41 -19
  87. data/lib/rubygems/commands/unpack_command.rb +16 -7
  88. data/lib/rubygems/commands/update_command.rb +28 -23
  89. data/lib/rubygems/commands/which_command.rb +4 -5
  90. data/lib/rubygems/commands/yank_command.rb +1 -2
  91. data/lib/rubygems/compatibility.rb +1 -21
  92. data/lib/rubygems/config_file.rb +36 -36
  93. data/lib/rubygems/core_ext/kernel_require.rb +6 -6
  94. data/lib/rubygems/core_ext/kernel_warn.rb +45 -0
  95. data/lib/rubygems/defaults.rb +31 -12
  96. data/lib/rubygems/dependency.rb +14 -14
  97. data/lib/rubygems/dependency_installer.rb +29 -31
  98. data/lib/rubygems/dependency_list.rb +8 -9
  99. data/lib/rubygems/deprecate.rb +2 -3
  100. data/lib/rubygems/doctor.rb +5 -6
  101. data/lib/rubygems/errors.rb +3 -3
  102. data/lib/rubygems/exceptions.rb +11 -4
  103. data/lib/rubygems/ext.rb +0 -1
  104. data/lib/rubygems/ext/build_error.rb +0 -1
  105. data/lib/rubygems/ext/builder.rb +50 -23
  106. data/lib/rubygems/ext/cmake_builder.rb +2 -2
  107. data/lib/rubygems/ext/configure_builder.rb +2 -3
  108. data/lib/rubygems/ext/ext_conf_builder.rb +8 -7
  109. data/lib/rubygems/ext/rake_builder.rb +16 -18
  110. data/lib/rubygems/gem_runner.rb +2 -2
  111. data/lib/rubygems/gemcutter_utilities.rb +40 -13
  112. data/lib/rubygems/indexer.rb +19 -12
  113. data/lib/rubygems/install_default_message.rb +0 -1
  114. data/lib/rubygems/install_message.rb +0 -1
  115. data/lib/rubygems/install_update_options.rb +2 -28
  116. data/lib/rubygems/installer.rb +95 -75
  117. data/lib/rubygems/installer_test_case.rb +0 -14
  118. data/lib/rubygems/local_remote_options.rb +5 -4
  119. data/lib/rubygems/mock_gem_ui.rb +3 -4
  120. data/lib/rubygems/name_tuple.rb +4 -4
  121. data/lib/rubygems/package.rb +90 -73
  122. data/lib/rubygems/package/digest_io.rb +3 -4
  123. data/lib/rubygems/package/file_source.rb +3 -4
  124. data/lib/rubygems/package/io_source.rb +1 -2
  125. data/lib/rubygems/package/old.rb +8 -16
  126. data/lib/rubygems/package/source.rb +0 -1
  127. data/lib/rubygems/package/tar_header.rb +2 -2
  128. data/lib/rubygems/package/tar_reader.rb +2 -4
  129. data/lib/rubygems/package/tar_reader/entry.rb +20 -4
  130. data/lib/rubygems/package/tar_test_case.rb +2 -8
  131. data/lib/rubygems/package/tar_writer.rb +13 -15
  132. data/lib/rubygems/package_task.rb +0 -1
  133. data/lib/rubygems/path_support.rb +16 -6
  134. data/lib/rubygems/platform.rb +4 -5
  135. data/lib/rubygems/psych_tree.rb +1 -1
  136. data/lib/rubygems/rdoc.rb +0 -311
  137. data/lib/rubygems/remote_fetcher.rb +34 -48
  138. data/lib/rubygems/request.rb +16 -15
  139. data/lib/rubygems/request/connection_pools.rb +24 -13
  140. data/lib/rubygems/request/http_pool.rb +3 -4
  141. data/lib/rubygems/request/https_pool.rb +1 -3
  142. data/lib/rubygems/request_set.rb +52 -25
  143. data/lib/rubygems/request_set/gem_dependency_api.rb +36 -40
  144. data/lib/rubygems/request_set/lockfile.rb +12 -12
  145. data/lib/rubygems/request_set/lockfile/parser.rb +18 -29
  146. data/lib/rubygems/request_set/lockfile/tokenizer.rb +9 -9
  147. data/lib/rubygems/requirement.rb +16 -16
  148. data/lib/rubygems/resolver.rb +10 -15
  149. data/lib/rubygems/resolver/activation_request.rb +6 -6
  150. data/lib/rubygems/resolver/api_set.rb +5 -6
  151. data/lib/rubygems/resolver/api_specification.rb +2 -3
  152. data/lib/rubygems/resolver/best_set.rb +5 -6
  153. data/lib/rubygems/resolver/composed_set.rb +5 -6
  154. data/lib/rubygems/resolver/conflict.rb +5 -5
  155. data/lib/rubygems/resolver/current_set.rb +1 -2
  156. data/lib/rubygems/resolver/dependency_request.rb +4 -4
  157. data/lib/rubygems/resolver/git_set.rb +5 -6
  158. data/lib/rubygems/resolver/git_specification.rb +4 -5
  159. data/lib/rubygems/resolver/index_set.rb +5 -6
  160. data/lib/rubygems/resolver/index_specification.rb +3 -4
  161. data/lib/rubygems/resolver/installed_specification.rb +3 -4
  162. data/lib/rubygems/resolver/installer_set.rb +12 -12
  163. data/lib/rubygems/resolver/local_specification.rb +1 -2
  164. data/lib/rubygems/resolver/lock_set.rb +5 -6
  165. data/lib/rubygems/resolver/lock_specification.rb +7 -8
  166. data/lib/rubygems/resolver/requirement_list.rb +1 -1
  167. data/lib/rubygems/resolver/set.rb +2 -2
  168. data/lib/rubygems/resolver/source_set.rb +4 -5
  169. data/lib/rubygems/resolver/spec_specification.rb +1 -2
  170. data/lib/rubygems/resolver/specification.rb +10 -7
  171. data/lib/rubygems/resolver/stats.rb +1 -1
  172. data/lib/rubygems/resolver/vendor_set.rb +4 -5
  173. data/lib/rubygems/resolver/vendor_specification.rb +2 -3
  174. data/lib/rubygems/safe_yaml.rb +18 -10
  175. data/lib/rubygems/security.rb +21 -22
  176. data/lib/rubygems/security/policies.rb +1 -2
  177. data/lib/rubygems/security/policy.rb +25 -25
  178. data/lib/rubygems/security/signer.rb +72 -24
  179. data/lib/rubygems/security/trust_dir.rb +10 -10
  180. data/lib/rubygems/server.rb +21 -21
  181. data/lib/rubygems/source.rb +16 -25
  182. data/lib/rubygems/source/git.rb +9 -10
  183. data/lib/rubygems/source/installed.rb +3 -4
  184. data/lib/rubygems/source/local.rb +7 -7
  185. data/lib/rubygems/source/lock.rb +4 -4
  186. data/lib/rubygems/source/specific_file.rb +5 -5
  187. data/lib/rubygems/source/vendor.rb +2 -3
  188. data/lib/rubygems/source_list.rb +2 -2
  189. data/lib/rubygems/source_local.rb +0 -1
  190. data/lib/rubygems/spec_fetcher.rb +5 -6
  191. data/lib/rubygems/specification.rb +199 -536
  192. data/lib/rubygems/specification_policy.rb +407 -0
  193. data/lib/rubygems/stub_specification.rb +11 -15
  194. data/lib/rubygems/test_case.rb +141 -66
  195. data/lib/rubygems/test_utilities.rb +20 -35
  196. data/lib/rubygems/text.rb +6 -6
  197. data/lib/rubygems/uninstaller.rb +37 -26
  198. data/lib/rubygems/uri_formatter.rb +1 -2
  199. data/lib/rubygems/user_interaction.rb +38 -93
  200. data/lib/rubygems/util.rb +20 -14
  201. data/lib/rubygems/util/licenses.rb +27 -1
  202. data/lib/rubygems/util/list.rb +1 -1
  203. data/lib/rubygems/validator.rb +4 -5
  204. data/lib/rubygems/version.rb +15 -15
  205. data/lib/rubygems/version_option.rb +2 -3
  206. data/rubygems-update.gemspec +43 -0
  207. data/setup.rb +2 -8
  208. data/test/rubygems/rubygems_plugin.rb +0 -1
  209. data/test/rubygems/simple_gem.rb +1 -1
  210. data/test/rubygems/test_config.rb +7 -2
  211. data/test/rubygems/test_gem.rb +161 -130
  212. data/test/rubygems/test_gem_command.rb +0 -1
  213. data/test/rubygems/test_gem_command_manager.rb +8 -3
  214. data/test/rubygems/test_gem_commands_build_command.rb +219 -15
  215. data/test/rubygems/test_gem_commands_cert_command.rb +69 -8
  216. data/test/rubygems/test_gem_commands_check_command.rb +1 -1
  217. data/test/rubygems/test_gem_commands_cleanup_command.rb +27 -1
  218. data/test/rubygems/test_gem_commands_contents_command.rb +1 -2
  219. data/test/rubygems/test_gem_commands_dependency_command.rb +33 -34
  220. data/test/rubygems/test_gem_commands_environment_command.rb +1 -0
  221. data/test/rubygems/test_gem_commands_fetch_command.rb +0 -1
  222. data/test/rubygems/test_gem_commands_generate_index_command.rb +0 -1
  223. data/test/rubygems/test_gem_commands_help_command.rb +7 -4
  224. data/test/rubygems/test_gem_commands_info_command.rb +44 -0
  225. data/test/rubygems/test_gem_commands_install_command.rb +79 -12
  226. data/test/rubygems/test_gem_commands_lock_command.rb +0 -1
  227. data/test/rubygems/test_gem_commands_open_command.rb +29 -0
  228. data/test/rubygems/test_gem_commands_outdated_command.rb +0 -1
  229. data/test/rubygems/test_gem_commands_owner_command.rb +93 -57
  230. data/test/rubygems/test_gem_commands_pristine_command.rb +65 -30
  231. data/test/rubygems/test_gem_commands_push_command.rb +39 -0
  232. data/test/rubygems/test_gem_commands_query_command.rb +102 -100
  233. data/test/rubygems/test_gem_commands_search_command.rb +0 -1
  234. data/test/rubygems/test_gem_commands_server_command.rb +0 -1
  235. data/test/rubygems/test_gem_commands_setup_command.rb +39 -8
  236. data/test/rubygems/test_gem_commands_signin_command.rb +1 -1
  237. data/test/rubygems/test_gem_commands_sources_command.rb +0 -1
  238. data/test/rubygems/test_gem_commands_specification_command.rb +2 -3
  239. data/test/rubygems/test_gem_commands_stale_command.rb +3 -2
  240. data/test/rubygems/test_gem_commands_uninstall_command.rb +81 -7
  241. data/test/rubygems/test_gem_commands_unpack_command.rb +17 -1
  242. data/test/rubygems/test_gem_commands_update_command.rb +19 -2
  243. data/test/rubygems/test_gem_commands_which_command.rb +0 -1
  244. data/test/rubygems/test_gem_commands_yank_command.rb +0 -1
  245. data/test/rubygems/test_gem_config_file.rb +4 -2
  246. data/test/rubygems/test_gem_dependency.rb +0 -1
  247. data/test/rubygems/test_gem_dependency_installer.rb +8 -5
  248. data/test/rubygems/test_gem_dependency_list.rb +6 -7
  249. data/test/rubygems/test_gem_dependency_resolution_error.rb +0 -1
  250. data/test/rubygems/test_gem_doctor.rb +1 -2
  251. data/test/rubygems/test_gem_ext_builder.rb +10 -23
  252. data/test/rubygems/test_gem_ext_cmake_builder.rb +5 -4
  253. data/test/rubygems/test_gem_ext_configure_builder.rb +3 -3
  254. data/test/rubygems/test_gem_ext_ext_conf_builder.rb +8 -9
  255. data/test/rubygems/test_gem_ext_rake_builder.rb +20 -5
  256. data/test/rubygems/test_gem_gem_runner.rb +0 -1
  257. data/test/rubygems/test_gem_gemcutter_utilities.rb +32 -6
  258. data/test/rubygems/test_gem_impossible_dependencies_error.rb +0 -1
  259. data/test/rubygems/test_gem_indexer.rb +1 -2
  260. data/test/rubygems/test_gem_install_update_options.rb +1 -20
  261. data/test/rubygems/test_gem_installer.rb +69 -203
  262. data/test/rubygems/test_gem_local_remote_options.rb +3 -3
  263. data/test/rubygems/test_gem_name_tuple.rb +0 -1
  264. data/test/rubygems/test_gem_package.rb +59 -50
  265. data/test/rubygems/test_gem_package_old.rb +0 -1
  266. data/test/rubygems/test_gem_package_tar_header.rb +1 -2
  267. data/test/rubygems/test_gem_package_tar_reader.rb +0 -1
  268. data/test/rubygems/test_gem_package_tar_reader_entry.rb +11 -0
  269. data/test/rubygems/test_gem_package_tar_writer.rb +40 -7
  270. data/test/rubygems/test_gem_package_task.rb +2 -2
  271. data/test/rubygems/test_gem_path_support.rb +28 -11
  272. data/test/rubygems/test_gem_platform.rb +4 -5
  273. data/test/rubygems/test_gem_rdoc.rb +1 -2
  274. data/test/rubygems/test_gem_remote_fetcher.rb +111 -130
  275. data/test/rubygems/test_gem_request.rb +5 -5
  276. data/test/rubygems/test_gem_request_connection_pools.rb +24 -3
  277. data/test/rubygems/test_gem_request_set.rb +5 -5
  278. data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +2 -7
  279. data/test/rubygems/test_gem_request_set_lockfile.rb +1 -2
  280. data/test/rubygems/test_gem_request_set_lockfile_parser.rb +4 -9
  281. data/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb +1 -1
  282. data/test/rubygems/test_gem_requirement.rb +18 -4
  283. data/test/rubygems/test_gem_resolver.rb +13 -17
  284. data/test/rubygems/test_gem_resolver_activation_request.rb +0 -1
  285. data/test/rubygems/test_gem_resolver_api_set.rb +0 -1
  286. data/test/rubygems/test_gem_resolver_api_specification.rb +0 -1
  287. data/test/rubygems/test_gem_resolver_best_set.rb +0 -1
  288. data/test/rubygems/test_gem_resolver_composed_set.rb +0 -1
  289. data/test/rubygems/test_gem_resolver_conflict.rb +0 -1
  290. data/test/rubygems/test_gem_resolver_dependency_request.rb +0 -1
  291. data/test/rubygems/test_gem_resolver_git_set.rb +0 -1
  292. data/test/rubygems/test_gem_resolver_git_specification.rb +0 -1
  293. data/test/rubygems/test_gem_resolver_index_set.rb +0 -1
  294. data/test/rubygems/test_gem_resolver_index_specification.rb +0 -1
  295. data/test/rubygems/test_gem_resolver_installed_specification.rb +0 -1
  296. data/test/rubygems/test_gem_resolver_installer_set.rb +2 -3
  297. data/test/rubygems/test_gem_resolver_local_specification.rb +0 -1
  298. data/test/rubygems/test_gem_resolver_lock_set.rb +0 -1
  299. data/test/rubygems/test_gem_resolver_lock_specification.rb +0 -1
  300. data/test/rubygems/test_gem_resolver_requirement_list.rb +0 -1
  301. data/test/rubygems/test_gem_resolver_specification.rb +1 -2
  302. data/test/rubygems/test_gem_resolver_vendor_set.rb +0 -1
  303. data/test/rubygems/test_gem_resolver_vendor_specification.rb +0 -1
  304. data/test/rubygems/test_gem_security.rb +1 -3
  305. data/test/rubygems/test_gem_security_policy.rb +4 -5
  306. data/test/rubygems/test_gem_security_signer.rb +4 -3
  307. data/test/rubygems/test_gem_security_trust_dir.rb +1 -2
  308. data/test/rubygems/test_gem_server.rb +4 -4
  309. data/test/rubygems/test_gem_source.rb +0 -13
  310. data/test/rubygems/test_gem_source_fetch_problem.rb +0 -1
  311. data/test/rubygems/test_gem_source_git.rb +0 -1
  312. data/test/rubygems/test_gem_source_installed.rb +0 -1
  313. data/test/rubygems/test_gem_source_lock.rb +0 -1
  314. data/test/rubygems/test_gem_source_vendor.rb +0 -1
  315. data/test/rubygems/test_gem_spec_fetcher.rb +0 -1
  316. data/test/rubygems/test_gem_specification.rb +334 -198
  317. data/test/rubygems/test_gem_stream_ui.rb +13 -30
  318. data/test/rubygems/test_gem_stub_specification.rb +0 -2
  319. data/test/rubygems/test_gem_text.rb +4 -5
  320. data/test/rubygems/test_gem_uninstaller.rb +21 -1
  321. data/test/rubygems/test_gem_unsatisfiable_dependency_error.rb +0 -1
  322. data/test/rubygems/test_gem_uri_formatter.rb +0 -1
  323. data/test/rubygems/test_gem_util.rb +6 -11
  324. data/test/rubygems/test_gem_validator.rb +0 -1
  325. data/test/rubygems/test_gem_version.rb +11 -11
  326. data/test/rubygems/test_gem_version_option.rb +0 -1
  327. data/test/rubygems/test_remote_fetch_error.rb +0 -1
  328. data/test/rubygems/test_require.rb +67 -52
  329. data/util/CL2notes +1 -2
  330. data/util/ci +15 -12
  331. data/util/create_certs.rb +6 -7
  332. data/util/create_encrypted_key.rb +0 -1
  333. data/util/patch_with_prs.rb +1 -1
  334. data/util/rubocop +8 -0
  335. data/util/update_bundled_ca_certificates.rb +12 -13
  336. data/util/update_changelog.rb +1 -1
  337. metadata +61 -53
  338. data/.autotest +0 -71
  339. data/.document +0 -5
  340. data/CONTRIBUTING.rdoc +0 -130
  341. data/CVE-2013-4287.txt +0 -35
  342. data/CVE-2013-4363.txt +0 -45
  343. data/CVE-2015-3900.txt +0 -40
  344. data/POLICIES.rdoc +0 -74
  345. data/test/rubygems/fix_openssl_warnings.rb +0 -13
@@ -24,7 +24,7 @@ class Gem::Security::Policy
24
24
  # Create a new Gem::Security::Policy object with the given mode and
25
25
  # options.
26
26
 
27
- def initialize name, policy = {}, opt = {}
27
+ def initialize(name, policy = {}, opt = {})
28
28
  require 'openssl'
29
29
 
30
30
  @name = name
@@ -55,7 +55,7 @@ class Gem::Security::Policy
55
55
  # Verifies each certificate in +chain+ has signed the following certificate
56
56
  # and is valid for the given +time+.
57
57
 
58
- def check_chain chain, time
58
+ def check_chain(chain, time)
59
59
  raise Gem::Security::Exception, 'missing signing chain' unless chain
60
60
  raise Gem::Security::Exception, 'empty signing chain' if chain.empty?
61
61
 
@@ -74,7 +74,7 @@ class Gem::Security::Policy
74
74
  # Verifies that +data+ matches the +signature+ created by +public_key+ and
75
75
  # the +digest+ algorithm.
76
76
 
77
- def check_data public_key, digest, signature, data
77
+ def check_data(public_key, digest, signature, data)
78
78
  raise Gem::Security::Exception, "invalid signature" unless
79
79
  public_key.verify digest.new, signature, data.digest
80
80
 
@@ -85,22 +85,22 @@ class Gem::Security::Policy
85
85
  # Ensures that +signer+ is valid for +time+ and was signed by the +issuer+.
86
86
  # If the +issuer+ is +nil+ no verification is performed.
87
87
 
88
- def check_cert signer, issuer, time
88
+ def check_cert(signer, issuer, time)
89
89
  raise Gem::Security::Exception, 'missing signing certificate' unless
90
90
  signer
91
91
 
92
92
  message = "certificate #{signer.subject}"
93
93
 
94
- if not_before = signer.not_before and not_before > time then
94
+ if not_before = signer.not_before and not_before > time
95
95
  raise Gem::Security::Exception,
96
96
  "#{message} not valid before #{not_before}"
97
97
  end
98
98
 
99
- if not_after = signer.not_after and not_after < time then
99
+ if not_after = signer.not_after and not_after < time
100
100
  raise Gem::Security::Exception, "#{message} not valid after #{not_after}"
101
101
  end
102
102
 
103
- if issuer and not signer.verify issuer.public_key then
103
+ if issuer and not signer.verify issuer.public_key
104
104
  raise Gem::Security::Exception,
105
105
  "#{message} was not issued by #{issuer.subject}"
106
106
  end
@@ -111,8 +111,8 @@ class Gem::Security::Policy
111
111
  ##
112
112
  # Ensures the public key of +key+ matches the public key in +signer+
113
113
 
114
- def check_key signer, key
115
- unless signer and key then
114
+ def check_key(signer, key)
115
+ unless signer and key
116
116
  return true unless @only_signed
117
117
 
118
118
  raise Gem::Security::Exception, 'missing key or signature'
@@ -129,7 +129,7 @@ class Gem::Security::Policy
129
129
  # Ensures the root certificate in +chain+ is self-signed and valid for
130
130
  # +time+.
131
131
 
132
- def check_root chain, time
132
+ def check_root(chain, time)
133
133
  raise Gem::Security::Exception, 'missing signing chain' unless chain
134
134
 
135
135
  root = chain.first
@@ -148,7 +148,7 @@ class Gem::Security::Policy
148
148
  # Ensures the root of +chain+ has a trusted certificate in +trust_dir+ and
149
149
  # the digests of the two certificates match according to +digester+
150
150
 
151
- def check_trust chain, digester, trust_dir
151
+ def check_trust(chain, digester, trust_dir)
152
152
  raise Gem::Security::Exception, 'missing signing chain' unless chain
153
153
 
154
154
  root = chain.first
@@ -157,7 +157,7 @@ class Gem::Security::Policy
157
157
 
158
158
  path = Gem::Security.trust_dir.cert_path root
159
159
 
160
- unless File.exist? path then
160
+ unless File.exist? path
161
161
  message = "root cert #{root.subject} is not trusted".dup
162
162
 
163
163
  message << " (root of signing cert #{chain.last.subject})" if
@@ -183,7 +183,7 @@ class Gem::Security::Policy
183
183
  ##
184
184
  # Extracts the email or subject from +certificate+
185
185
 
186
- def subject certificate # :nodoc:
186
+ def subject(certificate) # :nodoc:
187
187
  certificate.extensions.each do |extension|
188
188
  next unless extension.oid == 'subjectAltName'
189
189
 
@@ -196,9 +196,9 @@ class Gem::Security::Policy
196
196
  def inspect # :nodoc:
197
197
  ("[Policy: %s - data: %p signer: %p chain: %p root: %p " +
198
198
  "signed-only: %p trusted-only: %p]") % [
199
- @name, @verify_chain, @verify_data, @verify_root, @verify_signer,
200
- @only_signed, @only_trusted,
201
- ]
199
+ @name, @verify_chain, @verify_data, @verify_root, @verify_signer,
200
+ @only_signed, @only_trusted,
201
+ ]
202
202
  end
203
203
 
204
204
  ##
@@ -208,13 +208,13 @@ class Gem::Security::Policy
208
208
  #
209
209
  # If +key+ is given it is used to validate the signing certificate.
210
210
 
211
- def verify chain, key = nil, digests = {}, signatures = {},
212
- full_name = '(unknown)'
213
- if signatures.empty? then
214
- if @only_signed then
211
+ def verify(chain, key = nil, digests = {}, signatures = {},
212
+ full_name = '(unknown)')
213
+ if signatures.empty?
214
+ if @only_signed
215
215
  raise Gem::Security::Exception,
216
216
  "unsigned gems are not allowed by the #{name} policy"
217
- elsif digests.empty? then
217
+ elsif digests.empty?
218
218
  # lack of signatures is irrelevant if there is nothing to check
219
219
  # against
220
220
  else
@@ -232,7 +232,7 @@ class Gem::Security::Policy
232
232
  file_digests.values.first.name == Gem::Security::DIGEST_NAME
233
233
  end
234
234
 
235
- if @verify_data then
235
+ if @verify_data
236
236
  raise Gem::Security::Exception, 'no digests provided (probable bug)' if
237
237
  signer_digests.nil? or signer_digests.empty?
238
238
  else
@@ -249,9 +249,9 @@ class Gem::Security::Policy
249
249
 
250
250
  check_root chain, time if @verify_root
251
251
 
252
- if @only_trusted then
252
+ if @only_trusted
253
253
  check_trust chain, digester, trust_dir
254
- elsif signatures.empty? and digests.empty? then
254
+ elsif signatures.empty? and digests.empty?
255
255
  # trust is irrelevant if there's no signatures to verify
256
256
  else
257
257
  alert_warning "#{subject signer} is not trusted for #{full_name}"
@@ -280,7 +280,7 @@ class Gem::Security::Policy
280
280
  # Extracts the certificate chain from the +spec+ and calls #verify to ensure
281
281
  # the signatures and certificate chain is valid according to the policy..
282
282
 
283
- def verify_signatures spec, digests, signatures
283
+ def verify_signatures(spec, digests, signatures)
284
284
  chain = spec.cert_chain.map do |cert_pem|
285
285
  OpenSSL::X509::Certificate.new cert_pem
286
286
  end
@@ -2,8 +2,12 @@
2
2
  ##
3
3
  # Basic OpenSSL-based package signing class.
4
4
 
5
+ require "rubygems/user_interaction"
6
+
5
7
  class Gem::Security::Signer
6
8
 
9
+ include Gem::UserInteraction
10
+
7
11
  ##
8
12
  # The chain of certificates for signing including the signing certificate
9
13
 
@@ -25,21 +29,54 @@ class Gem::Security::Signer
25
29
 
26
30
  attr_reader :digest_name # :nodoc:
27
31
 
32
+ ##
33
+ # Gem::Security::Signer options
34
+
35
+ attr_reader :options
36
+
37
+ DEFAULT_OPTIONS = {
38
+ expiration_length_days: 365
39
+ }.freeze
40
+
41
+ ##
42
+ # Attemps to re-sign an expired cert with a given private key
43
+ def self.re_sign_cert(expired_cert, expired_cert_path, private_key)
44
+ return unless expired_cert.not_after < Time.now
45
+
46
+ expiry = expired_cert.not_after.strftime('%Y%m%d%H%M%S')
47
+ expired_cert_file = "#{File.basename(expired_cert_path)}.expired.#{expiry}"
48
+ new_expired_cert_path = File.join(Gem.user_home, ".gem", expired_cert_file)
49
+
50
+ Gem::Security.write(expired_cert, new_expired_cert_path)
51
+
52
+ re_signed_cert = Gem::Security.re_sign(
53
+ expired_cert,
54
+ private_key,
55
+ (Gem::Security::ONE_DAY * Gem.configuration.cert_expiration_length_days)
56
+ )
57
+
58
+ Gem::Security.write(re_signed_cert, expired_cert_path)
59
+
60
+ yield(expired_cert_path, new_expired_cert_path) if block_given?
61
+ end
62
+
28
63
  ##
29
64
  # Creates a new signer with an RSA +key+ or path to a key, and a certificate
30
65
  # +chain+ containing X509 certificates, encoding certificates or paths to
31
66
  # certificates.
32
67
 
33
- def initialize key, cert_chain, passphrase = nil
68
+ def initialize(key, cert_chain, passphrase = nil, options = {})
34
69
  @cert_chain = cert_chain
35
70
  @key = key
71
+ @passphrase = passphrase
72
+ @options = DEFAULT_OPTIONS.merge(options)
36
73
 
37
- unless @key then
74
+ unless @key
38
75
  default_key = File.join Gem.default_key_path
39
76
  @key = default_key if File.exist? default_key
40
77
  end
41
78
 
42
- unless @cert_chain then
79
+ unless @cert_chain
43
80
  default_cert = File.join Gem.default_cert_path
44
81
  @cert_chain = [default_cert] if File.exist? default_cert
45
82
  end
@@ -47,10 +84,12 @@ class Gem::Security::Signer
47
84
  @digest_algorithm = Gem::Security::DIGEST_ALGORITHM
48
85
  @digest_name = Gem::Security::DIGEST_NAME
49
86
 
50
- @key = OpenSSL::PKey::RSA.new File.read(@key), passphrase if
51
- @key and not OpenSSL::PKey::RSA === @key
87
+ if @key && !@key.is_a?(OpenSSL::PKey::RSA)
88
+ @passphrase ||= ask_for_password("Enter PEM pass phrase:")
89
+ @key = OpenSSL::PKey::RSA.new(File.read(@key), @passphrase)
90
+ end
52
91
 
53
- if @cert_chain then
92
+ if @cert_chain
54
93
  @cert_chain = @cert_chain.compact.map do |cert|
55
94
  next cert if OpenSSL::X509::Certificate === cert
56
95
 
@@ -67,10 +106,10 @@ class Gem::Security::Signer
67
106
  # Extracts the full name of +cert+. If the certificate has a subjectAltName
68
107
  # this value is preferred, otherwise the subject is used.
69
108
 
70
- def extract_name cert # :nodoc:
109
+ def extract_name(cert) # :nodoc:
71
110
  subject_alt_name = cert.extensions.find { |e| 'subjectAltName' == e.oid }
72
111
 
73
- if subject_alt_name then
112
+ if subject_alt_name
74
113
  /\Aemail:/ =~ subject_alt_name.value
75
114
 
76
115
  $' || subject_alt_name.value
@@ -99,13 +138,15 @@ class Gem::Security::Signer
99
138
  ##
100
139
  # Sign data with given digest algorithm
101
140
 
102
- def sign data
141
+ def sign(data)
103
142
  return unless @key
104
143
 
105
144
  raise Gem::Security::Exception, 'no certs provided' if @cert_chain.empty?
106
145
 
107
- if @cert_chain.length == 1 and @cert_chain.last.not_after < Time.now then
108
- re_sign_key
146
+ if @cert_chain.length == 1 and @cert_chain.last.not_after < Time.now
147
+ re_sign_key(
148
+ expiration_length: (Gem::Security::ONE_DAY * options[:expiration_length_days])
149
+ )
109
150
  end
110
151
 
111
152
  full_name = extract_name @cert_chain.last
@@ -121,6 +162,7 @@ class Gem::Security::Signer
121
162
  # The key will be re-signed if:
122
163
  # * The expired certificate is self-signed
123
164
  # * The expired certificate is saved at ~/.gem/gem-public_cert.pem
165
+ # and the private key is saved at ~/.gem/gem-private_key.pem
124
166
  # * There is no file matching the expiry date at
125
167
  # ~/.gem/gem-public_cert.pem.expired.%Y%m%d%H%M%S
126
168
  #
@@ -128,25 +170,32 @@ class Gem::Security::Signer
128
170
  # be saved as ~/.gem/gem-public_cert.pem.expired.%Y%m%d%H%M%S where the
129
171
  # expiry time (not after) is used for the timestamp.
130
172
 
131
- def re_sign_key # :nodoc:
173
+ def re_sign_key(expiration_length: Gem::Security::ONE_YEAR) # :nodoc:
132
174
  old_cert = @cert_chain.last
133
175
 
134
- disk_cert_path = File.join Gem.default_cert_path
135
- disk_cert = File.read disk_cert_path rescue nil
136
- disk_key =
137
- File.read File.join(Gem.default_key_path) rescue nil
176
+ disk_cert_path = File.join(Gem.default_cert_path)
177
+ disk_cert = File.read(disk_cert_path) rescue nil
138
178
 
139
- if disk_key == @key.to_pem and disk_cert == old_cert.to_pem then
140
- expiry = old_cert.not_after.strftime '%Y%m%d%H%M%S'
179
+ disk_key_path = File.join(Gem.default_key_path)
180
+ disk_key =
181
+ OpenSSL::PKey::RSA.new(File.read(disk_key_path), @passphrase) rescue nil
182
+
183
+ return unless disk_key
184
+
185
+ if disk_key.to_pem == @key.to_pem && disk_cert == old_cert.to_pem
186
+ expiry = old_cert.not_after.strftime('%Y%m%d%H%M%S')
141
187
  old_cert_file = "gem-public_cert.pem.expired.#{expiry}"
142
- old_cert_path = File.join Gem.user_home, ".gem", old_cert_file
188
+ old_cert_path = File.join(Gem.user_home, ".gem", old_cert_file)
143
189
 
144
- unless File.exist? old_cert_path then
145
- Gem::Security.write old_cert, old_cert_path
190
+ unless File.exist?(old_cert_path)
191
+ Gem::Security.write(old_cert, old_cert_path)
146
192
 
147
- cert = Gem::Security.re_sign old_cert, @key
193
+ cert = Gem::Security.re_sign(old_cert, @key, expiration_length)
148
194
 
149
- Gem::Security.write cert, disk_cert_path
195
+ Gem::Security.write(cert, disk_cert_path)
196
+
197
+ alert("Your cert: #{disk_cert_path} has been auto re-signed with the key: #{disk_key_path}")
198
+ alert("Your expired cert will be located at: #{old_cert_path}")
150
199
 
151
200
  @cert_chain = [cert]
152
201
  end
@@ -154,4 +203,3 @@ class Gem::Security::Signer
154
203
  end
155
204
 
156
205
  end
157
-
@@ -11,7 +11,7 @@ class Gem::Security::TrustDir
11
11
  DEFAULT_PERMISSIONS = {
12
12
  :trust_dir => 0700,
13
13
  :trusted_cert => 0600,
14
- }
14
+ }.freeze
15
15
 
16
16
  ##
17
17
  # The directory where trusted certificates will be stored.
@@ -22,7 +22,7 @@ class Gem::Security::TrustDir
22
22
  # Creates a new TrustDir using +dir+ where the directory and file
23
23
  # permissions will be checked according to +permissions+
24
24
 
25
- def initialize dir, permissions = DEFAULT_PERMISSIONS
25
+ def initialize(dir, permissions = DEFAULT_PERMISSIONS)
26
26
  @dir = dir
27
27
  @permissions = permissions
28
28
 
@@ -32,7 +32,7 @@ class Gem::Security::TrustDir
32
32
  ##
33
33
  # Returns the path to the trusted +certificate+
34
34
 
35
- def cert_path certificate
35
+ def cert_path(certificate)
36
36
  name_path certificate.subject
37
37
  end
38
38
 
@@ -59,7 +59,7 @@ class Gem::Security::TrustDir
59
59
  # Returns the issuer certificate of the given +certificate+ if it exists in
60
60
  # the trust directory.
61
61
 
62
- def issuer_of certificate
62
+ def issuer_of(certificate)
63
63
  path = name_path certificate.issuer
64
64
 
65
65
  return unless File.exist? path
@@ -70,7 +70,7 @@ class Gem::Security::TrustDir
70
70
  ##
71
71
  # Returns the path to the trusted certificate with the given ASN.1 +name+
72
72
 
73
- def name_path name
73
+ def name_path(name)
74
74
  digest = @digester.hexdigest name.to_s
75
75
 
76
76
  File.join @dir, "cert-#{digest}.pem"
@@ -79,7 +79,7 @@ class Gem::Security::TrustDir
79
79
  ##
80
80
  # Loads the given +certificate_file+
81
81
 
82
- def load_certificate certificate_file
82
+ def load_certificate(certificate_file)
83
83
  pem = File.read certificate_file
84
84
 
85
85
  OpenSSL::X509::Certificate.new pem
@@ -88,13 +88,14 @@ class Gem::Security::TrustDir
88
88
  ##
89
89
  # Add a certificate to trusted certificate list.
90
90
 
91
- def trust_cert certificate
91
+ def trust_cert(certificate)
92
92
  verify
93
93
 
94
94
  destination = cert_path certificate
95
95
 
96
- File.open destination, 'wb', @permissions[:trusted_cert] do |io|
96
+ File.open destination, 'wb', 0600 do |io|
97
97
  io.write certificate.to_pem
98
+ io.chmod(@permissions[:trusted_cert])
98
99
  end
99
100
  end
100
101
 
@@ -104,7 +105,7 @@ class Gem::Security::TrustDir
104
105
  # permissions.
105
106
 
106
107
  def verify
107
- if File.exist? @dir then
108
+ if File.exist? @dir
108
109
  raise Gem::Security::Exception,
109
110
  "trust directory #{@dir} is not a directory" unless
110
111
  File.directory? @dir
@@ -116,4 +117,3 @@ class Gem::Security::TrustDir
116
117
  end
117
118
 
118
119
  end
119
-
@@ -35,7 +35,7 @@ class Gem::Server
35
35
  include ERB::Util
36
36
  include Gem::UserInteraction
37
37
 
38
- SEARCH = <<-ERB
38
+ SEARCH = <<-ERB.freeze
39
39
  <form class="headerSearch" name="headerSearchForm" method="get" action="/rdoc">
40
40
  <div id="search" style="float:right">
41
41
  <label for="q">Filter/Search</label>
@@ -45,7 +45,7 @@ class Gem::Server
45
45
  </form>
46
46
  ERB
47
47
 
48
- DOC_TEMPLATE = <<-'ERB'
48
+ DOC_TEMPLATE = <<-'ERB'.freeze
49
49
  <?xml version="1.0" encoding="iso-8859-1"?>
50
50
  <!DOCTYPE html
51
51
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
@@ -129,7 +129,7 @@ class Gem::Server
129
129
  ERB
130
130
 
131
131
  # CSS is copy & paste from rdoc-style.css, RDoc V1.0.1 - 20041108
132
- RDOC_CSS = <<-CSS
132
+ RDOC_CSS = <<-CSS.freeze
133
133
  body {
134
134
  font-family: Verdana,Arial,Helvetica,sans-serif;
135
135
  font-size: 90%;
@@ -339,7 +339,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
339
339
  .ruby-value { color: #7fffd4; background: transparent; }
340
340
  CSS
341
341
 
342
- RDOC_NO_DOCUMENTATION = <<-'ERB'
342
+ RDOC_NO_DOCUMENTATION = <<-'ERB'.freeze
343
343
  <?xml version="1.0" encoding="iso-8859-1"?>
344
344
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
345
345
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@@ -373,7 +373,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
373
373
  </html>
374
374
  ERB
375
375
 
376
- RDOC_SEARCH_TEMPLATE = <<-'ERB'
376
+ RDOC_SEARCH_TEMPLATE = <<-'ERB'.freeze
377
377
  <?xml version="1.0" encoding="iso-8859-1"?>
378
378
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
379
379
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@@ -450,7 +450,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
450
450
  @have_rdoc_4_plus = nil
451
451
  end
452
452
 
453
- def add_date res
453
+ def add_date(res)
454
454
  res['date'] = @spec_dirs.map do |spec_dir|
455
455
  File.stat(spec_dir).mtime
456
456
  end.max
@@ -462,8 +462,8 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
462
462
  end
463
463
  end
464
464
 
465
- def doc_root gem_name
466
- if have_rdoc_4_plus? then
465
+ def doc_root(gem_name)
466
+ if have_rdoc_4_plus?
467
467
  "/doc_root/#{u gem_name}/"
468
468
  else
469
469
  "/doc_root/#{u gem_name}/rdoc/index.html"
@@ -491,14 +491,14 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
491
491
 
492
492
  specs = Marshal.dump specs
493
493
 
494
- if req.path =~ /\.gz$/ then
494
+ if req.path =~ /\.gz$/
495
495
  specs = Gem::Util.gzip specs
496
496
  res['content-type'] = 'application/x-gzip'
497
497
  else
498
498
  res['content-type'] = 'application/octet-stream'
499
499
  end
500
500
 
501
- if req.request_method == 'HEAD' then
501
+ if req.request_method == 'HEAD'
502
502
  res['content-length'] = specs.length
503
503
  else
504
504
  res.body << specs
@@ -509,7 +509,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
509
509
  # Creates server sockets based on the addresses option. If no addresses
510
510
  # were given a server socket for all interfaces is created.
511
511
 
512
- def listen addresses = @addresses
512
+ def listen(addresses = @addresses)
513
513
  addresses = [nil] unless addresses
514
514
 
515
515
  listeners = 0
@@ -529,14 +529,14 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
529
529
  end
530
530
  end
531
531
 
532
- if @server.listeners.empty? then
532
+ if @server.listeners.empty?
533
533
  say "Unable to start a server."
534
534
  say "Check for running servers or your --bind and --port arguments"
535
535
  terminate_interaction 1
536
536
  end
537
537
  end
538
538
 
539
- def prerelease_specs req, res
539
+ def prerelease_specs(req, res)
540
540
  reset_gems
541
541
 
542
542
  res['content-type'] = 'application/x-gzip'
@@ -552,14 +552,14 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
552
552
 
553
553
  specs = Marshal.dump specs
554
554
 
555
- if req.path =~ /\.gz$/ then
555
+ if req.path =~ /\.gz$/
556
556
  specs = Gem::Util.gzip specs
557
557
  res['content-type'] = 'application/x-gzip'
558
558
  else
559
559
  res['content-type'] = 'application/octet-stream'
560
560
  end
561
561
 
562
- if req.request_method == 'HEAD' then
562
+ if req.request_method == 'HEAD'
563
563
  res['content-length'] = specs.length
564
564
  else
565
565
  res.body << specs
@@ -579,13 +579,13 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
579
579
 
580
580
  selector = full_name.inspect
581
581
 
582
- if specs.empty? then
582
+ if specs.empty?
583
583
  res.status = 404
584
584
  res.body = "No gems found matching #{selector}"
585
- elsif specs.length > 1 then
585
+ elsif specs.length > 1
586
586
  res.status = 500
587
587
  res.body = "Multiple gems found matching #{selector}"
588
- elsif marshal_format then
588
+ elsif marshal_format
589
589
  res['content-type'] = 'application/x-deflate'
590
590
  res.body << Gem.deflate(Marshal.dump(specs.first))
591
591
  end
@@ -818,7 +818,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
818
818
  '/gems' => '/cache/',
819
819
  }
820
820
 
821
- if have_rdoc_4_plus? then
821
+ if have_rdoc_4_plus?
822
822
  @server.mount '/doc_root', RDoc::Servlet, '/doc_root'
823
823
  else
824
824
  file_handlers['/doc_root'] = '/doc/'
@@ -851,14 +851,14 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
851
851
 
852
852
  specs = Marshal.dump specs
853
853
 
854
- if req.path =~ /\.gz$/ then
854
+ if req.path =~ /\.gz$/
855
855
  specs = Gem::Util.gzip specs
856
856
  res['content-type'] = 'application/x-gzip'
857
857
  else
858
858
  res['content-type'] = 'application/octet-stream'
859
859
  end
860
860
 
861
- if req.request_method == 'HEAD' then
861
+ if req.request_method == 'HEAD'
862
862
  res['content-length'] = specs.length
863
863
  else
864
864
  res.body << specs